Compare commits

...

52 Commits

Author SHA1 Message Date
admin 6cec4b69b7 changing peg disposition so that none = 0 and neutral = -2, will make it easier to sort peg actions later to divide them up by disposition type (will need to delay peg turns by disposition) so that it goes neutral to hostile to friendly. will need to account for this in other methods as well 2026-07-05 03:17:40 -04:00
admin bfcd48e657 think i finally solved movement going into enemy territory 2026-07-05 02:51:09 -04:00
admin dbafefd660 still working out movement 2026-07-04 03:04:56 -04:00
admin 336b72e4cb continuing to switch to MapCell orientation 2026-07-03 02:16:29 -04:00
admin e6355167e3 continuing to set up map and pegs 2026-07-02 22:50:21 -04:00
admin 0231c9d136 minor change for testing, still a bunch to do. someh=thing that popped up, should hostile and friendly pegs go at the same time or staggered 2026-07-02 03:51:22 -04:00
admin cbdca6f3cb implemented more code for adding more pegs, but still a lot of work to do on pathfinding, targeting, map etc. 2026-07-02 03:15:15 -04:00
admin 909f466f92 starting to build out more actions and pegs, first thing to do tho is rework movement / targeting a little bit 2026-07-02 00:20:52 -04:00
admin bbe9eefcfa minor changes, next step is to add 2-3 friendly pegs, 2 neutral pegs, 2 hostile pegs, 2 buildings and all associated actions for these additions 2026-07-01 02:36:31 -04:00
admin 2c289333f0 small change 2026-06-30 18:25:28 -04:00
admin b1625b15a0 implemented visibility, so pegs can only scope out as far as they can see. 2026-06-30 18:24:11 -04:00
admin c8e81e4f48 moved bucket to the playercontroller, changed tweenStages to a list of pegactions, so processtween takes in actions and builds off of that so that movement/actions priority will line up properly. change tweenstages key to be priority:loop. added category to actions to divide into movement vs action 2026-06-30 02:46:00 -04:00
admin 982c3e6786 added friendly and neutral peg, added disposition 2026-06-29 18:11:28 -04:00
admin ebdff1b200 undergoing a shift to change movement into another action that a peg can perform and giving pegs a list of actions order by priority 2026-06-29 02:43:25 -04:00
admin f6c54e0730 some formatting - note, i need to still fix attacks not starting / ending in the right spot, since an attack might be initiated from one cell then called while peg is at another cell 2026-06-26 16:46:16 -04:00
admin 2529d01ff4 cleared up issue with pathing, but still an issue with attacks? 2026-06-26 02:52:08 -04:00
admin 350d2bc4d1 adding in some example pegs and their actions. organizing folders, still working on pathing for some reason it won't move sometimes, and causes the looping to break 2026-06-26 02:36:01 -04:00
admin fc32baa071 switching up some more clicking 2026-06-25 18:11:43 -04:00
admin 37da9a4e84 altering enemies into peg to open up for the future with hostile and friendly pegs. made some changes to the pathfinding. starting to add a mouse handler that will more easily handle single and double clicks, and holds. Enemy controller becomes peg controller and will handle all peg interactions 2026-06-25 16:31:13 -04:00
admin e3cb4ef7ac fixed earlier problem 2026-06-25 03:29:46 -04:00
admin 61539e9250 still updating enemy movement and pathing and tweening 2026-06-25 03:14:21 -04:00
admin 98ca292901 still attempting to allow enemies to handle their own animations. still a matter of improving performance and there's some issue when enemies reach rank 0? 2026-06-24 03:00:23 -04:00
admin 8ae8ec3e58 trying out enemy animation again 2026-06-24 00:13:05 -04:00
admin 6af5f248ed finishing revert to older version 2026-06-24 00:09:17 -04:00
admin 95cdd81a3f Merge branch 'main' of https://git.cojoedmo.com/admin/peggle-roguelike 2026-06-24 00:08:32 -04:00
admin b1bae1f973 reverting to prior change 2026-06-23 23:55:12 -04:00
admin f022333c9b merge 2026-06-23 23:41:20 -04:00
admin e244572402 merge 2026-06-23 23:40:19 -04:00
admin 4a9143780f reverting to prior change 2026-06-23 23:28:57 -04:00
admin 556f97184d starting to implement the enemy performing tweens 2026-06-23 17:54:37 -04:00
admin 2cf3428b8c Finishing up basic pathfinding? later down the line will want to implement warping 2026-06-23 03:14:49 -04:00
admin 1903e1a1aa starting to work on enemy attacks and player health 2026-06-12 02:03:17 -04:00
admin 9f75ec525c Gave Get best path to enemy, enemy controller hands it a map 2026-06-12 01:02:00 -04:00
admin a96d935ad4 still some bug fixes to work out but not sure how to duplicate them? starting to work on enemy attacks 2026-06-10 01:57:06 -04:00
admin 86113141bf trying to prevent error 2026-06-09 20:02:48 -04:00
admin e243d45d27 making a slight edit to make note of what is going on bc i finally figured it out. When a new enemy is spawned in, its initial position is set as 0,0 which gets turned off then. going to try to initialize as -1,-1 and see if that helps 2026-06-09 19:54:31 -04:00
admin d2993b17a4 debugging 2026-06-09 19:43:36 -04:00
admin 9a0a33b82c cleanup 2026-06-09 19:12:40 -04:00
admin 4722cf882b mostly fixed movement but there's still a problem with enemies in the top left cell (0,0) being set to not solid 2026-06-09 18:11:06 -04:00
admin e209861cb3 a little bit of cleanup, still some edge cases but took care of the big stuff 2026-06-09 03:29:59 -04:00
admin 7a10f4a9fc still working on movement, for some reason some cells do not get set as solid that's why multiple can go on a cell 2026-06-09 03:15:35 -04:00
admin 813ca5f633 reworking pathfinding to update with each step, removing the need to worry about obstacles, but still needs work 2026-06-08 04:28:30 -04:00
admin 648a00ccf1 still working on some pathfinding, it is seizing up when trying to find a new goal 2026-06-08 03:38:33 -04:00
admin 3c9a51bd6a working some more on enemy movement, they stilldon't always want to move to the sides when they reach the front so still some more work to do. also updated the aiming a bit to clamp the arc for firing and drawing, rewrote the draw arc function 2026-06-07 21:14:46 -04:00
admin 12b565715a updating movement and added a bucket, still some clean up to do on movement. TODO: if enemy becomes stuck, reclculate path. 2026-06-05 03:48:07 -04:00
admin 0cbc6cbfc7 changing map size 2026-06-04 17:29:47 -04:00
admin 1e928bacb0 changed how the wall works 2026-06-04 03:50:04 -04:00
admin cfc13d9350 working on aiming 2026-06-04 03:42:07 -04:00
admin c97b0e5cc2 finished reowrking grid maps, polished astar pathfinding, started work on aiming functions --todo: change launch speed to constant, change aim function to take into account the angle it would need to launch at to hit mouse position like in peggle, add raycasting 2026-06-03 02:44:13 -04:00
admin 7b5cd9d5f6 starting to rework grid maps to be tile map layers 2026-06-02 18:43:19 -04:00
admin 03004dbcd3 Merge branch 'main' of https://git.cojoedmo.com/admin/peggle-roguelike 2026-06-02 01:30:57 -04:00
admin bc65b5170e reverting to previous version 2026-06-02 01:30:51 -04:00
98 changed files with 2299 additions and 526 deletions
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://m4wfj36twmqy"
path="res://.godot/imported/attack.png-c625624f48e39eb3c9d0bdfb20bcabb8.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Art/attack.png"
dest_files=["res://.godot/imported/attack.png-c625624f48e39eb3c9d0bdfb20bcabb8.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
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://m1mlr1s38on8"
path="res://.godot/imported/bucket.png-4311011eff24918ebca7b2ac543f4bea.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Art/bucket.png"
dest_files=["res://.godot/imported/bucket.png-4311011eff24918ebca7b2ac543f4bea.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
Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dpwvh7kwkyfqi"
path="res://.godot/imported/bucket_bottom.png-5ddd021ef89e7830e28acc827066d67c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Art/bucket_bottom.png"
dest_files=["res://.godot/imported/bucket_bottom.png-5ddd021ef89e7830e28acc827066d67c.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
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://baukn3uw3c3c3"
path="res://.godot/imported/bucket_top.png-99768a6b7a98df6d51966e9a1d3b56d2.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Art/bucket_top.png"
dest_files=["res://.godot/imported/bucket_top.png-99768a6b7a98df6d51966e9a1d3b56d2.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
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c5jj7yhlnodxt"
path="res://.godot/imported/star.png-7953868fbd7392e6e06ff69587708912.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Art/star.png"
dest_files=["res://.godot/imported/star.png-7953868fbd7392e6e06ff69587708912.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
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cf554xlykq1o4"
path="res://.godot/imported/tile_set.png-fd4f1e60b744017efffa1399a3d8e420.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Art/tile_set.png"
dest_files=["res://.godot/imported/tile_set.png-fd4f1e60b744017efffa1399a3d8e420.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
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bekb6ulekgb0b"
path="res://.godot/imported/tile_set_hex.png-4e21f3d721b662d063b200f1e5a89a7d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Art/tile_set_hex.png"
dest_files=["res://.godot/imported/tile_set_hex.png-4e21f3d721b662d063b200f1e5a89a7d.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
-42
View File
@@ -1,42 +0,0 @@
using Godot;
public partial class Attack : RigidBody2D
{
[Signal]
public delegate void HitEventHandler(Node NODE);
public bool _hovered = false;
public int _damage = 1;
public Vector2 _speed;
public Commander _commanderOwner;
public override void _PhysicsProcess(double delta)
{
base._PhysicsProcess(delta);
if (_speed != Vector2.Zero){
ApplyCentralForce(_speed);
_speed = Vector2.Zero;
}
}
public void Shoot(Vector2 FORCE){
_speed = FORCE;
GravityScale = 1;
}
public void TakeAction(Node BODY)
{
EmitSignal(SignalName.Hit, BODY);
if (BODY is Enemy enemy)
{
enemy.TakeDamage(_damage, _commanderOwner);
}
}
public void OnMouseEntered(){
_hovered = true;
}
public void OnMouseExited(){
_hovered = true;
}
}
+63
View File
@@ -0,0 +1,63 @@
using System.Collections.Generic;
using Godot;
public partial class Ball : RigidBody2D
{
[Signal]
public delegate void HitEventHandler(Node NODE);
[Signal]
public delegate void BucketEnteredEventHandler();
public bool _hovered = false;
public int _healthChange = -1, _hits = 0;
public Vector2 _speed;
public Path2D _predictionPath;
public Commander _commanderOwner;
public override void _Ready()
{
base._Ready();
_predictionPath = GetNode<Path2D>("PredictedPath");
}
public void Act(Node BODY)
{
EmitSignal(SignalName.Hit, BODY);
if (BODY is Peg peg)
{
peg.ChangeHealth(_healthChange);
_hits++;
}
}
public override void _PhysicsProcess(double delta)
{
base._PhysicsProcess(delta);
if (_speed != Vector2.Zero){
LinearVelocity = _speed;
_speed = Vector2.Zero;
}
}
public void DrawPath(List<Vector2> POINTS)
{
_predictionPath.Curve.ClearPoints();
for (int i = 0; i < POINTS.Count; i++)
{
_predictionPath.Curve.AddPoint(POINTS[i]);
}
}
public void EnteredBucket()
{
EmitSignal(SignalName.BucketEntered);
}
public void Shoot(Vector2 FORCE){
_speed = FORCE;
GravityScale = 1;
}
}
View File
+36
View File
@@ -0,0 +1,36 @@
using Godot;
using System;
public partial class Bucket : Node2D
{
[Signal]
public delegate void BallEnteredEventHandler(Ball BALL);
public int _minX = -500, _maxX = 500, _movementSign = 1, _movementSpeed = 3;
public Vector2 _startPoisition;
public override void _Ready()
{
base._Ready();
_startPoisition = GlobalPosition;
}
public void Move()
{
GlobalPosition += new Vector2(_movementSign * _movementSpeed, 0);
Vector2 offset = _startPoisition - GlobalPosition;
if (offset.X >= _maxX || offset.X <= _minX)
{
_movementSign *= -1;
}
}
public void OnBodyEntered(Node2D BODY)
{
if (BODY is Ball ball)
{
EmitSignal(SignalName.BallEntered, ball);
ball.EnteredBucket();
}
}
}
+1
View File
@@ -0,0 +1 @@
uid://cn8hskwnfxc8f
+28 -28
View File
@@ -3,57 +3,57 @@ using System;
public partial class Commander : Sprite2D public partial class Commander : Sprite2D
{ {
[Signal]
public delegate void DeathEventHandler(Commander THIS);
[Signal] [Signal]
public delegate void ActionsUpEventHandler(); public delegate void ActionsUpEventHandler();
public int _health = 10, _actionsMax = 1, _actions; public int _actionsMax = 1, _actions;
public PackedScene _attackScene = GD.Load<PackedScene>("res://Attack.tscn"); public PackedScene _ballScene = GD.Load<PackedScene>("res://Ball.tscn");
public Attack _attack; public Ball _ball;
public PlayerController _playerController; public PlayerController _playerController;
public override void _Process(double delta) public override void _Process(double delta)
{ {
base._Process(delta); base._Process(delta);
if (_attack != null) if (_ball != null)
{ {
if (_attack.Position.Y > GetViewportRect().Size.Y + 50) if (_ball.Position.Y > GetViewportRect().Size.Y + 50)
{
UnloadBall();
if (_actions <= 0)
{ {
_attack.QueueFree();
_attack = null;
EmitSignal(SignalName.ActionsUp); EmitSignal(SignalName.ActionsUp);
} }
} }
} }
}
public void LoadAttack() public void BallEnteredBucket()
{ {
if (_attack == null) _actions += (_actions + 1) > _actionsMax ? 0 : 1;
UnloadBall();
}
public void LoadBall(Vector2 OFFSET)
{ {
_attack = _attackScene.Instantiate<Attack>(); if (_ball == null)
_attack._commanderOwner = this; {
_attack.GravityScale = 0; _ball = _ballScene.Instantiate<Ball>();
AddChild(_attack); _ball.Position = OFFSET;
_ball._commanderOwner = this;
_ball.GravityScale = 0;
_ball.BucketEntered += BallEnteredBucket;
AddChild(_ball);
} }
} }
public void TakeDamage(int DAMAGE, Enemy ATTACKER) public void ShootCurrentBall(Vector2 FORCE){
{
_health -= DAMAGE;
if (_health <= 0)
{
EmitSignal(SignalName.Death, this);
}
}
public void ShootCurrentAttack(Vector2 FORCE){ _ball.Shoot(FORCE);
_attack.Shoot(FORCE);
_actions--; _actions--;
} }
public void UnloadAttack() public void UnloadBall()
{ {
_attack.QueueFree(); _ball.QueueFree();
_ball = null;
} }
} }
-115
View File
@@ -1,115 +0,0 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
public partial class Enemy : StaticBody2D
{
[Signal]
public delegate void DeathEventHandler(Enemy THIS);
public int _damage = 1, _health = 2, _speed;
public Vector2I _range = Vector2I.Up;
public float _movement = 0;
public GridMarker _gridMarker;
public Commander _commander;
public override void _Ready()
{
base._Ready();
}
public override void _PhysicsProcess(double delta)
{
base._PhysicsProcess(delta);
}
public void Attack(Commander COMMANDER)
{
COMMANDER.TakeDamage(_damage, this);
}
public void CounterAttack(Commander COMMANDER)
{
}
public List<GridMarker> Pathfinding(List<GridMarker> DESTINATIONS, bool INCLUDE_SELF = false)
{
PriorityQueue<GridMarker, float> queue = new();
queue.Enqueue(_gridMarker, 0f);
Dictionary<GridMarker, GridMarker> cameFrom = new(), best = new();
Dictionary<GridMarker, float> costSoFar = new();
cameFrom[_gridMarker] = null;
costSoFar[_gridMarker] = 0f;
GridMarker current;
float newCost, priority;
for (int i = 0; i < DESTINATIONS.Count; i++)
{
GridMarker destination = DESTINATIONS[i];
while (queue.Count > 0)
{
current = queue.Dequeue();
if (current == destination)
{
best = cameFrom;
GD.Print("breaking at line 56");
continue;
}
List<GridMarker> neighbors = current.GetMarkersInRange(1.5f);
for (int j = 0; j < neighbors.Count; j++)
{
GridMarker next = neighbors[j];
if (next._occupant != null)
{
continue;
}
newCost = costSoFar[current] + 1;
if (best.Count > 0 && newCost >= best.Count)
{
GD.Print("breaking at line 70");
break;
}
if (!costSoFar.TryGetValue(next, out float value) || newCost < value)
{
costSoFar[next] = newCost;
priority = newCost;
queue.Enqueue(next, priority);
cameFrom[next] = current;
}
}
}
}
GD.Print(best.Last().Value._address);
List<GridMarker> path = new();
GridMarker pathMarker = best.Last().Value;
if (best.TryGetValue(pathMarker, out GridMarker marker))
{
while (pathMarker != null)
{
path.Add(pathMarker);
pathMarker = marker;
}
path.Reverse();
if (!INCLUDE_SELF)
{
path.Remove(_gridMarker);
}
}
return path;
}
public void TakeDamage(int DAMAGE, Commander ATTACKER)
{
GD.Print(_health, _health - DAMAGE);
_health -= DAMAGE;
CounterAttack(ATTACKER);
if (_health <= 0)
{
EmitSignal(SignalName.Death, this);
}
}
}
-91
View File
@@ -1,91 +0,0 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
public partial class EnemyController : TurnController
{
public PackedScene _enemyScene = GD.Load<PackedScene>("res://Enemy.tscn");
public List<Enemy> _enemies = new();
public PlayerController _playerController;
public void AddEnemies(int ENEMY_COUNT = 1)
{
for (int i = 0; i < ENEMY_COUNT; i++)
{
Enemy newEnemy = _enemyScene.Instantiate<Enemy>();
newEnemy.Death += RemoveEnemy;
List<GridMarker> lastRow = _grid._gridMarkers.Last();
List<GridMarker> unoccupiedMarkers = [.. lastRow.Where(m => m._occupant == null).Cast<GridMarker>()];
GridMarker randomMarker = unoccupiedMarkers[Globals._rng.Next(unoccupiedMarkers.Count)];
newEnemy._speed = Globals._rng.Next(2,4+1);
newEnemy.Modulate = new Color(newEnemy._speed == 2 ? "#FF0000" : newEnemy._speed == 3 ? "#00FF00" : "#0000FF");
WarpEnemy(newEnemy, randomMarker);
_enemies.Add(newEnemy);
AddChild(newEnemy);
}
}
public void Initiate()
{
AddEnemies(3);
}
// public void MoveEnemy(Enemy ENEMY)
// {
// ENEMY._gridMarker = _grid.GetMarkerFromOffset(ENEMY._gridMarker, ENEMY._speed);
// Tween tween = CreateTween();
// tween.TweenProperty(ENEMY, "global_position", ENEMY._gridMarker.GlobalPosition, 1.0f);
// }
public void MoveEnemies(List<Enemy> ENEMIES = null)
{
ENEMIES ??= _enemies;
ENEMIES = [.. ENEMIES.OrderByDescending(e => e._gridMarker._address.Y).ThenByDescending(e => e._gridMarker._address.X)];
Tween tween = CreateTween();
tween.SetParallel();
Dictionary<Enemy, List<GridMarker>> enemyPaths = new();
for (int i = 0; i < ENEMIES.Count; i++)
{
enemyPaths[ENEMIES[i]] = ENEMIES[i].Pathfinding(_grid._gridMarkers.ToList());
}
int maxSteps = enemyPaths.Select(p => p.Value.Count).Max();
GD.Print(enemyPaths.Count, " ", maxSteps);
for (int i = 0; i < maxSteps; i++)
{
Dictionary<Enemy, List<GridMarker>> qualifyingPaths = (Dictionary<Enemy, List<GridMarker>>)enemyPaths.Where(p => p.Value.Count <= maxSteps);
for (int j = 0; j < qualifyingPaths.Count; j++)
{
Enemy enemy = qualifyingPaths.ElementAt(j).Key;
GridMarker marker = qualifyingPaths.ElementAt(j).Value.ElementAt(i);
if (j == 0)
{
tween.Chain();
}
tween.TweenProperty(enemy, "global_position", enemy._gridMarker.GlobalPosition, 0.4f);
}
}
}
public void RemoveEnemy(Enemy ENEMY_TO_REMOVE)
{
_enemies.Remove(ENEMY_TO_REMOVE);
ENEMY_TO_REMOVE.QueueFree();
}
public override void StartTurn()
{
AddEnemies();
MoveEnemies();
}
public void WarpEnemy(Enemy ENEMY, GridMarker DESTINATION_MARKER)
{
ENEMY._gridMarker = DESTINATION_MARKER;
ENEMY.GlobalPosition = DESTINATION_MARKER.GlobalPosition;
}
}
+10 -1
View File
@@ -1,7 +1,16 @@
using Godot; using Godot;
using System; using System;
using System.Collections.Generic;
public partial class Globals : Node public partial class Globals : Node2D
{ {
public static Random _rng = new(); public static Random _rng = new();
public static float _gravity = (float)ProjectSettings.GetSetting("physics/2d/default_gravity"), _drag = (float)ProjectSettings.GetSetting("physics/2d/default_linear_damp");
public static MouseHandler _mouse;
public static T GetRandomFromList<T>(List<T> TYPED_LIST)
{
return TYPED_LIST[_rng.Next(0,TYPED_LIST.Count)];
}
} }
-79
View File
@@ -1,79 +0,0 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
public partial class GridMap2D : Node2D
{
public int _cellSize = 16;
public Vector2 _sizeInPixels, _sizeInCells;
public Area2D _playArea;
public GridMarker _gridMarker;
public List<StaticBody2D> _leftEdges = new(), _rightEdges = new();
public List<List<GridMarker>> _gridMarkers = new();
public override void _Ready()
{
base._Ready();
_playArea = GetNode<Area2D>("PlayArea");
StaticBody2D firstOnLeft = GetNode<StaticBody2D>("LeftEdge1");
StaticBody2D firstOnRight = GetNode<StaticBody2D>("RightEdge1");
_leftEdges.Add(firstOnLeft);
_rightEdges.Add(firstOnRight);
CollisionShape2D firstOnLeftBounds = firstOnLeft.GetNode<CollisionShape2D>("Bounds");
CollisionShape2D firstOnRightBounds = firstOnRight.GetNode<CollisionShape2D>("Bounds");
_gridMarker = GetNode<GridMarker>("GridMarker");
CollisionShape2D playAreaBounds = _playArea.GetNode<CollisionShape2D>("Bounds");
_sizeInPixels = new Vector2((int)playAreaBounds.Shape.GetRect().Size.X, (int)playAreaBounds.Shape.GetRect().Size.Y);
_sizeInCells = new Vector2(_sizeInPixels.X / _cellSize, _sizeInPixels.Y / _cellSize);
for (int i = 0; i < _sizeInCells.Y; i++)
{
_gridMarkers.Add([]);
for (int j = 0; j < _sizeInCells.X; j++)
{
GridMarker newGridMarker = (GridMarker)_gridMarker.Duplicate();
newGridMarker._address = new Vector2I(j, i);
newGridMarker.Position = new Vector2(_playArea.Position.X - playAreaBounds.Shape.GetRect().Size.X / 2 + (j+.5f)*_cellSize, _playArea.Position.Y - playAreaBounds.Shape.GetRect().Size.Y / 2 + (i+.5f)*_cellSize);
_gridMarkers[i].Add(newGridMarker);
AddChild(newGridMarker);
}
}
int leftEdgeSectionSizeY = (int)firstOnLeftBounds.Shape.GetRect().Size.Y, rightEdgeSectionSizeY = (int)firstOnRightBounds.Shape.GetRect().Size.Y;
int leftEdgeSectionsCount = (int)_sizeInPixels.Y / leftEdgeSectionSizeY, rightEdgeSectionsCount = (int)_sizeInPixels.Y / rightEdgeSectionSizeY;
for (int i = 1; i < leftEdgeSectionsCount; i++)
{
StaticBody2D newLeftSection = (StaticBody2D)firstOnLeft.Duplicate();
newLeftSection.Position += new Vector2(0, leftEdgeSectionSizeY * i);
_leftEdges.Add(newLeftSection);
AddChild(newLeftSection);
}
for (int i = 1; i < rightEdgeSectionsCount; i++)
{
StaticBody2D newRightSection = (StaticBody2D)firstOnRight.Duplicate();
newRightSection.Position += new Vector2(0, rightEdgeSectionSizeY * i);
_rightEdges.Add(newRightSection);
AddChild(newRightSection);
}
_gridMarker.QueueFree();
}
public GridMarker GetMarkerByAddress(Vector2I COORDINATES)
{
return _gridMarkers[COORDINATES.Y][COORDINATES.X];
}
public GridMarker GetMarkerFromOffset(GridMarker GRID_MARKER, Vector2I STEP)
{
return _gridMarkers[GRID_MARKER._address.Y + STEP.Y][GRID_MARKER._address.X + STEP.X];
}
public List<GridMarker> GetMarkerInRange(GridMarker GRID_MARKER, int RANGE)
{
return [.. _gridMarkers.SelectMany(m => m).Where(m => (GRID_MARKER._address - m._address).Length() <= RANGE).Cast<GridMarker>()];
}
}
-25
View File
@@ -1,25 +0,0 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
public partial class GridMarker : Marker2D
{
public Vector2I _address;
public Node _occupant;
public List<GridMarker> _gridMarkers;
public override void _Ready()
{
base._Ready();
}
public List<GridMarker> GetMarkersInRange(float RANGE = 1.0f){
if (_gridMarkers == null || _gridMarkers.Count == 0)
{
_gridMarkers = [.. GetTree().GetNodesInGroup("GridMarkers").Cast<GridMarker>()];
}
return [.. _gridMarkers.Where(m => m._address.Length() <= RANGE).Cast<GridMarker>()];
}
}
-1
View File
@@ -1 +0,0 @@
uid://cob0pwghnubxa
+52
View File
@@ -0,0 +1,52 @@
using Godot;
using System;
public partial class HoverableNode : Node2D
{
[Signal]
public delegate void HoverEventHandler(HoverableNode THIS, bool IS_HOVERED);
[Signal]
public delegate void ClickEventHandler(HoverableNode THIS, int CLICK_TYPE);
public bool _hovered;
public Area2D _bounds;
public override void _Ready()
{
base._Ready();
_bounds = GetNode<Area2D>("HoverBounds");
_bounds.MouseEntered += OnMouseEntered;
_bounds.MouseExited += OnMouseExited;
}
public override void _Process(double delta)
{
base._Process(delta);
if (_hovered)
{
if (Input.IsActionJustPressed("leftClick"))
{
EmitSignal(SignalName.Click, this, 0);
}
if (Input.IsActionJustPressed("rightClick"))
{
EmitSignal(SignalName.Click, this, 2);
}
if (Input.IsActionJustPressed("middleClick"))
{
EmitSignal(SignalName.Click, this, 1);
}
}
}
public virtual void OnMouseEntered()
{
_hovered = true;
EmitSignal(SignalName.Hover, this,_hovered);
}
public virtual void OnMouseExited()
{
_hovered = false;
EmitSignal(SignalName.Hover, this, _hovered);
}
}
+1
View File
@@ -0,0 +1 @@
uid://dqvysa2n208d3
+27 -20
View File
@@ -5,28 +5,32 @@ using System.Linq;
public partial class Main : Node public partial class Main : Node
{ {
public GridMap2D _grid; public PlayArea _playArea;
public PlayerController _playerController; public PlayerController _playerController;
public EnemyController _enemyController; public PegController _pegController;
public TurnController _turnController; public TurnController _turnController;
public Random _rng = new(); public Random _rng = new();
public override void _Ready() public override void _Ready()
{ {
base._Ready(); base._Ready();
_grid = GetNode<GridMap2D>("GridMap2D"); Globals._mouse = GetNode<MouseHandler>("MouseHandler");
_playArea = GetNode<PlayArea>("PlayArea");
_playerController = GetNode<PlayerController>("PlayerController"); _playerController = GetNode<PlayerController>("PlayerController");
_enemyController = GetNode<EnemyController>("EnemyController"); _pegController = GetNode<PegController>("PegController");
_playerController._enemyController = _enemyController; _playerController._pegController = _pegController;
_enemyController._playerController = _playerController; _pegController._playerController = _playerController;
_playerController._grid = _grid; _playerController._playArea = _playArea;
_enemyController._grid = _grid; _pegController._playArea = _playArea;
_playerController._map = _playArea._map;
_pegController._map = _playArea._map;
_playerController.TurnDone += ChangeTurn; _playerController.TurnDone += ChangeTurn;
_enemyController.TurnDone += ChangeTurn; _playerController.Death += EndGame;
_pegController.TurnDone += ChangeTurn;
_enemyController.Initiate(); _pegController.Initiate();
_playerController.SetUpTowers(); _playerController.SetUpTowers();
ChangeTurn(); ChangeTurn();
} }
@@ -36,23 +40,26 @@ public partial class Main : Node
base._Process(delta); base._Process(delta);
if (Input.IsActionJustPressed("escape")) if (Input.IsActionJustPressed("escape"))
{ {
GetTree().Quit(); EndGame(_playerController);
}
if (Input.IsActionJustPressed("changeTurn"))
{
if(_turnController == _playerController)
{
_playerController.EndTurn();
}
} }
} }
public void ChangeTurn() public void ChangeTurn()
{ {
_turnController = _turnController == _playerController ? _pegController : _playerController;
_turnController.StartTurn();
}
if (_turnController != _playerController) public void EndGame(PlayerController PLAYER)
{ {
_turnController = _playerController; GetTree().Quit();
_playerController.StartTurn();
}
else
{
_turnController = _enemyController;
_enemyController.StartTurn();
}
} }
} }
+214
View File
@@ -0,0 +1,214 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
public partial class Map : TileMapLayer
{
public PackedScene _mapCellScene = GD.Load<PackedScene>("res://map_cell.tscn");
public int _minX, _maxX, _minY, _maxY, _mainSource = 0;
public string _isSolidString = "is_solid", _dispositionString = "disposition";
public Vector2 _cellSize, _sizeInPixels, _sizeInCells;
public AStarGrid2D _astar = new();
public Dictionary<Vector2I, MapCell> _cells = new(), _leftmostColumn = new(), _rightmostColumn = new(), _topRow = new(), _bottomRow = new();
public int _firstOpenRow
{
get
{
for (int i = 0; i < _maxY; i++)
{
if (!IsRowFull(i))
{
return i;
}
}
return -1;
}
}
public int _lastOpenRow
{
get
{
for (int i = _maxY; i > _minY; i--)
{
if (!IsRowFull(i))
{
return i;
}
}
return -1;
}
}
public int _firstOpenColumn
{
get
{
for (int i = 0; i < _maxX; i++)
{
if (!IsColumnnFull(i))
{
return i;
}
}
return -1;
}
}
public int _lastOpenColumn
{
get
{
for (int i = _maxX; i > _minX; i--)
{
if (!IsColumnnFull(i))
{
return i;
}
}
return -1;
}
}
public override void _Ready()
{
base._Ready();
// GD.Print(GlobalPosition);
List<Vector2I> usedCells = [.. GetUsedCells()];
_cellSize = TileSet.TileSize;
for (int i = 0; i < usedCells.Count; i++)
{
MapCell newMapCell = _mapCellScene.Instantiate<MapCell>();
Vector2I usedCell = usedCells[i];
newMapCell._address = usedCell;
newMapCell.GlobalPosition = newMapCell._address * _cellSize + _cellSize / 2;
// GD.Print(GlobalPosition, newMapCell.GlobalPosition);
newMapCell._occupant = null;
_cells[usedCell] = newMapCell;
AddChild(newMapCell);
}
_minX = _cells.Min(c => c.Value._address.X);
_maxX = _cells.Max(c => c.Value._address.X);
_minY = _cells.Min(c => c.Value._address.Y);
_maxY = _cells.Max(c => c.Value._address.Y);
_leftmostColumn = _cells.Where(c => c.Value._address.X == _minX).ToDictionary();
_rightmostColumn = _cells.Where(c => c.Value._address.X == _maxX).ToDictionary();
_topRow = _cells.Where(c => c.Value._address.Y == _minY).ToDictionary();
_bottomRow = _cells.Where(c => c.Value._address.Y == _maxY).ToDictionary();
_sizeInCells = new Vector2(_topRow.Count, _leftmostColumn.Count);
_sizeInPixels = _sizeInCells * _cellSize;
SetupAstar();
}
public Vector2I GetAddressFromPosition(Vector2 POSITION)
{
if (POSITION.X < GlobalPosition.X || POSITION.Y < GlobalPosition.Y)
{
return new Vector2I(-1,-1);
}
else if (POSITION.X > (GlobalPosition + (new Vector2(_maxX, _maxY) * _cellSize)).X || POSITION.Y > (GlobalPosition + (new Vector2(_maxX, _maxY) * _cellSize)).Y)
{
return new Vector2I(-1,-1);
}
return new Vector2I((int)Math.Floor(POSITION.X / _cellSize.X), (int)Math.Floor(POSITION.Y / _cellSize.Y));
}
public int GetCellDisposition(Vector2I ADDRESS)
{
return (int)GetCellTileData(ADDRESS).GetCustomData(_dispositionString);
}
public MapCellOccupant GetOccupant(Vector2I CELL_TO_CHECK)
{
return _cells[CELL_TO_CHECK]._occupant;
}
public bool HasOccupant(Vector2I CELL_TO_CHECK)
{
return GetOccupant(CELL_TO_CHECK) != null;
}
public bool IsCellSolid(Vector2I CELL_TO_CHECK)
{
bool hasOccupant = HasOccupant(CELL_TO_CHECK);
bool isSolid = (bool)GetCellTileData(CELL_TO_CHECK).GetCustomData(_isSolidString);
return hasOccupant || isSolid;
}
public bool IsColumnnFull(int COLUMN_TO_CHECK)
{
List<Vector2I> rowCells = [.. _cells.Where(c => c.Value._address.X == COLUMN_TO_CHECK).ToDictionary().Keys];
return rowCells.All(_astar.IsPointSolid);
}
public bool IsRowFull(int ROW_TO_CHECK)
{
List<Vector2I> rowCells = [.. _cells.Where(c => c.Value._address.Y == ROW_TO_CHECK).ToDictionary().Keys];
return rowCells.All(_astar.IsPointSolid);
}
public void SetCellPeg(MapCell CELL, Peg PEG)
{
if (PEG != null)
{
if (PEG._cell != null)
{
PEG._cell._occupant = null;
SetCellSolid(_cells[PEG._address]);
}
PEG._cell = CELL;
PEG._address = CELL._address;
}
CELL._occupant = PEG;
SetCellSolid(CELL);
}
public void SetCellSolid(MapCell CELL)
{
_astar.SetPointSolid(CELL._address, IsCellSolid(CELL._address));
// _astar.SetPointWeightScale(ADDRESS, IsCellSolid(ADDRESS) ? 1000 : 1);
}
public void SetupAstar()
{
_astar.Region = new Rect2I(_minX, _minY, _topRow.Count, _leftmostColumn.Count);
_astar.CellSize = _cellSize;
_astar.DefaultComputeHeuristic = AStarGrid2D.Heuristic.Manhattan;
_astar.DiagonalMode = AStarGrid2D.DiagonalModeEnum.Never;
_astar.Update();
for (int i = 0; i < _cells.Count; i++)
{
_astar.SetPointWeightScale(_cells.ElementAt(i).Value._address, Math.Abs(_cells.ElementAt(i).Value._address.Y * 2));
}
EvaluateSolidCells();
}
public List<Vector2I> GetPath(Vector2I FROM, Vector2I TO, bool INCLUDE_FROM = false, bool PARTIAL = false)
{
_astar.SetPointSolid(FROM, false);
List<Vector2I> pathTaken = [.. _astar.GetIdPath(FROM, TO, PARTIAL)];
_astar.SetPointSolid(FROM, true);
if (!INCLUDE_FROM)
{
pathTaken.Remove(FROM);
}
return pathTaken;
}
public void EvaluateSolidCells()
{
for (int i = 0; i < _cells.Count; i++)
{
SetCellSolid(_cells.ElementAt(i).Value);
}
}
}
+1
View File
@@ -0,0 +1 @@
uid://d2ri1sa0jwtqm
+38
View File
@@ -0,0 +1,38 @@
[gd_scene format=3 uid="uid://dqknim3lldrmv"]
[ext_resource type="Texture2D" uid="uid://cf554xlykq1o4" path="res://Art/tile_set.png" id="1_gfjgm"]
[ext_resource type="Script" uid="uid://d2ri1sa0jwtqm" path="res://Map.cs" id="2_3vi7k"]
[sub_resource type="TileMapPattern" id="TileMapPattern_fjt81"]
tile_data = PackedInt32Array(0, 1, 0, 65536, 1, 1, 1, 1, 1, 65537, 1, 0)
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_trj13"]
texture = ExtResource("1_gfjgm")
texture_region_size = Vector2i(40, 40)
0:0/0 = 0
1:0/0 = 0
1:0/0/custom_data_1 = -1
2:0/0 = 0
2:0/0/custom_data_1 = 1
3:0/0 = 0
3:0/0/custom_data_0 = true
4:0/0 = 0
0:1/0 = 0
1:1/0 = 0
2:1/0 = 0
2:1/0/custom_data_0 = true
3:1/0 = 0
4:1/0 = 0
[sub_resource type="TileSet" id="TileSet_ah0i1"]
tile_size = Vector2i(40, 40)
custom_data_layer_0/name = "is_solid"
custom_data_layer_0/type = 1
custom_data_layer_1/name = "disposition"
custom_data_layer_1/type = 2
sources/1 = SubResource("TileSetAtlasSource_trj13")
pattern_0 = SubResource("TileMapPattern_fjt81")
[node name="Map" type="TileMapLayer" unique_id=1033871459]
tile_set = SubResource("TileSet_ah0i1")
script = ExtResource("2_3vi7k")
+15
View File
@@ -0,0 +1,15 @@
using Godot;
using System;
public partial class MapCell : Node2D
{
public Vector2I _address;
public MapCellOccupant _occupant;
public override void _Ready()
{
base._Ready();
}
}
+1
View File
@@ -0,0 +1 @@
uid://b8fx1wwyj30bg
+16
View File
@@ -0,0 +1,16 @@
using Godot;
using System;
public partial class MapCellOccupant : HoverableNode
{
public Vector2I _address;
public MapCell _cell;
public Disposition _disposition = Disposition.NONE;
public enum Disposition
{
NONE = 0,
FRIENDLY = 1,
HOSTILE = -1,
NEUTRAL = -2
}
}
+1
View File
@@ -0,0 +1 @@
uid://b3dlktsgeteuw
+18
View File
@@ -0,0 +1,18 @@
using Godot;
using System;
public partial class MouseHandler : Node
{
public enum ClickType
{
LEFT_CLICK,
MIDDLE_CLICK,
RIGHT_CLICK,
LEFT_HOLD,
MIDDLE_HOLD,
RIGHT_HOLD,
LEFT_DOUBLE,
MIDDLE_DOUBLE,
RIGHT_DOUBLE
}
}
+1
View File
@@ -0,0 +1 @@
uid://dewxuppyw2gtp
+91
View File
@@ -0,0 +1,91 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
public partial class Peg : MapCellOccupant
{
[Signal]
public delegate void DeathEventHandler(Peg THIS);
public int _id, _health = 2, _healthMax = 2, _stamina, _staminaRemaining, _movement = 0, _visibility;
public List<MapCell> _path = new();
public PegController _pegController;
public Map _map;
public List<PegAction> _actions;
public int _distanceToGoal
{
get
{
return GetBestPath().Count;
}
}
public override void _Ready()
{
base._Ready();
_actions = [.. GetNode<Node2D>("Actions").GetChildren().Cast<PegAction>()];
_map = _pegController._playArea._map;
}
public virtual PegAction SelectAction()
{
return _actions.FirstOrDefault(a => a.MeetsCriteria(this), null);
}
public virtual void CounterAct(Commander COMMANDER)
{
}
public virtual List<MapCell> GetBestPath(bool PARTIAL = false)
{
MapCell goal = Goal();
return [.. _map.GetPath(_address, goal._address, false, PARTIAL).Select(a => _map._cells[a])];
}
public virtual Dictionary<Vector2I, MapCell> GetEnemies()
{
return _map._cells.Where(c => (int)(c.Value._occupant?._disposition ?? Disposition.NONE) == -(int)_disposition).ToDictionary();
}
public virtual Dictionary<Vector2I, MapCell> GetVisibleCells()
{
Map map = _pegController._playArea._map;
return map._cells.Where(c => (c.Value._address - _address).Length() <= _visibility).ToDictionary();
}
public virtual Dictionary<Vector2I, MapCell> GetVisibleEnemies()
{
Dictionary<Vector2I, MapCell> visible = GetVisibleCells();
Dictionary<Vector2I, MapCell> enemies = GetEnemies();
return enemies.Keys.Intersect(visible.Keys).ToDictionary(e => e, e => enemies[e]);
}
public virtual MapCell Goal()
{
Dictionary<Vector2I, MapCell> enemyTerritory = _map._cells.Where(c => _map.GetCellDisposition(c.Value._address) == (_disposition == Disposition.FRIENDLY ? -1 : 1)).ToDictionary();
Dictionary<Vector2I, MapCell> closest = enemyTerritory.OrderByDescending(c => c.Value._address.Y).ThenBy(c => Math.Abs(c.Value._address.X - _address.X)).ToDictionary();
return closest.ElementAt(0).Value;
}
public virtual void StartTurn()
{
_staminaRemaining = _stamina;
_actions.ForEach(a => a.Reset());
}
public virtual void ChangeHealth(int DELTA)
{
_health += DELTA;
if (_health <= 0)
{
EmitSignal(SignalName.Death, this);
}
else if (_health > _healthMax)
{
_health = _healthMax;
}
}
}
+1
View File
@@ -0,0 +1 @@
uid://g2ucwg3k342p
+267
View File
@@ -0,0 +1,267 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
public partial class PegController : TurnController
{
public int _pegsCreated = 0, _pegsDestroyed = 0;
public List<PackedScene> _hostilePegScenes, _friendlyPegScenes, _neutralPegScenes;
public List<Peg> _pegs = new();
public PlayerController _playerController;
public Dictionary<string, List<Tuple<Peg, PegAction>>> _tweenStages = new();
public Tween _tween;
public XmlDocument _pegProbabilities = new();
public override void _Ready()
{
base._Ready();
_hostilePegScenes = [.. Directory.GetFiles("Pegs/HostilePegs/", "*.tscn").Select(f => GD.Load<PackedScene>(f))];
_friendlyPegScenes = [.. Directory.GetFiles("Pegs/FriendlyPegs/", "*.tscn").Select(f => GD.Load<PackedScene>(f))];
// _neutralPegScenes = [.. Directory.GetFiles("Pegs/NeutralPegs/", "*.tscn").Select(f => GD.Load<PackedScene>(f))];
// _pegProbabilities.Load("res://PegProbabilities.xml");
}
public void AddFriendlyPegs(int PEG_COUNT = 1)
{
for (int i = 0; i < PEG_COUNT; i++)
{
FriendlyPeg newFriendlyPeg = Globals.GetRandomFromList(_friendlyPegScenes).Instantiate<FriendlyPeg>();
newFriendlyPeg._id = _pegsCreated;
newFriendlyPeg.Death += HandlePegRemoval;
newFriendlyPeg.Click += HandlePegClick;
newFriendlyPeg._pegController = this;
Dictionary<Vector2I, MapCell> unoccupied = _playArea._map._bottomRow.Where(c => c.Value._occupant == null).ToDictionary();
MapCell randomCell = unoccupied.ElementAt(Globals._rng.Next(unoccupied.Keys.Count)).Value;
SetPeg(newFriendlyPeg, randomCell);
_pegs.Add(newFriendlyPeg);
AddChild(newFriendlyPeg);
_pegsCreated++;
}
}
public void AddFriendlyPegs(List<Vector2I> POSITIONS)
{
for (int i = 0; i < POSITIONS.Count; i++)
{
FriendlyPeg newFriendlyPeg = Globals.GetRandomFromList(_friendlyPegScenes).Instantiate<FriendlyPeg>();
newFriendlyPeg._id = _pegsCreated;
newFriendlyPeg.Scale *= _pegsCreated == 4 ? 1.5f : 1f;
newFriendlyPeg.Death += HandlePegRemoval;
newFriendlyPeg.Click += HandlePegClick;
newFriendlyPeg._pegController = this;
SetPeg(newFriendlyPeg, _map._cells[POSITIONS[i]]);
_pegs.Add(newFriendlyPeg);
AddChild(newFriendlyPeg);
_pegsCreated++;
}
}
public void AddHostilePegs(int PEG_COUNT = 1)
{
for (int i = 0; i < PEG_COUNT; i++)
{
HostilePeg newHostilePeg = Globals.GetRandomFromList(_hostilePegScenes).Instantiate<HostilePeg>();
newHostilePeg._id = _pegsCreated;
newHostilePeg.Death += HandlePegRemoval;
newHostilePeg.Click += HandlePegClick;
newHostilePeg._pegController = this;
Dictionary<Vector2I, MapCell> unoccupied = _map._bottomRow.Where(c => c.Value._occupant == null).ToDictionary();
MapCell randomCell = unoccupied.ElementAt(Globals._rng.Next(unoccupied.Count)).Value;
SetPeg(newHostilePeg, randomCell);
_pegs.Add(newHostilePeg);
AddChild(newHostilePeg);
_pegsCreated++;
}
}
public void AddHostilePegs(List<Vector2I> POSITIONS)
{
for (int i = 0; i < POSITIONS.Count; i++)
{
HostilePeg newHostilePeg = Globals.GetRandomFromList(_hostilePegScenes).Instantiate<HostilePeg>();
newHostilePeg._id = _pegsCreated;
newHostilePeg.Scale *= _pegsCreated == 4 ? 1.5f : 1f;
newHostilePeg.Death += HandlePegRemoval;
newHostilePeg.Click += HandlePegClick;
newHostilePeg._pegController = this;
newHostilePeg._map = _playArea._map;
SetPeg(newHostilePeg, _map._cells[POSITIONS[i]]);
_pegs.Add(newHostilePeg);
AddChild(newHostilePeg);
_pegsCreated++;
}
}
public void HandlePegTurn()
{
_tweenStages.Clear();
int loop = 0;
bool anyPegsActed = true;
while (anyPegsActed)
{
anyPegsActed = false;
for (int i = 0; i < _pegs.Count; i++)
{
Peg peg = _pegs[i];
PegAction action = peg.SelectAction();
if (action != null)
{
action.DoImmediately(peg);
string key = action._priority + ":" + loop;
if (!_tweenStages.ContainsKey(key))
{
_tweenStages[key] = new();
}
_tweenStages[key].Add(new(peg, action));
if (!anyPegsActed)
{
anyPegsActed = true;
}
peg._staminaRemaining -= action._cost;
}
}
loop++;
}
ProcessTween();
}
public void HandlePegClick(Node CLICKED_NODE, int CLICK_TYPE)
{
if (CLICKED_NODE is not Peg peg)
{
return;
}
if (CLICK_TYPE == 0)
{
Map map = _playArea._map;
TileMapLayer pathLayer = _playArea.GetNode<TileMapLayer>("PathLayer");
List<Vector2I> pl = [.. pathLayer.GetUsedCells()];
Dictionary<Vector2I, MapCell> visible = peg.GetVisibleCells();
for (int i = 0; i < pl.Count; i++)
{
Vector2I cell = pl[i];
pathLayer.GetUsedCells().ToList().ForEach(c => pathLayer.SetCell(cell,0,Vector2I.Down + Vector2I.Right*(visible.ContainsKey(cell) ? 1 : 4)));
}
}
else if (CLICK_TYPE == 1)
{
TileMapLayer pathLayer = _playArea.GetNode<TileMapLayer>("PathLayer");
List<MapCell> newPath = peg.GetBestPath(true);
pathLayer.GetUsedCells().ToList().ForEach(c => pathLayer.SetCell(c,0,Vector2I.Down + Vector2I.Right*4));
for (int i = 0; i < newPath.Count; i++)
{
pathLayer.SetCell(newPath[i]._address,0,Vector2I.One);
}
}
else if (CLICK_TYPE == 2)
{
HandlePegRemoval(peg);
}
}
public void HandlePegRemoval(Peg PEG_TO_REMOVE)
{
_pegs.Remove(PEG_TO_REMOVE);
_playArea._map.SetCellPeg(_map._cells[PEG_TO_REMOVE._address], null);
PEG_TO_REMOVE.QueueFree();
_pegsDestroyed++;
}
public void HandlePegSort()
{
_pegs = [.. _pegs.OrderBy(p => p._address.Y).ThenBy(p => p._distanceToGoal).ThenBy(p => Math.Abs(p._address.X - _playArea._map._maxX / 2))];
}
public void Initiate()
{
TileMapLayer init = _playArea.GetNode<TileMapLayer>("InitialPositions");
List<Vector2I> initPos = [.. init.GetUsedCells()];
List<Vector2I> positions = [.. initPos.OrderBy(c => c.Y).ThenBy(c => c.X)];
List<Vector2I> hPositions = [.. positions.Where(c => (int)init.GetCellTileData(c).GetCustomData("disposition") == -1)];
List<Vector2I> fPositions = [.. positions.Where(c => (int)init.GetCellTileData(c).GetCustomData("disposition") == 1)];
AddHostilePegs(hPositions);
AddFriendlyPegs(fPositions);
_playArea.HighlightCells();
}
public void ProcessTween()
{
_tweenStages = _tweenStages.OrderBy(s => int.Parse(s.Key.Split(":")[0])).ThenBy(s => int.Parse(s.Key.Split(":")[1])).ToDictionary();
if (_tweenStages.Count <= 0)
{
EndTurn();
return;
}
_tween?.Kill();
_tween = CreateTween();
for (int i = 0; i < _tweenStages.Count; i++)
{
_tween.Chain().TweenInterval(0.5f);
List<Tuple<Peg, PegAction>> tweenSteps = _tweenStages.Values.ElementAt(i);
for (int j = 0; j < tweenSteps.Count; j++)
{
Tuple<Peg, PegAction> step = tweenSteps[j];
Peg peg = step.Item1;
PegAction action = step.Item2;
Tween tween = action.CreateAnimation(peg);
if (tween != null)
{
_tween.Parallel().TweenSubtween(tween);
}
}
}
_tween.TweenCallback(Callable.From(EndTurn));
}
public override void StartTurn()
{
AddHostilePegs(4);
for (int i = 0; i < _pegs.Count; i++)
{
_pegs[i].StartTurn();
}
HandlePegSort();
HandlePegTurn();
_playArea.HighlightCells();
}
public void SetPeg(Peg PEG, MapCell CELL)
{
_map.SetCellPeg(CELL, PEG);
PEG.GlobalPosition = CELL.GlobalPosition;
}
}
+3
View File
@@ -0,0 +1,3 @@
<xml>
</xml>
+58
View File
@@ -0,0 +1,58 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
public partial class BasicMovement : PegAction
{
public override void _Ready()
{
base._Ready();
_category = "movement";
_priority = 0;
_cost = 1;
_range = 2^32;
_usesMax = 2^32;
_usesRemaining = _usesMax;
}
public override Tween CreateAnimation(Peg PEG)
{
PegController pegController = PEG._pegController;
Map map = pegController._playArea._map;
MapCell cell = PEG._path[0];
Tween subtween = CreateTween();
Vector2 target = cell.GlobalPosition;
subtween.TweenProperty(PEG, "global_position", target, 0.25f);
PEG._path.RemoveAt(0);
return subtween;
}
public override void DoImmediately(Peg PEG)
{
List<MapCell> path = PEG.GetBestPath(true);
PegController pegController = PEG._pegController;
Map map = pegController._playArea._map;
if (path?.Count == 0)
{
return;
}
MapCell cell = path[0];
map.SetCellPeg(cell, PEG);
PEG._path.Add(cell);
}
public override bool MeetsCriteria(Peg PEG)
{
List<MapCell> bestPath = PEG.GetBestPath(true);
return base.MeetsCriteria(PEG)
&& bestPath.Count > 0
&& PEG._map.GetCellDisposition(bestPath[0]._address) != -(int)PEG._disposition;
}
}
+1
View File
@@ -0,0 +1 @@
uid://hp5iucbq5brg
+35
View File
@@ -0,0 +1,35 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
public partial class ShootShortbow : PegAction
{
public override void _Ready()
{
base._Ready();
_category = "attack";
_priority = 1;
_cost = 2;
_range = 2;
_usesMax = 1;
_usesRemaining = _usesMax;
}
public override Tween CreateAnimation(Peg PEG)
{
MapCell target = Target(PEG);
Tween subtween = CreateTween();
subtween.TweenProperty(_image, "visible", true, 0.0f);
subtween.TweenProperty(_image, "rotation", PEG.GetAngleTo(target.GlobalPosition), 0.0f);
subtween.TweenProperty(_image, "global_position", target.GlobalPosition, 0.5f);
subtween.TweenCallback(Callable.From(() =>
{
PEG._pegController._playerController.ChangeHealth(-2, this);
Position = Vector2.Zero;
Visible = false;
}));
return subtween;
}
}
+1
View File
@@ -0,0 +1 @@
uid://dt7qbvowj1sm4
+35
View File
@@ -0,0 +1,35 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
public partial class SwingShortsword : PegAction
{
public override void _Ready()
{
base._Ready();
_category = "attack";
_priority = 1;
_cost = 2;
_range = 1;
_usesMax = 1;
_usesRemaining = _usesMax;
}
public override Tween CreateAnimation(Peg PEG)
{
MapCell target = Target(PEG);
// GD.Print(target);
Tween subtween = CreateTween();
subtween.TweenProperty(_image, "visible", true, 0.0f);
subtween.TweenProperty(_image, "rotation", PEG.GetAngleTo(target.GlobalPosition), 0.0f);
subtween.TweenProperty(_image, "global_position", target.GlobalPosition, 0.5f);
subtween.TweenCallback(Callable.From(() =>
{
PEG._pegController._playerController.ChangeHealth(-2, this);
_image.Position = Vector2.Zero;
_image.Visible = false;
}));
return subtween;
}
}
+1
View File
@@ -0,0 +1 @@
uid://td6dv1t4y5os
+43
View File
@@ -0,0 +1,43 @@
using Godot;
using System;
public partial class ThrustSpear : PegAction
{
public override void _Ready()
{
base._Ready();
_category = "attack";
_priority = 1;
_cost = 1;
_range = 1;
_usesMax = 1;
_usesRemaining = _usesMax;
}
public override Tween CreateAnimation(Peg PEG)
{
MapCell target = Target(PEG);
if (target == PEG._cell)
{
return null;
}
Tween subtween = CreateTween();
subtween.TweenProperty(_image, "visible", true, 0.0f);
subtween.TweenProperty(_image, "rotation", PEG.GetAngleTo(target.GlobalPosition), 0.0f);
subtween.TweenProperty(_image, "global_position", target.GlobalPosition, 0.5f);
subtween.TweenCallback(Callable.From(() =>
{
((Peg)target?._occupant)?.ChangeHealth(-1);
_image.Position = Vector2.Zero;
_image.Visible = false;
}));
return subtween;
}
public override MapCell Target(Peg PEG)
{
return PEG.Goal();
}
}
+1
View File
@@ -0,0 +1 @@
uid://bj2lg1voxioq7
+9
View File
@@ -0,0 +1,9 @@
[gd_scene format=3 uid="uid://bup5oli00p3lg"]
[ext_resource type="Script" uid="uid://hp5iucbq5brg" path="res://Pegs/Actions/BasicMovement.cs" id="1_u1rld"]
[node name="BasicMovement" type="Node2D" unique_id=460007250]
script = ExtResource("1_u1rld")
[node name="Image" type="Sprite2D" parent="." unique_id=1133735272]
visible = false
+12
View File
@@ -0,0 +1,12 @@
[gd_scene format=3 uid="uid://duspilwelsiy3"]
[ext_resource type="Script" uid="uid://dt7qbvowj1sm4" path="res://Pegs/Actions/ShootShortbow.cs" id="1_yhiab"]
[ext_resource type="Texture2D" uid="uid://32m5teus1cjj" path="res://Art/tower.png" id="2_uaien"]
[node name="ShootShortbow" type="Node2D" unique_id=518048625]
script = ExtResource("1_yhiab")
[node name="Image" type="Sprite2D" parent="." unique_id=944294157]
visible = false
scale = Vector2(0.1, 0.1)
texture = ExtResource("2_uaien")
+12
View File
@@ -0,0 +1,12 @@
[gd_scene format=3 uid="uid://c6df6ib0qan5g"]
[ext_resource type="Script" uid="uid://td6dv1t4y5os" path="res://Pegs/Actions/SwingShortsword.cs" id="1_rflgk"]
[ext_resource type="Texture2D" uid="uid://32m5teus1cjj" path="res://Art/tower.png" id="2_fs74r"]
[node name="Shortsword" type="Node2D" unique_id=518048625]
script = ExtResource("1_rflgk")
[node name="Image" type="Sprite2D" parent="." unique_id=906537972]
visible = false
scale = Vector2(0.1, 0.1)
texture = ExtResource("2_fs74r")
+13
View File
@@ -0,0 +1,13 @@
[gd_scene format=3 uid="uid://xx4n81m8hbxv"]
[ext_resource type="Script" uid="uid://bj2lg1voxioq7" path="res://Pegs/Actions/ThrustSpear.cs" id="1_revbx"]
[ext_resource type="Texture2D" uid="uid://32m5teus1cjj" path="res://Art/tower.png" id="2_nwcvh"]
[node name="ThrustSpear" type="Node2D" unique_id=460007250]
script = ExtResource("1_revbx")
[node name="Image" type="Sprite2D" parent="." unique_id=1133735272]
visible = false
position = Vector2(0, -4.999999)
scale = Vector2(0.1, 0.1)
texture = ExtResource("2_nwcvh")
+13
View File
@@ -0,0 +1,13 @@
using Godot;
using System;
public partial class FriendlyPeg : Peg
{
public override void _Ready()
{
base._Ready();
_disposition = Disposition.FRIENDLY;
}
}
+1
View File
@@ -0,0 +1 @@
uid://fxx1mrrxxqip
+25
View File
@@ -0,0 +1,25 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
public partial class Spearman : FriendlyPeg
{
public override void _Ready()
{
base._Ready();
_stamina = 2;
_visibility = 4;
}
public override MapCell Goal()
{
Dictionary<Vector2I, MapCell> enemies = GetVisibleEnemies();
if (enemies.Count == 0)
{
return _cell;
}
Dictionary<Vector2I, MapCell> closest = enemies.OrderBy(e => (e.Value._occupant._address - _address).Length()).ToDictionary();
return closest.ElementAt(0).Value;
}
}
+1
View File
@@ -0,0 +1 @@
uid://dd4k8egcg3r2v
+43
View File
@@ -0,0 +1,43 @@
[gd_scene format=3 uid="uid://b5rrpaj7up7w3"]
[ext_resource type="Script" uid="uid://dd4k8egcg3r2v" path="res://Pegs/FriendlyPegs/Spearman.cs" id="1_rd6ui"]
[ext_resource type="Texture2D" uid="uid://nwj4n7if8kqd" path="res://Art/circle25r.png" id="2_v2nt8"]
[ext_resource type="PackedScene" uid="uid://xx4n81m8hbxv" path="res://Pegs/Actions/thrust_spear.tscn" id="3_ig48t"]
[ext_resource type="PackedScene" uid="uid://bup5oli00p3lg" path="res://Pegs/Actions/basic_movement.tscn" id="4_gi7y5"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_7k104"]
bounce = 0.5
[sub_resource type="CircleShape2D" id="CircleShape2D_4gyqm"]
radius = 12.5
[sub_resource type="CircleShape2D" id="CircleShape2D_6w6fg"]
radius = 12.5
[node name="Spearman" type="StaticBody2D" unique_id=1417697759]
input_pickable = true
physics_material_override = SubResource("PhysicsMaterial_7k104")
script = ExtResource("1_rd6ui")
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1762191899]
shape = SubResource("CircleShape2D_4gyqm")
[node name="Sprite2D" type="Sprite2D" parent="." unique_id=1941012605]
modulate = Color(1, 1, 0, 1)
texture_filter = 1
scale = Vector2(0.5, 0.5)
texture = ExtResource("2_v2nt8")
[node name="Actions" type="Node2D" parent="." unique_id=2023031702]
[node name="ThrustSpear" parent="Actions" unique_id=460007250 instance=ExtResource("3_ig48t")]
[node name="BasicMovement" parent="Actions" unique_id=791425339 instance=ExtResource("4_gi7y5")]
[node name="HoverBounds" type="Area2D" parent="." unique_id=937525982]
[node name="CollisionShape2D" type="CollisionShape2D" parent="HoverBounds" unique_id=2142666816]
shape = SubResource("CircleShape2D_6w6fg")
[connection signal="mouse_entered" from="." to="." method="OnMouseEntered"]
[connection signal="mouse_exited" from="." to="." method="OnMouseExited"]
+17
View File
@@ -0,0 +1,17 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public partial class HostilePeg : Peg
{
public override void _Ready()
{
base._Ready();
_disposition = Disposition.HOSTILE;
}
}
+12
View File
@@ -0,0 +1,12 @@
using Godot;
using System;
public partial class Archer : HostilePeg
{
public override void _Ready()
{
base._Ready();
_stamina = 2;
_visibility = 4;
}
}
+1
View File
@@ -0,0 +1 @@
uid://b3a0x3r3yx861
+12
View File
@@ -0,0 +1,12 @@
using Godot;
using System;
public partial class Infantry : HostilePeg
{
public override void _Ready()
{
base._Ready();
_stamina = 3;
_visibility = 3;
}
}
+1
View File
@@ -0,0 +1 @@
uid://xlg4cblo1vf1
+43
View File
@@ -0,0 +1,43 @@
[gd_scene format=3 uid="uid://dwqhme11j5ihb"]
[ext_resource type="Script" uid="uid://b3a0x3r3yx861" path="res://Pegs/HostilePegs/Archer.cs" id="1_ij48w"]
[ext_resource type="Texture2D" uid="uid://nwj4n7if8kqd" path="res://Art/circle25r.png" id="2_j7but"]
[ext_resource type="PackedScene" uid="uid://duspilwelsiy3" path="res://Pegs/Actions/shoot_shortbow.tscn" id="3_c81uf"]
[ext_resource type="PackedScene" uid="uid://bup5oli00p3lg" path="res://Pegs/Actions/basic_movement.tscn" id="3_j7but"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_7k104"]
bounce = 0.5
[sub_resource type="CircleShape2D" id="CircleShape2D_4gyqm"]
radius = 12.5
[sub_resource type="CircleShape2D" id="CircleShape2D_6w6fg"]
radius = 12.5
[node name="Archer" type="StaticBody2D" unique_id=1417697759]
input_pickable = true
physics_material_override = SubResource("PhysicsMaterial_7k104")
script = ExtResource("1_ij48w")
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1762191899]
shape = SubResource("CircleShape2D_4gyqm")
[node name="Sprite2D" type="Sprite2D" parent="." unique_id=1941012605]
self_modulate = Color(0, 0, 1, 1)
texture_filter = 1
scale = Vector2(0.5, 0.5)
texture = ExtResource("2_j7but")
[node name="Actions" type="Node2D" parent="." unique_id=96111050]
[node name="ShootShortbow" parent="Actions" unique_id=518048625 instance=ExtResource("3_c81uf")]
[node name="BasicMovement" parent="Actions" unique_id=460007250 instance=ExtResource("3_j7but")]
[node name="HoverBounds" type="Area2D" parent="." unique_id=937525982]
[node name="CollisionShape2D" type="CollisionShape2D" parent="HoverBounds" unique_id=2142666816]
shape = SubResource("CircleShape2D_6w6fg")
[connection signal="mouse_entered" from="." to="." method="OnMouseEntered"]
[connection signal="mouse_exited" from="." to="." method="OnMouseExited"]
+43
View File
@@ -0,0 +1,43 @@
[gd_scene format=3 uid="uid://d55ut168gh3k"]
[ext_resource type="Script" uid="uid://xlg4cblo1vf1" path="res://Pegs/HostilePegs/Infantry.cs" id="1_wlksp"]
[ext_resource type="Texture2D" uid="uid://nwj4n7if8kqd" path="res://Art/circle25r.png" id="2_b77ka"]
[ext_resource type="PackedScene" uid="uid://c6df6ib0qan5g" path="res://Pegs/Actions/swing_shortsword.tscn" id="3_b77ka"]
[ext_resource type="PackedScene" uid="uid://bup5oli00p3lg" path="res://Pegs/Actions/basic_movement.tscn" id="4_b77ka"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_7k104"]
bounce = 0.5
[sub_resource type="CircleShape2D" id="CircleShape2D_4gyqm"]
radius = 12.5
[sub_resource type="CircleShape2D" id="CircleShape2D_6w6fg"]
radius = 12.5
[node name="Infantry" type="StaticBody2D" unique_id=1417697759]
input_pickable = true
physics_material_override = SubResource("PhysicsMaterial_7k104")
script = ExtResource("1_wlksp")
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1762191899]
shape = SubResource("CircleShape2D_4gyqm")
[node name="Sprite2D" type="Sprite2D" parent="." unique_id=1941012605]
self_modulate = Color(1, 0, 0, 1)
texture_filter = 1
scale = Vector2(0.5, 0.5)
texture = ExtResource("2_b77ka")
[node name="Actions" type="Node2D" parent="." unique_id=1442443799]
[node name="Shortsword" parent="Actions" unique_id=518048625 instance=ExtResource("3_b77ka")]
[node name="BasicMovement" parent="Actions" unique_id=460007250 instance=ExtResource("4_b77ka")]
[node name="HoverBounds" type="Area2D" parent="." unique_id=937525982]
[node name="CollisionShape2D" type="CollisionShape2D" parent="HoverBounds" unique_id=2142666816]
shape = SubResource("CircleShape2D_6w6fg")
[connection signal="mouse_entered" from="." to="." method="OnMouseEntered"]
[connection signal="mouse_exited" from="." to="." method="OnMouseExited"]
+14
View File
@@ -0,0 +1,14 @@
using Godot;
using System;
public partial class NeutralPeg : Peg
{
public override void _Ready()
{
base._Ready();
_disposition = Disposition.NEUTRAL;
}
}
+1
View File
@@ -0,0 +1 @@
uid://hcna8x41gtkq
+43
View File
@@ -0,0 +1,43 @@
using Godot;
using System;
public partial class PegAction : Node2D
{
public string _category;
public int _priority, _cost, _range, _usesMax, _usesRemaining, _triggers = 0;
public Sprite2D _image;
public override void _Ready()
{
base._Ready();
_image = GetNode<Sprite2D>("Image");
}
public virtual Tween CreateAnimation(Peg PEG)
{
return null;
}
public virtual void DoImmediately(Peg PEG)
{
}
public virtual bool MeetsCriteria(Peg PEG)
{
MapCell target = Target(PEG);
return PEG._staminaRemaining >= _cost
&& _usesRemaining > 0
&& (PEG._address - target._address).Length() <= _range;
}
public virtual void Reset()
{
_usesRemaining = _usesMax;
}
public virtual MapCell Target(Peg PEG)
{
return PEG.Goal();
}
}
+1
View File
@@ -0,0 +1 @@
uid://dpa15pxib2qyr
+36
View File
@@ -0,0 +1,36 @@
[gd_scene format=3 uid="uid://tym3gfecxnhf"]
[ext_resource type="Script" uid="uid://fxx1mrrxxqip" path="res://Pegs/FriendlyPeg.cs" id="1_d26yj"]
[ext_resource type="Texture2D" uid="uid://nwj4n7if8kqd" path="res://Art/circle25r.png" id="1_q81kk"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_7k104"]
bounce = 0.5
[sub_resource type="CircleShape2D" id="CircleShape2D_4gyqm"]
radius = 12.5
[sub_resource type="CircleShape2D" id="CircleShape2D_6w6fg"]
radius = 12.5
[node name="FriendlyPeg" type="StaticBody2D" unique_id=1417697759]
input_pickable = true
physics_material_override = SubResource("PhysicsMaterial_7k104")
script = ExtResource("1_d26yj")
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1762191899]
shape = SubResource("CircleShape2D_4gyqm")
[node name="Sprite2D" type="Sprite2D" parent="." unique_id=1941012605]
texture_filter = 1
scale = Vector2(0.5, 0.5)
texture = ExtResource("1_q81kk")
[node name="Actions" type="Node2D" parent="." unique_id=2023031702]
[node name="HoverBounds" type="Area2D" parent="." unique_id=937525982]
[node name="CollisionShape2D" type="CollisionShape2D" parent="HoverBounds" unique_id=2142666816]
shape = SubResource("CircleShape2D_6w6fg")
[connection signal="mouse_entered" from="." to="." method="OnMouseEntered"]
[connection signal="mouse_exited" from="." to="." method="OnMouseExited"]
+36
View File
@@ -0,0 +1,36 @@
[gd_scene format=3 uid="uid://43ty0uit6ylb"]
[ext_resource type="Script" uid="uid://dfba4vq6jv0a6" path="res://Pegs/HostilePeg.cs" id="1_nc8fp"]
[ext_resource type="Texture2D" uid="uid://nwj4n7if8kqd" path="res://Art/circle25r.png" id="2_0icqg"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_7k104"]
bounce = 0.5
[sub_resource type="CircleShape2D" id="CircleShape2D_4gyqm"]
radius = 12.5
[sub_resource type="CircleShape2D" id="CircleShape2D_6w6fg"]
radius = 12.5
[node name="HostilePeg" type="StaticBody2D" unique_id=1417697759]
input_pickable = true
physics_material_override = SubResource("PhysicsMaterial_7k104")
script = ExtResource("1_nc8fp")
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1762191899]
shape = SubResource("CircleShape2D_4gyqm")
[node name="Sprite2D" type="Sprite2D" parent="." unique_id=1941012605]
texture_filter = 1
scale = Vector2(0.5, 0.5)
texture = ExtResource("2_0icqg")
[node name="Actions" type="Node2D" parent="." unique_id=2023031702]
[node name="HoverBounds" type="Area2D" parent="." unique_id=937525982]
[node name="CollisionShape2D" type="CollisionShape2D" parent="HoverBounds" unique_id=2142666816]
shape = SubResource("CircleShape2D_6w6fg")
[connection signal="mouse_entered" from="." to="." method="OnMouseEntered"]
[connection signal="mouse_exited" from="." to="." method="OnMouseExited"]
+36
View File
@@ -0,0 +1,36 @@
[gd_scene format=3 uid="uid://d3jw2bvkr8ahq"]
[ext_resource type="Texture2D" uid="uid://nwj4n7if8kqd" path="res://Art/circle25r.png" id="1_bdrbe"]
[ext_resource type="Script" uid="uid://hcna8x41gtkq" path="res://Pegs/NeutralPeg.cs" id="1_vrgbl"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_7k104"]
bounce = 0.5
[sub_resource type="CircleShape2D" id="CircleShape2D_4gyqm"]
radius = 12.5
[sub_resource type="CircleShape2D" id="CircleShape2D_6w6fg"]
radius = 12.5
[node name="NeutralPeg" type="StaticBody2D" unique_id=1417697759]
input_pickable = true
physics_material_override = SubResource("PhysicsMaterial_7k104")
script = ExtResource("1_vrgbl")
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1762191899]
shape = SubResource("CircleShape2D_4gyqm")
[node name="Sprite2D" type="Sprite2D" parent="." unique_id=1941012605]
texture_filter = 1
scale = Vector2(0.5, 0.5)
texture = ExtResource("1_bdrbe")
[node name="Actions" type="Node2D" parent="." unique_id=2023031702]
[node name="HoverBounds" type="Area2D" parent="." unique_id=937525982]
[node name="CollisionShape2D" type="CollisionShape2D" parent="HoverBounds" unique_id=2142666816]
shape = SubResource("CircleShape2D_6w6fg")
[connection signal="mouse_entered" from="." to="." method="OnMouseEntered"]
[connection signal="mouse_exited" from="." to="." method="OnMouseExited"]
+9
View File
@@ -0,0 +1,9 @@
[gd_scene format=3 uid="uid://bj2qrn0l01us1"]
[ext_resource type="Script" uid="uid://dpa15pxib2qyr" path="res://Pegs/PegAction.cs" id="1_8o8tf"]
[node name="PegAction" type="Node2D" unique_id=460007250]
script = ExtResource("1_8o8tf")
[node name="Image" type="Sprite2D" parent="." unique_id=1133735272]
visible = false
+52
View File
@@ -0,0 +1,52 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
public partial class PlayArea : Node2D
{
public Node2D _leftEdge, _rightEdge;
public Area2D _region;
public Map _map;
public override void _Ready()
{
base._Ready();
_region = GetNode<Area2D>("Region");
_leftEdge = GetNode<Node2D>("LeftEdge");
_rightEdge = GetNode<Node2D>("RightEdge");
CollisionShape2D regionBounds = _region.GetNode<CollisionShape2D>("Bounds");
_map = GetNode<Map>("Map");
TileMapLayer occupiedSpaces = GetNode<TileMapLayer>("OccupiedSpaces");
}
public override void _Process(double delta)
{
base._Process(delta);
}
public void HighlightCells()
{
TileMapLayer occupiedSpaces = GetNode<TileMapLayer>("OccupiedSpaces");
for (int i = 0; i < _map._cells.Count; i++)
{
MapCell c = _map._cells.ElementAt(i).Value;
if (c._occupant != null)
{
occupiedSpaces.SetCell(c._address, 0, new Vector2I(4,0));
}
else if (_map._astar.IsPointSolid(c._address))
{
occupiedSpaces.SetCell(c._address, 0, new Vector2I(3,1));
}
else
{
occupiedSpaces.SetCell(c._address, 0, new Vector2I(4,1));
}
}
}
}
+34 -7
View File
@@ -2,16 +2,43 @@ using Godot;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
public partial class PlayerController : TurnController public partial class PlayerController : TurnController
{ {
public EnemyController _enemyController; [Signal]
public delegate void DeathEventHandler(PlayerController THIS);
public bool _dead = false;
public int _health, _healthMax = 100, _gold = 0;
public PegController _pegController;
public PackedScene _commanderScene = GD.Load<PackedScene>("res://Commander.tscn"); public PackedScene _commanderScene = GD.Load<PackedScene>("res://Commander.tscn");
public List<Tower> _towers = new(); public List<Tower> _towers = new();
public Bucket _bucket;
public override void _Ready() public override void _Ready()
{ {
_health = _healthMax;
base._Ready(); base._Ready();
_bucket = GetNode<Bucket>("Bucket");
}
public override void _Process(double delta)
{
base._Process(delta);
_bucket.Move();
}
public void ChangeHealth(int DAMAGE, Node IMPETUS = null)
{
_health += DAMAGE;
_health = Math.Clamp(_health, 0, _healthMax);
if (_health == 0 && !_dead)
{
_dead = !_dead;
GD.Print("YOU DIED");
EmitSignal(SignalName.Death, this);
}
} }
public void CheckForTurnEnd() public void CheckForTurnEnd()
@@ -22,18 +49,18 @@ public partial class PlayerController : TurnController
} }
} }
public void SetUpTowers(int TOWER_COUNT = 8) public void SetUpTowers(int TOWER_COUNT = 5)
{ {
Tower tower = GetNode<Tower>("Tower1"); Tower tower = GetNode<Tower>("Tower1");
Vector2 towerPositionCorrection = tower._area.GetNode<CollisionShape2D>("Bounds").Shape.GetRect().Size / 2 * (Vector2.Right + Vector2.Up); Vector2 towerPositionCorrection = tower._offset.Position;
float spaceBetweenTowers = _grid._sizeInPixels.X / (TOWER_COUNT - 1); float spaceBetweenTowers = _playArea._map._sizeInPixels.X / (TOWER_COUNT - 1);
tower.Position = _grid.Position - _grid._sizeInPixels / 2 + towerPositionCorrection; tower.GlobalPosition = _playArea._map.GlobalPosition + towerPositionCorrection;
_towers.Add(tower); _towers.Add(tower);
for (int i = 1; i < TOWER_COUNT; i++) for (int i = 1; i < TOWER_COUNT; i++)
{ {
Tower newTower = (Tower)tower.Duplicate(); Tower newTower = (Tower)tower.Duplicate();
newTower.Position += new Vector2(spaceBetweenTowers * i - towerPositionCorrection.X * i / (TOWER_COUNT - 1) * 2, 0); newTower.GlobalPosition += new Vector2(spaceBetweenTowers * i - towerPositionCorrection.X * i / (TOWER_COUNT - 1) * 2, 0);
_towers.Add(newTower); _towers.Add(newTower);
AddChild(newTower); AddChild(newTower);
} }
@@ -47,7 +74,7 @@ public partial class PlayerController : TurnController
public override void StartTurn() public override void StartTurn()
{ {
_towers.Where(t=> t._commander != null).ToList().ForEach(t=>t._commander._actions = t._commander._actionsMax); _towers.ForEach(t => t.StartTurn());
} }
} }
+166 -21
View File
@@ -1,51 +1,196 @@
using Godot; using Godot;
using System; using System;
using System.Collections.Generic;
using System.Diagnostics;
public partial class Tower : Sprite2D public partial class Tower : HoverableNode
{ {
public bool _hovered, _aiming; public bool _aiming;
public Commander _commander; public int _launchSpeed = 1000, _arcIterations = 50;
public Vector2 _aimOffset, _arcEnd;
public List<Vector2> _arc = new();
public Marker2D _offset, _ballSpawn;
public Area2D _area; public Area2D _area;
public Commander _commander;
public override void _Ready() public override void _Ready()
{ {
base._Ready(); base._Ready();
_area = GetNode<Area2D>("Area");
_offset = GetNode<Marker2D>("Offset");
_ballSpawn = GetNode<Marker2D>("BallSpawn");
// Click += HandleClick;
} }
public override void _Process(double delta) public override void _Process(double delta)
{ {
base._Process(delta); base._Process(delta);
if (_commander?._actions > 0) if (_commander?._actions > 0)
{ {
if (Input.IsActionJustPressed("leftClick"))
{
if (_hovered)
{
_aiming = true;
_commander.LoadAttack();
}
}
if (_aiming) if (_aiming)
{ {
if (Input.IsActionJustReleased("rightClick")) if (_arcEnd != GetGlobalMousePosition())
{ {
Vector2 offset = (GlobalPosition - GetGlobalMousePosition()) * 500; DrawArc(_ballSpawn.GlobalPosition, GetGlobalMousePosition());
_commander.ShootCurrentAttack(offset); }
if (Input.IsActionJustPressed("rightClick"))
{
_commander.UnloadBall();
_aiming = false; _aiming = false;
} }
else if (Input.IsActionJustReleased("leftClick")) else if (Input.IsActionJustPressed("leftClick"))
{ {
_commander.UnloadAttack();
_aimOffset = ToLaunchVector(CalculateLaunchAngle(_ballSpawn.GlobalPosition, GetGlobalMousePosition()));
_commander.ShootCurrentBall(_aimOffset);
ClearArc();
_aiming = false; _aiming = false;
} }
} }
else if (_hovered)
{
if (Input.IsActionJustPressed("leftClick"))
{
_aiming = true;
_commander.LoadBall(_ballSpawn.Position);
}
} }
} }
public void OnMouseEntered(){
_hovered = true;
} }
public void OnMouseExited(){
_hovered = true; public float CalculateLaunchAngle(Vector2 START, Vector2 END, int MAX_ITERATIONS = 20)
{
Vector2 offset = END - START;
float baseAngle = offset.Angle();
float straightUpAngle = -Mathf.Pi / 2.0f;
float lowAngle = 0.0f;
float highAngle = 1.0f;
float bestAngle = baseAngle;
for (int i = 0; i < MAX_ITERATIONS; i++)
{
float averageAngle = (lowAngle + highAngle) / 2.0f;
float testAngle = Mathf.LerpAngle(baseAngle, straightUpAngle, averageAngle);
float error = EvaluateSimulationError(testAngle, START, END);
if (Mathf.Abs(error) < 0.2f)
{
bestAngle = testAngle;
break;
}
if (error > 0)
{
lowAngle = averageAngle;
}
else
{
highAngle = averageAngle;
}
bestAngle = testAngle;
}
if (ToLaunchVector(bestAngle).Y < 0)
{
if (END.X < START.X)
{
bestAngle = (float)Math.PI;
}
else
{
bestAngle = 0;
}
}
return bestAngle;
}
public void ClearArc()
{
Path2D path = _commander._ball.GetNode<Path2D>("PredictedPath");
path.Curve.ClearPoints();
}
public void DrawArc(Vector2 START, Vector2 END, int MAX_ITERATIONS = 20)
{
float arcAngle = CalculateLaunchAngle(START, END);
float speed = _launchSpeed, gravity = Globals._gravity, drag = Globals._drag, delta = 1.0f / 60.0f;
Vector2 velocity = new Vector2(Mathf.Cos(arcAngle), Mathf.Sin(arcAngle)) * speed;
Vector2 position = START;
float directionSign = Mathf.Sign(END.X - START.X);
float maxFlightTime = 6.0f;
int totalSteps = (int)(maxFlightTime / delta);
List<Vector2> arc = [START];
for (int step = 0; step < totalSteps; step++)
{
velocity.Y += gravity * delta;
velocity -= velocity * drag * delta;
position += velocity * delta;
arc.Add(position);
bool reachedTargetX = (directionSign >= 0) ? (position.X >= END.X) : (position.X <= END.X);
if (reachedTargetX)
{
break;
}
}
Path2D path = _commander._ball.GetNode<Path2D>("PredictedPath");
path.Curve.ClearPoints();
for (int i = 0; i < arc.Count; i++)
{
path.Curve.AddPoint(arc[i]);
}
}
private float EvaluateSimulationError(float ANGLE, Vector2 START, Vector2 TARGET)
{
float speed = _launchSpeed, gravity = Globals._gravity, drag = Globals._drag, delta = 1.0f / 60.0f;
Vector2 velocity = new Vector2(Mathf.Cos(ANGLE), Mathf.Sin(ANGLE)) * speed;
Vector2 position = START;
float directionSign = Mathf.Sign(TARGET.X - START.X);
float maxFlightTime = 6.0f;
int totalSteps = (int)(maxFlightTime / delta);
for (int step = 0; step < totalSteps; step++)
{
velocity.Y += gravity * delta;
velocity -= velocity * drag * delta;
position += velocity * delta;
bool reachedTargetX = (directionSign >= 0) ? (position.X >= TARGET.X) : (position.X <= TARGET.X);
if (reachedTargetX)
{
return position.Y - TARGET.Y;
}
}
return (position.Y > TARGET.Y) ? 99999f : -99999f;
}
public void StartTurn()
{
if (_commander != null)
{
_commander._actions = _commander._actionsMax;
}
}
public Vector2 ToLaunchVector(float ANGLE)
{
return Vector2.FromAngle(ANGLE) * _launchSpeed;
} }
} }
+8 -2
View File
@@ -1,13 +1,19 @@
using Godot; using Godot;
using System; using System;
using System.Threading.Tasks;
public partial class TurnController : Node2D public partial class TurnController : Node2D
{ {
[Signal] [Signal]
public delegate void TurnDoneEventHandler(); public delegate void TurnDoneEventHandler();
public GridMap2D _grid; public PlayArea _playArea;
public Map _map;
public virtual void StartTurn() public virtual void StartTurn()
{ {
}
public virtual void EndTurn()
{
EmitSignal(SignalName.TurnDone);
} }
} }
+20 -7
View File
@@ -1,23 +1,36 @@
[gd_scene format=3 uid="uid://cevk7yax5tvej"] [gd_scene format=3 uid="uid://cevk7yax5tvej"]
[ext_resource type="Script" uid="uid://dm2gyxmgwbmg8" path="res://Attack.cs" id="1_63pi1"] [ext_resource type="Script" uid="uid://dm2gyxmgwbmg8" path="res://Ball.cs" id="1_41u45"]
[ext_resource type="Texture2D" uid="uid://nwj4n7if8kqd" path="res://Art/circle25r.png" id="2_hqc8w"] [ext_resource type="Texture2D" uid="uid://nwj4n7if8kqd" path="res://Art/circle25r.png" id="2_ktgx5"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_63pi1"]
bounce = 0.25
[sub_resource type="CircleShape2D" id="CircleShape2D_7yfhp"] [sub_resource type="CircleShape2D" id="CircleShape2D_7yfhp"]
radius = 14.0 radius = 12.5
[node name="Attack" type="RigidBody2D" unique_id=1225359241] [sub_resource type="Curve2D" id="Curve2D_63pi1"]
[node name="Ball" type="RigidBody2D" unique_id=1225359241]
input_pickable = true input_pickable = true
physics_material_override = SubResource("PhysicsMaterial_63pi1")
contact_monitor = true contact_monitor = true
max_contacts_reported = 100 max_contacts_reported = 100
script = ExtResource("1_63pi1") script = ExtResource("1_41u45")
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1448070524] [node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1448070524]
shape = SubResource("CircleShape2D_7yfhp") shape = SubResource("CircleShape2D_7yfhp")
[node name="Sprite2D" type="Sprite2D" parent="." unique_id=1583277900] [node name="Sprite2D" type="Sprite2D" parent="." unique_id=1583277900]
scale = Vector2(0.56, 0.56) scale = Vector2(0.5, 0.5)
texture = ExtResource("2_hqc8w") texture = ExtResource("2_ktgx5")
[node name="Ray" type="RayCast2D" parent="." unique_id=113171676]
[node name="PredictedPath" type="Path2D" parent="." unique_id=1505290715]
modulate = Color(1, 0, 1, 1)
top_level = true
curve = SubResource("Curve2D_63pi1")
[connection signal="body_entered" from="." to="." method="TakeAction"] [connection signal="body_entered" from="." to="." method="TakeAction"]
[connection signal="mouse_entered" from="." to="." method="OnMouseEntered"] [connection signal="mouse_entered" from="." to="." method="OnMouseEntered"]
+24
View File
@@ -0,0 +1,24 @@
[gd_scene format=3 uid="uid://b2mb7mimdu5ad"]
[ext_resource type="Script" uid="uid://cn8hskwnfxc8f" path="res://Bucket.cs" id="2_caem6"]
[ext_resource type="Texture2D" uid="uid://dpwvh7kwkyfqi" path="res://Art/bucket_bottom.png" id="2_m1vr3"]
[ext_resource type="Texture2D" uid="uid://baukn3uw3c3c3" path="res://Art/bucket_top.png" id="3_ghrs3"]
[node name="Bucket" type="Node2D" unique_id=1168722558]
script = ExtResource("2_caem6")
[node name="Bottom" type="Sprite2D" parent="." unique_id=150417931]
texture = ExtResource("2_m1vr3")
[node name="Top" type="Sprite2D" parent="." unique_id=201162499]
texture = ExtResource("3_ghrs3")
[node name="Top2" type="Sprite2D" parent="." unique_id=203916174]
texture = ExtResource("3_ghrs3")
[node name="Area2D" type="Area2D" parent="." unique_id=1275030855]
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Area2D" unique_id=1086458018]
polygon = PackedVector2Array(-30, -39, -30, -38, -43, -38, -43, -37, -52, -37, -52, -36, -59, -36, -59, -35, -66, -35, -66, -34, -71, -34, -71, -33, -76, -33, -76, -32, -80, -32, -80, -31, -83, -31, -83, -30, -86, -30, -86, -29, -89, -29, -89, -28, -92, -28, -92, -27, -93, -27, -93, -26, -95, -26, -95, -25, -96, -25, -96, -24, -97, -24, -97, -23, -98, -23, -98, -22, -99, -22, -99, -18, -98, -18, -98, -17, -97, -17, -97, -16, -96, -16, -96, -15, -95, -15, -95, -14, -93, -14, -93, -13, -92, -13, -92, -12, -89, -12, -89, -11, -86, -11, -86, -10, -83, -10, -83, -9, -80, -9, -80, -8, -76, -8, -76, -7, -71, -7, -71, -6, -66, -6, -66, -5, -59, -5, -59, -4, -52, -4, -52, -3, -43, -3, -43, -2, -30, -2, -30, -1, 30, -1, 30, -2, 43, -2, 43, -3, 52, -3, 52, -4, 59, -4, 59, -5, 66, -5, 66, -6, 71, -6, 71, -7, 76, -7, 76, -8, 80, -8, 80, -9, 83, -9, 83, -10, 86, -10, 86, -11, 89, -11, 89, -12, 92, -12, 92, -13, 93, -13, 93, -14, 95, -14, 95, -15, 96, -15, 96, -16, 97, -16, 97, -17, 98, -17, 98, -18, 99, -18, 99, -22, 98, -22, 98, -23, 97, -23, 97, -24, 96, -24, 96, -25, 95, -25, 95, -26, 93, -26, 93, -27, 92, -27, 92, -28, 89, -28, 89, -29, 86, -29, 86, -30, 83, -30, 83, -31, 80, -31, 80, -32, 76, -32, 76, -33, 71, -33, 71, -34, 66, -34, 66, -35, 59, -35, 59, -36, 52, -36, 52, -37, 43, -37, 43, -38, 30, -38, 30, -39)
[connection signal="body_entered" from="Area2D" to="." method="OnBodyEntered"]
-21
View File
@@ -1,21 +0,0 @@
[gd_scene format=3 uid="uid://drt7w0eqp13tu"]
[ext_resource type="Script" uid="uid://dfba4vq6jv0a6" path="res://Enemy.cs" id="1_4gyqm"]
[ext_resource type="Texture2D" uid="uid://nwj4n7if8kqd" path="res://Art/circle25r.png" id="1_7k104"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_7k104"]
bounce = 0.5
[sub_resource type="CircleShape2D" id="CircleShape2D_4gyqm"]
radius = 25.0
[node name="Enemy" type="StaticBody2D" unique_id=1417697759]
scale = Vector2(0.56, 0.56)
physics_material_override = SubResource("PhysicsMaterial_7k104")
script = ExtResource("1_4gyqm")
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1762191899]
shape = SubResource("CircleShape2D_4gyqm")
[node name="Sprite2D" type="Sprite2D" parent="." unique_id=1941012605]
texture = ExtResource("1_7k104")
-6
View File
@@ -1,6 +0,0 @@
[gd_scene format=3 uid="uid://c6b188d2a20eq"]
[ext_resource type="Script" uid="uid://brsi76xcgx3et" path="res://EnemyController.cs" id="1_tkpyo"]
[node name="EnemyController" type="Node2D" unique_id=197453707]
script = ExtResource("1_tkpyo")
-42
View File
@@ -1,42 +0,0 @@
[gd_scene format=3 uid="uid://la8pwcc0tjuu"]
[ext_resource type="Script" uid="uid://bnaxgcafcvtfv" path="res://GridMap2D.cs" id="1_lq4m8"]
[ext_resource type="PackedScene" uid="uid://bxqhci3fya80t" path="res://grid_marker.tscn" id="2_gc0wv"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_q4dkg"]
size = Vector2(1600, 800)
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_7h2rc"]
bounce = 0.4
[sub_resource type="RectangleShape2D" id="RectangleShape2D_7h2rc"]
size = Vector2(400, 16)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_fjt81"]
size = Vector2(400, 16)
[node name="GridMap2D" type="Node2D" unique_id=1123610167]
script = ExtResource("1_lq4m8")
[node name="PlayArea" type="Area2D" parent="." unique_id=1719758298]
[node name="Bounds" type="CollisionShape2D" parent="PlayArea" unique_id=1902214362]
shape = SubResource("RectangleShape2D_q4dkg")
[node name="LeftEdge1" type="StaticBody2D" parent="." unique_id=1883047200]
physics_material_override = SubResource("PhysicsMaterial_7h2rc")
[node name="Bounds" type="CollisionShape2D" parent="LeftEdge1" unique_id=1546734575]
position = Vector2(-1000, -392)
shape = SubResource("RectangleShape2D_7h2rc")
debug_color = Color(0.98836404, 0, 0.30800217, 0.41960785)
[node name="RightEdge1" type="StaticBody2D" parent="." unique_id=258284814]
physics_material_override = SubResource("PhysicsMaterial_7h2rc")
[node name="Bounds" type="CollisionShape2D" parent="RightEdge1" unique_id=773927888]
position = Vector2(1000, -392)
shape = SubResource("RectangleShape2D_fjt81")
debug_color = Color(0.9882353, 0, 0.30980393, 0.41960785)
[node name="GridMarker" parent="." unique_id=1390656323 instance=ExtResource("2_gc0wv")]
-6
View File
@@ -1,6 +0,0 @@
[gd_scene format=3 uid="uid://bxqhci3fya80t"]
[ext_resource type="Script" uid="uid://cob0pwghnubxa" path="res://GridMarker.cs" id="1_u0re5"]
[node name="GridMarker" type="Marker2D" unique_id=1390656323 groups=["GridMarkers"]]
script = ExtResource("1_u0re5")
+10
View File
@@ -0,0 +1,10 @@
[gd_scene format=3 uid="uid://dse0sugndsrs"]
[ext_resource type="Script" uid="uid://dqvysa2n208d3" path="res://HoverableNode.cs" id="1_14v3m"]
[node name="HoverableNode" type="Node2D" unique_id=946672764]
script = ExtResource("1_14v3m")
[node name="HoverBounds" type="Area2D" parent="." unique_id=783465962]
[node name="CollisionShape2D" type="CollisionShape2D" parent="HoverBounds" unique_id=585114419]
+8 -5
View File
@@ -1,16 +1,19 @@
[gd_scene format=3 uid="uid://dcp7p6al4i0b7"] [gd_scene format=3 uid="uid://dcp7p6al4i0b7"]
[ext_resource type="Script" uid="uid://cg1m762ed04kv" path="res://Main.cs" id="1_ig7tw"] [ext_resource type="Script" uid="uid://cg1m762ed04kv" path="res://Main.cs" id="1_ig7tw"]
[ext_resource type="PackedScene" uid="uid://la8pwcc0tjuu" path="res://grid_map_2d.tscn" id="3_h2yge"] [ext_resource type="PackedScene" uid="uid://dumcridek4xy3" path="res://play_area.tscn" id="2_1bvp3"]
[ext_resource type="PackedScene" uid="uid://c6b188d2a20eq" path="res://enemy_controller.tscn" id="4_1bvp3"] [ext_resource type="PackedScene" uid="uid://bxlt2ap0dym1x" path="res://peg_controller.tscn" id="3_lquwl"]
[ext_resource type="PackedScene" uid="uid://b7kvx7p0b2086" path="res://player_controller.tscn" id="4_lquwl"] [ext_resource type="PackedScene" uid="uid://b7kvx7p0b2086" path="res://player_controller.tscn" id="4_lquwl"]
[ext_resource type="PackedScene" path="res://mouse_handler.tscn" id="5_lquwl"]
[node name="Main" type="Node" unique_id=535208469] [node name="Main" type="Node" unique_id=535208469]
script = ExtResource("1_ig7tw") script = ExtResource("1_ig7tw")
[node name="GridMap2D" parent="." unique_id=1123610167 instance=ExtResource("3_h2yge")] [node name="PlayArea" parent="." unique_id=1123610167 instance=ExtResource("2_1bvp3")]
position = Vector2(960, 600) position = Vector2(360, 180)
[node name="EnemyController" parent="." unique_id=1894449838 instance=ExtResource("4_1bvp3")] [node name="PegController" parent="." unique_id=197453707 instance=ExtResource("3_lquwl")]
[node name="PlayerController" parent="." unique_id=364781168 instance=ExtResource("4_lquwl")] [node name="PlayerController" parent="." unique_id=364781168 instance=ExtResource("4_lquwl")]
[node name="MouseHandler" parent="." unique_id=1823071759 instance=ExtResource("5_lquwl")]
+11
View File
@@ -0,0 +1,11 @@
[gd_scene format=3 uid="uid://cqwi2kesqh5wt"]
[ext_resource type="Script" uid="uid://b8fx1wwyj30bg" path="res://MapCell.cs" id="1_jkeij"]
[ext_resource type="Texture2D" uid="uid://c5jj7yhlnodxt" path="res://Art/star.png" id="2_ugbl7"]
[node name="MapCell" type="Node2D" unique_id=953237004]
script = ExtResource("1_jkeij")
[node name="Sprite2D" type="Sprite2D" parent="." unique_id=733491629]
scale = Vector2(0.025, 0.025)
texture = ExtResource("2_ugbl7")
+10
View File
@@ -0,0 +1,10 @@
[gd_scene format=3 uid="uid://d4nyjj5740ww5"]
[ext_resource type="Script" uid="uid://b3dlktsgeteuw" path="res://MapCellOccupant.cs" id="1_2wshj"]
[node name="MapCellOccupant" type="Node2D" unique_id=946672764]
script = ExtResource("1_2wshj")
[node name="HoverBounds" type="Area2D" parent="." unique_id=783465962]
[node name="CollisionShape2D" type="CollisionShape2D" parent="HoverBounds" unique_id=585114419]
+6
View File
@@ -0,0 +1,6 @@
[gd_scene format=3 uid="uid://by0a5f2ft0u03"]
[ext_resource type="Script" uid="uid://dewxuppyw2gtp" path="res://MouseHandler.cs" id="1_r4hv2"]
[node name="MouseHandler" type="Node2D" unique_id=215972463]
script = ExtResource("1_r4hv2")
+34
View File
@@ -0,0 +1,34 @@
[gd_scene format=3 uid="uid://01m32xxk1ryh"]
[ext_resource type="Script" uid="uid://g2ucwg3k342p" path="res://Peg.cs" id="1_cavuh"]
[ext_resource type="Texture2D" uid="uid://nwj4n7if8kqd" path="res://Art/circle25r.png" id="2_cut4e"]
[ext_resource type="PackedScene" uid="uid://bj2qrn0l01us1" path="res://Pegs/peg_action.tscn" id="3_cavuh"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_7k104"]
bounce = 0.5
[sub_resource type="CircleShape2D" id="CircleShape2D_4gyqm"]
radius = 12.5
[node name="Peg" type="StaticBody2D" unique_id=1417697759]
input_pickable = true
physics_material_override = SubResource("PhysicsMaterial_7k104")
script = ExtResource("1_cavuh")
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1762191899]
shape = SubResource("CircleShape2D_4gyqm")
[node name="Sprite2D" type="Sprite2D" parent="." unique_id=1941012605]
texture_filter = 1
scale = Vector2(0.5, 0.5)
texture = ExtResource("2_cut4e")
[node name="PegAction" parent="." unique_id=637569115 instance=ExtResource("3_cavuh")]
[node name="HoverBounds" type="Area2D" parent="." unique_id=2086452813]
[node name="CollisionShape2D" type="CollisionShape2D" parent="HoverBounds" unique_id=252175102]
shape = SubResource("CircleShape2D_4gyqm")
[connection signal="mouse_entered" from="." to="." method="OnMouseEntered"]
[connection signal="mouse_exited" from="." to="." method="OnMouseExited"]
+6
View File
@@ -0,0 +1,6 @@
[gd_scene format=3 uid="uid://bxlt2ap0dym1x"]
[ext_resource type="Script" path="res://PegController.cs" id="1_31br5"]
[node name="PegController" type="Node2D" unique_id=197453707]
script = ExtResource("1_31br5")
+109
View File
File diff suppressed because one or more lines are too long
+4
View File
@@ -2,8 +2,12 @@
[ext_resource type="Script" uid="uid://cfohujgs5dygx" path="res://PlayerController.cs" id="1_lvefo"] [ext_resource type="Script" uid="uid://cfohujgs5dygx" path="res://PlayerController.cs" id="1_lvefo"]
[ext_resource type="PackedScene" uid="uid://d06n7p75u130s" path="res://tower.tscn" id="2_f0yg5"] [ext_resource type="PackedScene" uid="uid://d06n7p75u130s" path="res://tower.tscn" id="2_f0yg5"]
[ext_resource type="PackedScene" uid="uid://b2mb7mimdu5ad" path="res://bucket.tscn" id="3_va7e3"]
[node name="PlayerController" type="Node2D" unique_id=317732890] [node name="PlayerController" type="Node2D" unique_id=317732890]
script = ExtResource("1_lvefo") script = ExtResource("1_lvefo")
[node name="Tower1" parent="." unique_id=1315831332 instance=ExtResource("2_f0yg5")] [node name="Tower1" parent="." unique_id=1315831332 instance=ExtResource("2_f0yg5")]
[node name="Bucket" parent="." unique_id=1168722558 instance=ExtResource("3_va7e3")]
position = Vector2(960, 1040)
+10
View File
@@ -46,6 +46,16 @@ rightClick={
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":2,"position":Vector2(109, 18),"global_position":Vector2(118, 66),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null) "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":2,"position":Vector2(109, 18),"global_position":Vector2(118, 66),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null)
] ]
} }
changeTurn={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":84,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
middleClick={
"deadzone": 0.2,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":4,"position":Vector2(222, 10),"global_position":Vector2(231, 58),"factor":1.0,"button_index":3,"canceled":false,"pressed":true,"double_click":false,"script":null)
]
}
[physics] [physics]
+11 -5
View File
@@ -4,19 +4,25 @@
[ext_resource type="Texture2D" uid="uid://32m5teus1cjj" path="res://Art/tower.png" id="1_vedim"] [ext_resource type="Texture2D" uid="uid://32m5teus1cjj" path="res://Art/tower.png" id="1_vedim"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_vedim"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_vedim"]
size = Vector2(50, 99) size = Vector2(50, 100)
[node name="Tower" type="Sprite2D" unique_id=1315831332] [node name="Tower" type="Sprite2D" unique_id=1315831332]
self_modulate = Color(0, 0, 0, 1) self_modulate = Color(0, 0, 0, 1)
texture = ExtResource("1_vedim") texture = ExtResource("1_vedim")
script = ExtResource("1_k1sas") script = ExtResource("1_k1sas")
[node name="Area" type="Area2D" parent="." unique_id=620986087] [node name="HoverBounds" type="Area2D" parent="." unique_id=620986087]
[node name="Bounds" type="CollisionShape2D" parent="Area" unique_id=1639875880] [node name="CollisionShape2D" type="CollisionShape2D" parent="HoverBounds" unique_id=1639875880]
position = Vector2(0, 0.5) position = Vector2(0, 0.5)
shape = SubResource("RectangleShape2D_vedim") shape = SubResource("RectangleShape2D_vedim")
debug_color = Color(0.6411928, 0.52469516, 0, 0.41960785) debug_color = Color(0.6411928, 0.52469516, 0, 0.41960785)
[connection signal="mouse_entered" from="Area" to="." method="OnMouseEntered"] [node name="Offset" type="Marker2D" parent="." unique_id=2053853274]
[connection signal="mouse_exited" from="Area" to="." method="OnMouseExited"] position = Vector2(25, -50)
[node name="BallSpawn" type="Marker2D" parent="." unique_id=715904909]
position = Vector2(0, -24)
[connection signal="mouse_entered" from="HoverBounds" to="." method="OnMouseEntered"]
[connection signal="mouse_exited" from="HoverBounds" to="." method="OnMouseExited"]