Refactor, first attempt at slides.
Slides currently have no texture and need deletion
This commit is contained in:
parent
8aa139646e
commit
8e5f51cce9
8
Bezel.gd
8
Bezel.gd
|
@ -10,18 +10,18 @@ func _draw():
|
|||
draw_rect(Rect2(0, 0, x_margin, screen_height), bezel_color)
|
||||
draw_rect(Rect2(1920-x_margin, 0, x_margin, screen_height), bezel_color)
|
||||
|
||||
bezel_points = arc_point_list(screen_center, screen_height/2, 0, 90)
|
||||
bezel_points = arc_point_list(screen_center, screen_height/2, 0, -90)
|
||||
bezel_points.push_back(Vector2(1920-x_margin, 0))
|
||||
draw_polygon(bezel_points, bezel_colors)
|
||||
|
||||
bezel_points = arc_point_list(screen_center, screen_height/2, 90, 180)
|
||||
bezel_points = arc_point_list(screen_center, screen_height/2, -90, -180)
|
||||
bezel_points.push_back(Vector2(x_margin, 0))
|
||||
draw_polygon(bezel_points, bezel_colors)
|
||||
|
||||
bezel_points = arc_point_list(screen_center, screen_height/2, 180, 270)
|
||||
bezel_points = arc_point_list(screen_center, screen_height/2, -180, -270)
|
||||
bezel_points.push_back(Vector2(x_margin, screen_height))
|
||||
draw_polygon(bezel_points, bezel_colors)
|
||||
|
||||
bezel_points = arc_point_list(screen_center, screen_height/2, 270, 360)
|
||||
bezel_points = arc_point_list(screen_center, screen_height/2, -270, -360)
|
||||
bezel_points.push_back(Vector2(1920-x_margin, screen_height))
|
||||
draw_polygon(bezel_points, bezel_colors)
|
||||
|
|
|
@ -6,6 +6,9 @@ class SRT:
|
|||
const ID_BREAK := 4
|
||||
const ID_HOLD := 2
|
||||
const ID_SLIDE_END := 128
|
||||
const ID3_SLIDE_CHORD := 0 # Straight line
|
||||
const ID3_SLIDE_ARC_CW := 1
|
||||
const ID3_SLIDE_ARC_ACW := 2
|
||||
|
||||
static func load_file(filename):
|
||||
var file = File.new()
|
||||
|
@ -16,6 +19,7 @@ class SRT:
|
|||
var notes = []
|
||||
var beats_per_measure := 4
|
||||
var length = file.get_len()
|
||||
var slide_idxs = {}
|
||||
while (file.get_position() < (length-2)):
|
||||
var noteline = file.get_csv_line()
|
||||
var time_hit := (float(noteline[0]) + float(noteline[1])) * beats_per_measure
|
||||
|
@ -31,16 +35,63 @@ class SRT:
|
|||
ID_BREAK:
|
||||
notes.push_back(Note.make_break(time_hit, column))
|
||||
ID_SLIDE_END:
|
||||
pass # id2 is slide ID
|
||||
# id2 is slide ID
|
||||
if id2 in slide_idxs:
|
||||
notes[slide_idxs[id2]].column_release = column
|
||||
_:
|
||||
if id2 == 0:
|
||||
notes.push_back(Note.make_tap(time_hit, column))
|
||||
else:
|
||||
# id2 is slide ID, id3 is slide pattern
|
||||
# In order to properly declare the slide, we need the paired endcap which may not be the next note
|
||||
notes.push_back(Note.make_slide(time_hit, duration, column, column))
|
||||
slide_idxs[id2] = len(notes)
|
||||
notes.push_back(Note.make_slide(time_hit, duration, column, -1))
|
||||
match id3:
|
||||
ID3_SLIDE_CHORD:
|
||||
notes[slide_idxs[id2]].slide_type = Note.SlideType.CHORD
|
||||
ID3_SLIDE_ARC_CW:
|
||||
notes[slide_idxs[id2]].slide_type = Note.SlideType.ARC_CW
|
||||
ID3_SLIDE_ARC_ACW:
|
||||
notes[slide_idxs[id2]].slide_type = Note.SlideType.ARC_ACW
|
||||
_:
|
||||
print("Unknown slide type: ", id3)
|
||||
return notes
|
||||
|
||||
|
||||
class SRB:
|
||||
func load_file(filename):
|
||||
static func load_file(filename):
|
||||
pass
|
||||
|
||||
|
||||
class Test:
|
||||
static func stress_pattern():
|
||||
var notes = []
|
||||
for bar in range(8):
|
||||
notes.push_back(Note.make_hold(bar*4, 1, bar%8))
|
||||
for i in range(1, 8):
|
||||
notes.push_back(Note.make_tap(bar*4 + (i/2.0), (bar + i)%8))
|
||||
notes.push_back(Note.make_tap(bar*4 + (7/2.0), (bar + 3)%8))
|
||||
for bar in range(8, 16):
|
||||
notes.push_back(Note.make_hold(bar*4, 2, bar%8))
|
||||
for i in range(1, 8):
|
||||
notes.push_back(Note.make_tap(bar*4 + (i/2.0), (bar + i)%8))
|
||||
notes.push_back(Note.make_tap(bar*4 + ((i+0.5)/2.0), (bar + i)%8))
|
||||
notes.push_back(Note.make_slide(bar*4 + ((i+1)/2.0), 1, (bar + i)%8, 0))
|
||||
for bar in range(16, 24):
|
||||
notes.push_back(Note.make_hold(bar*4, 2, bar%8))
|
||||
notes.push_back(Note.make_hold(bar*4, 1, (bar+1)%8))
|
||||
for i in range(2, 8):
|
||||
notes.push_back(Note.make_tap(bar*4 + (i/2.0), (bar + i)%8))
|
||||
notes.push_back(Note.make_hold(bar*4 + ((i+1)/2.0), 0.5, (bar + i)%8))
|
||||
for bar in range(24, 32):
|
||||
notes.push_back(Note.make_hold(bar*4, 1, bar%8))
|
||||
for i in range(1, 32):
|
||||
notes.push_back(Note.make_tap(bar*4 + (i/8.0), (bar + i)%8))
|
||||
if (i%2) > 0:
|
||||
notes.push_back(Note.make_tap(bar*4 + (i/8.0), (bar + i + 4)%8))
|
||||
for bar in range(32, 48):
|
||||
notes.push_back(Note.make_hold(bar*4, 1, bar%8))
|
||||
for i in range(1, 32):
|
||||
notes.push_back(Note.make_tap(bar*4 + (i/8.0), (bar + i)%8))
|
||||
notes.push_back(Note.make_tap(bar*4 + (i/8.0), (bar + i + 3)%8))
|
||||
return notes
|
|
@ -1,50 +1,65 @@
|
|||
extends Label
|
||||
|
||||
var touch_points = {} # array containing all points touched on the screen
|
||||
var touch_points = {} # dict containing all points touched on the screen
|
||||
var touch_positions = [] # array of above
|
||||
var fingers = 0 setget set_fingers # setter for show fingers number on screen
|
||||
var txt_ball = preload("res://assets/ball.png") # preload our ball texture
|
||||
var default_font = preload("res://assets/NotoSans.tres") # point to godot standard font
|
||||
|
||||
|
||||
|
||||
func _init():
|
||||
pass
|
||||
|
||||
func _ready():
|
||||
set_process_unhandled_input(true) # process user input
|
||||
set_fingers(0)
|
||||
|
||||
|
||||
##########################################################################
|
||||
# draw fingers points on screen
|
||||
func _draw():
|
||||
var touch_positions = PoolVector2Array()
|
||||
# draw points
|
||||
for i in touch_points:
|
||||
var point = touch_points[i]
|
||||
if point.pressed:
|
||||
touch_positions.push_back(point.position)
|
||||
# DRAW POINTS ################################################
|
||||
draw_texture(txt_ball, point.position - Vector2(24, 24))
|
||||
draw_string(default_font, point.position - Vector2(24, 24), str(i))
|
||||
if len(touch_positions) > 1:
|
||||
for i in range(len(touch_positions)-1):
|
||||
# Draw line
|
||||
draw_line(touch_positions[i], touch_positions[i+1], Color(1,1,1,1))
|
||||
# if point.pressed:
|
||||
# DRAW POINTS ################################################
|
||||
draw_texture(txt_ball, point.position - Vector2(24, 24))
|
||||
draw_string(default_font, point.position - Vector2(24, 24), str(i))
|
||||
# if len(touch_positions) > 1:
|
||||
# for i in range(len(touch_positions)-1):
|
||||
# # Draw line
|
||||
# draw_line(touch_positions[i], touch_positions[i+1], Color(1,1,1,1))
|
||||
|
||||
func update_data():
|
||||
touch_positions.clear()
|
||||
for i in touch_points:
|
||||
touch_positions.push_back(touch_points[i].position)
|
||||
set_fingers(len(touch_positions))
|
||||
update()
|
||||
|
||||
##########################################################################
|
||||
func _input(event):
|
||||
# Unfortunately event.device does NOT differentiate touchscreen inputs on X11, Godot v3.1.1
|
||||
# As such, we'll need to do some fancy mapping for multiple inputs
|
||||
if (event is InputEventScreenDrag):
|
||||
touch_points[event.index] = {pressed = true, position = event.position}
|
||||
if (event is InputEventScreenTouch):
|
||||
elif (event is InputEventScreenTouch):
|
||||
if event.pressed:
|
||||
if not touch_points.has(event.index):
|
||||
touch_points[event.index] = {}
|
||||
touch_points[event.index].position = event.position # update position
|
||||
touch_points[event.index].pressed = event.pressed # update "pressed" flag
|
||||
# touch_points[event.index].pressed = event.pressed # update "pressed" flag
|
||||
else:
|
||||
if touch_points.has(event.index):
|
||||
touch_points.erase(event.index)
|
||||
update()
|
||||
update_data()
|
||||
|
||||
##########################################################################
|
||||
# write how many fingers are tapping the screen
|
||||
func set_fingers(value):
|
||||
fingers = value
|
||||
if fingers > 0:
|
||||
set_text(str(fingers))
|
||||
set_text("Fingers: " + str(fingers))
|
||||
else:
|
||||
set_text("0")
|
||||
set_text("Fingers: 0")
|
1
Note.gd
1
Note.gd
|
@ -4,6 +4,7 @@ extends Node
|
|||
#class_name Note
|
||||
|
||||
enum {NOTE_TAP, NOTE_HOLD, NOTE_SLIDE, NOTE_ARROW, NOTE_TOUCH, NOTE_TOUCH_HOLD}
|
||||
enum SlideType {CHORD, ARC_CW, ARC_ACW}
|
||||
const DEATH_DELAY := 0.45
|
||||
|
||||
static func make_tap(time_hit: float, column: int) -> Dictionary:
|
||||
|
|
340
NoteHandler.gd
340
NoteHandler.gd
|
@ -3,22 +3,35 @@ extends "res://main.gd"
|
|||
# This script will draw all note events.
|
||||
|
||||
var tex := preload("res://assets/spritesheet-1024.png")
|
||||
var tex_slide_arrow := preload("res://assets/slide-arrow-512.png")
|
||||
var slide_trail_shadermaterial := preload("res://shaders/slidetrail.tres")
|
||||
|
||||
const first_column_angle_deg := -67.5
|
||||
var radial_col_angles := PoolRealArray()
|
||||
var radial_unit_vectors := PoolVector2Array()
|
||||
# Constants for the overall notefield
|
||||
var RADIAL_COL_ANGLES := PoolRealArray() # ideally const
|
||||
var RADIAL_UNIT_VECTORS := PoolVector2Array() # ideally const
|
||||
|
||||
const RING_LINE_SEGMENTS_PER_COLUMN := 12
|
||||
var RING_LINE_SEGMENTS_VECTORS := PoolVector2Array()
|
||||
# ------------------------------------------------------
|
||||
# Ring segments is only for CPU drawing, superceded for now.
|
||||
# ------------------------------------------------------
|
||||
#const RING_LINE_SEGMENTS_PER_COLUMN := 12
|
||||
#var RING_LINE_SEGMENTS_VECTORS := PoolVector2Array()
|
||||
#const ring_segs := Rules.COLS * RING_LINE_SEGMENTS_PER_COLUMN
|
||||
#const ring_seg_angle := 360.0/ring_segs
|
||||
#var ring_line_segments_alphas = PoolRealArray()
|
||||
#var ring_line_segments_widths = PoolRealArray()
|
||||
func init_radial_values():
|
||||
for i in range(Rules.COLS):
|
||||
var angle = deg2rad(fmod(Rules.FIRST_COLUMN_ANGLE_DEG + (i * Rules.COLS_ANGLE_DEG), 360.0))
|
||||
RADIAL_COL_ANGLES.push_back(angle)
|
||||
RADIAL_UNIT_VECTORS.push_back(Vector2(cos(angle), sin(angle)))
|
||||
# for i in range(ring_segs):
|
||||
# var angle = deg2rad(Rules.FIRST_COLUMN_ANGLE_DEG + (i * ring_seg_angle))
|
||||
# RING_LINE_SEGMENTS_VECTORS.push_back(Vector2(cos(angle), sin(angle)))
|
||||
# for i in range(ring_segs/4):
|
||||
# var alpha := 1.0 - (i/float(ring_segs/4))
|
||||
# ring_line_segments_alphas.push_back(alpha)
|
||||
# ring_line_segments_widths.push_back(lerp(alpha, 1.0, 0.5))
|
||||
|
||||
const cols := 8
|
||||
const cols_angle := 360.0/cols
|
||||
const ring_segs := cols * RING_LINE_SEGMENTS_PER_COLUMN
|
||||
const ring_seg_angle := 360.0/ring_segs
|
||||
|
||||
var sprite_size := 128
|
||||
var sprite_size2 := sprite_size/2
|
||||
const INNER_NOTE_CIRCLE_RATIO := 0.3
|
||||
const SQRT2 := sqrt(2)
|
||||
const DEG45 := deg2rad(45.0)
|
||||
const DEG90 := deg2rad(90.0)
|
||||
|
@ -27,10 +40,11 @@ const DEG135 := deg2rad(135.0)
|
|||
var time := 0.0
|
||||
var t := 0.0
|
||||
var bpm := 120.0
|
||||
var note_forecast_beats := 2.0
|
||||
var active_notes := []
|
||||
var all_notes := []
|
||||
var next_note_to_load := 0
|
||||
var slide_trail_meshes := []
|
||||
var slide_trail_mesh_instances := []
|
||||
|
||||
# UV vertex arrays for our sprites
|
||||
# tap/star/arrow are 4-vertex 2-triangle simple squares
|
||||
|
@ -42,8 +56,11 @@ const UV_ARRAY_HOLD := PoolVector2Array([
|
|||
])
|
||||
const UV_ARRAY_STAR := PoolVector2Array([Vector2(0.5, 0), Vector2(1, 0), Vector2(0.5, 0.5), Vector2(1, 0.5)])
|
||||
const UV_ARRAY_ARROW := PoolVector2Array([Vector2(0, 0), Vector2(0.5, 0), Vector2(0, 0.5), Vector2(0.5, 0.5)])
|
||||
# Slide trail arrow. Single tri.
|
||||
const UV_ARRAY_SLIDE_ARROW := PoolVector2Array([Vector2(0, 0), Vector2(1, 0), Vector2(0, 1)])
|
||||
const UV_ARRAY_SLIDE_ARROW2 := PoolVector2Array([Vector2(1, 1), Vector2(0, 1), Vector2(1, 0)])
|
||||
|
||||
# Normal vertex arrays for our sprites
|
||||
# Normal vertex arrays for our sprites. Might be unnecessary?
|
||||
const DEFAULT_NORMAL := Vector3(0, 0, 1)
|
||||
var NORMAL_ARRAY_4 := PoolVector3Array([DEFAULT_NORMAL, DEFAULT_NORMAL, DEFAULT_NORMAL, DEFAULT_NORMAL])
|
||||
var NORMAL_ARRAY_8 := PoolVector3Array([
|
||||
|
@ -51,90 +68,145 @@ var NORMAL_ARRAY_8 := PoolVector3Array([
|
|||
DEFAULT_NORMAL, DEFAULT_NORMAL, DEFAULT_NORMAL, DEFAULT_NORMAL
|
||||
])
|
||||
|
||||
# Color definitions
|
||||
const COLOR_TAP := Color(1, 0.15, 0.15, 1)
|
||||
const COLOR_TAP2 := Color(0.75, 0.5, 0, 1) # High-score taps ("breaks" in maimai)
|
||||
const COLOR_HOLD := Color(1, 0.15, 0.15, 1)
|
||||
const COLOR_HOLD_HELD := Color(1, 1, 1, 1)
|
||||
const COLOR_STAR := Color(0, 0, 1, 1)
|
||||
const COLOR_DOUBLE := Color(1, 1, 0, 1) # When two (or more in master) hit events coincide
|
||||
|
||||
var COLOR_ARRAY_TAP := PoolColorArray([COLOR_TAP, COLOR_TAP, COLOR_TAP, COLOR_TAP])
|
||||
var COLOR_ARRAY_TAP2 := PoolColorArray([COLOR_TAP2, COLOR_TAP2, COLOR_TAP2, COLOR_TAP2])
|
||||
var COLOR_ARRAY_HOLD := PoolColorArray([
|
||||
COLOR_HOLD, COLOR_HOLD, COLOR_HOLD, COLOR_HOLD,
|
||||
COLOR_HOLD, COLOR_HOLD, COLOR_HOLD, COLOR_HOLD
|
||||
])
|
||||
var COLOR_ARRAY_HOLD_HELD := PoolColorArray([
|
||||
COLOR_HOLD_HELD, COLOR_HOLD_HELD, COLOR_HOLD_HELD, COLOR_HOLD_HELD,
|
||||
COLOR_HOLD_HELD, COLOR_HOLD_HELD, COLOR_HOLD_HELD, COLOR_HOLD_HELD
|
||||
])
|
||||
var COLOR_ARRAY_STAR := PoolColorArray([COLOR_STAR, COLOR_STAR, COLOR_STAR, COLOR_STAR])
|
||||
var COLOR_ARRAY_DOUBLE_4 := PoolColorArray([COLOR_DOUBLE, COLOR_DOUBLE, COLOR_DOUBLE, COLOR_DOUBLE])
|
||||
var COLOR_ARRAY_DOUBLE_8 := PoolColorArray([
|
||||
COLOR_DOUBLE, COLOR_DOUBLE, COLOR_DOUBLE, COLOR_DOUBLE,
|
||||
COLOR_DOUBLE, COLOR_DOUBLE, COLOR_DOUBLE, COLOR_DOUBLE
|
||||
])
|
||||
|
||||
# Helper functions to generate meshes from vertex arrays
|
||||
func make_tap_mesh(mesh: ArrayMesh, vertex_array, color_array = COLOR_ARRAY_TAP):
|
||||
func make_tap_mesh(mesh: ArrayMesh, vertex_array, color_array = theme.COLOR_ARRAY_TAP):
|
||||
var arrays = []
|
||||
arrays.resize(Mesh.ARRAY_MAX)
|
||||
arrays[Mesh.ARRAY_VERTEX] = vertex_array
|
||||
arrays[Mesh.ARRAY_NORMAL] = NORMAL_ARRAY_4
|
||||
# arrays[Mesh.ARRAY_NORMAL] = NORMAL_ARRAY_4
|
||||
arrays[Mesh.ARRAY_TEX_UV] = UV_ARRAY_TAP
|
||||
arrays[Mesh.ARRAY_COLOR] = color_array
|
||||
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLE_STRIP, arrays)
|
||||
|
||||
func make_hold_mesh(mesh: ArrayMesh, vertex_array, color_array = COLOR_ARRAY_HOLD):
|
||||
func make_hold_mesh(mesh: ArrayMesh, vertex_array, color_array = theme.COLOR_ARRAY_HOLD):
|
||||
var arrays = []
|
||||
arrays.resize(Mesh.ARRAY_MAX)
|
||||
arrays[Mesh.ARRAY_VERTEX] = vertex_array
|
||||
arrays[Mesh.ARRAY_NORMAL] = NORMAL_ARRAY_8
|
||||
# arrays[Mesh.ARRAY_NORMAL] = NORMAL_ARRAY_8
|
||||
arrays[Mesh.ARRAY_TEX_UV] = UV_ARRAY_HOLD
|
||||
arrays[Mesh.ARRAY_COLOR] = color_array
|
||||
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLE_STRIP, arrays)
|
||||
|
||||
func make_star_mesh(mesh: ArrayMesh, vertex_array, color_array = COLOR_ARRAY_STAR):
|
||||
func make_star_mesh(mesh: ArrayMesh, vertex_array, color_array = theme.COLOR_ARRAY_STAR):
|
||||
var arrays = []
|
||||
arrays.resize(Mesh.ARRAY_MAX)
|
||||
arrays[Mesh.ARRAY_VERTEX] = vertex_array
|
||||
arrays[Mesh.ARRAY_NORMAL] = NORMAL_ARRAY_4
|
||||
# arrays[Mesh.ARRAY_NORMAL] = NORMAL_ARRAY_4
|
||||
arrays[Mesh.ARRAY_TEX_UV] = UV_ARRAY_STAR
|
||||
arrays[Mesh.ARRAY_COLOR] = color_array
|
||||
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLE_STRIP, arrays)
|
||||
|
||||
func make_arrow_mesh(mesh: ArrayMesh, vertex_array, color_array = COLOR_ARRAY_TAP):
|
||||
func make_arrow_mesh(mesh: ArrayMesh, vertex_array, color_array = theme.COLOR_ARRAY_TAP):
|
||||
var arrays = []
|
||||
arrays.resize(Mesh.ARRAY_MAX)
|
||||
arrays[Mesh.ARRAY_VERTEX] = vertex_array
|
||||
arrays[Mesh.ARRAY_NORMAL] = NORMAL_ARRAY_4
|
||||
# arrays[Mesh.ARRAY_NORMAL] = NORMAL_ARRAY_4
|
||||
arrays[Mesh.ARRAY_TEX_UV] = UV_ARRAY_ARROW
|
||||
arrays[Mesh.ARRAY_COLOR] = color_array
|
||||
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLE_STRIP, arrays)
|
||||
|
||||
|
||||
func make_tap_note(mesh: ArrayMesh, column: int, position: float, scale := 1.0, color_array := COLOR_ARRAY_TAP) -> ArrayMesh:
|
||||
if position < INNER_NOTE_CIRCLE_RATIO:
|
||||
scale *= position/INNER_NOTE_CIRCLE_RATIO
|
||||
position = INNER_NOTE_CIRCLE_RATIO
|
||||
var note_center = screen_center + (radial_unit_vectors[column] * position * receptor_ring_radius)
|
||||
var dim = sprite_size2 * scale
|
||||
const slide_arrows_per_unit_length := 10
|
||||
func make_slide_trail_mesh(note: Dictionary) -> ArrayMesh:
|
||||
# Generates a mesh centered around origin. Make sure the MeshInstance2D that draws this is centered on the screen.
|
||||
var mesh = ArrayMesh.new()
|
||||
var arrays = []
|
||||
arrays.resize(Mesh.ARRAY_MAX)
|
||||
var vertices := PoolVector2Array()
|
||||
var uvs := PoolVector2Array()
|
||||
var colors := PoolColorArray()
|
||||
# First we need to determine how many arrows to leave.
|
||||
# Chord length is 2r*sin(theta/2)
|
||||
# Arc length is r*theta (in rads)
|
||||
# 18 for a 3chord in maimai
|
||||
# 20 for a 4chord
|
||||
# 6 per arc segment +1 for every receptor crossed over, ~7 per
|
||||
var unit_length: float
|
||||
var trail_length: int
|
||||
match note.slide_type:
|
||||
Note.SlideType.CHORD:
|
||||
unit_length = 2*abs(sin(RADIAL_COL_ANGLES[note.column_release] - RADIAL_COL_ANGLES[note.column]))
|
||||
Note.SlideType.ARC_CW:
|
||||
unit_length = fposmod(RADIAL_COL_ANGLES[note.column_release] - RADIAL_COL_ANGLES[note.column], TAU)
|
||||
Note.SlideType.ARC_ACW:
|
||||
unit_length = fposmod(RADIAL_COL_ANGLES[note.column] - RADIAL_COL_ANGLES[note.column_release], TAU)
|
||||
trail_length = int(floor(unit_length * slide_arrows_per_unit_length))
|
||||
vertices.resize(3*trail_length)
|
||||
# uvs.resize(3*trail_length)
|
||||
colors.resize(3*trail_length)
|
||||
for i in trail_length:
|
||||
uvs.append_array(UV_ARRAY_SLIDE_ARROW if i%2 else UV_ARRAY_SLIDE_ARROW2)
|
||||
for j in 3:
|
||||
# uvs[i*3+j] = UV_ARRAY_SLIDE_ARROW[j] if i%2 else UV_ARRAY_SLIDE_ARROW2[j]
|
||||
colors[i*3+j] = Color(1.0, 1.0, 1.0, 1.0+float(i))
|
||||
|
||||
match note.slide_type:
|
||||
Note.SlideType.CHORD:
|
||||
var angle : float = RADIAL_UNIT_VECTORS[note.column].angle_to_point(RADIAL_UNIT_VECTORS[note.column_release])
|
||||
var start : Vector2 = RADIAL_UNIT_VECTORS[note.column] * theme.receptor_ring_radius
|
||||
var end : Vector2 = RADIAL_UNIT_VECTORS[note.column_release] * theme.receptor_ring_radius
|
||||
var uv1o : Vector2 = polar2cartesian(theme.sprite_size2, angle)
|
||||
var uv2o : Vector2 = polar2cartesian(theme.sprite_size2, angle+PI/2.0)
|
||||
var uv3o : Vector2 = polar2cartesian(theme.sprite_size2, angle-PI/2.0)
|
||||
for i in trail_length:
|
||||
var offset : Vector2 = lerp(start, end, (i+1)/float(trail_length))
|
||||
vertices[i*3] = offset + uv1o
|
||||
vertices[i*3+1] = offset + uv2o
|
||||
vertices[i*3+2] = offset + uv3o
|
||||
Note.SlideType.ARC_CW:
|
||||
var start_a : float = RADIAL_COL_ANGLES[note.column]
|
||||
var end_a : float = RADIAL_COL_ANGLES[note.column_release]
|
||||
if end_a < start_a:
|
||||
end_a += TAU
|
||||
for i in trail_length:
|
||||
var circle_angle : float = lerp(start_a, end_a, (i+1)/float(trail_length))
|
||||
var angle : float = circle_angle + PI/2.0
|
||||
var offset : Vector2 = polar2cartesian(theme.receptor_ring_radius, circle_angle)
|
||||
vertices[i*3] = offset + polar2cartesian(theme.sprite_size2, angle)
|
||||
vertices[i*3+1] = offset + polar2cartesian(theme.sprite_size2, angle+PI/2.0)
|
||||
vertices[i*3+2] = offset + polar2cartesian(theme.sprite_size2, angle-PI/2.0)
|
||||
Note.SlideType.ARC_ACW:
|
||||
var start_a : float = RADIAL_COL_ANGLES[note.column]
|
||||
var end_a : float = RADIAL_COL_ANGLES[note.column_release]
|
||||
if end_a > start_a:
|
||||
end_a -= TAU
|
||||
for i in trail_length:
|
||||
var circle_angle : float = lerp(start_a, end_a, (i+1)/float(trail_length))
|
||||
var angle : float = circle_angle - PI/2.0
|
||||
var offset : Vector2 = polar2cartesian(theme.receptor_ring_radius, circle_angle)
|
||||
vertices[i*3] = offset + polar2cartesian(theme.sprite_size2, angle)
|
||||
vertices[i*3+1] = offset + polar2cartesian(theme.sprite_size2, angle+PI/2.0)
|
||||
vertices[i*3+2] = offset + polar2cartesian(theme.sprite_size2, angle-PI/2.0)
|
||||
|
||||
arrays[Mesh.ARRAY_VERTEX] = vertices
|
||||
arrays[Mesh.ARRAY_TEX_UV] = uvs
|
||||
arrays[Mesh.ARRAY_COLOR] = colors
|
||||
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)
|
||||
return mesh
|
||||
|
||||
|
||||
|
||||
func make_tap_note(mesh: ArrayMesh, column: int, position: float, scale := 1.0, color_array := theme.COLOR_ARRAY_TAP) -> ArrayMesh:
|
||||
if position < theme.INNER_NOTE_CIRCLE_RATIO:
|
||||
scale *= position/theme.INNER_NOTE_CIRCLE_RATIO
|
||||
position = theme.INNER_NOTE_CIRCLE_RATIO
|
||||
var note_center = screen_center + (RADIAL_UNIT_VECTORS[column] * position * theme.receptor_ring_radius)
|
||||
var dim = theme.sprite_size2 * scale
|
||||
var vertices = PoolVector2Array([note_center + Vector2(-dim, -dim), note_center + Vector2(dim, -dim), note_center + Vector2(-dim, dim), note_center + Vector2(dim, dim)])
|
||||
make_tap_mesh(mesh, vertices, color_array)
|
||||
return mesh
|
||||
|
||||
func make_hold_note(mesh: ArrayMesh, column: int, position1: float, position2: float, scale := 1.0, color_array = COLOR_ARRAY_HOLD) -> ArrayMesh:
|
||||
if position1 < INNER_NOTE_CIRCLE_RATIO:
|
||||
scale *= position1/INNER_NOTE_CIRCLE_RATIO
|
||||
position1 = INNER_NOTE_CIRCLE_RATIO
|
||||
if position2 < INNER_NOTE_CIRCLE_RATIO:
|
||||
position2 = INNER_NOTE_CIRCLE_RATIO
|
||||
var note_center1 = screen_center + (radial_unit_vectors[column] * position1 * receptor_ring_radius)
|
||||
var note_center2 = screen_center + (radial_unit_vectors[column] * position2 * receptor_ring_radius)
|
||||
var dim = sprite_size2 * scale
|
||||
func make_hold_note(mesh: ArrayMesh, column: int, position1: float, position2: float, scale := 1.0, color_array = theme.COLOR_ARRAY_HOLD) -> ArrayMesh:
|
||||
if position1 < theme.INNER_NOTE_CIRCLE_RATIO:
|
||||
scale *= position1/theme.INNER_NOTE_CIRCLE_RATIO
|
||||
position1 = theme.INNER_NOTE_CIRCLE_RATIO
|
||||
if position2 < theme.INNER_NOTE_CIRCLE_RATIO:
|
||||
position2 = theme.INNER_NOTE_CIRCLE_RATIO
|
||||
var note_center1 = screen_center + (RADIAL_UNIT_VECTORS[column] * position1 * theme.receptor_ring_radius)
|
||||
var note_center2 = screen_center + (RADIAL_UNIT_VECTORS[column] * position2 * theme.receptor_ring_radius)
|
||||
var dim = theme.sprite_size2 * scale
|
||||
var dim2 = dim * SQRT2
|
||||
var angle = radial_col_angles[column]
|
||||
var angle = RADIAL_COL_ANGLES[column]
|
||||
var a1 = angle - DEG45
|
||||
var a2 = angle + DEG45
|
||||
var a3 = angle - DEG90
|
||||
|
@ -150,12 +222,12 @@ func make_hold_note(mesh: ArrayMesh, column: int, position1: float, position2: f
|
|||
make_hold_mesh(mesh, vertices, color_array)
|
||||
return mesh
|
||||
|
||||
func make_slide_note(mesh: ArrayMesh, column: int, position: float, scale := 1.0, color_array := COLOR_ARRAY_STAR) -> ArrayMesh:
|
||||
if position < INNER_NOTE_CIRCLE_RATIO:
|
||||
scale *= position/INNER_NOTE_CIRCLE_RATIO
|
||||
position = INNER_NOTE_CIRCLE_RATIO
|
||||
var note_center = screen_center + (radial_unit_vectors[column] * position * receptor_ring_radius)
|
||||
var dim = sprite_size2 * scale * SQRT2
|
||||
func make_slide_note(mesh: ArrayMesh, column: int, position: float, scale := 1.0, color_array := theme.COLOR_ARRAY_STAR) -> ArrayMesh:
|
||||
if position < theme.INNER_NOTE_CIRCLE_RATIO:
|
||||
scale *= position/theme.INNER_NOTE_CIRCLE_RATIO
|
||||
position = theme.INNER_NOTE_CIRCLE_RATIO
|
||||
var note_center = screen_center + (RADIAL_UNIT_VECTORS[column] * position * theme.receptor_ring_radius)
|
||||
var dim = theme.sprite_size2 * scale * SQRT2
|
||||
var angle = deg2rad(fmod(t*270.0, 360.0))
|
||||
var a1 = angle - DEG45
|
||||
var a2 = angle + DEG45
|
||||
|
@ -168,28 +240,17 @@ func make_slide_note(mesh: ArrayMesh, column: int, position: float, scale := 1.0
|
|||
make_star_mesh(mesh, vertices, color_array)
|
||||
return mesh
|
||||
|
||||
var ring_line_segments_alphas = PoolRealArray()
|
||||
var ring_line_segments_widths = PoolRealArray()
|
||||
|
||||
#----------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
func _init():
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN)
|
||||
for i in range(cols):
|
||||
var angle = deg2rad(first_column_angle_deg + (i * cols_angle))
|
||||
radial_col_angles.push_back(angle)
|
||||
radial_unit_vectors.push_back(Vector2(cos(angle), sin(angle)))
|
||||
for i in range(ring_segs):
|
||||
var angle = deg2rad(first_column_angle_deg + (i * ring_seg_angle))
|
||||
RING_LINE_SEGMENTS_VECTORS.push_back(Vector2(cos(angle), sin(angle)))
|
||||
|
||||
for i in range(ring_segs/4):
|
||||
var alpha := 1.0 - (i/float(ring_segs/4))
|
||||
ring_line_segments_alphas.push_back(alpha)
|
||||
ring_line_segments_widths.push_back(lerp(alpha, 1.0, 0.5))
|
||||
|
||||
init_radial_values()
|
||||
|
||||
func _draw():
|
||||
var mesh := ArrayMesh.new()
|
||||
var dots := PoolVector2Array()
|
||||
var dots_dict := {}
|
||||
# var dots := PoolVector2Array()
|
||||
# var dots_dict := {}
|
||||
|
||||
var noteline_data : Image = noteline_array_image.get_rect(Rect2(0, 0, 16, 16))
|
||||
noteline_data.lock()
|
||||
|
@ -197,31 +258,36 @@ func _draw():
|
|||
var j := 0
|
||||
|
||||
for note in active_notes:
|
||||
var position : float = (t+note_forecast_beats-note.time_hit)/note_forecast_beats
|
||||
var note_center := screen_center + (radial_unit_vectors[note.column] * position * receptor_ring_radius)
|
||||
var position : float = (t+theme.note_forecast_beats-note.time_hit)/theme.note_forecast_beats
|
||||
var note_center := screen_center + (RADIAL_UNIT_VECTORS[note.column] * position * theme.receptor_ring_radius)
|
||||
# dots.push_back(note_center)
|
||||
# if not dots_dict.has(position):
|
||||
# dots_dict[position] = []
|
||||
# dots_dict[position].push_back(note.column)
|
||||
noteline_data.set_pixel(i%16, i/16, Color(position, note.column, radial_col_angles[note.column]))
|
||||
noteline_data.set_pixel(i%16, i/16, Color(position, note.column, RADIAL_COL_ANGLES[note.column]))
|
||||
i += 1
|
||||
match note.type:
|
||||
Note.NOTE_TAP:
|
||||
var color = COLOR_ARRAY_DOUBLE_4 if note.double_hit else COLOR_ARRAY_TAP
|
||||
var color = theme.COLOR_ARRAY_DOUBLE_4 if note.double_hit else theme.COLOR_ARRAY_TAP
|
||||
make_tap_note(mesh, note.column, position, 1, color)
|
||||
Note.NOTE_HOLD:
|
||||
var color = COLOR_ARRAY_DOUBLE_8 if note.double_hit else COLOR_ARRAY_HOLD
|
||||
var position_rel : float = (t+note_forecast_beats-note.time_release)/note_forecast_beats
|
||||
var color = theme.COLOR_ARRAY_DOUBLE_8 if note.double_hit else theme.COLOR_ARRAY_HOLD
|
||||
var position_rel : float = (t+theme.note_forecast_beats-note.time_release)/theme.note_forecast_beats
|
||||
if position_rel > 0:
|
||||
var note_rel_center := screen_center + (radial_unit_vectors[note.column] * position_rel * receptor_ring_radius)
|
||||
var note_rel_center := screen_center + (RADIAL_UNIT_VECTORS[note.column] * position_rel * theme.receptor_ring_radius)
|
||||
# dots.push_back(note_rel_center)
|
||||
noteline_data.set_pixel(j%16, 15, Color(position_rel, note.column, radial_col_angles[note.column]))
|
||||
noteline_data.set_pixel(j%16, 15, Color(position_rel, note.column, RADIAL_COL_ANGLES[note.column]))
|
||||
j += 1
|
||||
make_hold_note(mesh, note.column, position, position_rel, 1.0, COLOR_ARRAY_HOLD_HELD)
|
||||
make_hold_note(mesh, note.column, position, position_rel, 1.0, theme.COLOR_ARRAY_HOLD_HELD)
|
||||
Note.NOTE_SLIDE:
|
||||
var color = COLOR_ARRAY_DOUBLE_4 if note.double_hit else COLOR_ARRAY_STAR
|
||||
var color = theme.COLOR_ARRAY_DOUBLE_4 if note.double_hit else theme.COLOR_ARRAY_STAR
|
||||
make_slide_note(mesh, note.column, position, 1.0, color)
|
||||
|
||||
noteline_data.unlock()
|
||||
var noteline_data_tex = ImageTexture.new()
|
||||
noteline_data_tex.create_from_image(noteline_data, 0)
|
||||
$notelines.set_texture(noteline_data_tex)
|
||||
|
||||
# var dot_scale := 1.0 - abs(0.25-fmod(t+0.25, 0.5))
|
||||
# var dot_inner := 6.0 * dot_scale
|
||||
# var dot_outer := 9.0 * dot_scale
|
||||
|
@ -232,10 +298,6 @@ func _draw():
|
|||
|
||||
# var line_inner := 3.0 * dot_scale
|
||||
# var line_outer := 6.0 * dot_scale
|
||||
noteline_data.unlock()
|
||||
var noteline_data_tex = ImageTexture.new()
|
||||
noteline_data_tex.create_from_image(noteline_data, 0)
|
||||
$notelines.set_texture(noteline_data_tex)
|
||||
|
||||
# for position in dots_dict:
|
||||
# for col in dots_dict[position]:
|
||||
|
@ -243,17 +305,17 @@ func _draw():
|
|||
# for i in range(ring_segs/4):
|
||||
# var alpha :float = ring_line_segments_alphas[i]*dot_scale
|
||||
# var width_scale : float = ring_line_segments_widths[i]
|
||||
# draw_line(screen_center + RING_LINE_SEGMENTS_VECTORS[(c0+i)%ring_segs]*position*receptor_ring_radius,
|
||||
# screen_center + RING_LINE_SEGMENTS_VECTORS[(c0+i+1)%ring_segs]*position*receptor_ring_radius,
|
||||
# draw_line(screen_center + RING_LINE_SEGMENTS_VECTORS[(c0+i)%ring_segs]*position*theme.receptor_ring_radius,
|
||||
# screen_center + RING_LINE_SEGMENTS_VECTORS[(c0+i+1)%ring_segs]*position*theme.receptor_ring_radius,
|
||||
# Color(1.0, 1.0, 0.65, alpha*0.8), line_inner*width_scale)
|
||||
# draw_line(screen_center + RING_LINE_SEGMENTS_VECTORS[(c0+i)%ring_segs]*position*receptor_ring_radius,
|
||||
# screen_center + RING_LINE_SEGMENTS_VECTORS[(c0+i+1)%ring_segs]*position*receptor_ring_radius,
|
||||
# draw_line(screen_center + RING_LINE_SEGMENTS_VECTORS[(c0+i)%ring_segs]*position*theme.receptor_ring_radius,
|
||||
# screen_center + RING_LINE_SEGMENTS_VECTORS[(c0+i+1)%ring_segs]*position*theme.receptor_ring_radius,
|
||||
# Color(1.0, 1.0, 0.65, alpha*0.2), line_outer*width_scale)
|
||||
# draw_line(screen_center + RING_LINE_SEGMENTS_VECTORS[(c0-i)%ring_segs]*position*receptor_ring_radius,
|
||||
# screen_center + RING_LINE_SEGMENTS_VECTORS[(c0-i-1)%ring_segs]*position*receptor_ring_radius,
|
||||
# draw_line(screen_center + RING_LINE_SEGMENTS_VECTORS[(c0-i)%ring_segs]*position*theme.receptor_ring_radius,
|
||||
# screen_center + RING_LINE_SEGMENTS_VECTORS[(c0-i-1)%ring_segs]*position*theme.receptor_ring_radius,
|
||||
# Color(1.0, 1.0, 0.65, alpha*0.8), line_inner*width_scale)
|
||||
# draw_line(screen_center + RING_LINE_SEGMENTS_VECTORS[(c0-i)%ring_segs]*position*receptor_ring_radius,
|
||||
# screen_center + RING_LINE_SEGMENTS_VECTORS[(c0-i-1)%ring_segs]*position*receptor_ring_radius,
|
||||
# draw_line(screen_center + RING_LINE_SEGMENTS_VECTORS[(c0-i)%ring_segs]*position*theme.receptor_ring_radius,
|
||||
# screen_center + RING_LINE_SEGMENTS_VECTORS[(c0-i-1)%ring_segs]*position*theme.receptor_ring_radius,
|
||||
# Color(1.0, 1.0, 0.65, alpha*0.2), line_outer*width_scale)
|
||||
|
||||
# var alpha_array = PoolRealArray()
|
||||
|
@ -270,11 +332,11 @@ func _draw():
|
|||
# for i in range(ring_segs):
|
||||
# var alpha := min(alpha_array[i], 1.0)*dot_scale
|
||||
# var width_scale : float = lerp(min(alpha_array[i], 1.0), 1.0, 0.5)
|
||||
# draw_line(screen_center + RING_LINE_SEGMENTS_VECTORS[i]*position*receptor_ring_radius,
|
||||
# screen_center + RING_LINE_SEGMENTS_VECTORS[(i+1)%ring_segs]*position*receptor_ring_radius,
|
||||
# draw_line(screen_center + RING_LINE_SEGMENTS_VECTORS[i]*position*theme.receptor_ring_radius,
|
||||
# screen_center + RING_LINE_SEGMENTS_VECTORS[(i+1)%ring_segs]*position*theme.receptor_ring_radius,
|
||||
# Color(1.0, 1.0, 0.65, alpha*0.8), line_inner*width_scale)
|
||||
# draw_line(screen_center + RING_LINE_SEGMENTS_VECTORS[i]*position*receptor_ring_radius,
|
||||
# screen_center + RING_LINE_SEGMENTS_VECTORS[(i+1)%ring_segs]*position*receptor_ring_radius,
|
||||
# draw_line(screen_center + RING_LINE_SEGMENTS_VECTORS[i]*position*theme.receptor_ring_radius,
|
||||
# screen_center + RING_LINE_SEGMENTS_VECTORS[(i+1)%ring_segs]*position*theme.receptor_ring_radius,
|
||||
# Color(1.0, 1.0, 0.65, alpha*0.2), line_outer*width_scale)
|
||||
|
||||
$meshinstance.set_mesh(mesh)
|
||||
|
@ -291,13 +353,13 @@ func _ready():
|
|||
all_notes = []
|
||||
next_note_to_load = 0
|
||||
|
||||
$meshinstance.material.set_shader_param("star_color", COLOR_STAR)
|
||||
$meshinstance.material.set_shader_param("held_color", COLOR_HOLD_HELD)
|
||||
$meshinstance.material.set_shader_param("star_color", theme.COLOR_STAR)
|
||||
$meshinstance.material.set_shader_param("held_color", theme.COLOR_HOLD_HELD)
|
||||
$meshinstance.material.set_shader_param("bps", bpm/60.0)
|
||||
$meshinstance.material.set_shader_param("screen_size", get_viewport().get_size())
|
||||
$meshinstance.set_texture(tex)
|
||||
|
||||
var rec_scale1 = (float(screen_height)/float(receptor_ring_radius))*0.5
|
||||
var rec_scale1 = (float(screen_height)/float(theme.receptor_ring_radius))*0.5
|
||||
var uv_array_playfield := PoolVector2Array([Vector2(-1.0, -1.0)*rec_scale1, Vector2(-1.0, 1.0)*rec_scale1, Vector2(1.0, -1.0)*rec_scale1, Vector2(1.0, 1.0)*rec_scale1])
|
||||
var vertex_array_playfield := PoolVector2Array([
|
||||
Vector2(x_margin, screen_height), Vector2(x_margin, 0.0),
|
||||
|
@ -317,37 +379,13 @@ func _ready():
|
|||
# Format: first 15 rows are for hit events, last row is for releases only (no ring glow)
|
||||
|
||||
all_notes = FileLoader.SRT.load_file("res://songs/199_cirno_master.srt")
|
||||
# all_notes = FileLoader.Test.stress_pattern()
|
||||
bpm = 175.0
|
||||
# for bar in range(8):
|
||||
# all_notes.push_back(Note.make_hold(bar*4, 1, bar%8))
|
||||
# for i in range(1, 8):
|
||||
# all_notes.push_back(Note.make_tap(bar*4 + (i/2.0), (bar + i)%8))
|
||||
# all_notes.push_back(Note.make_tap(bar*4 + (7/2.0), (bar + 3)%8))
|
||||
# for bar in range(8, 16):
|
||||
# all_notes.push_back(Note.make_hold(bar*4, 2, bar%8))
|
||||
# for i in range(1, 8):
|
||||
# all_notes.push_back(Note.make_tap(bar*4 + (i/2.0), (bar + i)%8))
|
||||
# all_notes.push_back(Note.make_tap(bar*4 + ((i+0.5)/2.0), (bar + i)%8))
|
||||
# all_notes.push_back(Note.make_slide(bar*4 + ((i+1)/2.0), 1, (bar + i)%8, 0))
|
||||
# for bar in range(16, 24):
|
||||
# all_notes.push_back(Note.make_hold(bar*4, 2, bar%8))
|
||||
# all_notes.push_back(Note.make_hold(bar*4, 1, (bar+1)%8))
|
||||
# for i in range(2, 8):
|
||||
# all_notes.push_back(Note.make_tap(bar*4 + (i/2.0), (bar + i)%8))
|
||||
# all_notes.push_back(Note.make_hold(bar*4 + ((i+1)/2.0), 0.5, (bar + i)%8))
|
||||
# for bar in range(24, 32):
|
||||
# all_notes.push_back(Note.make_hold(bar*4, 1, bar%8))
|
||||
# for i in range(1, 32):
|
||||
# all_notes.push_back(Note.make_tap(bar*4 + (i/8.0), (bar + i)%8))
|
||||
# if (i%2) > 0:
|
||||
# all_notes.push_back(Note.make_tap(bar*4 + (i/8.0), (bar + i + 4)%8))
|
||||
# for bar in range(32, 48):
|
||||
# all_notes.push_back(Note.make_hold(bar*4, 1, bar%8))
|
||||
# for i in range(1, 32):
|
||||
# all_notes.push_back(Note.make_tap(bar*4 + (i/8.0), (bar + i)%8))
|
||||
# all_notes.push_back(Note.make_tap(bar*4 + (i/8.0), (bar + i + 3)%8))
|
||||
|
||||
Note.process_doubles(all_notes)
|
||||
for note in all_notes:
|
||||
if note.type == Note.NOTE_SLIDE:
|
||||
slide_trail_meshes.push_back(make_slide_trail_mesh(note))
|
||||
|
||||
func game_time(realtime: float) -> float:
|
||||
return time * bpm / 60.0
|
||||
|
@ -355,13 +393,12 @@ func game_time(realtime: float) -> float:
|
|||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta):
|
||||
$meshinstance.material.set_shader_param("bps", bpm/60.0)
|
||||
$meshinstance.material.set_shader_param("screen_size", get_viewport().get_size())
|
||||
$notelines.material.set_shader_param("bps", bpm/60.0)
|
||||
|
||||
var t_old := game_time(time)
|
||||
time += delta
|
||||
t = game_time(time)
|
||||
if (t >= 0) and (t_old < 0):
|
||||
if (t_old < 0) and (t >= 0):
|
||||
get_node("/root/main/video").play()
|
||||
|
||||
# Clean out expired notes
|
||||
|
@ -374,11 +411,20 @@ func _process(delta):
|
|||
if next_note_to_load >= len(all_notes):
|
||||
# All notes have been loaded, maybe do something
|
||||
break
|
||||
if all_notes[next_note_to_load].time_hit > (t + note_forecast_beats):
|
||||
if all_notes[next_note_to_load].time_hit > (t + theme.note_forecast_beats):
|
||||
# Next chronological note isn't ready to load yet
|
||||
break
|
||||
# Next chronological note is ready to load, load it
|
||||
active_notes.push_back(all_notes[next_note_to_load])
|
||||
if active_notes[-1].type == Note.NOTE_SLIDE:
|
||||
slide_trail_mesh_instances.push_back(MeshInstance2D.new())
|
||||
slide_trail_mesh_instances[-1].set_mesh(slide_trail_meshes.pop_front())
|
||||
slide_trail_mesh_instances[-1].set_position(screen_center)
|
||||
add_child(slide_trail_mesh_instances[-1])
|
||||
slide_trail_mesh_instances[-1].set_material(slide_trail_shadermaterial)
|
||||
slide_trail_mesh_instances[-1].material.set_shader_param("trail_progress", 0.0)
|
||||
slide_trail_mesh_instances[-1].set_texture(tex_slide_arrow)
|
||||
|
||||
next_note_to_load += 1
|
||||
|
||||
# DEBUG: Reset after all notes are done
|
||||
|
|
|
@ -8,8 +8,8 @@ var receptor_color := Color.blue
|
|||
|
||||
func _draw():
|
||||
# Receptor ring
|
||||
var receptor_circle := arc_point_list(screen_center, receptor_ring_radius, 0.0, 360.0, 360)
|
||||
var receptor_centers := arc_point_list(screen_center, receptor_ring_radius, 22.5, 360.0-22.5, 7)
|
||||
var receptor_circle := arc_point_list(screen_center, theme.receptor_ring_radius, 0.0, 360.0, 360)
|
||||
var receptor_centers := arc_point_list(screen_center, theme.receptor_ring_radius, Rules.FIRST_COLUMN_ANGLE_DEG, Rules.FIRST_COLUMN_ANGLE_DEG+360.0-Rules.COLS_ANGLE_DEG, Rules.COLS)
|
||||
|
||||
# Shadows
|
||||
for i in range(len(receptor_circle)-1):
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
extends Node
|
||||
|
||||
const COLS := 8
|
||||
const COLS_ANGLE_DEG := 360.0/COLS
|
||||
const COLS_ANGLE_RAD := COLS_ANGLE_DEG * TAU/360.0 # deg2rad isn't a const function which is completely stupid
|
||||
const FIRST_COLUMN_ANGLE_DEG := (COLS_ANGLE_DEG/2.0 if !(COLS%2) else 0.0) - 90.0 #-67.5
|
||||
|
||||
const COLS_TOUCH_ARC_DEG := 240.0/COLS
|
12
main.gd
12
main.gd
|
@ -1,18 +1,16 @@
|
|||
extends Node2D
|
||||
|
||||
# Declare member variables here. Examples:
|
||||
# member variables
|
||||
var screen_height := 1080
|
||||
var x_margin := (1920 - screen_height)/2
|
||||
var screen_center := Vector2(1920/2, screen_height/2)
|
||||
|
||||
var receptor_ring_radius := 460
|
||||
|
||||
func arc_point_list(center: Vector2, radius: float, angle_from:=0.0, angle_to:=360.0, points:=90) -> PoolVector2Array:
|
||||
var point_list = PoolVector2Array()
|
||||
for i in range(points + 1):
|
||||
# positive Y going down makes for confusing angle plane. I prefer to work CCW as in mathematics.
|
||||
var angle = -deg2rad(angle_from + i * (angle_to - angle_from) / points)
|
||||
point_list.push_back(center + Vector2(cos(angle), sin(angle)) * radius)
|
||||
for i in range(points):
|
||||
var angle = deg2rad(angle_from + i * (angle_to - angle_from) / (points-1))
|
||||
# point_list.push_back(center + Vector2(cos(angle), sin(angle)) * radius)
|
||||
point_list.push_back(center + polar2cartesian(radius, angle))
|
||||
return point_list
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
|
|
37
main.tscn
37
main.tscn
|
@ -1,17 +1,18 @@
|
|||
[gd_scene load_steps=12 format=2]
|
||||
[gd_scene load_steps=13 format=2]
|
||||
|
||||
[ext_resource path="res://main.gd" type="Script" id=1]
|
||||
[ext_resource path="res://songs/cirno_9th_anniversary_best_cpu1_3M.webm" type="VideoStream" id=2]
|
||||
[ext_resource path="res://Receptors.gd" type="Script" id=3]
|
||||
[ext_resource path="res://NoteHandler.gd" type="Script" id=4]
|
||||
[ext_resource path="res://shaders/notelines.shader" type="Shader" id=5]
|
||||
[ext_resource path="res://shaders/notemesh.shader" type="Shader" id=6]
|
||||
[ext_resource path="res://Bezel.gd" type="Script" id=7]
|
||||
[ext_resource path="res://assets/NotoSans.tres" type="DynamicFont" id=8]
|
||||
[ext_resource path="res://lbl_main.gd" type="Script" id=9]
|
||||
[ext_resource path="res://songs/cirno_1080p_rt_cpu1_3M.webm" type="VideoStream" id=2]
|
||||
[ext_resource path="res://video.gd" type="Script" id=3]
|
||||
[ext_resource path="res://Receptors.gd" type="Script" id=4]
|
||||
[ext_resource path="res://NoteHandler.gd" type="Script" id=5]
|
||||
[ext_resource path="res://shaders/notelines.shader" type="Shader" id=6]
|
||||
[ext_resource path="res://shaders/notemesh.shader" type="Shader" id=7]
|
||||
[ext_resource path="res://Bezel.gd" type="Script" id=8]
|
||||
[ext_resource path="res://assets/NotoSans.tres" type="DynamicFont" id=9]
|
||||
[ext_resource path="res://InputHandler.gd" type="Script" id=10]
|
||||
|
||||
[sub_resource type="ShaderMaterial" id=1]
|
||||
shader = ExtResource( 5 )
|
||||
shader = ExtResource( 6 )
|
||||
shader_param/line_color = Plane( 0.8, 0.8, 1, 0.8 )
|
||||
shader_param/line_color_double = Plane( 1, 1, 0.6, 0.9 )
|
||||
shader_param/dot_color = Plane( 1, 1, 1, 0.8 )
|
||||
|
@ -23,7 +24,7 @@ shader_param/dot_fullbright_thickness = 0.013
|
|||
shader_param/max_angle = 1.0708
|
||||
|
||||
[sub_resource type="ShaderMaterial" id=2]
|
||||
shader = ExtResource( 6 )
|
||||
shader = ExtResource( 7 )
|
||||
shader_param/bps = null
|
||||
shader_param/star_color = null
|
||||
shader_param/held_color = null
|
||||
|
@ -33,7 +34,6 @@ shader_param/screen_size = null
|
|||
script = ExtResource( 1 )
|
||||
|
||||
[node name="video" type="VideoPlayer" parent="."]
|
||||
anchor_right = 0.37
|
||||
margin_left = 420.0
|
||||
margin_right = 1500.0
|
||||
margin_bottom = 1080.0
|
||||
|
@ -43,15 +43,16 @@ rect_pivot_offset = Vector2( 540, 540 )
|
|||
mouse_filter = 2
|
||||
stream = ExtResource( 2 )
|
||||
volume_db = -11.6
|
||||
script = ExtResource( 3 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Receptors" type="Node2D" parent="."]
|
||||
script = ExtResource( 3 )
|
||||
script = ExtResource( 4 )
|
||||
|
||||
[node name="NoteHandler" type="Node2D" parent="."]
|
||||
script = ExtResource( 4 )
|
||||
script = ExtResource( 5 )
|
||||
|
||||
[node name="notelines" type="MeshInstance2D" parent="NoteHandler"]
|
||||
material = SubResource( 1 )
|
||||
|
@ -60,11 +61,11 @@ material = SubResource( 1 )
|
|||
material = SubResource( 2 )
|
||||
|
||||
[node name="Bezel" type="Node2D" parent="."]
|
||||
script = ExtResource( 7 )
|
||||
script = ExtResource( 8 )
|
||||
|
||||
[node name="lbl_main" type="Label" parent="."]
|
||||
[node name="InputHandler" type="Label" parent="."]
|
||||
margin_right = 424.0
|
||||
margin_bottom = 216.0
|
||||
custom_fonts/font = ExtResource( 8 )
|
||||
custom_fonts/font = ExtResource( 9 )
|
||||
text = "Fingers on the screen:"
|
||||
script = ExtResource( 9 )
|
||||
script = ExtResource( 10 )
|
||||
|
|
|
@ -29,6 +29,8 @@ channel_disable_time=5.0
|
|||
|
||||
Note="*res://Note.gd"
|
||||
FileLoader="*res://FileLoader.gd"
|
||||
Rules="*res://Rules.gd"
|
||||
theme="*res://theme.gd"
|
||||
|
||||
[debug]
|
||||
|
||||
|
@ -53,5 +55,6 @@ singletons=[ "res://addons/videodecoder.gdnlib" ]
|
|||
|
||||
[rendering]
|
||||
|
||||
environment/default_clear_color=Color( 0, 0, 0, 1 )
|
||||
quality/filters/msaa=1
|
||||
environment/default_environment="res://default_env.tres"
|
||||
|
|
|
@ -11,6 +11,10 @@ uniform vec2 screen_size;
|
|||
|
||||
void fragment() {
|
||||
vec4 sample = texture(TEXTURE, UV);
|
||||
|
||||
//Not sure if this helps or hurts performance
|
||||
//if (sample.a <= 0.0) discard;
|
||||
|
||||
float scale = sample.r;
|
||||
float dist = distance(FRAGCOORD.xy, screen_size/2.0);
|
||||
float dist_norm = dist*1.8 / screen_size.y;
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
shader_type canvas_item;
|
||||
//render_mode blend_premul_alpha;
|
||||
|
||||
uniform float trail_progress = 0.0;
|
||||
uniform float bps = 1.0;
|
||||
|
||||
// The idea here is to create a static mesh for each slide trail at scorefile load.
|
||||
// Since we need to be able to hide parts of the trail that we have passed,
|
||||
// we need to do that in this shader.
|
||||
// We don't need vertex alpha normally so we can just set that to large whole numbers
|
||||
// on each arrow (1.0, 2.0, 3.0, ... 50.0) and then use a uniform progress float.
|
||||
void vertex() {
|
||||
COLOR.a = clamp(COLOR.a-trail_progress, 0.0, 1.0);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
[gd_resource type="ShaderMaterial" load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://shaders/slidetrail.shader" type="Shader" id=1]
|
||||
|
||||
[resource]
|
||||
shader = ExtResource( 1 )
|
||||
shader_param/trail_progress = 0.0
|
||||
shader_param/bps = 1.0
|
|
@ -0,0 +1,33 @@
|
|||
extends Node
|
||||
|
||||
var receptor_ring_radius := 460
|
||||
var note_forecast_beats := 2.0
|
||||
const INNER_NOTE_CIRCLE_RATIO := 0.3
|
||||
|
||||
var sprite_size := 128
|
||||
var sprite_size2 := sprite_size/2
|
||||
|
||||
# Color definitions
|
||||
const COLOR_TAP := Color(1, 0.15, 0.15, 1)
|
||||
const COLOR_TAP2 := Color(0.75, 0.5, 0, 1) # High-score taps ("breaks" in maimai)
|
||||
const COLOR_HOLD := Color(1, 0.15, 0.15, 1)
|
||||
const COLOR_HOLD_HELD := Color(1, 1, 1, 1)
|
||||
const COLOR_STAR := Color(0, 0, 1, 1)
|
||||
const COLOR_DOUBLE := Color(1, 1, 0, 1) # When two (or more in master) hit events coincide
|
||||
|
||||
var COLOR_ARRAY_TAP := PoolColorArray([COLOR_TAP, COLOR_TAP, COLOR_TAP, COLOR_TAP])
|
||||
var COLOR_ARRAY_TAP2 := PoolColorArray([COLOR_TAP2, COLOR_TAP2, COLOR_TAP2, COLOR_TAP2])
|
||||
var COLOR_ARRAY_HOLD := PoolColorArray([
|
||||
COLOR_HOLD, COLOR_HOLD, COLOR_HOLD, COLOR_HOLD,
|
||||
COLOR_HOLD, COLOR_HOLD, COLOR_HOLD, COLOR_HOLD
|
||||
])
|
||||
var COLOR_ARRAY_HOLD_HELD := PoolColorArray([
|
||||
COLOR_HOLD_HELD, COLOR_HOLD_HELD, COLOR_HOLD_HELD, COLOR_HOLD_HELD,
|
||||
COLOR_HOLD_HELD, COLOR_HOLD_HELD, COLOR_HOLD_HELD, COLOR_HOLD_HELD
|
||||
])
|
||||
var COLOR_ARRAY_STAR := PoolColorArray([COLOR_STAR, COLOR_STAR, COLOR_STAR, COLOR_STAR])
|
||||
var COLOR_ARRAY_DOUBLE_4 := PoolColorArray([COLOR_DOUBLE, COLOR_DOUBLE, COLOR_DOUBLE, COLOR_DOUBLE])
|
||||
var COLOR_ARRAY_DOUBLE_8 := PoolColorArray([
|
||||
COLOR_DOUBLE, COLOR_DOUBLE, COLOR_DOUBLE, COLOR_DOUBLE,
|
||||
COLOR_DOUBLE, COLOR_DOUBLE, COLOR_DOUBLE, COLOR_DOUBLE
|
||||
])
|
|
@ -0,0 +1,13 @@
|
|||
extends VideoPlayer
|
||||
|
||||
func _ready():
|
||||
pass
|
||||
# I need to put videoplayer resizing logic somewhere else, this is placeholder
|
||||
update_aspect_ratio(1440.0/1080.0)
|
||||
|
||||
func update_aspect_ratio(ratio: float):
|
||||
# e.g. for a 1920x1080 video you'd call update_aspect_ratio(1920.0/1080.0)
|
||||
# e.g. for a 1440x1080 video you'd call update_aspect_ratio(1440.0/1080.0)
|
||||
var height = 1080/ratio
|
||||
margin_top = (1080 - height)/2.0
|
||||
margin_bottom = margin_top + height
|
Loading…
Reference in New Issue