diff --git a/Game/Background/background.tscn b/Game/Background/background.tscn new file mode 100644 index 0000000..b95ba10 --- /dev/null +++ b/Game/Background/background.tscn @@ -0,0 +1,9 @@ +[gd_scene format=3 uid="uid://cvwvwv55n00ce"] + +[ext_resource type="Texture2D" uid="uid://cx1tr03f8rjck" path="res://Game/Background/purple.png" id="1_vaplv"] + +[node name="Background" type="TextureRect" unique_id=701555148] +offset_right = 1280.0 +offset_bottom = 768.0 +texture = ExtResource("1_vaplv") +stretch_mode = 1 diff --git a/Game/Background/purple.png b/Game/Background/purple.png new file mode 100644 index 0000000..4dd6f99 Binary files /dev/null and b/Game/Background/purple.png differ diff --git a/Game/Background/purple.png.import b/Game/Background/purple.png.import new file mode 100644 index 0000000..741a4eb --- /dev/null +++ b/Game/Background/purple.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cx1tr03f8rjck" +path="res://.godot/imported/purple.png-ab1cf2fd670db01a8dbd40ee0004fe5b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Game/Background/purple.png" +dest_files=["res://.godot/imported/purple.png-ab1cf2fd670db01a8dbd40ee0004fe5b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Game/Level/LevelData.cs b/Game/Level/LevelData.cs index 7a30ac2..c1a075b 100644 --- a/Game/Level/LevelData.cs +++ b/Game/Level/LevelData.cs @@ -7,7 +7,12 @@ namespace GodotHostTest.Game.Level; [GlobalClass] public partial class LevelData : Resource, ILevel { + [Export] public double SpawnDuration; [Export] public double TimeBetweenSpawns; + /// TimeSpan ILevel.TimeBetweenSpawns => TimeSpan.FromSeconds(TimeBetweenSpawns); + + /// + TimeSpan ILevel.SpawnDuration => TimeSpan.FromSeconds(SpawnDuration); } \ No newline at end of file diff --git a/Game/level.tscn b/Game/Level/level.tscn similarity index 96% rename from Game/level.tscn rename to Game/Level/level.tscn index b398458..a4facab 100644 --- a/Game/level.tscn +++ b/Game/Level/level.tscn @@ -77,27 +77,21 @@ _serviceScope = "GodotHostTest.Game.Level.LevelScope, godot-host-test, Version=1 [node name="Target" parent="." unique_id=2101558052 instance=ExtResource("1_y7rhs")] position = Vector2(198, 143) -TimeOutDurationInSeconds = 2.0 [node name="Target2" parent="." unique_id=1009901052 instance=ExtResource("1_y7rhs")] position = Vector2(669, 64) -TimeOutDurationInSeconds = 2.0 [node name="Target3" parent="." unique_id=1433382188 instance=ExtResource("1_y7rhs")] position = Vector2(1060, 263) -TimeOutDurationInSeconds = 2.0 [node name="Target4" parent="." unique_id=1553596281 instance=ExtResource("1_y7rhs")] position = Vector2(961, 620) -TimeOutDurationInSeconds = 2.0 [node name="Target5" parent="." unique_id=46923989 instance=ExtResource("1_y7rhs")] position = Vector2(469, 591) -TimeOutDurationInSeconds = 2.0 [node name="Target6" parent="." unique_id=2092179937 instance=ExtResource("1_y7rhs")] position = Vector2(53, 417) -TimeOutDurationInSeconds = 2.0 [node name="Spawner" type="Node2D" parent="." unique_id=251404460 node_paths=PackedStringArray("Timer")] script = ExtResource("2_5saw1") diff --git a/Game/Projectile/Explosion/explosion_gpu_particles_2d.tscn b/Game/Projectile/Explosion/explosion_gpu_particles_2d.tscn new file mode 100644 index 0000000..7117906 --- /dev/null +++ b/Game/Projectile/Explosion/explosion_gpu_particles_2d.tscn @@ -0,0 +1,41 @@ +[gd_scene format=3 uid="uid://dfvr0g5souli2"] + +[ext_resource type="Texture2D" uid="uid://bhm7kb18b1tbh" path="res://Game/Projectile/Explosion/fires.png" id="1_e3ife"] + +[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_bfsaf"] +particles_animation = true +particles_anim_h_frames = 2 +particles_anim_v_frames = 1 +particles_anim_loop = false + +[sub_resource type="Curve" id="Curve_ytfwl"] +_data = [Vector2(0.00554017, 0.021126747), 0.0, 0.0, 0, 0, Vector2(0.14681442, 0.99295783), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] +point_count = 3 + +[sub_resource type="CurveTexture" id="CurveTexture_jyg1o"] +curve = SubResource("Curve_ytfwl") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_u8d0v"] +lifetime_randomness = 0.1 +particle_flag_disable_z = true +spread = 180.0 +initial_velocity_min = 47.62 +initial_velocity_max = 47.62 +gravity = Vector3(0, 0, 0) +damping_min = 97.494 +damping_max = 97.494 +scale_min = 0.099999994 +scale_max = 0.099999994 +color = Color(1, 0.11372549, 0.22745098, 1) +alpha_curve = SubResource("CurveTexture_jyg1o") +anim_speed_min = 6.67 +anim_speed_max = 6.67 + +[node name="ExplosionGPUParticles2D" type="GPUParticles2D" unique_id=1991976710] +material = SubResource("CanvasItemMaterial_bfsaf") +emitting = false +amount = 16 +texture = ExtResource("1_e3ife") +lifetime = 0.3 +one_shot = true +process_material = SubResource("ParticleProcessMaterial_u8d0v") diff --git a/Game/Projectile/Explosion/fires.png b/Game/Projectile/Explosion/fires.png new file mode 100644 index 0000000..ef8ce17 Binary files /dev/null and b/Game/Projectile/Explosion/fires.png differ diff --git a/Game/Projectile/Explosion/fires.png.import b/Game/Projectile/Explosion/fires.png.import new file mode 100644 index 0000000..d4429dd --- /dev/null +++ b/Game/Projectile/Explosion/fires.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bhm7kb18b1tbh" +path="res://.godot/imported/fires.png-9cb25e6666cbbded849592a59c77604f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Game/Projectile/Explosion/fires.png" +dest_files=["res://.godot/imported/fires.png-9cb25e6666cbbded849592a59c77604f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Game/Projectile/Projectile.cs b/Game/Projectile/Projectile.cs index 304d62a..4976e4d 100644 --- a/Game/Projectile/Projectile.cs +++ b/Game/Projectile/Projectile.cs @@ -4,10 +4,25 @@ namespace GodotHostTest.Game.Projectile; public partial class Projectile : Node2D { + [Export] private PackedScene _explosionPackedScene = null!; [Export] private float _speed = 100; public override void _PhysicsProcess(double delta) { Position += (float)delta * _speed * Vector2.Up.Rotated(Rotation); } + + private void OnArea2DEntered(Area2D _) + { + var explosion = (GpuParticles2D)_explosionPackedScene.Instantiate(); + explosion.GlobalPosition = GlobalPosition; + explosion.Emitting = true; + GetTree().CurrentScene.AddChild(explosion); + QueueFree(); + } + + private void OnScreenExited() + { + QueueFree(); + } } \ No newline at end of file diff --git a/Game/Projectile/projectile.tscn b/Game/Projectile/projectile.tscn index ef3ac1c..6131181 100644 --- a/Game/Projectile/projectile.tscn +++ b/Game/Projectile/projectile.tscn @@ -2,6 +2,7 @@ [ext_resource type="Script" uid="uid://dc5mvle8lc40j" path="res://Game/Projectile/Projectile.cs" id="1_g2gsk"] [ext_resource type="Script" uid="uid://qjonl8stia46" path="res://addons/AetherBind/ServiceSource.cs" id="2_g4q5f"] +[ext_resource type="PackedScene" uid="uid://dfvr0g5souli2" path="res://Game/Projectile/Explosion/explosion_gpu_particles_2d.tscn" id="2_r0joc"] [ext_resource type="Texture2D" uid="uid://blwkfvcupjt0v" path="res://Game/Projectile/towerDefense_tile252.png" id="3_r0joc"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_u8d0v"] @@ -10,6 +11,7 @@ size = Vector2(22, 39) [node name="Projectile" type="Node2D" unique_id=1686616504] script = ExtResource("1_g2gsk") _speed = 600.0 +_explosionPackedScene = ExtResource("2_r0joc") [node name="Scope" type="Node" parent="." unique_id=513224818 node_paths=PackedStringArray("InjectedNodes")] script = ExtResource("2_g4q5f") @@ -24,3 +26,8 @@ collision_mask = 2 [node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D" unique_id=1209287052] position = Vector2(0, 0.5) shape = SubResource("RectangleShape2D_u8d0v") + +[node name="VisibleOnScreenNotifier2D" type="VisibleOnScreenNotifier2D" parent="." unique_id=2022746131] + +[connection signal="area_entered" from="Area2D" to="." method="OnArea2DEntered"] +[connection signal="screen_exited" from="VisibleOnScreenNotifier2D" to="." method="OnScreenExited"] diff --git a/Game/Target/Explosion/explosion_gpu_particles_2d.tscn b/Game/Target/Explosion/explosion_gpu_particles_2d.tscn new file mode 100644 index 0000000..040fd4b --- /dev/null +++ b/Game/Target/Explosion/explosion_gpu_particles_2d.tscn @@ -0,0 +1,44 @@ +[gd_scene format=3 uid="uid://cd8w4ydeugrxn"] + +[ext_resource type="Texture2D" uid="uid://ddv3d3cguh5hd" path="res://Game/Target/Explosion/scorches.png" id="1_rjvc0"] + +[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_bfsaf"] +particles_animation = true +particles_anim_h_frames = 3 +particles_anim_v_frames = 1 +particles_anim_loop = false + +[sub_resource type="Curve" id="Curve_ytfwl"] +_data = [Vector2(0.00554017, 0.021126747), 0.0, 0.0, 0, 0, Vector2(0.14681442, 0.99295783), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] +point_count = 3 + +[sub_resource type="CurveTexture" id="CurveTexture_jyg1o"] +curve = SubResource("Curve_ytfwl") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_u8d0v"] +lifetime_randomness = 0.1 +particle_flag_disable_z = true +emission_shape = 1 +emission_sphere_radius = 33.35 +spread = 180.0 +initial_velocity_min = 47.62 +initial_velocity_max = 47.62 +gravity = Vector3(0, 0, 0) +damping_min = 97.494 +damping_max = 97.494 +color = Color(1, 0.11372549, 0.22745098, 1) +alpha_curve = SubResource("CurveTexture_jyg1o") +anim_speed_min = 10.0 +anim_speed_max = 10.0 + +[node name="ExplosionGPUParticles2D" type="GPUParticles2D" unique_id=1991976710] +z_index = 1 +z_as_relative = false +material = SubResource("CanvasItemMaterial_bfsaf") +emitting = false +amount = 32 +texture = ExtResource("1_rjvc0") +lifetime = 0.3 +one_shot = true +visibility_rect = Rect2(-200, -75, 400, 150) +process_material = SubResource("ParticleProcessMaterial_u8d0v") diff --git a/Game/Target/Explosion/scorches.png b/Game/Target/Explosion/scorches.png new file mode 100644 index 0000000..5830957 Binary files /dev/null and b/Game/Target/Explosion/scorches.png differ diff --git a/Game/Target/Explosion/scorches.png.import b/Game/Target/Explosion/scorches.png.import new file mode 100644 index 0000000..e49fe39 --- /dev/null +++ b/Game/Target/Explosion/scorches.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ddv3d3cguh5hd" +path="res://.godot/imported/scorches.png-b8a9f74019ec3d75b5befcdf7090cc9b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Game/Target/Explosion/scorches.png" +dest_files=["res://.godot/imported/scorches.png-b8a9f74019ec3d75b5befcdf7090cc9b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Game/Target/Target.cs b/Game/Target/Target.cs index e1428ab..ed7b527 100644 --- a/Game/Target/Target.cs +++ b/Game/Target/Target.cs @@ -12,8 +12,9 @@ public partial class Target : Node2D, ITarget private readonly Subject _timedOut = new(); [Export] public required Area2D CollisionArea; [Export] public required Sprite2D Image; - [Export] public double TimeOutDurationInSeconds; [Export] public required Timer TimeOutTimer; + [Export] private PackedScene _explosionPackedScene = null!; + [Inject] private ILevel _level = null!; [Inject] private ITargetCollector _targetCollector = null!; @@ -25,7 +26,8 @@ public partial class Target : Node2D, ITarget { Image.Visible = true; CollisionArea.Monitoring = true; - TimeOutTimer.Start(TimeOutDurationInSeconds); + CollisionArea.Monitorable = true; + TimeOutTimer.Start(_level.SpawnDuration.TotalSeconds); } public override void _Ready() @@ -39,18 +41,29 @@ public partial class Target : Node2D, ITarget _hit.Dispose(); } - // todo: hook to collision + private void OnAreaEntered(Area2D _) + { + OnHit(); + } + private void OnHit() { Disable(); TimeOutTimer.Stop(); _hit.OnNext(Unit.Default); + + var explosion = (GpuParticles2D)_explosionPackedScene.Instantiate(); + explosion.GlobalPosition = GlobalPosition; + explosion.Emitting = true; + GetTree().CurrentScene.AddChild(explosion); } private void Disable() { Image.Visible = false; - CollisionArea.Monitoring = false; + // can't se monitoring/monitorable when inside the collision code, like during OnHit + CollisionArea.SetDeferred(Area2D.PropertyName.Monitoring, false); + CollisionArea.SetDeferred(Area2D.PropertyName.Monitorable, false); } private void OnTimeout() diff --git a/Game/Target/target.tscn b/Game/Target/target.tscn index ed47502..5e07510 100644 --- a/Game/Target/target.tscn +++ b/Game/Target/target.tscn @@ -2,6 +2,7 @@ [ext_resource type="Script" uid="uid://bv2hat41dyxiv" path="res://Game/Target/Target.cs" id="1_ouani"] [ext_resource type="Texture2D" uid="uid://m4pvy8kkw7k4" path="res://Game/Target/towerDefense_tile136.png" id="2_olsqn"] +[ext_resource type="PackedScene" uid="uid://cd8w4ydeugrxn" path="res://Game/Target/Explosion/explosion_gpu_particles_2d.tscn" id="2_uqpd1"] [sub_resource type="CircleShape2D" id="CircleShape2D_uqpd1"] radius = 60.033325 @@ -10,8 +11,8 @@ radius = 60.033325 script = ExtResource("1_ouani") CollisionArea = NodePath("CollisionArea") Image = NodePath("Sprite2D") -TimeOutDurationInSeconds = 7.0 TimeOutTimer = NodePath("TimeOutTimer") +_explosionPackedScene = ExtResource("2_uqpd1") [node name="Sprite2D" type="Sprite2D" parent="." unique_id=31059524] visible = false @@ -30,4 +31,5 @@ shape = SubResource("CircleShape2D_uqpd1") [node name="TimeOutTimer" type="Timer" parent="." unique_id=1079777109] one_shot = true +[connection signal="area_entered" from="CollisionArea" to="." method="OnAreaEntered"] [connection signal="timeout" from="TimeOutTimer" to="." method="OnTimeout"] diff --git a/Game/levels_data.tres b/Game/levels_data.tres index 6167fc4..02a99f5 100644 --- a/Game/levels_data.tres +++ b/Game/levels_data.tres @@ -5,7 +5,8 @@ [sub_resource type="Resource" id="Resource_bbjqm"] script = ExtResource("1_bkfnq") -TimeBetweenSpawns = 0.5 +TimeBetweenSpawns = 1.0 +SpawnDuration = 4.0 metadata/_custom_type_script = "uid://ywe7vkywrdvk" [resource] diff --git a/Interfaces/ILevel.cs b/Interfaces/ILevel.cs index 5d8b597..c1bf0a0 100644 --- a/Interfaces/ILevel.cs +++ b/Interfaces/ILevel.cs @@ -4,5 +4,13 @@ namespace GodotHostTest.Interfaces; public interface ILevel { + /// + /// Time between successive spawns. + /// public TimeSpan TimeBetweenSpawns { get; } + + /// + /// Duration of a single spawn. + /// + public TimeSpan SpawnDuration { get; } } \ No newline at end of file diff --git a/root_scene.tscn b/root_scene.tscn index 8c814eb..6faf007 100644 --- a/root_scene.tscn +++ b/root_scene.tscn @@ -1,9 +1,10 @@ [gd_scene format=3 uid="uid://vsburk37p4u"] -[ext_resource type="Script" uid="uid://bvjvojer872c8" path="res://Game/Root.cs" id="1_iqet6"] -[ext_resource type="PackedScene" uid="uid://xfd48ep5qi1k" path="res://Game/level.tscn" id="3_bbjqm"] -[ext_resource type="Script" uid="uid://bpes6mnv21f2v" path="res://Game/GameServiceSource.cs" id="3_iqet6"] +[ext_resource type="Script" uid="uid://bvjvojer872c8" path="res://Game/Root/Root.cs" id="1_iqet6"] +[ext_resource type="PackedScene" uid="uid://xfd48ep5qi1k" path="res://Game/Level/level.tscn" id="3_bbjqm"] +[ext_resource type="Script" uid="uid://bpes6mnv21f2v" path="res://Game/Root/GameServiceSource.cs" id="3_iqet6"] [ext_resource type="Resource" uid="uid://c4ym7vrpgk4e6" path="res://Game/levels_data.tres" id="4_t2jh2"] +[ext_resource type="PackedScene" uid="uid://cvwvwv55n00ce" path="res://Game/Background/background.tscn" id="5_bbjqm"] [node name="Root" type="Node2D" unique_id=920849082] script = ExtResource("1_iqet6") @@ -13,3 +14,5 @@ _levelScene = ExtResource("3_bbjqm") script = ExtResource("3_iqet6") _levelsData = ExtResource("4_t2jh2") InjectedNodes = [NodePath("..")] + +[node name="Background" parent="." unique_id=701555148 instance=ExtResource("5_bbjqm")]