commit 31723217eaa44fe92c9940f536755c32f47ef467 Author: LittleSheep Date: Tue Aug 26 18:36:50 2025 +0800 :tada: Initial Commit :sparkles: Grid system, player movement etc diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f28239b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +charset = utf-8 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0af181c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# Godot 4+ specific ignores +.godot/ +/android/ diff --git a/.idea/.idea.AceField New Horizon/.idea/.gitignore b/.idea/.idea.AceField New Horizon/.idea/.gitignore new file mode 100644 index 0000000..0c2d326 --- /dev/null +++ b/.idea/.idea.AceField New Horizon/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/contentModel.xml +/projectSettingsUpdater.xml +/modules.xml +/.idea.AceField New Horizon.iml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.AceField New Horizon/.idea/.name b/.idea/.idea.AceField New Horizon/.idea/.name new file mode 100644 index 0000000..65078d0 --- /dev/null +++ b/.idea/.idea.AceField New Horizon/.idea/.name @@ -0,0 +1 @@ +AceField New Horizon \ No newline at end of file diff --git a/.idea/.idea.AceField New Horizon/.idea/encodings.xml b/.idea/.idea.AceField New Horizon/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.AceField New Horizon/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.AceField New Horizon/.idea/indexLayout.xml b/.idea/.idea.AceField New Horizon/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.AceField New Horizon/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.AceField New Horizon/.idea/libraries/GdSdk.xml b/.idea/.idea.AceField New Horizon/.idea/libraries/GdSdk.xml new file mode 100644 index 0000000..72a9c1b --- /dev/null +++ b/.idea/.idea.AceField New Horizon/.idea/libraries/GdSdk.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.AceField New Horizon/.idea/misc.xml b/.idea/.idea.AceField New Horizon/.idea/misc.xml new file mode 100644 index 0000000..69f0353 --- /dev/null +++ b/.idea/.idea.AceField New Horizon/.idea/misc.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/AceField New Horizon.csproj b/AceField New Horizon.csproj new file mode 100644 index 0000000..d2ec174 --- /dev/null +++ b/AceField New Horizon.csproj @@ -0,0 +1,7 @@ + + + net8.0 + true + AceFieldNewHorizon + + \ No newline at end of file diff --git a/AceField New Horizon.sln b/AceField New Horizon.sln new file mode 100644 index 0000000..f351eec --- /dev/null +++ b/AceField New Horizon.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AceField New Horizon", "AceField New Horizon.csproj", "{CE3B1579-E05C-445D-8D60-44193679F36A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + ExportDebug|Any CPU = ExportDebug|Any CPU + ExportRelease|Any CPU = ExportRelease|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CE3B1579-E05C-445D-8D60-44193679F36A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE3B1579-E05C-445D-8D60-44193679F36A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE3B1579-E05C-445D-8D60-44193679F36A}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU + {CE3B1579-E05C-445D-8D60-44193679F36A}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU + {CE3B1579-E05C-445D-8D60-44193679F36A}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU + {CE3B1579-E05C-445D-8D60-44193679F36A}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU + EndGlobalSection +EndGlobal diff --git a/Scenes/Entities/Player.png b/Scenes/Entities/Player.png new file mode 100644 index 0000000..319f0f4 Binary files /dev/null and b/Scenes/Entities/Player.png differ diff --git a/Scenes/Entities/Player.png.import b/Scenes/Entities/Player.png.import new file mode 100644 index 0000000..499f129 --- /dev/null +++ b/Scenes/Entities/Player.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://jye6c2ehuxtg" +path="res://.godot/imported/Player.png-a47763ac98e2bfa7959d9f7899f4e3bc.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Scenes/Entities/Player.png" +dest_files=["res://.godot/imported/Player.png-a47763ac98e2bfa7959d9f7899f4e3bc.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Scenes/Entities/Player.tscn b/Scenes/Entities/Player.tscn new file mode 100644 index 0000000..6ac8ad7 --- /dev/null +++ b/Scenes/Entities/Player.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=3 format=3 uid="uid://doxy60afddg1m"] + +[ext_resource type="Script" uid="uid://dgm1o21sv2o1x" path="res://Scripts/Entities/Player.cs" id="1_08t41"] +[ext_resource type="Texture2D" uid="uid://jye6c2ehuxtg" path="res://Scenes/Entities/Player.png" id="1_ucweq"] + +[node name="Player" type="CharacterBody2D"] +script = ExtResource("1_08t41") + +[node name="Sprite2D" type="Sprite2D" parent="."] +scale = Vector2(0.1, 0.1) +texture = ExtResource("1_ucweq") + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="."] +position = Vector2(1, 2.5) +polygon = PackedVector2Array(54, 87.5, 62, 76.5, 7, -89.5, -1, -92.5, -10, -89.5, -64, 76.5, -55, 87.5) + +[node name="Camera2D" type="Camera2D" parent="."] +process_callback = 0 +position_smoothing_enabled = true diff --git a/Scenes/Root.tscn b/Scenes/Root.tscn new file mode 100644 index 0000000..ec9820e --- /dev/null +++ b/Scenes/Root.tscn @@ -0,0 +1,22 @@ +[gd_scene load_steps=5 format=3 uid="uid://c22aprj452aha"] + +[ext_resource type="Script" uid="uid://cudpc3w17mbsw" path="res://Scripts/System/GridManager.cs" id="1_knkkn"] +[ext_resource type="Script" uid="uid://bx1wj7gn6vrqe" path="res://Scripts/System/PlacementManager.cs" id="2_sxhdm"] +[ext_resource type="PackedScene" uid="uid://doxy60afddg1m" path="res://Scenes/Entities/Player.tscn" id="3_oss8w"] +[ext_resource type="PackedScene" uid="uid://d1pudmkg5nnhj" path="res://Scenes/Tiles/WallTile.tscn" id="3_sxhdm"] + +[node name="Root" type="Node2D"] + +[node name="GridSystem" type="Node2D" parent="."] +script = ExtResource("1_knkkn") + +[node name="PlacementSystem" type="Node2D" parent="." node_paths=PackedStringArray("Grid")] +script = ExtResource("2_sxhdm") +BuildingScene = ExtResource("3_sxhdm") +Grid = NodePath("../GridSystem") + +[node name="WallTile" parent="." instance=ExtResource("3_sxhdm")] + +[node name="Player" parent="." instance=ExtResource("3_oss8w")] +position = Vector2(602, 324) +scale = Vector2(0.5, 0.5) diff --git a/Scenes/Tiles/WallTile.png b/Scenes/Tiles/WallTile.png new file mode 100644 index 0000000..066a425 Binary files /dev/null and b/Scenes/Tiles/WallTile.png differ diff --git a/Scenes/Tiles/WallTile.png.import b/Scenes/Tiles/WallTile.png.import new file mode 100644 index 0000000..17cf9ab --- /dev/null +++ b/Scenes/Tiles/WallTile.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://14ohvtl6eroj" +path="res://.godot/imported/WallTile.png-6f272ac3f660cd90075e54aa0a66efaf.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Scenes/Tiles/WallTile.png" +dest_files=["res://.godot/imported/WallTile.png-6f272ac3f660cd90075e54aa0a66efaf.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Scenes/Tiles/WallTile.tscn b/Scenes/Tiles/WallTile.tscn new file mode 100644 index 0000000..6e96293 --- /dev/null +++ b/Scenes/Tiles/WallTile.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=4 format=3 uid="uid://d1pudmkg5nnhj"] + +[ext_resource type="Texture2D" uid="uid://14ohvtl6eroj" path="res://Scenes/Tiles/WallTile.png" id="1_8o613"] +[ext_resource type="Script" uid="uid://cywgb6hvlw8lr" path="res://Scripts/Tiles/WallTile.cs" id="1_ph7y3"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_8o613"] +size = Vector2(54, 54) + +[node name="WallTile" type="StaticBody2D"] +script = ExtResource("1_ph7y3") + +[node name="Sprite2D" type="Sprite2D" parent="."] +scale = Vector2(0.05, 0.05) +texture = ExtResource("1_8o613") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("RectangleShape2D_8o613") diff --git a/Scripts/Entities/Player.cs b/Scripts/Entities/Player.cs new file mode 100644 index 0000000..890efa5 --- /dev/null +++ b/Scripts/Entities/Player.cs @@ -0,0 +1,26 @@ +using System; +using Godot; + +namespace AceFieldNewHorizon.Scripts.Entities; + +public partial class Player : CharacterBody2D +{ + [Export] public float Speed = 400.0f; + + public override void _Process(double delta) + { + // Get direction to mouse and calculate angle + var mousePos = GetGlobalMousePosition(); + var direction = GlobalPosition.DirectionTo(mousePos); + Rotation = direction.Angle() + (float)Math.PI / 2; + } + + public override void _PhysicsProcess(double delta) + { + // Get movement input + var inputDirection = Input.GetVector("move_left", "move_right", "move_up", "move_down"); + Velocity = inputDirection * Speed; + + MoveAndSlide(); + } +} \ No newline at end of file diff --git a/Scripts/Entities/Player.cs.uid b/Scripts/Entities/Player.cs.uid new file mode 100644 index 0000000..ecaec45 --- /dev/null +++ b/Scripts/Entities/Player.cs.uid @@ -0,0 +1 @@ +uid://dgm1o21sv2o1x diff --git a/Scripts/System/GridManager.cs b/Scripts/System/GridManager.cs new file mode 100644 index 0000000..41f7e50 --- /dev/null +++ b/Scripts/System/GridManager.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using Godot; + +namespace AceFieldNewHorizon.Scripts.System; + +public partial class GridManager : Node +{ + private Dictionary _grid = new(); + + public bool IsCellFree(Vector2I cell) + { + return !_grid.ContainsKey(cell); + } + + public void OccupyCell(Vector2I cell, Node2D building) + { + _grid[cell] = building; + } + + public void FreeCell(Vector2I cell) + { + _grid.Remove(cell); + } +} + +public static class GridUtils +{ + public const int TileSize = 54; + + public static Vector2I WorldToGrid(Vector2 pos) + { + return new Vector2I( + Mathf.FloorToInt(pos.X / TileSize), + Mathf.FloorToInt(pos.Y / TileSize) + ); + } + + public static Vector2 GridToWorld(Vector2I cell) + { + return new Vector2( + cell.X * TileSize, + cell.Y * TileSize + ); + } +} \ No newline at end of file diff --git a/Scripts/System/GridManager.cs.uid b/Scripts/System/GridManager.cs.uid new file mode 100644 index 0000000..ae9ac33 --- /dev/null +++ b/Scripts/System/GridManager.cs.uid @@ -0,0 +1 @@ +uid://cudpc3w17mbsw diff --git a/Scripts/System/PlacementManager.cs b/Scripts/System/PlacementManager.cs new file mode 100644 index 0000000..810c05e --- /dev/null +++ b/Scripts/System/PlacementManager.cs @@ -0,0 +1,40 @@ +using AceFieldNewHorizon.Scripts.Tiles; +using Godot; + +namespace AceFieldNewHorizon.Scripts.System; + +public partial class PlacementManager : Node2D +{ + [Export] public PackedScene BuildingScene { get; set; } + [Export] public GridManager Grid { get; set; } + + private Vector2I _hoveredCell; + private BaseTile _ghostBuilding; + + public override void _Process(double delta) + { + // Snap mouse to grid + var mousePos = GetGlobalMousePosition(); + _hoveredCell = GridUtils.WorldToGrid(mousePos); + + if (_ghostBuilding == null) + { + _ghostBuilding = (BaseTile)BuildingScene.Instantiate(); + _ghostBuilding.SetGhostMode(true); + AddChild(_ghostBuilding); + } + + _ghostBuilding.Position = GridUtils.GridToWorld(_hoveredCell); + _ghostBuilding.SetGhostMode(true); + + // Left click to place + if (!Input.IsActionPressed("build_tile") || !Grid.IsCellFree(_hoveredCell)) return; + + _ghostBuilding.SetGhostMode(false); + Grid.OccupyCell(_hoveredCell, _ghostBuilding); + + _ghostBuilding = (BaseTile)BuildingScene.Instantiate(); + _ghostBuilding.SetGhostMode(true); + AddChild(_ghostBuilding); + } +} \ No newline at end of file diff --git a/Scripts/System/PlacementManager.cs.uid b/Scripts/System/PlacementManager.cs.uid new file mode 100644 index 0000000..b296ca2 --- /dev/null +++ b/Scripts/System/PlacementManager.cs.uid @@ -0,0 +1 @@ +uid://bx1wj7gn6vrqe diff --git a/Scripts/Tiles/BaseTile.cs b/Scripts/Tiles/BaseTile.cs new file mode 100644 index 0000000..915c330 --- /dev/null +++ b/Scripts/Tiles/BaseTile.cs @@ -0,0 +1,30 @@ +using Godot; + +namespace AceFieldNewHorizon.Scripts.Tiles; + +public partial class BaseTile : Node2D +{ + protected CollisionShape2D CollisionShape; + protected Sprite2D Sprite; + + public override void _Ready() + { + // Get references (optional: you can also Export and assign in editor) + CollisionShape = GetNode("CollisionShape2D"); + Sprite = GetNode("Sprite2D"); + } + + public void SetGhostMode(bool ghost) + { + if (CollisionShape != null) + CollisionShape.Disabled = ghost; + + if (Sprite != null) + { + if (ghost) + Sprite.Modulate = new Color(1, 1, 1, 0.5f); // semi-transparent + else + Sprite.Modulate = Colors.White; + } + } +} \ No newline at end of file diff --git a/Scripts/Tiles/BaseTile.cs.uid b/Scripts/Tiles/BaseTile.cs.uid new file mode 100644 index 0000000..27774aa --- /dev/null +++ b/Scripts/Tiles/BaseTile.cs.uid @@ -0,0 +1 @@ +uid://clw4adumlgw43 diff --git a/Scripts/Tiles/WallTile.cs b/Scripts/Tiles/WallTile.cs new file mode 100644 index 0000000..7309e63 --- /dev/null +++ b/Scripts/Tiles/WallTile.cs @@ -0,0 +1,8 @@ +using Godot; + +namespace AceFieldNewHorizon.Scripts.Tiles; + +public partial class WallTile : BaseTile +{ + +} \ No newline at end of file diff --git a/Scripts/Tiles/WallTile.cs.uid b/Scripts/Tiles/WallTile.cs.uid new file mode 100644 index 0000000..7be322a --- /dev/null +++ b/Scripts/Tiles/WallTile.cs.uid @@ -0,0 +1 @@ +uid://cywgb6hvlw8lr diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..9d8b7fa --- /dev/null +++ b/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon.svg.import b/icon.svg.import new file mode 100644 index 0000000..601c350 --- /dev/null +++ b/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ca07uqmtp40q3" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..62a8eeb --- /dev/null +++ b/project.godot @@ -0,0 +1,53 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="AceField New Horizon" +run/main_scene="uid://c22aprj452aha" +config/features=PackedStringArray("4.4", "C#", "GL Compatibility") +config/icon="res://icon.svg" + +[dotnet] + +project/assembly_name="AceField New Horizon" + +[input] + +move_up={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null) +] +} +move_down={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +] +} +move_left={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null) +] +} +move_right={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null) +] +} +build_tile={ +"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":1,"position":Vector2(680, 19),"global_position":Vector2(699, 115),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null) +] +} + +[rendering] + +renderer/rendering_method="gl_compatibility" +renderer/rendering_method.mobile="gl_compatibility"