From e7dbb9cabb13efe946b27b5ff70b855da36ee84f Mon Sep 17 00:00:00 2001 From: redglow Date: Tue, 21 Jul 2026 20:49:24 +0200 Subject: [PATCH] . --- Game/Level/CurrentLevel.cs | 13 +++++- Game/Projectile/Projectile.cs | 14 ++---- Game/Projectile/projectile.tscn | 26 ++++++++++++ Game/Projectile/towerDefense_tile252.png | Bin 0 -> 702 bytes .../towerDefense_tile252.png.import | 40 ++++++++++++++++++ Game/Root/GameServiceSource.cs | 8 +++- Game/Root/Root.cs | 2 +- Game/Score/Score.cs | 24 ++++------- Game/Score/TotalScore.cs | 29 +++++++++++++ Game/Score/TotalScore.cs.uid | 1 + Game/Target/TargetEventBus.cs | 20 +++++++++ Game/Target/TargetEventBus.cs.uid | 1 + Game/Target/TargetSpawner.cs | 2 + Game/{ => Target}/target.tscn | 24 ++++++----- Game/Target/towerDefense_tile136.png | Bin 0 -> 1154 bytes Game/Target/towerDefense_tile136.png.import | 40 ++++++++++++++++++ Game/Turret/Turret.cs | 29 ++++++++++++- Game/Turret/towerDefense_tile181.png | Bin 0 -> 515 bytes Game/Turret/towerDefense_tile181.png.import | 40 ++++++++++++++++++ Game/Turret/towerDefense_tile206.png | Bin 0 -> 921 bytes Game/Turret/towerDefense_tile206.png.import | 40 ++++++++++++++++++ Game/Turret/turret.tscn | 29 +++++++++++++ Game/level.tscn | 12 ++---- Game/projectile.tscn | 18 -------- Interfaces/ICurrentLevel.cs | 4 +- Interfaces/IScore.cs | 4 +- Interfaces/ITarget.cs | 7 +-- Interfaces/ITargetEventBus.cs | 22 ++++++++++ Interfaces/ITargetEventBus.cs.uid | 1 + .../AetherBind/SceneInstantiatorExtensions.cs | 2 +- project.godot | 18 ++++++++ 31 files changed, 394 insertions(+), 76 deletions(-) create mode 100644 Game/Projectile/projectile.tscn create mode 100644 Game/Projectile/towerDefense_tile252.png create mode 100644 Game/Projectile/towerDefense_tile252.png.import create mode 100644 Game/Score/TotalScore.cs create mode 100644 Game/Score/TotalScore.cs.uid create mode 100644 Game/Target/TargetEventBus.cs create mode 100644 Game/Target/TargetEventBus.cs.uid rename Game/{ => Target}/target.tscn (60%) create mode 100644 Game/Target/towerDefense_tile136.png create mode 100644 Game/Target/towerDefense_tile136.png.import create mode 100644 Game/Turret/towerDefense_tile181.png create mode 100644 Game/Turret/towerDefense_tile181.png.import create mode 100644 Game/Turret/towerDefense_tile206.png create mode 100644 Game/Turret/towerDefense_tile206.png.import create mode 100644 Game/Turret/turret.tscn delete mode 100644 Game/projectile.tscn create mode 100644 Interfaces/ITargetEventBus.cs create mode 100644 Interfaces/ITargetEventBus.cs.uid diff --git a/Game/Level/CurrentLevel.cs b/Game/Level/CurrentLevel.cs index ea1b3a0..dcf999c 100644 --- a/Game/Level/CurrentLevel.cs +++ b/Game/Level/CurrentLevel.cs @@ -1,13 +1,22 @@ using GodotHostTest.Interfaces; +using R3; namespace GodotHostTest.Game.Level; public class CurrentLevel : ICurrentLevel { - public int LevelNumber { get; private set; } = 1; + private readonly ReactiveProperty _levelNumber; + + public CurrentLevel() + { + _levelNumber = new ReactiveProperty(1); + LevelNumber = _levelNumber.ToReadOnlyReactiveProperty(); + } + + public ReadOnlyReactiveProperty LevelNumber { get; } public void NextLevel() { - LevelNumber++; + _levelNumber.Value++; } } \ No newline at end of file diff --git a/Game/Projectile/Projectile.cs b/Game/Projectile/Projectile.cs index 716108d..304d62a 100644 --- a/Game/Projectile/Projectile.cs +++ b/Game/Projectile/Projectile.cs @@ -1,21 +1,13 @@ using Godot; -using GodotHostTest.Helpers; -using GodotHostTest.Interfaces; -using Microsoft.Extensions.Logging; -using OwofGames.AetherBind; -using R3; namespace GodotHostTest.Game.Projectile; public partial class Projectile : Node2D { - [Inject] private ILogger _logger = null!; - [Inject] private ITargetSpawner _targetSpawner = null!; + [Export] private float _speed = 100; - // Called when the node enters the scene tree for the first time. - public override void _Ready() + public override void _PhysicsProcess(double delta) { - _targetSpawner.TargetSpawned - .Subscribe(_ => _logger.LogInformation("Projectile got informed of target spawning")).AddTo(this); + Position += (float)delta * _speed * Vector2.Up.Rotated(Rotation); } } \ No newline at end of file diff --git a/Game/Projectile/projectile.tscn b/Game/Projectile/projectile.tscn new file mode 100644 index 0000000..ef3ac1c --- /dev/null +++ b/Game/Projectile/projectile.tscn @@ -0,0 +1,26 @@ +[gd_scene format=3 uid="uid://brbufibn7hi3o"] + +[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="Texture2D" uid="uid://blwkfvcupjt0v" path="res://Game/Projectile/towerDefense_tile252.png" id="3_r0joc"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_u8d0v"] +size = Vector2(22, 39) + +[node name="Projectile" type="Node2D" unique_id=1686616504] +script = ExtResource("1_g2gsk") +_speed = 600.0 + +[node name="Scope" type="Node" parent="." unique_id=513224818 node_paths=PackedStringArray("InjectedNodes")] +script = ExtResource("2_g4q5f") +InjectedNodes = [NodePath("..")] + +[node name="Sprite2D" type="Sprite2D" parent="." unique_id=1021740171] +texture = ExtResource("3_r0joc") + +[node name="Area2D" type="Area2D" parent="." unique_id=863162079] +collision_mask = 2 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D" unique_id=1209287052] +position = Vector2(0, 0.5) +shape = SubResource("RectangleShape2D_u8d0v") diff --git a/Game/Projectile/towerDefense_tile252.png b/Game/Projectile/towerDefense_tile252.png new file mode 100644 index 0000000000000000000000000000000000000000..2187b8711cab229f137b50ccecf5c5bece7cd8b2 GIT binary patch literal 702 zcmV;v0zv(WP)EUq>yuQ)A&l9sA7BCk0tfs>U0005b;v4V|`g@=f?jEJ{M zJ+_I3y*)6;K{J_sdW(E}i=U#)LNt%0ro=!pwmUAGu(P_2iPA(i&}?F|IxVBFu;58L z)kZhKJ~5uOxR3}uaECPU%wxJFP}dT&wl_<>#7t000D+cL_t(o!|m3`a)U4s z24Ir7m)IB#cH-U}ZWx>>fA;+!D~L9egFGYo;LL>o#AUw`2x(XA-We?eGT?szEtu9l zfC<31)PV+^t%I5}px1GvBk-yUm^cy92~9;n2Mz&nxVZ%F<_;{0XNjsBP{bt!E~r~7 zfPoc7S>ag)Xki=!W0)#HGuXo@N7yO=;KzUuC;$dLO5%w(QVf))laC~mX-OV&HOfgRM&fyx!l%z|QwjH{<|bPqYu~_ray+p(qDL z7vd%aHn*-t@d|iTiQZusHWynCFfr%1={|Y`qPeIwXu`>WH)a~Tt~;c#MK|OC0}ihn zyfZf74-O=Ep&PdL3kq6+e~p8%wP@nTwj~+`<4p@AqOEYq5CUa{(fOFcQ() + .AddSingleton() + .AddLevelServices(_levelsData); } } \ No newline at end of file diff --git a/Game/Root/Root.cs b/Game/Root/Root.cs index 9562a0f..6748a80 100644 --- a/Game/Root/Root.cs +++ b/Game/Root/Root.cs @@ -20,7 +20,7 @@ public partial class Root : Node2D [WithProvider] private void OnInstantiate(IValueSetter levelValueSetter) { - var levelData = _levelDataProvider.GetLevelData(_currentLevel.LevelNumber); + var levelData = _levelDataProvider.GetLevelData(_currentLevel.LevelNumber.CurrentValue); levelValueSetter.Set(levelData); } } \ No newline at end of file diff --git a/Game/Score/Score.cs b/Game/Score/Score.cs index 86e0cc6..41d64b5 100644 --- a/Game/Score/Score.cs +++ b/Game/Score/Score.cs @@ -6,34 +6,28 @@ using R3; namespace GodotHostTest.Game.Score; -public partial class Score : Control, IScore +public partial class Score : Control { [Export] private AnimationPlayer _animationPlayer = null!; + [Inject] private ICurrentLevel _currentLevel = null!; [Export] private Label _label = null!; - private int _score; - [Inject] private ITargetSpawner _targetSpawner = null!; - - int IScore.Score => _score; + [Inject] private IScore _score = null!; public override void _Ready() { - _targetSpawner.TargetSpawned.Subscribe(OnTargetSpawned).AddTo(this); - base._Ready(); + _score.Score.Subscribe(UpdateScore).AddTo(this); + _score.Score.Chunk(2, 1).Where(values => values.Length == 2 && values[1] < values[0]) + .Subscribe(OnScoreDecreasing).AddTo(this); } - private void OnTargetSpawned(ITarget target) + private void OnScoreDecreasing(T _) { _animationPlayer.Play("wiggle"); - target.Hit.Select(_ => 20).Merge(target.TimedOut.Select(_ => -5)).SubscribeOnce(delta => - { - _score += delta; - UpdateScore(); - }).AddTo(this); } - private void UpdateScore() + private void UpdateScore(int newScore) { - _label.Text = $"Score: {_score}"; + _label.Text = $"Level {_currentLevel.LevelNumber} - Score: {newScore}"; } } \ No newline at end of file diff --git a/Game/Score/TotalScore.cs b/Game/Score/TotalScore.cs new file mode 100644 index 0000000..3d56c9a --- /dev/null +++ b/Game/Score/TotalScore.cs @@ -0,0 +1,29 @@ +using System; +using GodotHostTest.Interfaces; +using R3; + +namespace GodotHostTest.Game.Score; + +public class TotalScore : IScore, IDisposable +{ + private readonly IDisposable _connectedObservableDisposable; + + public TotalScore(ITargetEventBus targetEventBus) + { + var connectedObservable = targetEventBus.Hit.Select(_ => 20) + .Merge(targetEventBus.TimedOut.Select(_ => -5)) + .Scan(0, (x1, x2) => x1 + x2) + .Prepend(0) + .Replay(1); + _connectedObservableDisposable = connectedObservable.Connect(); + Score = connectedObservable.AsObservable(); + } + + public void Dispose() + { + _connectedObservableDisposable.Dispose(); + GC.SuppressFinalize(this); + } + + public Observable Score { get; } +} \ No newline at end of file diff --git a/Game/Score/TotalScore.cs.uid b/Game/Score/TotalScore.cs.uid new file mode 100644 index 0000000..29660fb --- /dev/null +++ b/Game/Score/TotalScore.cs.uid @@ -0,0 +1 @@ +uid://gymu1u4w882o diff --git a/Game/Target/TargetEventBus.cs b/Game/Target/TargetEventBus.cs new file mode 100644 index 0000000..9a17f12 --- /dev/null +++ b/Game/Target/TargetEventBus.cs @@ -0,0 +1,20 @@ +using GodotHostTest.Helpers; +using GodotHostTest.Interfaces; +using R3; + +namespace GodotHostTest.Game.Target; + +public class TargetEventBus : ITargetEventBus +{ + private readonly Pipe _hitOutPipe = new(); + private readonly Pipe _timedOutPipe = new(); + + public Observable TimedOut => _timedOutPipe.Observable; + public Observable Hit => _hitOutPipe.Observable; + + public void NewTargetSpawner(ITargetSpawner targetSpawner) + { + _timedOutPipe.PipeIn(targetSpawner.TargetSpawned.SelectMany(target => target.TimedOut)); + _hitOutPipe.PipeIn(targetSpawner.TargetSpawned.SelectMany(target => target.Hit)); + } +} \ No newline at end of file diff --git a/Game/Target/TargetEventBus.cs.uid b/Game/Target/TargetEventBus.cs.uid new file mode 100644 index 0000000..fd2181f --- /dev/null +++ b/Game/Target/TargetEventBus.cs.uid @@ -0,0 +1 @@ +uid://clr4u1sedssqu diff --git a/Game/Target/TargetSpawner.cs b/Game/Target/TargetSpawner.cs index 6179cde..4957c3b 100644 --- a/Game/Target/TargetSpawner.cs +++ b/Game/Target/TargetSpawner.cs @@ -15,6 +15,7 @@ public partial class TargetSpawner : Node2D, ITargetCollector, ITargetSpawner [Export] public required Timer Timer; [Inject] private ILevel _level = null!; + [Inject] private ITargetEventBus _targetEventBus = null!; public void NewTarget(ITarget target) { @@ -26,6 +27,7 @@ public partial class TargetSpawner : Node2D, ITargetCollector, ITargetSpawner public override void _Ready() { + _targetEventBus.NewTargetSpawner(this); Spawn(); Timer.Start(_level.TimeBetweenSpawns.TotalSeconds); } diff --git a/Game/target.tscn b/Game/Target/target.tscn similarity index 60% rename from Game/target.tscn rename to Game/Target/target.tscn index c3f9212..ed47502 100644 --- a/Game/target.tscn +++ b/Game/Target/target.tscn @@ -1,29 +1,31 @@ [gd_scene format=3 uid="uid://3v8kq1rfwhmr"] -[ext_resource type="Texture2D" uid="uid://y1ros3y7hag2" path="res://icon.svg" id="1_032qf"] -[ext_resource type="Script" uid="uid://bv2hat41dyxiv" path="res://Game/Target.cs" id="1_c0a8e"] +[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"] -[sub_resource type="RectangleShape2D" id="RectangleShape2D_u8d0v"] -size = Vector2(128, 128) +[sub_resource type="CircleShape2D" id="CircleShape2D_uqpd1"] +radius = 60.033325 -[node name="Target" type="Node2D" unique_id=2101558052 node_paths=PackedStringArray("TimeOutTimer", "Image", "CollisionArea")] -script = ExtResource("1_c0a8e") +[node name="Target" type="Node2D" unique_id=2101558052 node_paths=PackedStringArray("CollisionArea", "Image", "TimeOutTimer")] +script = ExtResource("1_ouani") +CollisionArea = NodePath("CollisionArea") +Image = NodePath("Sprite2D") TimeOutDurationInSeconds = 7.0 TimeOutTimer = NodePath("TimeOutTimer") -Image = NodePath("Sprite2D") -CollisionArea = NodePath("CollisionArea") [node name="Sprite2D" type="Sprite2D" parent="." unique_id=31059524] visible = false -modulate = Color(1, 0.20392157, 0.015686275, 1) -texture = ExtResource("1_032qf") +position = Vector2(3.8146973e-06, 3.8146973e-06) +scale = Vector2(1.9687501, 1.9687501) +texture = ExtResource("2_olsqn") [node name="CollisionArea" type="Area2D" parent="." unique_id=116681968] +collision_layer = 2 monitoring = false monitorable = false [node name="CollisionShape2D" type="CollisionShape2D" parent="CollisionArea" unique_id=1558252366] -shape = SubResource("RectangleShape2D_u8d0v") +shape = SubResource("CircleShape2D_uqpd1") [node name="TimeOutTimer" type="Timer" parent="." unique_id=1079777109] one_shot = true diff --git a/Game/Target/towerDefense_tile136.png b/Game/Target/towerDefense_tile136.png new file mode 100644 index 0000000000000000000000000000000000000000..0e2d58baa1404d6172554bc233d984533480480e GIT binary patch literal 1154 zcmV-|1bzF7P)P)t-sYlMbtgotZ|glmO|YlVhvg@|m0hHHd|Y=wtyf{1H{hh~U~Y=nkw zhK6i}hX4QombA8srl^Ocrh}oQeVCesqNH?=kb9Pxd6brPkCBk&}0klZ&XTa*U3Rs;r5nrnV!HA})fuEsmhlzffn{kVcfSa9gii~xSk(9Eup~A$QyS<>n!-u1# zrN_yGpP`qvw~nl?ZitF(g@=cxsHe%xnz_4>t*?@l0+av%01$LiPE(IhAD_=}uU~&J z-w*FUzW}Nkn?>2K~z}7?Uz?~;xH71O*6%1d+)ubw@oj*=?SD)Qb-74Z0rBO zt_;SKESq?fw>_CRF!LSh-YYRy?%YtyE#SWeXqlXG6F^P}U>es2WDCGdxgHl01SF{a z@X~Q=7cmhcz%Z%3!)Yicf(PWOz5dAY6$`-t$rQC;)Er(h5G{a4?I?@(ScoP-b36C& z#0gUakv5rBO$Mm6bK!O$!O4^WNz^Z$cB)-6-CIB|2+)8IC#LR_c_1I$f`a-)Gc`{`2!S7eI((FX$Q#T=&BOfj{o$)8%2dL!BYX?RAs<+JAjIL0YEmSah~2?XOox> z0(7jBfVPE3OpaNWH8m>Ck#Lw+h^*2CYvBjWmA8l$36Q}-2w>c@#(sRCbQ>^kc^cs6 zhy$ptIp#Ixc|J~mv6u#j!T=_IOa5P0ga(S&+bDvB14vsh%De7{kKoHi+N4Nderv& z0OhKn>Bf!2x!KU|)8!|wj=GJ+0`$Fl5%BlZ<>zB%Wi62^xQzX0{d+?9Qd<15oy@9@ zh4e0VJ@C4xXa6;==QCy_7xm7~cI^k3A2;qBO1hb@RPEaD3$!GrnYn#ux&=h(FDpVc UteEzsO#lD@07*qoM6N<$f AddChild(_sceneInstantiator.Instantiate(_projectilePackedScene)); + var projectile = _sceneInstantiator.Instantiate(_projectilePackedScene); + projectile.Rotation = _launcher.Rotation; + AddChild(projectile); + } + + public override void _Input(InputEvent @event) + { + _rotationDirection = 0; + if (@event.IsActionPressed("rotate_clockwise")) _rotationDirection = 1; + + if (@event.IsActionPressed("rotate_counterclockwise")) _rotationDirection = -1; + } + + public override void _PhysicsProcess(double delta) + { + _rotationDirection = 0; + if (Input.IsActionPressed("rotate_clockwise")) _rotationDirection = 1; + + if (Input.IsActionPressed("rotate_counterclockwise")) _rotationDirection = -1; + + _launcher.Rotation += (float)(_rotationSpeed * delta * _rotationDirection); + base._PhysicsProcess(delta); } } \ No newline at end of file diff --git a/Game/Turret/towerDefense_tile181.png b/Game/Turret/towerDefense_tile181.png new file mode 100644 index 0000000000000000000000000000000000000000..cba726c642a5931dfaa3104a8048c558d9e85eb4 GIT binary patch literal 515 zcmV+e0{s1nP)Zx^;|>qr=9Ov9yV#riND|PXGV_3UpFVQ-9x&@2}5KU!MRG?qVMR00Cb~L_t(o z!|m70a>F1Dg<*1Y+!#qF@Bgp`;|mf(&P==LOkvCX-_jhruOA-QfnNuPJDr^SU;$71 z;5^$v>?aK7!AS^C^z&>AIL|_GvNr`x_grvQZwQ$0nc(WaDd2Wr3Qp-80v`8;umS_? zRRPQUC=3jE@Lmy+-%s>l01*h_Esg+yNB{xMUI-9spcIsz2@o{k5Y)a9Vy^<5(CBv| z^*WG+X1@wc-vE+e^ox-D77)Pfqp<@=G`z$Cx@pO5!UxXT9kEb{LBvgQSzP;H;K>!zeiT7U)46z?x zbYXxaE=6A zjct%UpZiGwd+vki#Sh2$$q&b9{qkIIXZh{g{~P}v@C})R+Z9pj5_bRq002ovPDHLk FV1o8a=3@W= literal 0 HcmV?d00001 diff --git a/Game/Turret/towerDefense_tile181.png.import b/Game/Turret/towerDefense_tile181.png.import new file mode 100644 index 0000000..cd567b8 --- /dev/null +++ b/Game/Turret/towerDefense_tile181.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://wq1ylxxdyo3t" +path="res://.godot/imported/towerDefense_tile181.png-175b1fdaaa15393876652158f79f62d1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Game/Turret/towerDefense_tile181.png" +dest_files=["res://.godot/imported/towerDefense_tile181.png-175b1fdaaa15393876652158f79f62d1.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/Turret/towerDefense_tile206.png b/Game/Turret/towerDefense_tile206.png new file mode 100644 index 0000000000000000000000000000000000000000..81801e0564368d31724066015de6d5a0a2fd6443 GIT binary patch literal 921 zcmV;K17`e*P)v<9 zoVh$N<4QY^qo%`vdalLEkC~c=hK7KXm7le^pP!$vIW4``+viL?a&mH$lauJz93=n% z02g#pPE#+BU(Zjkzu)gae;<#3@6SK4-w&Uk0NLoV=l}o#`$2)K^O+$ zC?Y7GBr0M@QF<@ZO9Ck*Y}kNgoY!ys|9`^WDa#>lmdtPg7kRJt?8*C_Ey;Y7)T?_Y z)dB7VULupe50C-Sm39Z7qLeS;i8IjGiy{?)7p_1CXGC;{=Z-)hP!51{;w7XK-@p!q z*+I7((1V%;YUoY704Z#d$`+or3k;8lC~vW$fen0$&W;Qx0z)@_F&4Z-l_EahoE}O9 zg!rq&IZ)R?9pL7?5bXlv@X5r-7kglRW$nsjZDrjac*C}Tn{2aPd*GVwMZg}rb^*L! zCY~E`{>S9}L4aL$90A8Jzy-UEfXhb!Ts#0U$5;d~7l7Xa<{W_6Ecz-l=J0dQ&CYnb z|8ZtEXAR^E@aHu!@1yX+64(s-^@;{6bsrO_cECx{C#uSRHCWVq{ICPmf_Nx_L$xg0 zUO_li)IC(>a5=F9j<6rDrd4$ZMEf|h0}kY1rbW;57DH=l~tyaRdJVznigkCQ}DK00000NkvXXu0mjfb&jQo literal 0 HcmV?d00001 diff --git a/Game/Turret/towerDefense_tile206.png.import b/Game/Turret/towerDefense_tile206.png.import new file mode 100644 index 0000000..3d3a60d --- /dev/null +++ b/Game/Turret/towerDefense_tile206.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ce3yr5qcy6tn8" +path="res://.godot/imported/towerDefense_tile206.png-1691c021ff92a454ed8143a8198835e0.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Game/Turret/towerDefense_tile206.png" +dest_files=["res://.godot/imported/towerDefense_tile206.png-1691c021ff92a454ed8143a8198835e0.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/Turret/turret.tscn b/Game/Turret/turret.tscn new file mode 100644 index 0000000..11abb0e --- /dev/null +++ b/Game/Turret/turret.tscn @@ -0,0 +1,29 @@ +[gd_scene format=3 uid="uid://cgixjjrc2kdui"] + +[ext_resource type="Texture2D" uid="uid://wq1ylxxdyo3t" path="res://Game/Turret/towerDefense_tile181.png" id="1_fa2t6"] +[ext_resource type="Script" uid="uid://ce7gnp1lcrrdv" path="res://Game/Turret/Turret.cs" id="2_tkk1n"] +[ext_resource type="PackedScene" uid="uid://brbufibn7hi3o" path="res://Game/Projectile/projectile.tscn" id="3_eoix6"] +[ext_resource type="Texture2D" uid="uid://ce3yr5qcy6tn8" path="res://Game/Turret/towerDefense_tile206.png" id="4_q6l7p"] + +[sub_resource type="Curve" id="Curve_u8d0v"] +_data = [Vector2(0, 1), 0.0, -1.0, 0, 1, Vector2(1, 0), -1.0, 0.0, 1, 0] +point_count = 2 + +[node name="Turret" type="Sprite2D" unique_id=682995021 node_paths=PackedStringArray("_launcher")] +texture = ExtResource("1_fa2t6") +script = ExtResource("2_tkk1n") +_projectilePackedScene = ExtResource("3_eoix6") +_launcher = NodePath("Launcher") + +[node name="Launcher" type="Sprite2D" parent="." unique_id=1492355681] +texture = ExtResource("4_q6l7p") + +[node name="Line2D" type="Line2D" parent="Launcher" unique_id=777442120] +points = PackedVector2Array(0, 0, 0, -270) +width_curve = SubResource("Curve_u8d0v") +default_color = Color(1, 0.1764706, 0.19215687, 0.38039216) + +[node name="Timer" type="Timer" parent="." unique_id=95651717] +autostart = true + +[connection signal="timeout" from="Timer" to="." method="OnTimerTimeout"] diff --git a/Game/level.tscn b/Game/level.tscn index 7e9f14f..b398458 100644 --- a/Game/level.tscn +++ b/Game/level.tscn @@ -1,12 +1,10 @@ [gd_scene format=3 uid="uid://xfd48ep5qi1k"] [ext_resource type="Script" uid="uid://dk578xnlxjwrr" path="res://Game/Level/LevelServiceSource.cs" id="1_5saw1"] -[ext_resource type="PackedScene" uid="uid://3v8kq1rfwhmr" path="res://Game/target.tscn" id="1_y7rhs"] +[ext_resource type="PackedScene" uid="uid://3v8kq1rfwhmr" path="res://Game/Target/target.tscn" id="1_y7rhs"] [ext_resource type="Script" uid="uid://cxfrtglku2gfa" path="res://Game/Target/TargetSpawner.cs" id="2_5saw1"] [ext_resource type="Script" uid="uid://bgrjeadxhgmvi" path="res://Game/Score/Score.cs" id="3_spj1u"] -[ext_resource type="Texture2D" uid="uid://y1ros3y7hag2" path="res://icon.svg" id="4_esqs7"] -[ext_resource type="Script" uid="uid://ce7gnp1lcrrdv" path="res://Game/Turret/Turret.cs" id="5_himod"] -[ext_resource type="PackedScene" uid="uid://brbufibn7hi3o" path="res://Game/projectile.tscn" id="6_sin03"] +[ext_resource type="PackedScene" uid="uid://cgixjjrc2kdui" path="res://Game/Turret/turret.tscn" id="5_m3hgq"] [sub_resource type="Animation" id="Animation_bbjqm"] length = 0.001 @@ -133,11 +131,7 @@ vertical_alignment = 1 root_node = NodePath("../..") libraries/ = SubResource("AnimationLibrary_rckqj") -[node name="Turret" type="Sprite2D" parent="." unique_id=152356196] -modulate = Color(1.92523e-07, 0.88004553, 0.8802661, 1) +[node name="Turret" parent="." unique_id=682995021 instance=ExtResource("5_m3hgq")] position = Vector2(539, 307) -texture = ExtResource("4_esqs7") -script = ExtResource("5_himod") -_projectilePackedScene = ExtResource("6_sin03") [connection signal="timeout" from="Spawner/Timer" to="Spawner" method="OnTimer"] diff --git a/Game/projectile.tscn b/Game/projectile.tscn deleted file mode 100644 index 127de57..0000000 --- a/Game/projectile.tscn +++ /dev/null @@ -1,18 +0,0 @@ -[gd_scene format=3 uid="uid://brbufibn7hi3o"] - -[ext_resource type="Script" uid="uid://dc5mvle8lc40j" path="res://Game/Projectile.cs" id="1_80yud"] -[ext_resource type="Script" uid="uid://qjonl8stia46" path="res://addons/GodotDI/ServiceSource.cs" id="2_3kmdq"] -[ext_resource type="Texture2D" uid="uid://y1ros3y7hag2" path="res://icon.svg" id="3_1i54g"] - -[node name="Projectile" type="Node2D" unique_id=1686616504] -script = ExtResource("1_80yud") - -[node name="Scope" type="Node" parent="." unique_id=513224818 node_paths=PackedStringArray("InjectedNodes")] -script = ExtResource("2_3kmdq") -InjectedNodes = [NodePath("..")] - -[node name="Sprite2D" type="Sprite2D" parent="." unique_id=1021740171] -modulate = Color(1, 1, 0, 1) -rotation = 0.7853982 -scale = Vector2(0.3, 0.3) -texture = ExtResource("3_1i54g") diff --git a/Interfaces/ICurrentLevel.cs b/Interfaces/ICurrentLevel.cs index 292a516..63ec1a3 100644 --- a/Interfaces/ICurrentLevel.cs +++ b/Interfaces/ICurrentLevel.cs @@ -1,7 +1,9 @@ +using R3; + namespace GodotHostTest.Interfaces; public interface ICurrentLevel { - public int LevelNumber { get; } + public ReadOnlyReactiveProperty LevelNumber { get; } public void NextLevel(); } \ No newline at end of file diff --git a/Interfaces/IScore.cs b/Interfaces/IScore.cs index 377bf84..5465945 100644 --- a/Interfaces/IScore.cs +++ b/Interfaces/IScore.cs @@ -1,3 +1,5 @@ +using R3; + namespace GodotHostTest.Interfaces; /// @@ -8,5 +10,5 @@ public interface IScore /// /// The current score. /// - public int Score { get; } + public Observable Score { get; } } \ No newline at end of file diff --git a/Interfaces/ITarget.cs b/Interfaces/ITarget.cs index 7c94547..abb82de 100644 --- a/Interfaces/ITarget.cs +++ b/Interfaces/ITarget.cs @@ -8,12 +8,13 @@ namespace GodotHostTest.Interfaces; public interface ITarget { /// - /// The target hasn't been hit in the allotted time and has timed out. + /// The target hasn't been hit in the allotted time and has timed out; once this observable emits an event, both + /// it and complete. /// Observable TimedOut { get; } - + /// - /// The target has been hit. + /// The target has been hit; once this observable emits an event, both it and complete. /// Observable Hit { get; } diff --git a/Interfaces/ITargetEventBus.cs b/Interfaces/ITargetEventBus.cs new file mode 100644 index 0000000..f99130d --- /dev/null +++ b/Interfaces/ITargetEventBus.cs @@ -0,0 +1,22 @@ +using R3; + +namespace GodotHostTest.Interfaces; + +public interface ITargetEventBus +{ + /// + /// A target has timed out and disappeared. + /// + Observable TimedOut { get; } + + /// + /// A target has been hit. + /// + Observable Hit { get; } + + /// + /// A new target spawner has been added. + /// + /// + void NewTargetSpawner(ITargetSpawner targetSpawner); +} \ No newline at end of file diff --git a/Interfaces/ITargetEventBus.cs.uid b/Interfaces/ITargetEventBus.cs.uid new file mode 100644 index 0000000..ac7e155 --- /dev/null +++ b/Interfaces/ITargetEventBus.cs.uid @@ -0,0 +1 @@ +uid://bgexc7hcs5r4n diff --git a/addons/AetherBind/SceneInstantiatorExtensions.cs b/addons/AetherBind/SceneInstantiatorExtensions.cs index 4bf4456..166edaf 100644 --- a/addons/AetherBind/SceneInstantiatorExtensions.cs +++ b/addons/AetherBind/SceneInstantiatorExtensions.cs @@ -17,7 +17,7 @@ public static class SceneInstantiatorExtensions /// scene, with the provider as argument. /// /// The created node, with its dependencies satisfied. - private static T Instantiate(this ISceneInstantiator sceneInstantiator, PackedScene packedScene, + public static T Instantiate(this ISceneInstantiator sceneInstantiator, PackedScene packedScene, Action? onScopeCreated = null) where T : Node { return (T)sceneInstantiator.Instantiate(packedScene, onScopeCreated); diff --git a/project.godot b/project.godot index fc970ca..966d0cd 100644 --- a/project.godot +++ b/project.godot @@ -28,6 +28,24 @@ project/assembly_name="godot-host-test" enabled=PackedStringArray("res://addons/AetherBind/plugin.cfg") +[input] + +rotate_clockwise={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +rotate_counterclockwise={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} + +[layer_names] + +2d_physics/layer_1="Projectiles" +2d_physics/layer_2="Targets" + [physics] 3d/physics_engine="Jolt Physics"