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
This commit is contained in:
+3
-2
@@ -19,8 +19,7 @@ public partial class Commander : Sprite2D
|
||||
{
|
||||
if (_attack.Position.Y > GetViewportRect().Size.Y + 50)
|
||||
{
|
||||
_attack.QueueFree();
|
||||
_attack = null;
|
||||
UnloadAttack();
|
||||
if (_actions <= 0)
|
||||
{
|
||||
EmitSignal(SignalName.ActionsUp);
|
||||
@@ -32,6 +31,7 @@ public partial class Commander : Sprite2D
|
||||
public void AttackEnteredBucket()
|
||||
{
|
||||
_actions += (_actions + 1) > _actionsMax ? 0 : 1;
|
||||
UnloadAttack();
|
||||
}
|
||||
|
||||
public void LoadAttack(Vector2 OFFSET)
|
||||
@@ -65,5 +65,6 @@ public partial class Commander : Sprite2D
|
||||
public void UnloadAttack()
|
||||
{
|
||||
_attack.QueueFree();
|
||||
_attack = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,10 @@ public partial class Enemy : StaticBody2D
|
||||
{
|
||||
[Signal]
|
||||
public delegate void DeathEventHandler(Enemy THIS);
|
||||
public int _damage = 1, _health = 2, _speed, _visibilityRange = 10;
|
||||
public bool _hovered = false;
|
||||
public int _damage = 1, _health = 2, _speed, _speedRemaining, _visibilityRange = 4;
|
||||
public Vector2I _address, _range = Vector2I.Up;
|
||||
public List<Vector2I> _path = new();
|
||||
public float _movement = 0;
|
||||
public EnemyController _enemyController;
|
||||
|
||||
@@ -40,4 +42,11 @@ public partial class Enemy : StaticBody2D
|
||||
EmitSignal(SignalName.Death, this);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnMouseEntered(){
|
||||
_hovered = true;
|
||||
}
|
||||
public void OnMouseExited(){
|
||||
_hovered = true;
|
||||
}
|
||||
}
|
||||
|
||||
+59
-19
@@ -35,6 +35,7 @@ public partial class EnemyController : TurnController
|
||||
newEnemy.Death += RemoveEnemy;
|
||||
|
||||
newEnemy._speed = Globals._rng.Next(2,4+1);
|
||||
newEnemy._speed = 3;
|
||||
newEnemy.Modulate = new Color(newEnemy._speed == 2 ? "#FF0000" : newEnemy._speed == 3 ? "#00FF00" : "#0000FF");
|
||||
newEnemy._enemyController = this;
|
||||
|
||||
@@ -56,33 +57,69 @@ public partial class EnemyController : TurnController
|
||||
{
|
||||
Tween tween = CreateTween();
|
||||
tween.SetParallel();
|
||||
Dictionary<Enemy, List<Vector2I>> enemyPaths = new();
|
||||
Dictionary<Enemy, int> enemyOffsets = new();
|
||||
_enemies = [.. _enemies.OrderBy(e => e._address.Y).ThenBy(e => e._address.X)];
|
||||
|
||||
for (int i = 0; i < _enemies.Count; i++)
|
||||
{
|
||||
Enemy enemy = _enemies[i];
|
||||
List<Vector2I> path = _playArea._map.GetPath(enemy._address, new Vector2I(enemy._address.X, _playArea._map._minY));
|
||||
enemyPaths[enemy] = path;
|
||||
enemyOffsets[enemy] = 0;
|
||||
Vector2I goal = new(enemy._address.X, _playArea._map._minY);
|
||||
if (Math.Abs(goal.Y - enemy._address.Y) <= enemy._visibilityRange)
|
||||
{
|
||||
// GD.Print(goal.Y, enemy._address.Y,enemy._visibilityRange);
|
||||
while(_playArea._map.IsRowFull(goal.Y))
|
||||
{
|
||||
goal.Y++;
|
||||
}
|
||||
// if (_playArea._map.GetOccupant(goal) != null)
|
||||
// {
|
||||
// goal.X = Math.Clamp(goal.X+1, _playArea._map._minX+1, _playArea._map._maxX-1);
|
||||
// }
|
||||
int loop = 0;
|
||||
while (_playArea._map.GetOccupant(goal) != null)
|
||||
{
|
||||
goal.X = Math.Clamp(enemy._address.X + ((int)MathF.Floor(loop / 2) + 1) * (loop % 2 == 0 ? 1 : -1), _playArea._map._minX, _playArea._map._maxX);
|
||||
loop++;
|
||||
}
|
||||
}
|
||||
List<Vector2I> path = _playArea._map.GetPath(enemy._address, goal);
|
||||
enemy._path = path;
|
||||
enemy._speedRemaining = enemy._address.Y <= _playArea._map._minY ? 0 : enemy._speed;
|
||||
}
|
||||
_enemies = [.. _enemies.OrderByDescending(e => e._path.Count).ThenBy(e => e._address.Y).ThenBy(e => Math.Abs(e._address.X))];
|
||||
int maxSpeed = _enemies.Max(e => e._speedRemaining);
|
||||
|
||||
int maxSpeed = _enemies.Max(e => e._speed);
|
||||
List<Enemy> remainingEnemies = [.. _enemies];
|
||||
|
||||
for (int i = 0; i < maxSpeed; i++)
|
||||
{
|
||||
for (int j = 0; j < _enemies.Count; j++)
|
||||
for (int j = 0; j < remainingEnemies.Count; j++)
|
||||
{
|
||||
Enemy enemy = _enemies[j];
|
||||
int offset = enemyOffsets[enemy];
|
||||
if (i >= enemy._speed - offset)
|
||||
Enemy enemy = remainingEnemies[j];
|
||||
if (enemy._speedRemaining <= 0)
|
||||
{
|
||||
remainingEnemies.Remove(enemy);
|
||||
continue;
|
||||
}
|
||||
List<Vector2I> path = enemyPaths[enemy];
|
||||
Vector2I cell = path[i - offset];
|
||||
List<Vector2I> path = enemy._path;
|
||||
int pathIndex = enemy._speed - enemy._speedRemaining;
|
||||
Vector2I cell = path[pathIndex];
|
||||
Enemy obstacle = _playArea._map.GetOccupant(cell);
|
||||
if (obstacle != null)
|
||||
{
|
||||
int obstacleRemainingMoves = obstacle._speedRemaining;
|
||||
if (obstacleRemainingMoves <= 0)
|
||||
{
|
||||
_playArea._map.EvaluateSolidCells();
|
||||
List<Vector2I> newPath = _playArea._map.GetPath(enemy._address, new Vector2I(enemy._address.X, _playArea._map._minY));
|
||||
enemy._path = newPath;
|
||||
|
||||
if (_playArea._map.GetOccupant(cell) == null)
|
||||
newPath.InsertRange(0, [.. Enumerable.Repeat(newPath[0], pathIndex)]);
|
||||
|
||||
cell = enemy._path[pathIndex];
|
||||
obstacle = _playArea._map.GetOccupant(cell);
|
||||
}
|
||||
}
|
||||
|
||||
if (obstacle == null)
|
||||
{
|
||||
_playArea._map.SetCellEnemy(enemy._address, null);
|
||||
enemy._address = cell;
|
||||
@@ -96,12 +133,14 @@ public partial class EnemyController : TurnController
|
||||
tween.Parallel();
|
||||
}
|
||||
tween.TweenProperty(enemy, "global_position", _playArea._map.GetCellPositionFromAddress(enemy._address), .2f);
|
||||
}
|
||||
else
|
||||
{
|
||||
enemyOffsets[enemy]++;
|
||||
}
|
||||
|
||||
if (enemy._address.Y <= _playArea._map._minY)
|
||||
{
|
||||
remainingEnemies.Remove(enemy);
|
||||
continue;
|
||||
}
|
||||
enemy._speedRemaining--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +150,7 @@ public partial class EnemyController : TurnController
|
||||
public void RemoveEnemy(Enemy ENEMY_TO_REMOVE)
|
||||
{
|
||||
_enemies.Remove(ENEMY_TO_REMOVE);
|
||||
_playArea._map.SetCellEnemy(ENEMY_TO_REMOVE._address, null);
|
||||
ENEMY_TO_REMOVE.QueueFree();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,13 @@ public partial class Main : Node
|
||||
{
|
||||
GetTree().Quit();
|
||||
}
|
||||
if (Input.IsActionJustPressed("changeTurn"))
|
||||
{
|
||||
if(_turnController == _playerController)
|
||||
{
|
||||
ChangeTurn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeTurn()
|
||||
|
||||
@@ -17,11 +17,12 @@ public partial class Map : TileMapLayer
|
||||
{
|
||||
base._Ready();
|
||||
_cellSize = TileSet.TileSize;
|
||||
List<Vector2I> cells = GetUsedCells().ToList();
|
||||
List<Vector2I> cells = [.. GetUsedCells()];
|
||||
_minX = cells.Min(c => c.X);
|
||||
_maxX = cells.Max(c => c.X);
|
||||
_minY = cells.Min(c => c.Y);
|
||||
_maxY = cells.Max(c => c.Y);
|
||||
// GD.Print(_minX, _maxX, _minY, _maxY);
|
||||
_leftmostColumn = [.. cells.Where(c => c.X == _minX)];
|
||||
_rightmostColumn = [.. cells.Where(c => c.X == _maxX)];
|
||||
_topRow = [.. cells.Where(c => c.Y == _minY)];
|
||||
@@ -51,6 +52,14 @@ public partial class Map : TileMapLayer
|
||||
return hasOccupant || isSolid;
|
||||
}
|
||||
|
||||
public bool IsRowFull(int ROW_TO_CHECK)
|
||||
{
|
||||
List<Vector2I> cells = [.. GetUsedCells()];
|
||||
List<Vector2I> rowCells = [.. cells.Where(c => c.Y == ROW_TO_CHECK)];
|
||||
|
||||
return rowCells.All(c => GetOccupant(c) != null);
|
||||
}
|
||||
|
||||
public void SetCellEnemy(Vector2I ADDRESS, Enemy ENEMY)
|
||||
{
|
||||
_addressOccupants[ADDRESS] = ENEMY;
|
||||
@@ -89,4 +98,9 @@ public partial class Map : TileMapLayer
|
||||
return pathTaken;
|
||||
}
|
||||
|
||||
public void EvaluateSolidCells()
|
||||
{
|
||||
GetUsedCells().ToList().ForEach(c => IsCellSolid(c));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-3
@@ -1,7 +1,7 @@
|
||||
[gd_scene format=4 uid="uid://dumcridek4xy3"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bnaxgcafcvtfv" path="res://PlayArea.cs" id="1_lq4m8"]
|
||||
[ext_resource type="PackedScene" uid="uid://mjinvqj25wha" path="res://Map.tscn" id="2_wqv88"]
|
||||
[ext_resource type="PackedScene" path="res://Map.tscn" id="2_wqv88"]
|
||||
[ext_resource type="Texture2D" uid="uid://cf554xlykq1o4" path="res://Art/tile_set.png" id="3_md2b6"]
|
||||
[ext_resource type="PackedScene" uid="uid://b2mb7mimdu5ad" path="res://bucket.tscn" id="5_vqhsw"]
|
||||
|
||||
@@ -14,7 +14,7 @@ size = Vector2(400, 1000)
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_7h2rc"]
|
||||
size = Vector2(400, 80)
|
||||
|
||||
[sub_resource type="TileMapPattern" id="TileMapPattern_vqhsw"]
|
||||
[sub_resource type="TileMapPattern" id="TileMapPattern_xy0lb"]
|
||||
tile_data = PackedInt32Array(0, 0, 0, 65536, 0, 1, 1, 0, 1, 65537, 0, 0)
|
||||
|
||||
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_vqhsw"]
|
||||
@@ -38,7 +38,7 @@ tile_size = Vector2i(40, 40)
|
||||
custom_data_layer_0/name = "is_solid"
|
||||
custom_data_layer_0/type = 1
|
||||
sources/0 = SubResource("TileSetAtlasSource_vqhsw")
|
||||
pattern_0 = SubResource("TileMapPattern_vqhsw")
|
||||
pattern_0 = SubResource("TileMapPattern_xy0lb")
|
||||
|
||||
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_xy0lb"]
|
||||
texture = ExtResource("3_md2b6")
|
||||
@@ -233,5 +233,6 @@ tile_set = SubResource("TileSet_he03c")
|
||||
position = Vector2(0, 440)
|
||||
|
||||
[node name="InitialPositions" type="TileMapLayer" parent="." unique_id=555896823]
|
||||
visible = false
|
||||
tile_map_data = PackedByteArray("AAD0//3/AAADAAEAAAD1//z/AAADAAEAAAD1//7/AAADAAEAAAD2//3/AAADAAEAAAD5/wMAAAADAAEAAAD4/wIAAAADAAEAAAD6/wQAAAADAAEAAAD7/wMAAAADAAEAAAD8/wQAAAADAAEAAAD9/wMAAAADAAEAAAD+/wQAAAADAAEAAAD//wMAAAADAAEAAAAAAAMAAAADAAEAAAABAAQAAAADAAEAAAACAAMAAAADAAEAAAADAAQAAAADAAEAAAAEAAMAAAADAAEAAAAFAAQAAAADAAEAAAAGAAMAAAADAAEAAAAHAAIAAAADAAEAAAD8////AAADAAEAAAD9//7/AAADAAEAAAD+//3/AAADAAEAAAD///7/AAADAAEAAAAAAP7/AAADAAEAAAABAP3/AAADAAEAAAACAP7/AAADAAEAAAADAP//AAADAAEAAAAJAP3/AAADAAEAAAAKAP7/AAADAAEAAAALAP3/AAADAAEAAAAKAPz/AAADAAEAAAA=")
|
||||
tile_set = SubResource("TileSet_vqhsw")
|
||||
|
||||
@@ -29,7 +29,8 @@ public partial class Tower : Sprite2D
|
||||
{
|
||||
if (_arcEnd != GetGlobalMousePosition())
|
||||
{
|
||||
DrawArc(_attackSpawn.GlobalPosition, GetGlobalMousePosition());
|
||||
float arcAngle = CalculateLaunchAngle(_attackSpawn.GlobalPosition, GetGlobalMousePosition());
|
||||
DrawArc(arcAngle, _attackSpawn.GlobalPosition, GetGlobalMousePosition());
|
||||
}
|
||||
if (Input.IsActionJustPressed("rightClick"))
|
||||
{
|
||||
@@ -39,7 +40,7 @@ public partial class Tower : Sprite2D
|
||||
else if (Input.IsActionJustPressed("leftClick"))
|
||||
{
|
||||
|
||||
_aimOffset = CalculateLaunchAngle(_attackSpawn.GlobalPosition, GetGlobalMousePosition());
|
||||
_aimOffset = ToLaunchVector(CalculateLaunchAngle(_attackSpawn.GlobalPosition, GetGlobalMousePosition()));
|
||||
|
||||
_commander.ShootCurrentAttack(_aimOffset);
|
||||
|
||||
@@ -58,7 +59,7 @@ public partial class Tower : Sprite2D
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 CalculateLaunchAngle(Vector2 START, Vector2 END, int MAX_ITERATIONS = 20)
|
||||
public float CalculateLaunchAngle(Vector2 START, Vector2 END, int MAX_ITERATIONS = 20)
|
||||
{
|
||||
Vector2 offset = END - START;
|
||||
float baseAngle = offset.Angle();
|
||||
@@ -95,8 +96,9 @@ public partial class Tower : Sprite2D
|
||||
|
||||
bestAngle = testAngle;
|
||||
}
|
||||
bestAngle = (float)Mathf.Clamp(bestAngle, Math.PI, Math.PI * 2);
|
||||
|
||||
return Vector2.FromAngle(bestAngle) * _launchSpeed;
|
||||
return bestAngle;
|
||||
}
|
||||
|
||||
public void ClearArc()
|
||||
@@ -105,16 +107,40 @@ public partial class Tower : Sprite2D
|
||||
path.Curve.ClearPoints();
|
||||
}
|
||||
|
||||
public void DrawArc(Vector2 START, Vector2 END, int MAX_ITERATIONS = 20)
|
||||
public void DrawArc(float ANGLE, Vector2 START, Vector2 END, int MAX_ITERATIONS = 20)
|
||||
{
|
||||
CalculateLaunchAngle(START, END);
|
||||
|
||||
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(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._attack.GetNode<Path2D>("PredictedPath");
|
||||
path.Curve.ClearPoints();
|
||||
|
||||
for (int i = 0; i < _arc.Count; i++)
|
||||
for (int i = 0; i < arc.Count; i++)
|
||||
{
|
||||
path.Curve.AddPoint(_arc[i]);
|
||||
path.Curve.AddPoint(arc[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,14 +153,12 @@ public partial class Tower : Sprite2D
|
||||
float directionSign = Mathf.Sign(TARGET.X - START.X);
|
||||
float maxFlightTime = 6.0f;
|
||||
int totalSteps = (int)(maxFlightTime / delta);
|
||||
_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 >= TARGET.X) : (position.X <= TARGET.X);
|
||||
|
||||
@@ -144,7 +168,6 @@ public partial class Tower : Sprite2D
|
||||
}
|
||||
}
|
||||
|
||||
_arcEnd = _arc[^1];
|
||||
return (position.Y > TARGET.Y) ? 99999f : -99999f;
|
||||
}
|
||||
|
||||
@@ -156,6 +179,11 @@ public partial class Tower : Sprite2D
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 ToLaunchVector(float ANGLE)
|
||||
{
|
||||
return Vector2.FromAngle(ANGLE) * _launchSpeed;
|
||||
}
|
||||
|
||||
public void OnMouseEntered(){
|
||||
_hovered = true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[gd_scene format=3 uid="uid://dcp7p6al4i0b7"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cg1m762ed04kv" path="res://Main.cs" id="1_ig7tw"]
|
||||
[ext_resource type="PackedScene" path="res://PlayArea.tscn" id="2_1bvp3"]
|
||||
[ext_resource type="PackedScene" uid="uid://dumcridek4xy3" path="res://PlayArea.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://b7kvx7p0b2086" path="res://player_controller.tscn" id="4_lquwl"]
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
script = ExtResource("1_ig7tw")
|
||||
|
||||
[node name="PlayArea" parent="." unique_id=1123610167 instance=ExtResource("2_1bvp3")]
|
||||
position = Vector2(960, 510)
|
||||
position = Vector2(931, 542)
|
||||
|
||||
[node name="EnemyController" parent="." unique_id=1894449838 instance=ExtResource("4_1bvp3")]
|
||||
|
||||
|
||||
@@ -46,6 +46,11 @@ 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)
|
||||
]
|
||||
}
|
||||
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)
|
||||
]
|
||||
}
|
||||
|
||||
[physics]
|
||||
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ debug_color = Color(0.6411928, 0.52469516, 0, 0.41960785)
|
||||
position = Vector2(25, -50)
|
||||
|
||||
[node name="AttackSpawn" type="Marker2D" parent="." unique_id=715904909]
|
||||
position = Vector2(0, 50)
|
||||
position = Vector2(0, -24)
|
||||
|
||||
[connection signal="mouse_entered" from="Area" to="." method="OnMouseEntered"]
|
||||
[connection signal="mouse_exited" from="Area" to="." method="OnMouseExited"]
|
||||
|
||||
Reference in New Issue
Block a user