diff --git a/_Core/EventNames.gd b/_Core/EventNames.gd index 3110c98..cb7fd70 100644 --- a/_Core/EventNames.gd +++ b/_Core/EventNames.gd @@ -51,6 +51,8 @@ const SCENE_DATA_TRANSFER = "scene_data_transfer" const TILEMAP_READY = "tilemap_ready" const COMPONENT_MESSAGE = "component_message" const POSITION_UPDATE = "position_update" +const GRID_POSITION_CHANGED = "grid_position_changed" +const GRID_SNAP_REQUESTED = "grid_snap_requested" # ============================================================================ # 测试事件 diff --git a/_Core/ProjectPaths.gd b/_Core/ProjectPaths.gd index 9f9afc1..af5f419 100644 --- a/_Core/ProjectPaths.gd +++ b/_Core/ProjectPaths.gd @@ -19,6 +19,11 @@ const CORE_SYSTEMS = CORE_ROOT + "systems/" const CORE_COMPONENTS = CORE_ROOT + "components/" const CORE_UTILS = CORE_ROOT + "utils/" +# 系统文件路径 +const GRID_SYSTEM = CORE_SYSTEMS + "GridSystem.gd" +const EVENT_SYSTEM = CORE_SYSTEMS + "EventSystem.gd" +const TILE_SYSTEM = CORE_SYSTEMS + "TileSystem.gd" + # ============================================================================ # 场景路径 # ============================================================================ @@ -46,6 +51,10 @@ const ASSETS_FONTS = ASSETS_ROOT + "fonts/" const ASSETS_MATERIALS = ASSETS_ROOT + "materials/" const ASSETS_SHADERS = ASSETS_ROOT + "shaders/" +# 地形资源路径 +const ASSETS_TERRAIN = ASSETS_SPRITES + "terrain/" +const ASSETS_GRASS = ASSETS_TERRAIN + "grass/" + # ============================================================================ # 数据路径 # ============================================================================ diff --git a/_Core/managers/NetworkManager.gd b/_Core/managers/NetworkManager.gd index 36ba1c3..3e73627 100644 --- a/_Core/managers/NetworkManager.gd +++ b/_Core/managers/NetworkManager.gd @@ -698,4 +698,4 @@ func get_request_info(request_id: String) -> Dictionary: func _notification(what): if what == NOTIFICATION_WM_CLOSE_REQUEST: # 应用关闭时取消所有请求 - cancel_all_requests() \ No newline at end of file + cancel_all_requests() diff --git a/_Core/managers/ResponseHandler.gd b/_Core/managers/ResponseHandler.gd index 488f942..b382dca 100644 --- a/_Core/managers/ResponseHandler.gd +++ b/_Core/managers/ResponseHandler.gd @@ -587,4 +587,4 @@ func handle_response(operation_type: String, success: bool, data: Dictionary, er result.success = false result.message = _get_error_message(data.get("error_code", ""), data.get("message", "操作失败"), error_info) result.toast_type = "error" - return result \ No newline at end of file + return result diff --git a/_Core/systems/GridSystem.gd b/_Core/systems/GridSystem.gd new file mode 100644 index 0000000..06f44a3 --- /dev/null +++ b/_Core/systems/GridSystem.gd @@ -0,0 +1,143 @@ +# ============================================================================ +# 网格系统 - GridSystem.gd +# +# 提供32x32像素的最小网格单元控制,用于规范地图大小和位置计算 +# +# 使用方式: +# var grid_pos = GridSystem.world_to_grid(world_position) +# var world_pos = GridSystem.grid_to_world(grid_position) +# var snapped_pos = GridSystem.snap_to_grid(position) +# ============================================================================ + +class_name GridSystem +extends RefCounted + +# ============================================================================ +# 常量定义 +# ============================================================================ +const GRID_SIZE: int = 32 # 网格单元大小 32x32 像素 +const HALF_GRID_SIZE: float = GRID_SIZE * 0.5 # 网格中心偏移 + +# ============================================================================ +# 坐标转换方法 +# ============================================================================ + +# 世界坐标转换为网格坐标 +static func world_to_grid(world_pos: Vector2) -> Vector2i: + return Vector2i( + int(world_pos.x / GRID_SIZE), + int(world_pos.y / GRID_SIZE) + ) + +# 网格坐标转换为世界坐标(返回网格左上角) +static func grid_to_world(grid_pos: Vector2i) -> Vector2: + return Vector2( + grid_pos.x * GRID_SIZE, + grid_pos.y * GRID_SIZE + ) + +# 网格坐标转换为世界坐标(返回网格中心) +static func grid_to_world_center(grid_pos: Vector2i) -> Vector2: + return Vector2( + grid_pos.x * GRID_SIZE + HALF_GRID_SIZE, + grid_pos.y * GRID_SIZE + HALF_GRID_SIZE + ) + +# 将位置吸附到最近的网格点(左上角) +static func snap_to_grid(position: Vector2) -> Vector2: + return Vector2( + floor(position.x / GRID_SIZE) * GRID_SIZE, + floor(position.y / GRID_SIZE) * GRID_SIZE + ) + +# 将位置吸附到最近的网格中心 +static func snap_to_grid_center(position: Vector2) -> Vector2: + var grid_pos = world_to_grid(position) + return grid_to_world_center(grid_pos) + +# ============================================================================ +# 距离和区域计算 +# ============================================================================ + +# 计算两个网格坐标之间的曼哈顿距离 +static func grid_distance_manhattan(grid_pos1: Vector2i, grid_pos2: Vector2i) -> int: + return abs(grid_pos1.x - grid_pos2.x) + abs(grid_pos1.y - grid_pos2.y) + +# 计算两个网格坐标之间的欧几里得距离 +static func grid_distance_euclidean(grid_pos1: Vector2i, grid_pos2: Vector2i) -> float: + var diff = grid_pos1 - grid_pos2 + return sqrt(diff.x * diff.x + diff.y * diff.y) + +# 获取指定网格坐标周围的邻居网格(4方向) +static func get_grid_neighbors_4(grid_pos: Vector2i) -> Array[Vector2i]: + return [ + Vector2i(grid_pos.x, grid_pos.y - 1), # 上 + Vector2i(grid_pos.x + 1, grid_pos.y), # 右 + Vector2i(grid_pos.x, grid_pos.y + 1), # 下 + Vector2i(grid_pos.x - 1, grid_pos.y) # 左 + ] + +# 获取指定网格坐标周围的邻居网格(8方向) +static func get_grid_neighbors_8(grid_pos: Vector2i) -> Array[Vector2i]: + var neighbors: Array[Vector2i] = [] + for x in range(-1, 2): + for y in range(-1, 2): + if x == 0 and y == 0: + continue + neighbors.append(Vector2i(grid_pos.x + x, grid_pos.y + y)) + return neighbors + +# ============================================================================ +# 区域和边界检查 +# ============================================================================ + +# 检查网格坐标是否在指定矩形区域内 +static func is_grid_in_bounds(grid_pos: Vector2i, min_grid: Vector2i, max_grid: Vector2i) -> bool: + return (grid_pos.x >= min_grid.x and grid_pos.x <= max_grid.x and + grid_pos.y >= min_grid.y and grid_pos.y <= max_grid.y) + +# 获取矩形区域内的所有网格坐标 +static func get_grids_in_rect(min_grid: Vector2i, max_grid: Vector2i) -> Array[Vector2i]: + var grids: Array[Vector2i] = [] + for x in range(min_grid.x, max_grid.x + 1): + for y in range(min_grid.y, max_grid.y + 1): + grids.append(Vector2i(x, y)) + return grids + +# ============================================================================ +# 地图尺寸规范化 +# ============================================================================ + +# 将像素尺寸规范化为网格尺寸的倍数 +static func normalize_size_to_grid(pixel_size: Vector2i) -> Vector2i: + return Vector2i( + int(ceil(float(pixel_size.x) / GRID_SIZE)) * GRID_SIZE, + int(ceil(float(pixel_size.y) / GRID_SIZE)) * GRID_SIZE + ) + +# 计算指定像素尺寸需要多少个网格单元 +static func get_grid_count(pixel_size: Vector2i) -> Vector2i: + return Vector2i( + int(ceil(float(pixel_size.x) / GRID_SIZE)), + int(ceil(float(pixel_size.y) / GRID_SIZE)) + ) + +# ============================================================================ +# 调试和可视化辅助 +# ============================================================================ + +# 获取网格的边界矩形(用于调试绘制) +static func get_grid_rect(grid_pos: Vector2i) -> Rect2: + var world_pos = grid_to_world(grid_pos) + return Rect2(world_pos, Vector2(GRID_SIZE, GRID_SIZE)) + +# 打印网格信息(调试用) +static func print_grid_info(world_pos: Vector2) -> void: + var grid_pos = world_to_grid(world_pos) + var snapped_pos = snap_to_grid(world_pos) + var center_pos = grid_to_world_center(grid_pos) + + print("世界坐标: ", world_pos) + print("网格坐标: ", grid_pos) + print("吸附位置: ", snapped_pos) + print("网格中心: ", center_pos) \ No newline at end of file diff --git a/_Core/systems/GridSystem.gd.uid b/_Core/systems/GridSystem.gd.uid new file mode 100644 index 0000000..763e586 --- /dev/null +++ b/_Core/systems/GridSystem.gd.uid @@ -0,0 +1 @@ +uid://dceqpffgti4jb diff --git a/assets/sprites/environment/curb.png b/assets/sprites/environment/curb.png new file mode 100644 index 0000000..98d9121 Binary files /dev/null and b/assets/sprites/environment/curb.png differ diff --git a/assets/sprites/environment/curb.png.import b/assets/sprites/environment/curb.png.import new file mode 100644 index 0000000..6a9d8f9 --- /dev/null +++ b/assets/sprites/environment/curb.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b2gci3tcylfiw" +path="res://.godot/imported/curb.png-aea973bea0e48d7135256b05941024a3.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/sprites/environment/curb.png" +dest_files=["res://.godot/imported/curb.png-aea973bea0e48d7135256b05941024a3.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/sprites/environment/download_1767426187137.png b/assets/sprites/environment/download_1767426187137.png new file mode 100644 index 0000000..2030326 Binary files /dev/null and b/assets/sprites/environment/download_1767426187137.png differ diff --git a/assets/sprites/environment/download_1767426187137.png.import b/assets/sprites/environment/download_1767426187137.png.import new file mode 100644 index 0000000..aaf9643 --- /dev/null +++ b/assets/sprites/environment/download_1767426187137.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://djmpsp6t8vbra" +path="res://.godot/imported/download_1767426187137.png-a7252aa9f644c4f3ab14cefb1a59847c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/sprites/environment/download_1767426187137.png" +dest_files=["res://.godot/imported/download_1767426187137.png-a7252aa9f644c4f3ab14cefb1a59847c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/sprites/environment/floor_tile.png b/assets/sprites/environment/floor_tile.png new file mode 100644 index 0000000..b449207 Binary files /dev/null and b/assets/sprites/environment/floor_tile.png differ diff --git a/assets/sprites/environment/floor_tile.png.import b/assets/sprites/environment/floor_tile.png.import new file mode 100644 index 0000000..15732da --- /dev/null +++ b/assets/sprites/environment/floor_tile.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c3yr7cietnip3" +path="res://.godot/imported/floor_tile.png-922ec9c726f71491a3ebe25e6696192d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/sprites/environment/floor_tile.png" +dest_files=["res://.godot/imported/floor_tile.png-922ec9c726f71491a3ebe25e6696192d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/sprites/environment/square.png b/assets/sprites/environment/square.png new file mode 100644 index 0000000..27c0125 Binary files /dev/null and b/assets/sprites/environment/square.png differ diff --git a/assets/sprites/environment/square.png.import b/assets/sprites/environment/square.png.import new file mode 100644 index 0000000..637c1dd --- /dev/null +++ b/assets/sprites/environment/square.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://7o0xyqmqbvov" +path="res://.godot/imported/square.png-f3b8edd32d9382a7b98d24fd60e1b771.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/sprites/environment/square.png" +dest_files=["res://.godot/imported/square.png-f3b8edd32d9382a7b98d24fd60e1b771.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/sprites/environment/square1.png b/assets/sprites/environment/square1.png new file mode 100644 index 0000000..b595ca3 Binary files /dev/null and b/assets/sprites/environment/square1.png differ diff --git a/assets/sprites/environment/square1.png.import b/assets/sprites/environment/square1.png.import new file mode 100644 index 0000000..095166c --- /dev/null +++ b/assets/sprites/environment/square1.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dt33hewme0p1k" +path="res://.godot/imported/square1.png-5d845f041b32e4a2880ddc03c7e210e2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/sprites/environment/square1.png" +dest_files=["res://.godot/imported/square1.png-5d845f041b32e4a2880ddc03c7e210e2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/sprites/environment/广场瓦片集.png b/assets/sprites/environment/广场瓦片集.png new file mode 100644 index 0000000..7ce39ce Binary files /dev/null and b/assets/sprites/environment/广场瓦片集.png differ diff --git a/assets/sprites/environment/广场瓦片集.png.import b/assets/sprites/environment/广场瓦片集.png.import new file mode 100644 index 0000000..15b9589 --- /dev/null +++ b/assets/sprites/environment/广场瓦片集.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ignbtjvnp5k7" +path="res://.godot/imported/广场瓦片集.png-b224b40553b9f690e690f67a89e2b520.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/sprites/environment/广场瓦片集.png" +dest_files=["res://.godot/imported/广场瓦片集.png-b224b40553b9f690e690f67a89e2b520.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/sprites/environment/草地.png b/assets/sprites/environment/草地.png new file mode 100644 index 0000000..e6a9c48 Binary files /dev/null and b/assets/sprites/environment/草地.png differ diff --git a/assets/sprites/environment/草地.png.import b/assets/sprites/environment/草地.png.import new file mode 100644 index 0000000..6d17901 --- /dev/null +++ b/assets/sprites/environment/草地.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dvsb51jintro" +path="res://.godot/imported/草地.png-2fa7f2346d7dc837788dd21e5693cec7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/sprites/environment/草地.png" +dest_files=["res://.godot/imported/草地.png-2fa7f2346d7dc837788dd21e5693cec7.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/sprites/sprites/characters/.gitkeep b/assets/sprites/sprites/characters/.gitkeep deleted file mode 100644 index ec3e024..0000000 --- a/assets/sprites/sprites/characters/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# 保持目录结构 - 角色精灵资源目录 \ No newline at end of file diff --git a/assets/sprites/sprites/effects/.gitkeep b/assets/sprites/sprites/effects/.gitkeep deleted file mode 100644 index ae28815..0000000 --- a/assets/sprites/sprites/effects/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# 保持目录结构 - 特效精灵资源目录 \ No newline at end of file diff --git a/assets/sprites/sprites/environment/.gitkeep b/assets/sprites/sprites/environment/.gitkeep deleted file mode 100644 index 71129f4..0000000 --- a/assets/sprites/sprites/environment/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# 保持目录结构 - 环境精灵资源目录 \ No newline at end of file diff --git a/docs/06-功能模块/网格瓦片系统.md b/docs/06-功能模块/网格瓦片系统.md new file mode 100644 index 0000000..0557b65 --- /dev/null +++ b/docs/06-功能模块/网格瓦片系统.md @@ -0,0 +1,59 @@ +# 网格瓦片系统 + +## 概述 + +网格瓦片系统提供32x32像素的标准化网格管理,用于规范地图元素的位置和大小。 + +## 核心组件 + +### GridSystem (核心系统) +- **位置**: `_Core/systems/GridSystem.gd` +- **功能**: 提供网格坐标转换、位置计算等基础功能 +- **类型**: 静态工具类 + +### GrassTile (瓦片组件) +- **脚本**: `scenes/prefabs/GrassTile.gd` +- **场景**: `scenes/prefabs/grass_tile_prefab.tscn` +- **功能**: 可视化的草地瓦片,自动对齐32x32网格 + +## 使用方法 + +### 在编辑器中使用 +1. 拖拽 `scenes/prefabs/grass_tile_prefab.tscn` 到场景中 +2. 在Inspector中设置Texture和Grid Position +3. 瓦片会自动对齐到网格 + +### 通过代码使用 +```gdscript +# 预加载场景 +const GrassTileScene = preload("res://scenes/prefabs/grass_tile_prefab.tscn") + +# 创建瓦片 +var grass = GrassTileScene.instantiate() +add_child(grass) +grass.set_grid_position(Vector2i(0, 0)) +``` + +## 网格规范 + +### 基础规格 +- **网格大小**: 32x32像素 +- **坐标系**: 左上角为原点(0,0) +- **对齐方式**: 瓦片中心对齐到网格中心 + +### 纹理要求 +- 尺寸必须是32的倍数 +- 推荐格式: PNG +- 推荐尺寸: 32x32, 64x64, 96x96 + +## API参考 + +### GridSystem 方法 +- `world_to_grid(world_pos: Vector2) -> Vector2i` +- `grid_to_world_center(grid_pos: Vector2i) -> Vector2` +- `snap_to_grid(position: Vector2) -> Vector2` + +### GrassTile 属性和方法 +- `grid_position: Vector2i` - 网格坐标 +- `set_grid_position(pos: Vector2i)` - 设置网格位置 +- `snap_to_grid()` - 对齐到网格 \ No newline at end of file diff --git a/scenes/Maps/square.tscn b/scenes/Maps/square.tscn new file mode 100644 index 0000000..b51727a --- /dev/null +++ b/scenes/Maps/square.tscn @@ -0,0 +1,16 @@ +[gd_scene load_steps=4 format=3 uid="uid://5cc0c6cpnhe8"] + +[ext_resource type="Texture2D" uid="uid://7o0xyqmqbvov" path="res://assets/sprites/environment/square.png" id="1_a2ug0"] + +[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_1t0sv"] +texture = ExtResource("1_a2ug0") +15:1/size_in_atlas = Vector2i(2, 2) +15:1/0 = 0 + +[sub_resource type="TileSet" id="TileSet_g3awv"] +sources/0 = SubResource("TileSetAtlasSource_1t0sv") + +[node name="square" type="Node2D"] + +[node name="TileMapLayer" type="TileMapLayer" parent="."] +tile_set = SubResource("TileSet_g3awv") diff --git a/scenes/prefabs/GrassTile.gd b/scenes/prefabs/GrassTile.gd new file mode 100644 index 0000000..c1c66e1 --- /dev/null +++ b/scenes/prefabs/GrassTile.gd @@ -0,0 +1,122 @@ +# ============================================================================ +# 简单草地瓦片 - GrassTile.gd +# +# 一个简单的32x32草地瓦片,自动对齐网格 +# 使用方法: +# 1. 在场景中实例化 grass_tile_prefab.tscn +# 2. 设置 texture 属性 +# 3. 调用 set_grid_position() 设置网格位置 +# ============================================================================ + +class_name GrassTile +extends Sprite2D + +# ============================================================================ +# 导出属性 +# ============================================================================ +@export var grid_position: Vector2i = Vector2i.ZERO : set = set_grid_position +@export var auto_snap: bool = true # 是否自动对齐网格 + +# ============================================================================ +# 信号 +# ============================================================================ +signal position_changed(new_grid_pos: Vector2i) + +func _ready(): + # 如果没有纹理,创建一个默认的占位符 + if not texture: + _create_placeholder_texture() + + # 验证纹理尺寸 + _validate_texture() + + # 自动对齐到网格 + if auto_snap: + snap_to_grid() + +# ============================================================================ +# 公共方法 +# ============================================================================ + +# 设置网格位置并自动对齐 +func set_grid_position(new_pos: Vector2i): + if grid_position != new_pos: + grid_position = new_pos + if auto_snap: + snap_to_grid() + position_changed.emit(grid_position) + +# 对齐到网格中心 +func snap_to_grid(): + position = Vector2( + grid_position.x * 32.0 + 16.0, + grid_position.y * 32.0 + 16.0 + ) + +# 从世界坐标设置位置(会自动转换为网格坐标) +func set_world_position(world_pos: Vector2): + var new_grid_pos = Vector2i( + int(world_pos.x / 32.0), + int(world_pos.y / 32.0) + ) + set_grid_position(new_grid_pos) + +# 获取世界坐标 +func get_world_position() -> Vector2: + return position + +# ============================================================================ +# 私有方法 +# ============================================================================ + +# 创建占位符纹理 +func _create_placeholder_texture(): + var image = Image.create(32, 32, false, Image.FORMAT_RGBA8) + + # 创建简单的草地图案 + var grass_color = Color(0.3, 0.8, 0.3, 1.0) # 亮绿色 + var dark_color = Color(0.2, 0.6, 0.2, 1.0) # 深绿色 + + # 填充基础颜色 + image.fill(grass_color) + + # 添加简单的格子图案 + for x in range(32): + for y in range(32): + if (x + y) % 8 < 4: + image.set_pixel(x, y, dark_color) + + # 创建纹理 + var placeholder_texture = ImageTexture.new() + placeholder_texture.set_image(image) + texture = placeholder_texture + +# 验证纹理尺寸 +func _validate_texture(): + if texture: + var size = Vector2i(texture.get_width(), texture.get_height()) + if size.x % 32 != 0 or size.y % 32 != 0: + push_warning("GrassTile: 纹理尺寸不是32的倍数: " + str(size)) + return false + return true + return false + +# ============================================================================ +# 调试方法 +# ============================================================================ + +# 获取瓦片信息 +func get_tile_info() -> Dictionary: + return { + "grid_position": grid_position, + "world_position": position, + "texture_size": texture.get_size() if texture else Vector2.ZERO, + "auto_snap": auto_snap + } + +# 打印瓦片信息 +func print_info(): + var info = get_tile_info() + print("=== 草地瓦片信息 ===") + for key in info: + print(key, ": ", info[key]) \ No newline at end of file diff --git a/scenes/prefabs/grass_tile_prefab.tscn b/scenes/prefabs/grass_tile_prefab.tscn new file mode 100644 index 0000000..9c85898 --- /dev/null +++ b/scenes/prefabs/grass_tile_prefab.tscn @@ -0,0 +1,10 @@ +[gd_scene load_steps=3 format=3 uid="uid://bvxqm8n7qwqxe"] + +[ext_resource type="Script" path="res://scenes/prefabs/GrassTile.gd" id="1_0x8qm"] + +[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_1"] +size = Vector2(32, 32) + +[node name="GrassTile" type="Sprite2D"] +texture = SubResource("PlaceholderTexture2D_1") +script = ExtResource("1_0x8qm") \ No newline at end of file diff --git a/tools/README.md b/tools/README.md deleted file mode 100644 index aeef804..0000000 --- a/tools/README.md +++ /dev/null @@ -1,191 +0,0 @@ -# 🛠️ 构建和部署工具 - -本目录包含项目的构建和部署脚本。 - ---- - -## 📦 Web 构建工具 - -### build_web.sh (Linux/macOS) -### build_web.bat (Windows) - -**功能**: 将 Godot 项目导出为 Web 版本 - -#### 使用方法 - -**macOS/Linux:** -```bash -chmod +x tools/build_web.sh -./tools/build_web.sh -``` - -**Windows:** -```cmd -tools\build_web.bat -``` - -#### 输出目录 -- `build/web/` - 导出的 Web 游戏文件 - -#### 导出内容包括: -- `index.html` - Web 入口文件 -- `index.js` - 游戏主逻辑 -- `index.wasm` - WebAssembly 文件 -- `index.pck` - 游戏资源包 - ---- - -## 🌐 Web 测试服务器 - -### serve_web.sh (Linux/macOS) -### serve_web.bat (Windows) - -**功能**: 启动本地 HTTP 服务器预览 Web 游戏 - -#### 使用方法 - -**macOS/Linux:** -```bash -chmod +x tools/serve_web.sh -./tools/serve_web.sh -``` - -**Windows:** -```cmd -tools\serve_web.bat -``` - -#### 访问地址 -- 默认: `http://localhost:8000` -- 浏览器会自动打开 - -#### 注意事项 -⚠️ **必须使用 HTTP 服务器** -- 不能直接用 `file://` 打开 `index.html` -- Godot Web 版本需要 HTTP 环境 -- 本服务器已配置正确的 CORS 头 - ---- - -## 🔧 配置说明 - -### 修改 Godot 路径 - -编辑脚本中的 `GODOT_PATH` 变量: - -**macOS:** -```bash -GODOT_PATH="/usr/local/bin/godot" # Homebrew -# 或 -GODOT_PATH="$HOME/Applications/Godot.app/Contents/MacOS/Godot" # 应用程序 -``` - -**Windows:** -```batch -set GODOT_PATH=C:\Program Files\Godot\godot.exe -``` - -**Linux:** -```bash -GODOT_PATH="/usr/bin/godot" # 包管理器 -# 或 -GODOT_PATH="$HOME/bin/godot" # 手动安装 -``` - -### 修改端口 - -编辑 `serve_web.sh` 或 `serve_web.bat` 中的端口配置: -```bash -PORT=8080 # 改为其他端口 -``` - ---- - -## 📋 典型工作流程 - -### 1. 开发阶段 -在 Godot 编辑器中开发和测试游戏 - -### 2. 导出 Web 版本 -```bash -./tools/build_web.sh -``` - -### 3. 本地测试 -```bash -./tools/serve_web.sh -# 浏览器访问 http://localhost:8000 -``` - -### 4. 部署到服务器 -将 `build/web/` 目录的内容上传到你的 Web 服务器 - ---- - -## 🌍 部署平台示例 - -### GitHub Pages -```bash -./tools/build_web.sh -# 将 build/web/ 推送到 gh-pages 分支 -``` - -### Netlify -```bash -# 直接拖拽 build/web/ 目录到 Netlify -``` - -### Vercel -```bash -./tools/build_web.sh -vercel --prod build/web/ -``` - -### 自己的服务器 -```bash -scp -r build/web/* user@server:/var/www/html/ -``` - ---- - -## ⚠️ 常见问题 - -### 问题 1: 找不到 Godot -**解决方案**: 修改脚本中的 `GODOT_PATH` 变量 - -### 问题 2: 权限不足 (macOS/Linux) -**解决方案**: -```bash -chmod +x tools/build_web.sh tools/serve_web.sh -``` - -### 问题 3: 浏览器无法加载游戏 -**原因**: 必须使用 HTTP 服务器,不能用 `file://` -**解决方案**: 使用 `serve_web.sh` 启动本地服务器 - -### 问题 4: 游戏黑屏 -**检查**: -- 浏览器控制台是否有错误 -- WebAssembly 是否启用 -- 是否在 HTTPS 或 localhost 环境下运行 - ---- - -## 📚 相关文档 - -- [Godot Web 导出文档](https://docs.godotengine.org/en/stable/tutorials/export/exporting_for_web.html) -- [Web 服务器配置](https://docs.godotengine.org/en/stable/tutorials/export/binary_files_for_web_games.html) -- [项目 Web 部署指南](../docs/web_deployment_guide.md) - ---- - -## 🎯 下一步 - -1. 确保安装了 Godot 4.5+ -2. 运行 `./tools/build_web.sh` 测试导出 -3. 运行 `./tools/serve_web.sh` 本地预览 -4. 根据需要修改配置参数 - ---- - -**祝你发布顺利!** 🚀