✨ Miner tile
This commit is contained in:
		| @@ -19,7 +19,7 @@ | |||||||
| 	"buildTime": 3.0, | 	"buildTime": 3.0, | ||||||
| 	"allowedRotations": [0], | 	"allowedRotations": [0], | ||||||
| 	"layer": 1, | 	"layer": 1, | ||||||
| 	"size": [3, 3] | 	"size": [1, 1] | ||||||
|   }, |   }, | ||||||
|   "ground": { |   "ground": { | ||||||
| 	"scene": "res://Scenes/Tiles/GroundTile.tscn", | 	"scene": "res://Scenes/Tiles/GroundTile.tscn", | ||||||
|   | |||||||
| @@ -38,10 +38,8 @@ Inventory = NodePath("../ResourceSystem") | |||||||
| position = Vector2(-496, -245) | position = Vector2(-496, -245) | ||||||
| ItemId = "stone" | ItemId = "stone" | ||||||
| Quantity = 64 | Quantity = 64 | ||||||
| Infinite = true |  | ||||||
|  |  | ||||||
| [node name="ItemPickup2" parent="." instance=ExtResource("7_is6ib")] | [node name="ItemPickup2" parent="." instance=ExtResource("7_is6ib")] | ||||||
| position = Vector2(-495, 5) | position = Vector2(-495, 5) | ||||||
| ItemId = "ore_iron" | ItemId = "ore_iron" | ||||||
| Quantity = 16 | Quantity = 16 | ||||||
| Infinite = true |  | ||||||
|   | |||||||
| @@ -4,18 +4,17 @@ | |||||||
| [ext_resource type="Script" uid="uid://qgcue2doj2lf" path="res://Scripts/System/ItemPickup.cs" id="1_ps3kh"] | [ext_resource type="Script" uid="uid://qgcue2doj2lf" path="res://Scripts/System/ItemPickup.cs" id="1_ps3kh"] | ||||||
|  |  | ||||||
| [sub_resource type="RectangleShape2D" id="RectangleShape2D_4weev"] | [sub_resource type="RectangleShape2D" id="RectangleShape2D_4weev"] | ||||||
| size = Vector2(160, 160) | size = Vector2(50, 50) | ||||||
|  |  | ||||||
| [node name="ItemPickup" type="Node2D"] | [node name="ItemPickup" type="Area2D"] | ||||||
| script = ExtResource("1_ps3kh") | script = ExtResource("1_ps3kh") | ||||||
|  | MagnetRange = 96.0 | ||||||
|  |  | ||||||
| [node name="Sprite2D" type="Sprite2D" parent="."] | [node name="Sprite2D" type="Sprite2D" parent="."] | ||||||
| scale = Vector2(0.05, 0.05) | scale = Vector2(0.05, 0.05) | ||||||
| texture = ExtResource("1_4weev") | texture = ExtResource("1_4weev") | ||||||
|  |  | ||||||
| [node name="Area2D" type="Area2D" parent="."] | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] | ||||||
|  |  | ||||||
| [node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] |  | ||||||
| shape = SubResource("RectangleShape2D_4weev") | shape = SubResource("RectangleShape2D_4weev") | ||||||
|  |  | ||||||
| [node name="Label" type="Label" parent="."] | [node name="Label" type="Label" parent="."] | ||||||
|   | |||||||
| @@ -1,14 +1,15 @@ | |||||||
| [gd_scene load_steps=4 format=3 uid="uid://cbu81slklwq3u"] | [gd_scene load_steps=5 format=3 uid="uid://cbu81slklwq3u"] | ||||||
|  |  | ||||||
| [ext_resource type="Script" uid="uid://dyubkyqtpcg3a" path="res://Scripts/Tiles/MinerTile.cs" id="1_mecoy"] | [ext_resource type="Script" uid="uid://dyubkyqtpcg3a" path="res://Scripts/Tiles/MinerTile.cs" id="1_mecoy"] | ||||||
| [ext_resource type="Texture2D" uid="uid://bt6xmcgrbb078" path="res://Scenes/Tiles/MinerTile.png" id="2_mecoy"] | [ext_resource type="Texture2D" uid="uid://bt6xmcgrbb078" path="res://Scenes/Tiles/MinerTile.png" id="2_mecoy"] | ||||||
|  | [ext_resource type="PackedScene" uid="uid://xwkplaxmye3v" path="res://Scenes/System/ItemPickup.tscn" id="2_xhk0k"] | ||||||
|  |  | ||||||
| [sub_resource type="RectangleShape2D" id="RectangleShape2D_8o613"] | [sub_resource type="RectangleShape2D" id="RectangleShape2D_8o613"] | ||||||
| size = Vector2(54, 54) | size = Vector2(54, 54) | ||||||
|  |  | ||||||
| [node name="MinerTile" type="StaticBody2D"] | [node name="MinerTile" type="StaticBody2D"] | ||||||
| scale = Vector2(3, 3) |  | ||||||
| script = ExtResource("1_mecoy") | script = ExtResource("1_mecoy") | ||||||
|  | ItemPickup = ExtResource("2_xhk0k") | ||||||
| TileId = "miner" | TileId = "miner" | ||||||
|  |  | ||||||
| [node name="Sprite2D" type="Sprite2D" parent="."] | [node name="Sprite2D" type="Sprite2D" parent="."] | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ using Godot; | |||||||
|  |  | ||||||
| namespace AceFieldNewHorizon.Scripts.System; | namespace AceFieldNewHorizon.Scripts.System; | ||||||
|  |  | ||||||
| public partial class ItemPickup : Node2D | public partial class ItemPickup : Area2D | ||||||
| { | { | ||||||
|     public const string PickupGroupName = "ItemPickupTarget"; |     public const string PickupGroupName = "ItemPickupTarget"; | ||||||
|  |  | ||||||
| @@ -19,8 +19,7 @@ public partial class ItemPickup : Node2D | |||||||
|     // Called when the node enters the scene tree |     // Called when the node enters the scene tree | ||||||
|     public override void _Ready() |     public override void _Ready() | ||||||
|     { |     { | ||||||
|         var area = GetNode<Area2D>("Area2D"); |         BodyEntered += OnBodyEntered; | ||||||
|         area.BodyEntered += OnBodyEntered; |  | ||||||
|  |  | ||||||
|         _sprite = GetNode<Sprite2D>("Sprite2D"); |         _sprite = GetNode<Sprite2D>("Sprite2D"); | ||||||
|         UpdateTexture(); |         UpdateTexture(); | ||||||
| @@ -114,7 +113,29 @@ public partial class ItemPickup : Node2D | |||||||
|         if (body.IsInGroup(PickupGroupName)) |         if (body.IsInGroup(PickupGroupName)) | ||||||
|         { |         { | ||||||
|             if (body.HasMethod("AddItem")) |             if (body.HasMethod("AddItem")) | ||||||
|  |             { | ||||||
|  |                 // First check if we can merge with existing items | ||||||
|  |                 if (body.HasMethod("HasItem")) | ||||||
|  |                 { | ||||||
|  |                     var hasItem = (bool)body.Call("HasItem", ItemId); | ||||||
|  |                     if (hasItem && body.HasMethod("GetItemQuantity")) | ||||||
|  |                     { | ||||||
|  |                         // Get current quantity and add to it | ||||||
|  |                         var currentQuantity = (int)body.Call("GetItemQuantity", ItemId); | ||||||
|  |                         body.Call("SetItemQuantity", ItemId, currentQuantity + Quantity); | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         // No existing item, add as new | ||||||
|                         body.Call("AddItem", ItemId, Quantity); |                         body.Call("AddItem", ItemId, Quantity); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     // Fallback to original behavior if HasItem method doesn't exist | ||||||
|  |                     body.Call("AddItem", ItemId, Quantity); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|             if (!Infinite) |             if (!Infinite) | ||||||
|                 QueueFree(); // remove the pickup from the world |                 QueueFree(); // remove the pickup from the world | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ using Godot; | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using AceFieldNewHorizon.Scripts.Entities; | using AceFieldNewHorizon.Scripts.Entities; | ||||||
|  | using AceFieldNewHorizon.Scripts.Tiles; | ||||||
|  |  | ||||||
| namespace AceFieldNewHorizon.Scripts.System; | namespace AceFieldNewHorizon.Scripts.System; | ||||||
|  |  | ||||||
| @@ -376,7 +377,7 @@ public partial class NaturalResourceGenerator : Node2D | |||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (scene.Instantiate() is not Node2D instance) |             if (scene.Instantiate() is not BaseTile instance) | ||||||
|             { |             { | ||||||
|                 GD.PrintErr($"{LogPrefix} Failed to instantiate scene for: {tileType}"); |                 GD.PrintErr($"{LogPrefix} Failed to instantiate scene for: {tileType}"); | ||||||
|                 return false; |                 return false; | ||||||
| @@ -387,6 +388,7 @@ public partial class NaturalResourceGenerator : Node2D | |||||||
|             var offset = GridUtils.GetCenterOffset(rotatedSize, 0f); // 0f for no rotation |             var offset = GridUtils.GetCenterOffset(rotatedSize, 0f); // 0f for no rotation | ||||||
|             instance.GlobalPosition = GridUtils.GridToWorld(cell) + offset; |             instance.GlobalPosition = GridUtils.GridToWorld(cell) + offset; | ||||||
|             instance.ZIndex = (int)building.Layer; |             instance.ZIndex = (int)building.Layer; | ||||||
|  |             instance.Grid = Grid; | ||||||
|             AddChild(instance); |             AddChild(instance); | ||||||
|             Grid.OccupyArea(cell, instance, building.Size, 0f, building.Layer); |             Grid.OccupyArea(cell, instance, building.Size, 0f, building.Layer); | ||||||
|             // GD.Print($"{LogPrefix} Successfully placed {tileType} at {cell}"); |             // GD.Print($"{LogPrefix} Successfully placed {tileType} at {cell}"); | ||||||
|   | |||||||
| @@ -199,6 +199,7 @@ public partial class PlacementManager : Node2D | |||||||
|             var scene = building.Scene; |             var scene = building.Scene; | ||||||
|  |  | ||||||
|             _ghostBuilding = (BaseTile)scene.Instantiate(); |             _ghostBuilding = (BaseTile)scene.Instantiate(); | ||||||
|  |             _ghostBuilding.Grid = Grid; | ||||||
|             _ghostBuilding.SetGhostMode(true); |             _ghostBuilding.SetGhostMode(true); | ||||||
|             _ghostBuilding.RotationDegrees = _currentRotation; |             _ghostBuilding.RotationDegrees = _currentRotation; | ||||||
|             _ghostBuilding.ZAsRelative = false; |             _ghostBuilding.ZAsRelative = false; | ||||||
| @@ -232,6 +233,7 @@ public partial class PlacementManager : Node2D | |||||||
|             // Create the building instance first |             // Create the building instance first | ||||||
|             var scene = building.Scene; |             var scene = building.Scene; | ||||||
|             var buildingInstance = (BaseTile)scene.Instantiate(); |             var buildingInstance = (BaseTile)scene.Instantiate(); | ||||||
|  |             buildingInstance.Grid = Grid; | ||||||
|             buildingInstance.RotationDegrees = _currentRotation; |             buildingInstance.RotationDegrees = _currentRotation; | ||||||
|             buildingInstance.ZIndex = (int)building.Layer; |             buildingInstance.ZIndex = (int)building.Layer; | ||||||
|             buildingInstance.Position = _ghostBuilding.Position; |             buildingInstance.Position = _ghostBuilding.Position; | ||||||
|   | |||||||
| @@ -9,12 +9,15 @@ namespace AceFieldNewHorizon.Scripts.Tiles; | |||||||
| public partial class BaseTile : Node2D | public partial class BaseTile : Node2D | ||||||
| { | { | ||||||
|     [Export] public string TileId { get; set; } |     [Export] public string TileId { get; set; } | ||||||
|  |     [Export] public GridManager Grid { get; set; } | ||||||
|  |  | ||||||
|     private CollisionShape2D _collisionShape; |     private CollisionShape2D _collisionShape; | ||||||
|     private Sprite2D _sprite; |     private Sprite2D _sprite; | ||||||
|     private ColorRect _progressOverlay; |     private ColorRect _progressOverlay; | ||||||
|     private Action _onConstructionComplete; |     private Action _onConstructionComplete; | ||||||
|     private bool _isConstructing = false; |      | ||||||
|  |     public bool IsConstructing; | ||||||
|  |     public bool IsConstructed; | ||||||
|  |  | ||||||
|     public override void _Ready() |     public override void _Ready() | ||||||
|     { |     { | ||||||
| @@ -28,7 +31,7 @@ public partial class BaseTile : Node2D | |||||||
|     public void SetGhostMode(bool canPlace) |     public void SetGhostMode(bool canPlace) | ||||||
|     { |     { | ||||||
|         // Don't modify collision for constructing buildings |         // Don't modify collision for constructing buildings | ||||||
|         if (_isConstructing) return; |         if (IsConstructing) return; | ||||||
|              |              | ||||||
|         if (_collisionShape != null) |         if (_collisionShape != null) | ||||||
|             _collisionShape.Disabled = true; |             _collisionShape.Disabled = true; | ||||||
| @@ -50,13 +53,13 @@ public partial class BaseTile : Node2D | |||||||
|     // Building progress visualization |     // Building progress visualization | ||||||
|     public void StartConstruction(float buildTime, Action onComplete = null) |     public void StartConstruction(float buildTime, Action onComplete = null) | ||||||
|     { |     { | ||||||
|         _isConstructing = true; |         IsConstructing = true; | ||||||
|         if (_collisionShape != null) |         if (_collisionShape != null) | ||||||
|             _collisionShape.Disabled = true; |             _collisionShape.Disabled = true; | ||||||
|  |  | ||||||
|         if (_progressOverlay == null || _sprite?.Texture == null)  |         if (_progressOverlay == null || _sprite?.Texture == null)  | ||||||
|         { |         { | ||||||
|             _isConstructing = false; |             IsConstructing = false; | ||||||
|             onComplete?.Invoke(); |             onComplete?.Invoke(); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @@ -97,11 +100,12 @@ public partial class BaseTile : Node2D | |||||||
|             if (_sprite != null) |             if (_sprite != null) | ||||||
|                 _sprite.Modulate = Colors.White; |                 _sprite.Modulate = Colors.White; | ||||||
|                  |                  | ||||||
|             _isConstructing = false; |             IsConstructing = false; | ||||||
|             if (_collisionShape != null) |             if (_collisionShape != null) | ||||||
|                 _collisionShape.Disabled = false; |                 _collisionShape.Disabled = false; | ||||||
|                  |                  | ||||||
|             _onConstructionComplete?.Invoke(); |             _onConstructionComplete?.Invoke(); | ||||||
|  |             IsConstructed = true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         RunProgress(); |         RunProgress(); | ||||||
|   | |||||||
| @@ -1,8 +1,63 @@ | |||||||
|  | using AceFieldNewHorizon.Scripts.System; | ||||||
| using Godot; | using Godot; | ||||||
|  |  | ||||||
| namespace AceFieldNewHorizon.Scripts.Tiles; | namespace AceFieldNewHorizon.Scripts.Tiles; | ||||||
|  |  | ||||||
| public partial class MinerTile : BaseTile | public partial class MinerTile : BaseTile | ||||||
| { | { | ||||||
|  |     [Export] public PackedScene ItemPickup { get; set; } | ||||||
|  |     [Export] public string ItemToMine { get; set; } = "OreIron"; | ||||||
|  |     [Export] public int MiningRate = 1; // Items per second | ||||||
|  |  | ||||||
|  |     private Vector2I _gridPosition; | ||||||
|  |     private float _timeSinceLastMine; | ||||||
|  |  | ||||||
|  |     public override void _Ready() | ||||||
|  |     { | ||||||
|  |         base._Ready(); | ||||||
|  |         _gridPosition = GridUtils.WorldToGrid(Position); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public override void _Process(double delta) | ||||||
|  |     { | ||||||
|  |         // Don't mine if building is not completed | ||||||
|  |         if (!IsConstructed || ItemPickup == null) | ||||||
|  |             return; | ||||||
|  |  | ||||||
|  |         _timeSinceLastMine += (float)delta; | ||||||
|  |  | ||||||
|  |         if (!(_timeSinceLastMine >= 1f / MiningRate)) return; | ||||||
|  |         _timeSinceLastMine = 0f; | ||||||
|  |         SpawnItem(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private void SpawnItem() | ||||||
|  |     { | ||||||
|  |         var itemPickup = ItemPickup?.Instantiate<ItemPickup>(); | ||||||
|  |         if (itemPickup == null) return; | ||||||
|  |  | ||||||
|  |         itemPickup.ItemId = ItemToMine; | ||||||
|  |         itemPickup.Quantity = 1; | ||||||
|  |  | ||||||
|  |         // Initial position (slightly below the spawn point) | ||||||
|  |         var spawnPosition = GridUtils.GridToWorld(_gridPosition); | ||||||
|  |         var targetY = spawnPosition.Y - 27f; // Target Y position | ||||||
|  |         var targetX = spawnPosition.X + 27f + (GD.Randf() * 10f - 5f); | ||||||
|  |         itemPickup.Position = | ||||||
|  |             new Vector2(spawnPosition.X + 27f, spawnPosition.Y + 16); // Start below | ||||||
|  |         itemPickup.Scale = Vector2.Zero; // Start invisible | ||||||
|  |  | ||||||
|  |         // Add to the scene | ||||||
|  |         GetTree().CurrentScene.AddChild(itemPickup); | ||||||
|  |  | ||||||
|  |         // Create the pop-up animation | ||||||
|  |         var tween = CreateTween().SetTrans(Tween.TransitionType.Elastic).SetEase(Tween.EaseType.Out); | ||||||
|  |  | ||||||
|  |         // Animate the pop-up effect | ||||||
|  |         tween.TweenProperty(itemPickup, "position:y", targetY, 0.6f); | ||||||
|  |         tween.Parallel().TweenProperty(itemPickup, "scale", Vector2.One, 0.6f); | ||||||
|  |  | ||||||
|  |         // Optional: Add a slight horizontal wobble | ||||||
|  |         tween.Parallel().TweenProperty(itemPickup, "position:x", targetX, 0.6f); | ||||||
|  |     } | ||||||
| } | } | ||||||
		Reference in New Issue
	
	Block a user