Optimize turtle minigame
This commit is contained in:
@@ -4,25 +4,22 @@ extends Node2D
|
||||
signal pressed(gp: Dictionary)
|
||||
signal animation_changed(position: Vector2)
|
||||
|
||||
enum Colors {
|
||||
GREEN,
|
||||
KHAKI,
|
||||
PURPLE,
|
||||
}
|
||||
|
||||
const ANIMATIONS: Array[SpriteFrames] = [
|
||||
preload("res://sources/minigames/turtles/green_turtle_animations.tres"),
|
||||
preload("res://sources/minigames/turtles/khaki_turtle_animations.tres"),
|
||||
preload("res://sources/minigames/turtles/purple_turtle_animations.tres")
|
||||
]
|
||||
const TURTLE_BACK_RIGHT: CompressedTexture2D = preload("res://assets/minigames/turtles/graphic/turtle_back_right.png")
|
||||
const TURTLE_BACK_WRONG: CompressedTexture2D = preload("res://assets/minigames/turtles/graphic/turtle_back_wrong.png")
|
||||
# Only used when a turtle lands on the island, so they're instantiated on
|
||||
# demand instead of sitting idle inside every spawned turtle.
|
||||
const RIGHT_FX_SCENE: PackedScene = preload("res://sources/utils/fx/right.tscn")
|
||||
const WRONG_FX_SCENE: PackedScene = preload("res://sources/utils/fx/wrong.tscn")
|
||||
const RIGHT_STARS_SCENE: PackedScene = preload("res://sources/utils/fx/right_stars.tscn")
|
||||
|
||||
@export var color: Colors = Colors.PURPLE:
|
||||
# Set by the minigame after the random color is picked, so only one of the three
|
||||
# 6400x4800 turtle spritesheets is ever in memory.
|
||||
@export var sprite_frames: SpriteFrames:
|
||||
set(value):
|
||||
color = value
|
||||
if sprite:
|
||||
sprite.sprite_frames = ANIMATIONS[color]
|
||||
sprite_frames = value
|
||||
if sprite and value:
|
||||
sprite.sprite_frames = value
|
||||
sprite.play("swim")
|
||||
|
||||
var gp: Dictionary = {}:
|
||||
set(value):
|
||||
@@ -37,6 +34,9 @@ var direction: Vector2 = Vector2(0,-1):
|
||||
var is_moving: bool = true
|
||||
var is_changing_direction: bool = false
|
||||
var is_visible_on_screen: bool = false
|
||||
var right_fx: RightFX
|
||||
var right_stars: RightStarsFX
|
||||
var wrong_fx: WrongFX
|
||||
|
||||
@onready var body: Node2D = $Body
|
||||
@onready var body_back: Sprite2D = $Body/AnimatedSprite2D/Sprite2D_Back
|
||||
@@ -45,9 +45,8 @@ var is_visible_on_screen: bool = false
|
||||
@onready var head_area_collision_shape: CollisionShape2D = $Body/HeadArea/CollisionShape2D
|
||||
@onready var body_area_collision_shape: CollisionShape2D = $Body/BodyArea/CollisionShape2D
|
||||
@onready var highlight_fx: HighlightFX = %HighlightFX
|
||||
@onready var right_fx: RightFX = %RightFX
|
||||
@onready var right_stars: RightStarsFX = %Right_Stars
|
||||
@onready var wrong_fx: WrongFX = %WrongFX
|
||||
@onready var back_fx: Control = $BackFX
|
||||
@onready var front_fx: Control = $FrontFX
|
||||
@onready var delete_timer: Timer = $DeleteTimer
|
||||
@onready var audio_stream_player: AudioStreamPlayer2D = $AudioStreamPlayer2D
|
||||
|
||||
@@ -92,6 +91,28 @@ func highlight(value: bool = true) -> void:
|
||||
highlight_fx.stop()
|
||||
|
||||
|
||||
func _ensure_right_fx() -> void:
|
||||
if right_fx:
|
||||
return
|
||||
right_fx = RIGHT_FX_SCENE.instantiate()
|
||||
right_fx.set_anchors_and_offsets_preset(Control.PRESET_CENTER)
|
||||
right_fx.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
||||
right_fx.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
back_fx.add_child(right_fx)
|
||||
right_stars = RIGHT_STARS_SCENE.instantiate()
|
||||
front_fx.add_child(right_stars)
|
||||
|
||||
|
||||
func _ensure_wrong_fx() -> void:
|
||||
if wrong_fx:
|
||||
return
|
||||
wrong_fx = WRONG_FX_SCENE.instantiate()
|
||||
wrong_fx.set_anchors_and_offsets_preset(Control.PRESET_CENTER)
|
||||
wrong_fx.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
||||
wrong_fx.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
back_fx.add_child(wrong_fx)
|
||||
|
||||
|
||||
func right() -> void:
|
||||
is_moving = false
|
||||
change_font_color_after_collision()
|
||||
@@ -99,6 +120,7 @@ func right() -> void:
|
||||
sprite.play("victory")
|
||||
await sprite.animation_finished
|
||||
sprite.play_backwards("victory")
|
||||
_ensure_right_fx()
|
||||
right_fx.play()
|
||||
right_stars.play()
|
||||
await sprite.animation_finished
|
||||
@@ -109,6 +131,7 @@ func wrong() -> void:
|
||||
is_moving = false
|
||||
change_font_color_after_collision()
|
||||
body_back.texture = TURTLE_BACK_WRONG
|
||||
_ensure_wrong_fx()
|
||||
wrong_fx.play()
|
||||
sprite.play("defeat")
|
||||
await sprite.animation_finished
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
[gd_scene format=3 uid="uid://djykrpdu58f3v"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://doq6myv45i4w6" path="res://sources/minigames/turtles/turtle.gd" id="1_vx1yr"]
|
||||
[ext_resource type="PackedScene" uid="uid://cn2rw06pltyiu" path="res://sources/utils/fx/right.tscn" id="2_d5x3l"]
|
||||
[ext_resource type="PackedScene" uid="uid://cge0uyn30tcpv" path="res://sources/utils/fx/highlight.tscn" id="2_rllc5"]
|
||||
[ext_resource type="PackedScene" uid="uid://dlmbxcgiv8tpr" path="res://sources/utils/fx/wrong.tscn" id="4_yhidj"]
|
||||
[ext_resource type="SpriteFrames" uid="uid://gm2hqn76oaib" path="res://sources/minigames/turtles/purple_turtle_animations.tres" id="5_xbpgw"]
|
||||
[ext_resource type="Texture2D" uid="uid://bhahju7y2n5ke" path="res://assets/minigames/turtles/graphic/turtle_back_neutral.png" id="6_4juk7"]
|
||||
[ext_resource type="LabelSettings" uid="uid://dn32fpff81uu" path="res://resources/themes/minigames_label_settings_turtles.tres" id="6_8k7c6"]
|
||||
[ext_resource type="PackedScene" uid="uid://cs6g7fhc0bjvh" path="res://sources/utils/fx/right_stars.tscn" id="8_xbpgw"]
|
||||
[ext_resource type="AudioStream" uid="uid://cmsn7q4fxnghr" path="res://assets/sfx/splash.mp3" id="42_p3fqk"]
|
||||
[ext_resource type="PackedScene" uid="uid://cjg6pgc7yfp1p" path="res://sources/utils/swipe_detector.tscn" id="49_0qwwy"]
|
||||
|
||||
@@ -29,19 +25,6 @@ anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="RightFX" parent="BackFX" unique_id=1787877717 instance=ExtResource("2_d5x3l")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 4
|
||||
|
||||
[node name="HighlightFX" parent="BackFX" unique_id=462139651 instance=ExtResource("2_rllc5")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
@@ -54,19 +37,6 @@ grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
scale = Vector2(0.6, 0.6)
|
||||
|
||||
[node name="WrongFX" parent="BackFX" unique_id=777978196 instance=ExtResource("4_yhidj")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 4
|
||||
|
||||
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="." unique_id=799402224]
|
||||
stream = ExtResource("42_p3fqk")
|
||||
bus = &"Effects"
|
||||
@@ -77,9 +47,6 @@ bus = &"Effects"
|
||||
unique_name_in_owner = true
|
||||
position = Vector2(0, -16)
|
||||
scale = Vector2(0.8, 0.8)
|
||||
sprite_frames = ExtResource("5_xbpgw")
|
||||
animation = &"swim"
|
||||
autoplay = "swim"
|
||||
|
||||
[node name="Sprite2D_Back" type="Sprite2D" parent="Body/AnimatedSprite2D" unique_id=1980717066]
|
||||
position = Vector2(0, 19.999998)
|
||||
@@ -139,9 +106,6 @@ anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="Right_Stars" parent="FrontFX" unique_id=1474432273 instance=ExtResource("8_xbpgw")]
|
||||
unique_name_in_owner = true
|
||||
|
||||
[node name="DeleteTimer" type="Timer" parent="." unique_id=94467327]
|
||||
wait_time = 3.0
|
||||
one_shot = true
|
||||
|
||||
@@ -7,6 +7,12 @@ const TURTLE_SCENE: PackedScene = preload("res://sources/minigames/turtles/turtl
|
||||
const MAX_TURTLE_COUNT: int = 5
|
||||
# Defines the minimum distance between turtles when spawning them
|
||||
const MIN_DISTANCE: int = 500
|
||||
# Each spritesheet is ~123 MB of VRAM; never preload — load only the picked one.
|
||||
const TURTLE_ANIMATIONS_PATHS: Array[String] = [
|
||||
"res://sources/minigames/turtles/green_turtle_animations.tres",
|
||||
"res://sources/minigames/turtles/khaki_turtle_animations.tres",
|
||||
"res://sources/minigames/turtles/purple_turtle_animations.tres",
|
||||
]
|
||||
|
||||
var difficulty_settings: Array[DifficultySettings] = [
|
||||
DifficultySettings.new(.75, 200., 4.),
|
||||
@@ -22,7 +28,8 @@ var turtle_count: int = 0:
|
||||
can_spawn_turtle.emit()
|
||||
turtle_count = value
|
||||
var stimulus_spawned: bool = false
|
||||
var color: Turtle.Colors
|
||||
# Single shared SpriteFrames assigned to every spawned turtle this round.
|
||||
var turtle_sprite_frames: SpriteFrames
|
||||
|
||||
@onready var water: Water = $GameRoot/Water
|
||||
@onready var island: Island = $GameRoot/Island
|
||||
@@ -61,7 +68,12 @@ func _setup_minigame() -> void:
|
||||
|
||||
|
||||
func pick_random_color() -> void:
|
||||
color = randi_range(0, Turtle.Colors.size() - 1) as Turtle.Colors
|
||||
# Drop the previous color first so its ~123 MB texture can be freed by
|
||||
# refcount before we load the next one (turtles still fading out also
|
||||
# hold a ref, so peak overlap is brief).
|
||||
turtle_sprite_frames = null
|
||||
var index: int = randi_range(0, TURTLE_ANIMATIONS_PATHS.size() - 1)
|
||||
turtle_sprite_frames = load(TURTLE_ANIMATIONS_PATHS[index])
|
||||
|
||||
|
||||
func _highlight() -> void:
|
||||
@@ -121,7 +133,7 @@ func _on_spawn_timer_timeout() -> void:
|
||||
)
|
||||
|
||||
turtles.add_child(turtle)
|
||||
turtle.color = color
|
||||
turtle.sprite_frames = turtle_sprite_frames
|
||||
|
||||
# Set the direction of the turtle
|
||||
var random_offset: float = deg_to_rad(randf_range(-5, 5))
|
||||
|
||||
@@ -2,14 +2,31 @@ class_name Water
|
||||
extends TextureRect
|
||||
|
||||
const WATER_RING_SCENE: PackedScene = preload("res://sources/utils/fx/water_ring.tscn")
|
||||
# Up to MAX_TURTLE_COUNT (5) turtles each loop the swim animation roughly
|
||||
# every 0.7s, so ~7-8 rings/second. The pool absorbs the bursts without
|
||||
# instantiate/queue_free churn on every loop.
|
||||
const POOL_SIZE: int = 12
|
||||
|
||||
@export var ring_color: Color
|
||||
|
||||
var _available_rings: Array[WaterRingFX] = []
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
for _index: int in POOL_SIZE:
|
||||
var fx: WaterRingFX = WATER_RING_SCENE.instantiate()
|
||||
fx.modulate = ring_color
|
||||
fx.hide()
|
||||
add_child(fx)
|
||||
_available_rings.append(fx)
|
||||
|
||||
|
||||
func spawn_water_ring(pos: Vector2) -> void:
|
||||
var fx: WaterRingFX = WATER_RING_SCENE.instantiate()
|
||||
if _available_rings.is_empty():
|
||||
return
|
||||
var fx: WaterRingFX = _available_rings.pop_back()
|
||||
fx.position = pos
|
||||
fx.modulate = ring_color
|
||||
add_child(fx)
|
||||
fx.show()
|
||||
await fx.play()
|
||||
fx.queue_free()
|
||||
fx.hide()
|
||||
_available_rings.append(fx)
|
||||
|
||||
@@ -40,6 +40,8 @@ float circ(vec2 pos, vec2 c, float s)
|
||||
|
||||
float waterlayer(vec2 uv)
|
||||
{
|
||||
// Reduced from 73 to 42 circles by dropping radii < 0.01 — the smaller
|
||||
// ones barely contributed visually but each circ() is ~10 GPU ops.
|
||||
uv = mod(uv, 1.0);
|
||||
float ret = 1.0;
|
||||
ret += circ(uv, vec2(0.37378, 0.277169), 0.0268181);
|
||||
@@ -52,71 +54,38 @@ float waterlayer(vec2 uv)
|
||||
ret += circ(uv, vec2(0.310149, 0.686637), 0.0128496);
|
||||
ret += circ(uv, vec2(0.928617, 0.195986), 0.0152041);
|
||||
ret += circ(uv, vec2(0.0438506, 0.868153), 0.0268601);
|
||||
ret += circ(uv, vec2(0.308619, 0.194937), 0.00806102);
|
||||
ret += circ(uv, vec2(0.349922, 0.449714), 0.00928667);
|
||||
ret += circ(uv, vec2(0.0449556, 0.953415), 0.023126);
|
||||
ret += circ(uv, vec2(0.117761, 0.503309), 0.0151272);
|
||||
ret += circ(uv, vec2(0.563517, 0.244991), 0.0292322);
|
||||
ret += circ(uv, vec2(0.566936, 0.954457), 0.00981141);
|
||||
ret += circ(uv, vec2(0.0489944, 0.200931), 0.0178746);
|
||||
ret += circ(uv, vec2(0.569297, 0.624893), 0.0132408);
|
||||
ret += circ(uv, vec2(0.298347, 0.710972), 0.0114426);
|
||||
ret += circ(uv, vec2(0.878141, 0.771279), 0.00322719);
|
||||
ret += circ(uv, vec2(0.150995, 0.376221), 0.00216157);
|
||||
ret += circ(uv, vec2(0.119673, 0.541984), 0.0124621);
|
||||
ret += circ(uv, vec2(0.629598, 0.295629), 0.0198736);
|
||||
ret += circ(uv, vec2(0.334357, 0.266278), 0.0187145);
|
||||
ret += circ(uv, vec2(0.918044, 0.968163), 0.0182928);
|
||||
ret += circ(uv, vec2(0.965445, 0.505026), 0.006348);
|
||||
ret += circ(uv, vec2(0.514847, 0.865444), 0.00623523);
|
||||
ret += circ(uv, vec2(0.710575, 0.0415131), 0.00322689);
|
||||
ret += circ(uv, vec2(0.71403, 0.576945), 0.0215641);
|
||||
ret += circ(uv, vec2(0.748873, 0.413325), 0.0110795);
|
||||
ret += circ(uv, vec2(0.0623365, 0.896713), 0.0236203);
|
||||
ret += circ(uv, vec2(0.980482, 0.473849), 0.00573439);
|
||||
ret += circ(uv, vec2(0.647463, 0.654349), 0.0188713);
|
||||
ret += circ(uv, vec2(0.651406, 0.981297), 0.00710875);
|
||||
ret += circ(uv, vec2(0.428928, 0.382426), 0.0298806);
|
||||
ret += circ(uv, vec2(0.811545, 0.62568), 0.00265539);
|
||||
ret += circ(uv, vec2(0.400787, 0.74162), 0.00486609);
|
||||
ret += circ(uv, vec2(0.331283, 0.418536), 0.00598028);
|
||||
ret += circ(uv, vec2(0.894762, 0.0657997), 0.00760375);
|
||||
ret += circ(uv, vec2(0.525104, 0.572233), 0.0141796);
|
||||
ret += circ(uv, vec2(0.431526, 0.911372), 0.0213234);
|
||||
ret += circ(uv, vec2(0.658212, 0.910553), 0.000741023);
|
||||
ret += circ(uv, vec2(0.514523, 0.243263), 0.0270685);
|
||||
ret += circ(uv, vec2(0.0249494, 0.252872), 0.00876653);
|
||||
ret += circ(uv, vec2(0.502214, 0.47269), 0.0234534);
|
||||
ret += circ(uv, vec2(0.693271, 0.431469), 0.0246533);
|
||||
ret += circ(uv, vec2(0.415, 0.884418), 0.0271696);
|
||||
ret += circ(uv, vec2(0.149073, 0.41204), 0.00497198);
|
||||
ret += circ(uv, vec2(0.533816, 0.897634), 0.00650833);
|
||||
ret += circ(uv, vec2(0.0409132, 0.83406), 0.0191398);
|
||||
ret += circ(uv, vec2(0.638585, 0.646019), 0.0206129);
|
||||
ret += circ(uv, vec2(0.660342, 0.966541), 0.0053511);
|
||||
ret += circ(uv, vec2(0.513783, 0.142233), 0.00471653);
|
||||
ret += circ(uv, vec2(0.124305, 0.644263), 0.00116724);
|
||||
ret += circ(uv, vec2(0.99871, 0.583864), 0.0107329);
|
||||
ret += circ(uv, vec2(0.894879, 0.233289), 0.00667092);
|
||||
ret += circ(uv, vec2(0.246286, 0.682766), 0.00411623);
|
||||
ret += circ(uv, vec2(0.0761895, 0.16327), 0.0145935);
|
||||
ret += circ(uv, vec2(0.949386, 0.802936), 0.0100873);
|
||||
ret += circ(uv, vec2(0.480122, 0.196554), 0.0110185);
|
||||
ret += circ(uv, vec2(0.896854, 0.803707), 0.013969);
|
||||
ret += circ(uv, vec2(0.292865, 0.762973), 0.00566413);
|
||||
ret += circ(uv, vec2(0.0995585, 0.117457), 0.00869407);
|
||||
ret += circ(uv, vec2(0.377713, 0.00335442), 0.0063147);
|
||||
ret += circ(uv, vec2(0.506365, 0.531118), 0.0144016);
|
||||
ret += circ(uv, vec2(0.408806, 0.894771), 0.0243923);
|
||||
ret += circ(uv, vec2(0.143579, 0.85138), 0.00418529);
|
||||
ret += circ(uv, vec2(0.0902811, 0.181775), 0.0108896);
|
||||
ret += circ(uv, vec2(0.780695, 0.394644), 0.00475475);
|
||||
ret += circ(uv, vec2(0.298036, 0.625531), 0.00325285);
|
||||
ret += circ(uv, vec2(0.218423, 0.714537), 0.00157212);
|
||||
ret += circ(uv, vec2(0.658836, 0.159556), 0.00225897);
|
||||
ret += circ(uv, vec2(0.987324, 0.146545), 0.0288391);
|
||||
ret += circ(uv, vec2(0.222646, 0.251694), 0.00092276);
|
||||
ret += circ(uv, vec2(0.159826, 0.528063), 0.00605293);
|
||||
return max(ret, 0.0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user