extends Node2D ## Title screen: the big core with turning rings and bouncing balls, the player's progress, ## what unlocks next, and a music toggle. const BALL_SCENE := preload("res://scenes/ball.tscn") const BALLS := 6 const RING_SPEEDS := [12.0, -8.0] # degrees per second, one per decorative ring ## Kinds sprinkled into the decorative rings, as a taste of what is coming. const SHOWCASE := [ Block.Kind.INDESTRUCTIBLE, Block.Kind.WATER, Block.Kind.ICE, Block.Kind.TNT, Block.Kind.RUBBER, Block.Kind.MOSS, ] var _level := 0 var _rings: Array[Node2D] = [] @onready var core: Core = $Core func _ready() -> void: var screen := get_viewport_rect().size core.position = Vector2(screen.x / 2.0, screen.y * 0.28) _add_rings() for i in BALLS: var ball: Ball = BALL_SCENE.instantiate() ball.position = Vector2(screen.x / 2.0, screen.y - Params.BALL_RADIUS * 2.0) $Balls.add_child(ball) ball.throw() var progress := Progress.load_level() _level = progress[0] $UI/Info/Level.text = "Level %d" % _level $UI/Info/Totals/Count.text = str(Progress.total_stars()) var best := Progress.best_score() $UI/Info/Best.text = "Best score %d" % best if best > 0 else "" $UI/Play.text = "Play" if _level == 0 else "Continue" $UI/Next.text = _next_unlock(_level) if _level != 0: $UI/Decay.text = Params.MSG_LEVEL_BACK % [_level, progress[1]] $UI/Play.pressed.connect(_on_play_pressed) $UI/Levels.pressed.connect(func() -> void: get_tree().change_scene_to_file("res://scenes/levels.tscn")) $UI/MusicToggle.pressed.connect(_on_music_toggled) _show_music_state() Music.play("menu") func _physics_process(delta: float) -> void: for i in _rings.size(): _rings[i].rotation_degrees += RING_SPEEDS[i] * delta ## Two thin rings of segments around the core, mostly normal with a few special kinds. ## They are only decoration: no collisions. func _add_rings() -> void: var inner := core.radius + 6.0 for r in RING_SPEEDS.size(): var ring := Node2D.new() ring.position = core.position var segments := 12 + r * 4 var step := TAU / segments for i in segments: var kind: Block.Kind = SHOWCASE[(i + r * 3) % SHOWCASE.size()] if i % 3 == 0 else Block.Kind.NORMAL var block := Block.new(inner + r * 30.0, inner + r * 30.0 + 26.0, i * step, (i + 1) * step, kind) block.collision_layer = 0 block.set_physics_process(false) ring.add_child(block) add_child(ring) move_child(ring, core.get_index()) _rings.append(ring) ## "Next: Fireball at level 12" for the next power or segment to unlock after [param level]. static func _next_unlock(level: int) -> String: var best_level := -1 var best_name := "" for info: Dictionary in PowerUp.KINDS.values() + Block.KINDS.values(): var unlock: int = info.unlock if unlock > level and (best_level < 0 or unlock < best_level): best_level = unlock best_name = info.name if best_level < 0: return "Everything unlocked. How far can you go?" return "Next: %s at level %d" % [best_name, best_level] func _on_play_pressed() -> void: Progress.current_level = _level get_tree().change_scene_to_file("res://scenes/game.tscn") func _on_music_toggled() -> void: Music.set_enabled(not Progress.music_on()) _show_music_state() func _show_music_state() -> void: $UI/MusicToggle.text = "Music: %s" % ("on" if Progress.music_on() else "off")