Level runners

This commit is contained in:
Rendo 2025-07-16 20:17:58 +05:00
commit 5010c61309
11 changed files with 398 additions and 110 deletions

View file

@ -53,6 +53,6 @@ script = ExtResource("1_qb1ge")
startSun = 50.0
wavePercentage = 0.5
standardWaveDelay = 8.0
initialWaveDelay = 0.0
initialWaveDelay = 20.0
waves = [SubResource("Resource_s62qb"), SubResource("Resource_ulhin"), SubResource("Resource_dbrq5")]
metadata/_custom_type_script = "uid://bximdujbkj2n4"

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=21 format=3 uid="uid://dpxxjfd5lv5sv"]
[gd_scene load_steps=17 format=3 uid="uid://dpxxjfd5lv5sv"]
[ext_resource type="Theme" uid="uid://e8n88g31w7x7" path="res://resources/themes/ChooseYourSeeds.tres" id="1_bfo8i"]
[ext_resource type="Texture2D" uid="uid://dr8a0rx42o3qy" path="res://assets/sprites/gui/ChooseYourSeeds/PlantFrame.tres" id="2_so2bw"]
@ -13,95 +13,6 @@
[ext_resource type="Script" uid="uid://c1x4n4nqyq72f" path="res://scripts/audio/ChannelSettings.cs" id="10_nlh6x"]
[ext_resource type="PackedScene" uid="uid://bvpt0q4j6nx18" path="res://scenes/gui/almanach.tscn" id="11_nlh6x"]
[sub_resource type="Animation" id="Animation_0rps3"]
resource_name = "Hide"
length = 0.75
step = 0.1
tracks/0/type = "bezier"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("..:position:y")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(64, -0.25, 0, 0.5, 7.5, 402, -0.55, -95.5, 0.25, 0),
"times": PackedFloat32Array(0, 0.75)
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:disabled")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
[sub_resource type="Animation" id="Animation_8he0w"]
length = 0.001
tracks/0/type = "bezier"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("..:position:y")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(402, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0)
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:disabled")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_omiwq"]
resource_name = "Show"
length = 1.5
step = 0.25
tracks/0/type = "bezier"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("..:position:y")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"handle_modes": PackedInt32Array(0, 0, 0),
"points": PackedFloat32Array(402, -0.25, 0, 1, -336.5, 64, -1, 338.5, 0, 66.5, 64, -0.0571204, 1, 0.19288, 1.5),
"times": PackedFloat32Array(0, 1, 1.5)
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:disabled")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 1.5),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [true, false]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_tguwa"]
_data = {
&"Hide": SubResource("Animation_0rps3"),
&"RESET": SubResource("Animation_8he0w"),
&"Show": SubResource("Animation_omiwq")
}
[sub_resource type="ViewportTexture" id="ViewportTexture_rmoaa"]
viewport_path = NodePath("Panel/MarginContainer/VBoxContainer/HBoxContainer/Frame/Previewport")
@ -135,21 +46,14 @@ grow_vertical = 2
mouse_filter = 2
theme = ExtResource("1_bfo8i")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
root_node = NodePath("../Panel/LevelRunButton")
libraries = {
&"": SubResource("AnimationLibrary_tguwa")
}
autoplay = "Show"
[node name="Panel" type="Panel" parent="."]
layout_mode = 1
anchors_preset = -1
anchor_top = 2.005
anchor_right = 0.6
anchor_bottom = 2.845
offset_top = -400.0
offset_bottom = -400.0
offset_top = -738.0
offset_bottom = -738.0
grow_vertical = 2
metadata/_edit_use_anchors_ = true
@ -239,7 +143,7 @@ anchor_bottom = 0.131
offset_right = -16.16
offset_bottom = -16.016
script = ExtResource("7_k6b6g")
_player = NodePath("../../AnimationPlayer")
_player = NodePath("")
[node name="AlmanachButton" type="Button" parent="Panel"]
layout_mode = 0

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=26 format=3 uid="uid://dd3yegl1xo44m"]
[gd_scene load_steps=28 format=3 uid="uid://dd3yegl1xo44m"]
[ext_resource type="Script" uid="uid://bndu1h5kgcde8" path="res://scripts/level/RuntimeLevelData.cs" id="1_31ltw"]
[ext_resource type="Script" uid="uid://bso32xkw738sy" path="res://scripts/level/PoolContainer.cs" id="2_s5sti"]
@ -18,6 +18,7 @@
[ext_resource type="PackedScene" uid="uid://bpekho7leatr5" path="res://scenes/sun.tscn" id="15_7v6ps"]
[ext_resource type="PackedScene" uid="uid://jm7wm08d2mi7" path="res://scenes/level components/right_boundary_marker.tscn" id="16_s7icd"]
[ext_resource type="PackedScene" uid="uid://plc2gus4ppds" path="res://scenes/level components/left_boundary_marker.tscn" id="17_8qqc4"]
[ext_resource type="Script" uid="uid://812ldoyxd5n5" path="res://scripts/level/LoseCheckbox.cs" id="19_482ps"]
[sub_resource type="WorldBoundaryShape2D" id="WorldBoundaryShape2D_482ps"]
distance = -9.0
@ -166,9 +167,13 @@ region = Rect2(194, 221, 61, 20)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_xsaqy"]
size = Vector2(244, 399)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_jg5t3"]
size = Vector2(282, 399)
[node name="level_template" type="Node2D"]
[node name="MainAnimationPlayer" type="AnimationPlayer" parent="."]
process_mode = 3
[node name="Data" type="Node" parent="."]
script = ExtResource("1_31ltw")
@ -357,6 +362,14 @@ position = Vector2(755, 376)
[node name="LeftBoundaryMarker" parent="." instance=ExtResource("17_8qqc4")]
position = Vector2(305, 76)
[node name="Checkbox" type="Area2D" parent="."]
collision_mask = 24
script = ExtResource("19_482ps")
[node name="CollisionShape2D" type="CollisionShape2D" parent="Checkbox"]
position = Vector2(141, 199.5)
shape = SubResource("RectangleShape2D_jg5t3")
[connection signal="pressed" from="GameOverScreen/VBoxContainer/RestartButton" to="GameOverScreen/VBoxContainer/TapPlayer" method="Play"]
[connection signal="pressed" from="GameOverScreen/VBoxContainer/ExitButton" to="GameOverScreen/VBoxContainer/TapPlayer" method="Play"]
[connection signal="timeout" from="SunSpawner/Timer" to="SunSpawner" method="Spawn"]

View file

@ -1,15 +1,267 @@
[gd_scene load_steps=4 format=3 uid="uid://bu0dh5ct387xu"]
[gd_scene load_steps=12 format=3 uid="uid://bu0dh5ct387xu"]
[ext_resource type="PackedScene" uid="uid://dd3yegl1xo44m" path="res://scenes/templates/level_template.tscn" id="1_vdv3d"]
[ext_resource type="Resource" uid="uid://br3364jty1j0i" path="res://resources/levels/test_level_for_execution.tres" id="2_bpfdr"]
[ext_resource type="Texture2D" uid="uid://b0tb2hjum40aw" path="res://assets/sprites/background_summer.png" id="3_lsqv3"]
[ext_resource type="Script" uid="uid://84gvlkflxdhk" path="res://scripts/level/zombe_spawners/RowSpawner.cs" id="4_kn7hc"]
[ext_resource type="Script" uid="uid://puqxp2xeg1r2" path="res://scripts/level/LevelRunner.cs" id="5_vbgdr"]
[sub_resource type="Animation" id="Animation_vbgdr"]
resource_name = "CYS_Sequence"
length = 3.0
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Camera2D:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0.666667, 1.5),
"transitions": PackedFloat32Array(0.5, 1),
"update": 0,
"values": [Vector2(481, 200), Vector2(700, 200)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("GUI/ChooseYourSeeds:anchor_top")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 2, 3),
"transitions": PackedFloat32Array(1, 0.5, 1),
"update": 0,
"values": [1.0, 1.0, 0.0]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("GUI/ChooseYourSeeds:anchor_bottom")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 2, 3),
"transitions": PackedFloat32Array(1, 0.5, 1),
"update": 0,
"values": [2.0, 2.0, 1.0]
}
[sub_resource type="Animation" id="Animation_yw4uo"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Camera2D:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(481, 200)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("GUI/ChooseYourSeeds:anchor_top")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("GUI/ChooseYourSeeds:anchor_bottom")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [1.0]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("GUI/ReadySetPlant:text")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [""]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("GUI/ReadySetPlant:visible")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_8ajos"]
resource_name = "PG_Sequence"
length = 5.0
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("GUI/ChooseYourSeeds:anchor_top")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(0.5, 1),
"update": 0,
"values": [0.0, 1.0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("GUI/ChooseYourSeeds:anchor_bottom")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(0.5, 1),
"update": 0,
"values": [1.0, 2.0]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Camera2D:position")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0.7, 1.5334),
"transitions": PackedFloat32Array(0.5, 1),
"update": 0,
"values": [Vector2(700, 200), Vector2(481, 200)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("GUI/ReadySetPlant:text")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(2, 2.667, 3.334),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 1,
"values": ["ready", "set", "plant"]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("GUI/ReadySetPlant:visible")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0, 2, 5),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 1,
"values": [false, true, false]
}
tracks/5/type = "method"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("Data")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(3.33333),
"transitions": PackedFloat32Array(1),
"values": [{
"args": [2],
"method": &"SetLevelState"
}]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_yw4uo"]
_data = {
&"CYS_Sequence": SubResource("Animation_vbgdr"),
&"PG_Sequence": SubResource("Animation_8ajos"),
&"RESET": SubResource("Animation_yw4uo")
}
[sub_resource type="WorldBoundaryShape2D" id="WorldBoundaryShape2D_vbgdr"]
normal = Vector2(1, 0)
distance = 135.0
[sub_resource type="WorldBoundaryShape2D" id="WorldBoundaryShape2D_yw4uo"]
normal = Vector2(1, 0)
distance = 139.0
[node name="StandardPlayersHouse" instance=ExtResource("1_vdv3d")]
[node name="Data" parent="." index="1"]
[node name="MainAnimationPlayer" parent="." index="0"]
libraries = {
&"": SubResource("AnimationLibrary_yw4uo")
}
[node name="Data" parent="." index="1" node_paths=PackedStringArray("levelRunner", "player")]
levelResource = ExtResource("2_bpfdr")
levelRunner = NodePath("../LevelRunner")
player = NodePath("../MainAnimationPlayer")
[node name="Background" type="Sprite2D" parent="Background" index="0"]
position = Vector2(500, 200)
texture = ExtResource("3_lsqv3")
metadata/_edit_lock_ = true
[node name="ChooseYourSeeds" parent="GUI" index="0"]
anchors_preset = -1
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="ReadySetPlant" type="RichTextLabel" parent="GUI" index="2"]
visible = false
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
bbcode_enabled = true
shortcut_keys_enabled = false
horizontal_alignment = 1
vertical_alignment = 1
[node name="GameOverScreen" parent="." index="9"]
visible = false
[node name="CollisionShape2D" parent="GameOverZombie/LoseZone/Hitbox" index="0"]
shape = SubResource("WorldBoundaryShape2D_vbgdr")
[node name="RowSpawner" type="Node2D" parent="." index="14" node_paths=PackedStringArray("delayTimer")]
position = Vector2(837, 76)
script = ExtResource("4_kn7hc")
delayTimer = NodePath("DelayTimer")
[node name="DelayTimer" type="Timer" parent="RowSpawner" index="0"]
wait_time = 2.5
[node name="LevelRunner" type="Node" parent="." index="15" node_paths=PackedStringArray("rowSpawner", "waveTimer")]
script = ExtResource("5_vbgdr")
rowSpawner = NodePath("../RowSpawner")
waveTimer = NodePath("WaveTimer")
[node name="WaveTimer" type="Timer" parent="LevelRunner" index="0"]
one_shot = true
[node name="Checkbox" parent="." index="16" node_paths=PackedStringArray("gameOverLayer", "fadeAnimation")]
gameOverLayer = NodePath("../GameOverScreen")
fadeAnimation = NodePath("../GameOverScreen/AnimationPlayer")
[node name="CollisionShape2D" parent="Checkbox" index="0"]
shape = SubResource("WorldBoundaryShape2D_yw4uo")

View file

@ -8,9 +8,6 @@ public partial class LevelRunButton : Button
[Export] private AnimationPlayer _player;
public override void _Pressed()
{
RuntimeLevelData.Instance.SetLevelState(RuntimeLevelData.LevelStates.Game);
GetTree().Paused = false;
_player.Play("Hide");
RuntimeLevelData.Instance.SetLevelState(RuntimeLevelData.LevelStates.Pregame);
}
}

View file

@ -14,6 +14,7 @@ public class HotbarPregameHandler : SeedpacketHandler, ISeedpacketPress
public event Action Clicked;
public void Pressed()
{
if (RuntimeLevelData.Instance.GetLevelState() != RuntimeLevelData.LevelStates.ChooseYourSeeds) return;
if (Clicked != null) Clicked();
_owner.QueueFree();
AudioSequencer.Play("tap", Seedpacket.UntapStream);

View file

@ -0,0 +1,37 @@
using Godot;
namespace Newlon.Components.Level;
[GlobalClass]
public partial class LevelRunner : Node
{
private AdventureLevelResource resource;
[Export] private RowSpawner rowSpawner;
[Export] private Timer waveTimer;
private int waveIndex = -1;
public override void _Ready()
{
waveTimer.Timeout += SummonWave;
}
public void SetLevelResource(AdventureLevelResource data)
{
resource = data;
waveTimer.Stop();
waveTimer.WaitTime = resource.initialWaveDelay;
waveTimer.Start();
}
private void SummonWave()
{
waveIndex += 1;
rowSpawner.Add(resource.waves[waveIndex].zombiesOrdered);
if (waveIndex == resource.waves.Count - 1) return;
waveTimer.WaitTime = resource.waves[waveIndex].customWaveDelay > 0 ? resource.waves[waveIndex].customWaveDelay : resource.standardWaveDelay;
waveTimer.Start();
}
}

View file

@ -0,0 +1 @@
uid://puqxp2xeg1r2

View file

@ -18,17 +18,25 @@ public partial class RuntimeLevelData : Node
public float SunCount { get; private set; } = 0;
[Export]
public AdventureLevelResource levelResource;
public event Action<LevelStates> OnLevelStateChanged;
[Export]
private LevelRunner levelRunner;
[Export]
private AnimationPlayer player;
[Signal]
public delegate void OnLevelStateChangedEventHandler(LevelStates state);
public static RuntimeLevelData Instance { get; private set; }
private LevelStates _currentState = LevelStates.ChooseYourSeeds;
public override void _Ready()
{
Instance = this;
GetTree().Paused = true;
Engine.TimeScale = 1.0;
SetLevelState(LevelStates.ChooseYourSeeds);
}
#region Sun
@ -52,8 +60,31 @@ public partial class RuntimeLevelData : Node
public void SetLevelState(LevelStates state)
{
OnLevelStateChanged(state);
EmitSignal(SignalName.OnLevelStateChanged, (int)state);
_currentState = state;
switch (_currentState)
{
case LevelStates.ChooseYourSeeds:
player.Play("CYS_Sequence");
break;
case LevelStates.Pregame:
player.Play("PG_Sequence");
break;
case LevelStates.Game:
GetTree().Paused = false;
levelRunner.SetLevelResource(levelResource);
break;
case LevelStates.Win:
break;
case LevelStates.Loose:
break;
}
}
public LevelStates GetLevelState()
{
return _currentState;
}
//private Array<PlantResource> _selectedPlants;

View file

@ -0,0 +1,51 @@
using Godot;
using System.Collections.Generic;
using Newlon.Components.Zombies;
using Godot.Collections;
namespace Newlon.Components.Level;
[GlobalClass]
public partial class RowSpawner : Node2D
{
private Queue<RowSpawn> queue = [];
[Export] private Timer delayTimer;
public override void _Ready()
{
delayTimer.Timeout += FormSquad;
}
private void FormSquad()
{
if (queue.Count == 0) return;
var row = queue.Dequeue();
for (int i = 0; i < row.zombies.Count; i++)
{
if (row.zombies[i] != null)
Spawn(row.zombies[i], i+1);
}
if (queue.Count == 0) delayTimer.Stop();
}
private void Spawn(ZombieResource resource, int lane)
{
RuntimeZombieData zombie = resource.Scene.Instantiate<RuntimeZombieData>();
PoolContainer.Instance.Zombies.AddChild(zombie);
zombie.GlobalPosition = new Vector2(GlobalPosition.X, Utility.LeftFieldBoundary.Y + lane * Utility.TileHeight);
}
public void Add(Array<RowSpawn> rowSpawns)
{
foreach (var spawn in rowSpawns)
{
queue.Enqueue(spawn);
}
delayTimer.Start();
}
}

View file

@ -0,0 +1 @@
uid://84gvlkflxdhk