Switch slides from screenspace to unit circle space

Makes Curve2D calculations much nicer, at the potential cost of adding multiplies to the Chord path.
Also added an optimisation of sorts for Complex slides.
This commit is contained in:
Luke Hubmayer-Werner 2021-01-17 14:38:08 +10:30
parent 4b014bec31
commit c215c1e80b
2 changed files with 47 additions and 29 deletions

View File

@ -180,8 +180,9 @@ func make_slide_trail_mesh(note) -> ArrayMesh:
var size := GameTheme.sprite_size2 * sqrt(2) var size := GameTheme.sprite_size2 * sqrt(2)
var color := GameTheme.COLOR_DOUBLE_SLIDE if note.double_hit else GameTheme.COLOR_SLIDE var color := GameTheme.COLOR_DOUBLE_SLIDE if note.double_hit else GameTheme.COLOR_SLIDE
# First we need to determine how many arrows to leave. match note.get_points():
var trail_length : int = int(floor(note.get_slide_length() * slide_arrows_per_unit_length)) [var positions, var angles]:
var trail_length : int = len(positions)
vertices.resize(3*trail_length) vertices.resize(3*trail_length)
uvs.resize(3*trail_length) uvs.resize(3*trail_length)
colors.resize(3*trail_length) colors.resize(3*trail_length)
@ -190,10 +191,8 @@ func make_slide_trail_mesh(note) -> ArrayMesh:
for j in 3: for j in 3:
uvs[i*3+j] = u[j] uvs[i*3+j] = u[j]
colors[i*3+j] = Color(color.r, color.g, color.b, (1.0+float(i))/float(trail_length)) colors[i*3+j] = Color(color.r, color.g, color.b, (1.0+float(i))/float(trail_length))
var angle : float = angles[i]
for i in trail_length: var offset : Vector2 = positions[i] * GameTheme.receptor_ring_radius
var angle : float = note.get_angle((i+1)/float(trail_length))
var offset : Vector2 = note.get_position((i+1)/float(trail_length))
vertices[i*3] = offset vertices[i*3] = offset
vertices[i*3+1] = offset + polar2cartesian(size, angle+PI*0.75) vertices[i*3+1] = offset + polar2cartesian(size, angle+PI*0.75)
vertices[i*3+2] = offset + polar2cartesian(size, angle-PI*0.75) vertices[i*3+2] = offset + polar2cartesian(size, angle-PI*0.75)
@ -381,7 +380,7 @@ func _draw():
trail_alpha = min(1.0, (position-GameTheme.INNER_NOTE_CIRCLE_RATIO)/(1-GameTheme.INNER_NOTE_CIRCLE_RATIO*2)) trail_alpha = min(1.0, (position-GameTheme.INNER_NOTE_CIRCLE_RATIO)/(1-GameTheme.INNER_NOTE_CIRCLE_RATIO*2))
else: else:
var trail_progress : float = clamp((t - note.time_hit - GameTheme.SLIDE_DELAY)/(note.duration - GameTheme.SLIDE_DELAY), 0.0, 1.0) var trail_progress : float = clamp((t - note.time_hit - GameTheme.SLIDE_DELAY)/(note.duration - GameTheme.SLIDE_DELAY), 0.0, 1.0)
var star_pos : Vector2 = note.get_position(trail_progress) var star_pos : Vector2 = note.get_position(trail_progress) * GameTheme.receptor_ring_radius
var star_angle : float = note.get_angle(trail_progress) var star_angle : float = note.get_angle(trail_progress)
make_star_mesh(mesh, star_pos, 1.33, star_angle) make_star_mesh(mesh, star_pos, 1.33, star_angle)
if note.progress != INF: if note.progress != INF:
@ -417,8 +416,8 @@ func _input(event):
for i in range(len(active_slide_trails)-1, -1, -1): # Iterate backwards as we are potentially deleting entries for i in range(len(active_slide_trails)-1, -1, -1): # Iterate backwards as we are potentially deleting entries
var note = active_slide_trails[i] var note = active_slide_trails[i]
var center = note.get_position(note.progress) var center = note.get_position(note.progress) * GameTheme.receptor_ring_radius
var center2 = note.get_position(min(note.progress+0.06, 1.0)) var center2 = note.get_position(min(note.progress+0.06, 1.0)) * GameTheme.receptor_ring_radius
if ((pos - center).length_squared() < Rules.SLIDE_RADIUS2) or ((pos - center2).length_squared() < Rules.SLIDE_RADIUS2): if ((pos - center).length_squared() < Rules.SLIDE_RADIUS2) or ((pos - center2).length_squared() < Rules.SLIDE_RADIUS2):
note.progress += 0.09 note.progress += 0.09
if note.progress >= 1.0: if note.progress >= 1.0:

View File

@ -123,8 +123,8 @@ class NoteSlide extends NoteBase: # Fancy charts have naked slides which necess
func update_slide_variables(): func update_slide_variables():
match slide_type: match slide_type:
Note.SlideType.CHORD, Note.SlideType.CHORD_TRIPLE: Note.SlideType.CHORD, Note.SlideType.CHORD_TRIPLE:
values.start = GameTheme.RADIAL_UNIT_VECTORS[column] * GameTheme.receptor_ring_radius values.start = GameTheme.RADIAL_UNIT_VECTORS[column]
values.end = GameTheme.RADIAL_UNIT_VECTORS[column_release] * GameTheme.receptor_ring_radius values.end = GameTheme.RADIAL_UNIT_VECTORS[column_release]
values.angle = (values.end - values.start).angle() values.angle = (values.end - values.start).angle()
Note.SlideType.ARC_CW: Note.SlideType.ARC_CW:
values.start_a = GameTheme.RADIAL_COL_ANGLES[column] values.start_a = GameTheme.RADIAL_COL_ANGLES[column]
@ -138,23 +138,42 @@ class NoteSlide extends NoteBase: # Fancy charts have naked slides which necess
values.end_a -= TAU values.end_a -= TAU
Note.SlideType.COMPLEX: Note.SlideType.COMPLEX:
values.curve2d = Curve2D.new() values.curve2d = Curve2D.new()
values.curve2d.bake_interval = 0.005 # TODO: play around with this values.curve2d.bake_interval = 0.1 # TODO: play around with this
func get_position(progress: float) -> Vector2: func get_position(progress: float) -> Vector2:
match slide_type: match slide_type:
Note.SlideType.CHORD, Note.SlideType.CHORD_TRIPLE: Note.SlideType.CHORD, Note.SlideType.CHORD_TRIPLE:
return lerp(values.start, values.end, progress) return lerp(values.start, values.end, progress)
Note.SlideType.ARC_CW: Note.SlideType.ARC_CW, Note.SlideType.ARC_ACW:
var circle_angle : float = lerp(values.start_a, values.end_a, progress) var circle_angle : float = lerp(values.start_a, values.end_a, progress)
return polar2cartesian(GameTheme.receptor_ring_radius, circle_angle) return polar2cartesian(1.0, circle_angle)
Note.SlideType.ARC_ACW:
var circle_angle : float = lerp(values.start_a, values.end_a, progress)
return polar2cartesian(GameTheme.receptor_ring_radius, circle_angle)
Note.SlideType.COMPLEX: Note.SlideType.COMPLEX:
progress *= values.curve2d.get_baked_length() progress *= values.curve2d.get_baked_length()
return values.curve2d.interpolate_baked(progress) * GameTheme.receptor_ring_radius return values.curve2d.interpolate_baked(progress)
return Vector2(0.0, 0.0) return Vector2(0.0, 0.0)
func get_points(per_radius: float = 10.0) -> Array:
# Returns PoolVector2Array positions, PoolRealArray angles
match slide_type:
Note.SlideType.COMPLEX:
var interval = 1.0/per_radius
if values.curve2d.bake_interval != interval:
values.curve2d.set_bake_interval(interval) # Setting this, even to the same value triggers a new bake
var positions: PoolVector2Array = values.curve2d.get_baked_points()
var angles = []
for i in len(positions)-1:
angles.append((positions[i+1]-positions[i]).angle())
positions.remove(0) # Don't need an arrow pointing at the start position
return [positions, PoolRealArray(angles)]
_:
var trail_length : int = int(floor(get_slide_length() * per_radius))
var angles = []
var positions = []
for i in trail_length:
angles.append(get_angle((i+1)/float(trail_length)))
positions.append(get_position((i+1)/float(trail_length)))
return [PoolVector2Array(positions), PoolRealArray(angles)]
func get_angle(progress: float) -> float: func get_angle(progress: float) -> float:
match slide_type: match slide_type:
Note.SlideType.CHORD, Note.SlideType.CHORD_TRIPLE: Note.SlideType.CHORD, Note.SlideType.CHORD_TRIPLE: