diff --git a/.import/icons.png-67a334c68ca839e2c9d988e4ef34c645.md5 b/.import/icons.png-67a334c68ca839e2c9d988e4ef34c645.md5 new file mode 100644 index 0000000..49ca036 --- /dev/null +++ b/.import/icons.png-67a334c68ca839e2c9d988e4ef34c645.md5 @@ -0,0 +1,3 @@ +source_md5="a74561b8bcd64b6ca7fb83cdb6b5d485" +dest_md5="b3a45028e1b1186751f5f5159dad612f" + diff --git a/project.godot b/project.godot index 73ce8d4..a1af023 100644 --- a/project.godot +++ b/project.godot @@ -15,6 +15,21 @@ _global_script_classes=[ { "path": "res://scripts/ArrayTween.gd" }, { "base": "Sprite", +"class": "DoorSprite", +"language": "GDScript", +"path": "res://scripts/DoorSprite.gd" +}, { +"base": "StaticBody2D", +"class": "DoorStaticBody2D", +"language": "GDScript", +"path": "res://scripts/DoorStaticBody2D.gd" +}, { +"base": "Sprite", +"class": "ElixirsSprite", +"language": "GDScript", +"path": "res://scripts/ElixirsSprite.gd" +}, { +"base": "Sprite", "class": "KeySprite", "language": "GDScript", "path": "res://scripts/KeySprite.gd" @@ -41,6 +56,9 @@ _global_script_classes=[ { } ] _global_script_class_icons={ "ArrayTween": "", +"DoorSprite": "", +"DoorStaticBody2D": "", +"ElixirsSprite": "", "KeySprite": "", "NavigationTileMap": "", "PlayerKinematicBody2D": "", diff --git a/scenes/Doore.tscn b/scenes/Doore.tscn new file mode 100644 index 0000000..1ec06c2 --- /dev/null +++ b/scenes/Doore.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://images/mota.png" type="Texture" id=1] +[ext_resource path="res://scripts/DoorSprite.gd" type="Script" id=2] +[ext_resource path="res://scripts/DoorStaticBody2D.gd" type="Script" id=3] + +[sub_resource type="RectangleShape2D" id=1] +extents = Vector2( 16, 16 ) + +[node name="DoorSprite" type="Sprite"] +position = Vector2( 304, 208 ) +texture = ExtResource( 1 ) +region_enabled = true +region_rect = Rect2( 192, 480, 32, 32 ) +script = ExtResource( 2 ) + +[node name="StaticBody2D" type="StaticBody2D" parent="."] +script = ExtResource( 3 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="StaticBody2D"] +shape = SubResource( 1 ) diff --git a/scenes/Elixirs.tscn b/scenes/Elixirs.tscn new file mode 100644 index 0000000..84957ea --- /dev/null +++ b/scenes/Elixirs.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://scripts/ElixirsSprite.gd" type="Script" id=1] +[ext_resource path="res://images/mota.png" type="Texture" id=2] + +[sub_resource type="RectangleShape2D" id=1] + +[node name="ElixirsSprite" type="Sprite"] +position = Vector2( 272, 240 ) +texture = ExtResource( 2 ) +region_enabled = true +region_rect = Rect2( 96, 416, 32, 32 ) +script = ExtResource( 1 ) + +[node name="Area2D" type="Area2D" parent="."] + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] +shape = SubResource( 1 ) +[connection signal="body_entered" from="Area2D" to="." method="_on_Area2D_body_entered"] diff --git a/scenes/Key.tscn b/scenes/Key.tscn new file mode 100644 index 0000000..49fb5c7 --- /dev/null +++ b/scenes/Key.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://scripts/KeySprite.gd" type="Script" id=1] +[ext_resource path="res://images/mota.png" type="Texture" id=2] + +[sub_resource type="RectangleShape2D" id=1] + +[node name="KeySprite" type="Sprite"] +position = Vector2( 432, 208 ) +texture = ExtResource( 2 ) +region_enabled = true +region_rect = Rect2( 96, 448, 32, 32 ) +script = ExtResource( 1 ) + +[node name="Area2D" type="Area2D" parent="."] + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] +shape = SubResource( 1 ) +[connection signal="body_entered" from="Area2D" to="." method="_on_Area2D_body_entered"] diff --git a/scenes/Player.tscn b/scenes/Player.tscn index ac73af0..bd72268 100644 --- a/scenes/Player.tscn +++ b/scenes/Player.tscn @@ -6,7 +6,7 @@ [ext_resource path="res://images/mota.png" type="Texture" id=4] [sub_resource type="RectangleShape2D" id=1] -extents = Vector2( 8, 8 ) +extents = Vector2( 15.9, 15.9 ) [sub_resource type="Animation" id=2] resource_name = "down" diff --git a/scenes/UI.tscn b/scenes/UI.tscn index b68f6e3..a57af13 100644 --- a/scenes/UI.tscn +++ b/scenes/UI.tscn @@ -94,7 +94,7 @@ __meta__ = { margin_right = 104.0 margin_bottom = 24.0 custom_fonts/font = SubResource( 2 ) -text = "魔塔 第01层" +text = "魔塔 第1层" align = 1 valign = 1 __meta__ = { diff --git a/scenes/floors/Floor1.tscn b/scenes/floors/Floor1.tscn new file mode 100644 index 0000000..c2e2167 --- /dev/null +++ b/scenes/floors/Floor1.tscn @@ -0,0 +1,65 @@ +[gd_scene load_steps=7 format=2] + +[ext_resource path="res://images/mota_tileset.tres" type="TileSet" id=1] +[ext_resource path="res://scenes/Doore.tscn" type="PackedScene" id=2] +[ext_resource path="res://scripts/NavigationTileMap.gd" type="Script" id=3] +[ext_resource path="res://scenes/Elixirs.tscn" type="PackedScene" id=4] +[ext_resource path="res://scenes/Player.tscn" type="PackedScene" id=5] +[ext_resource path="res://scenes/Key.tscn" type="PackedScene" id=6] + +[node name="Floor1" type="Node2D"] + +[node name="NavigationTileMap" type="TileMap" parent="."] +tile_set = ExtResource( 1 ) +cell_size = Vector2( 32, 32 ) +collision_mask = 2147483649 +format = 1 +tile_data = PoolIntArray( 196618, 2, 0, 262151, 2, 0, 262152, 2, 0, 262153, 2, 0, 262154, 2, 0, 262155, 2, 0, 262156, 2, 0, 262157, 2, 0, 327687, 2, 0, 327690, 2, 0, 327693, 2, 0, 393222, 2, 0, 393223, 2, 0, 393224, 2, 0, 393225, 2, 0, 393226, 2, 0, 393227, 2, 0, 393228, 2, 0, 393229, 2, 0, 393230, 2, 0, 393231, 2, 0, 458759, 2, 0, 458760, 2, 0, 458762, 2, 0, 458765, 2, 0, 524296, 2, 0, 524297, 2, 0, 524298, 2, 0, 524299, 2, 0, 524300, 2, 0, 524301, 2, 0, 589834, 2, 0 ) +script = ExtResource( 3 ) + +[node name="Item" type="Node2D" parent="."] + +[node name="KeySprite" parent="Item" instance=ExtResource( 6 )] + +[node name="KeySprite2" parent="Item" instance=ExtResource( 6 )] +position = Vector2( 336, 144 ) +region_rect = Rect2( 160, 448, 32, 32 ) +key_type = 2 + +[node name="KeySprite3" parent="Item" instance=ExtResource( 6 )] +position = Vector2( 336, 272 ) +region_rect = Rect2( 192, 448, 32, 32 ) +key_type = 3 + +[node name="KeySprite4" parent="Item" instance=ExtResource( 6 )] +position = Vector2( 240, 208 ) +region_rect = Rect2( 128, 448, 32, 32 ) +key_type = 1 + +[node name="DoorSprite" parent="Item" instance=ExtResource( 2 )] + +[node name="DoorSprite2" parent="Item" instance=ExtResource( 2 )] +position = Vector2( 368, 208 ) +region_rect = Rect2( 256, 480, 32, 32 ) +door_type = 2 + +[node name="DoorSprite3" parent="Item" instance=ExtResource( 2 )] +position = Vector2( 336, 176 ) +region_rect = Rect2( 288, 480, 32, 32 ) +door_type = 3 + +[node name="DoorSprite4" parent="Item" instance=ExtResource( 2 )] +position = Vector2( 336, 240 ) +region_rect = Rect2( 288, 480, 32, 32 ) +door_type = 3 + +[node name="ElixirsSprite" parent="Item" instance=ExtResource( 4 )] + +[node name="ElixirsSprite2" parent="Item" instance=ExtResource( 4 )] +position = Vector2( 240, 144 ) +region_rect = Rect2( 128, 416, 32, 32 ) +elixirs_color = 1 +elixirs_value = 200 + +[node name="PlayerKinematicBody2D" parent="." instance=ExtResource( 5 )] +navigation_tile_map_path = NodePath("../../Floor1/NavigationTileMap") diff --git a/scripts/DoorSprite.gd b/scripts/DoorSprite.gd new file mode 100644 index 0000000..f3b7e34 --- /dev/null +++ b/scripts/DoorSprite.gd @@ -0,0 +1,26 @@ +tool +extends Sprite + +class_name DoorSprite + +# 门类型 +enum DoorType { Yellow,Blue,Red,Iron } + +export(DoorType) var door_type setget set_door_type + +# 默认数据初始化 +func _init(): + self.texture = load("res://images/mota.png") + self.region_enabled = true + +func set_door_type(value): + door_type = value + match value: + DoorType.Yellow: + region_rect = Rect2(192,480,32,32) + DoorType.Blue: + region_rect = Rect2(224,480,32,32) + DoorType.Red: + region_rect = Rect2(256,480,32,32) + DoorType.Iron: + region_rect = Rect2(288,480,32,32) diff --git a/scripts/DoorStaticBody2D.gd b/scripts/DoorStaticBody2D.gd new file mode 100644 index 0000000..b89a381 --- /dev/null +++ b/scripts/DoorStaticBody2D.gd @@ -0,0 +1,25 @@ +extends StaticBody2D + +class_name DoorStaticBody2D + +onready var door_sprite : DoorSprite = get_parent() + +func on_player_touched(): + match door_sprite.door_type: + DoorSprite.DoorType.Yellow: + if GameArchiveManager.player_info.yellow_key <= 0: + return + GameArchiveManager.player_info.yellow_key -= 1 + $"/root/Main/UI/KeyBackground/YellowKeyCountLabel".text = GameArchiveManager.player_info.yellow_key as String + DoorSprite.DoorType.Blue: + if GameArchiveManager.player_info.blue_key <= 0: + return + GameArchiveManager.player_info.blue_key -= 1 + $"/root/Main/UI/KeyBackground/BlueKeyCountLabel".text = GameArchiveManager.player_info.blue_key as String + DoorSprite.DoorType.Red: + if GameArchiveManager.player_info.red_key <= 0: + return + GameArchiveManager.player_info.red_key -= 1 + $"/root/Main/UI/KeyBackground/RedKeyCountLabel".text = GameArchiveManager.player_info.red_key as String + door_sprite.queue_free() + GameArchiveManager.add_used_item(door_sprite.get_path()) diff --git a/scripts/ElixirsSprite.gd b/scripts/ElixirsSprite.gd new file mode 100644 index 0000000..f800edc --- /dev/null +++ b/scripts/ElixirsSprite.gd @@ -0,0 +1,33 @@ +tool +extends Sprite + +class_name ElixirsSprite + +# 药水颜色 +enum ElixirsColor { Red,Blue,Gold } + +export(ElixirsColor) var elixirs_color = ElixirsColor.Red setget set_elixirs_color + +# 药剂回升血量 +export var elixirs_value : int = 100 + +# 默认数据初始化 +func _init(): + self.texture = load("res://images/mota.png") + self.region_enabled = true + +func set_elixirs_color(value): + elixirs_color = value + match value: + ElixirsColor.Red: + region_rect = Rect2(96,416,32,32) + ElixirsColor.Blue: + region_rect = Rect2(128,416,32,32) + ElixirsColor.Gold: + region_rect = Rect2(160,416,32,32) + +func _on_Area2D_body_entered(body): + GameArchiveManager.player_info.hp += elixirs_value + $"/root/Main/UI/HpSprite/HpBackground/HpLabel".text = GameArchiveManager.player_info.hp as String + GameArchiveManager.add_used_item(get_path()) + queue_free() diff --git a/scripts/GameArchiveManager.gd b/scripts/GameArchiveManager.gd new file mode 100644 index 0000000..82c6908 --- /dev/null +++ b/scripts/GameArchiveManager.gd @@ -0,0 +1,151 @@ +extends Node + +const archive_image_path_prefix = "user://" + +const archive_file_path = "user://mota.save" + +# 当前玩家信息 +var player_info = { + #英雄名称 + "username" : "hero", + #英雄当前位置 + "position" : Vector2.ZERO, + #英雄血量 + "hp" : 1000, + # 英雄攻击力 + "atk" : 1, + # 英雄防御力 + "def" : 1, + #默认金钱 + "money" : 0, + # 英雄等级 + "level" : 1, + # 英雄经验 + "experience" : 0, + # 当前楼层 + "now_floor" : 1, + # 去过的最大楼层 + "max_floor" : 1, + # 去过的最小楼层 + "min_floor" : 1, + # 黄钥匙数量 + "yellow_key" : 0, + # 蓝钥匙数量 + "blue_key" : 0, + # 红钥匙数量 + "red_key" : 0, + # 绿色钥匙数量 + "green_key" : 0, + # 被使用的道具 + "used_items" : {} +} + +# 增加已经使用的对象 +func add_used_item(path:String) -> void: + if not player_info.has("used_items"): + player_info.used_items = {} + var k = player_info.now_floor as String + if not player_info.used_items.has(k): + player_info.used_items[k] = [path] + else: + player_info.used_items[k].append(path) + +# 根据楼层查询被使用的道具 +func get_used_item(f:int) -> Array: + if not player_info.has("used_items"): + return [] + var k = f as String + if not player_info.used_items.has(k): + return [] + else: + return player_info.used_items[k] + return [] + +# 保存存档 +func save_to_index(index:int): + update_player_position() + var archives := get_archives() as Array + if index >= 0 and index < archives.size(): + var archive = archives[index] as Dictionary + archive.update_time = OS.get_unix_time() + archive.screenshot_file_path = save_screenshot_to_file(index) + archive.player_info = self.player_info + else: + var archive = {} + archive.create_time = OS.get_unix_time() + archive.update_time = archive.create_time + archive.screenshot_file_path = save_screenshot_to_file(index) + archive.player_info = self.player_info + archives.append(archive) + save_archives(archives) + +# 获取玩家对象 +func get_player() -> PlayerKinematicBody2D: + return get_tree().get_nodes_in_group("player")[0] as PlayerKinematicBody2D + +# 更新玩家位置 +func update_player_position() -> void: + var player = get_player() + player_info.position = player.position + +# 根据索引加载存档 +func load_by_index(index:int) -> void: + var archive = get_archives()[index] + self.player_info = archive.player_info + #加载楼层 + GameFloorManager.load_by_floor(self.player_info.now_floor) + #设置人物位置 + var player = get_player() + player.position = self.player_info.position + #更新楼层UI显示 + $"/root/Main/UI/LevelBackground/LevelLabel".text = "魔塔 第%s层" % player_info.now_floor + #更新人物血量 + $"/root/Main/UI/HpSprite/HpBackground/HpLabel".text = player_info.hp as String + #更新钥匙数量显示 + $"/root/Main/UI/KeyBackground/YellowKeyCountLabel".text = player_info.yellow_key as String + $"/root/Main/UI/KeyBackground/BlueKeyCountLabel".text = player_info.blue_key as String + $"/root/Main/UI/KeyBackground/RedKeyCountLabel".text = player_info.red_key as String + $"/root/Main/UI/KeyBackground/GreenKeyCountLabel".text = player_info.green_key as String + +# 保存屏幕截图到本地 +func save_screenshot_to_file(index:int) -> String: + var image = get_viewport().get_texture().get_data() + image.flip_y() + var image_path = "%s%s%s" % [archive_image_path_prefix,index,".png"] + var result = image.save_png(image_path) + if result != OK: + print("保存存档图片错误:",result) + return image_path + +# 得到所有存档文件对象 +func get_archives() -> Array: + var archive_file = File.new() + if not archive_file.file_exists(archive_file_path): + archive_file.close() + return [] + var result = archive_file.open(archive_file_path,File.READ) + if result == OK: + return archive_file.get_var(true) + else: + archive_file.close() + return [] + +# 保存所有存档文件对象 +func save_archives(archives:Array) -> void: + var archive_file = File.new() + var result = archive_file.open(archive_file_path,File.WRITE) + if result == OK: + archive_file.store_var(archives,true) + else: + print("保存游戏文件失败:",result) + archive_file.close() + + + + + + + + + + diff --git a/scripts/GameFloorManager.gd b/scripts/GameFloorManager.gd new file mode 100644 index 0000000..6d133cc --- /dev/null +++ b/scripts/GameFloorManager.gd @@ -0,0 +1,16 @@ +extends Node + +const floor_file_path = "res://scenes/floors/Floor" + +# 加载指定楼层 +func load_by_floor(f:int) -> void: + var root = get_tree().get_root().get_node("Main") + var next_floor = load("%s%s%s" % [floor_file_path,f,".tscn"]).instance() as Node2D + var used_items = GameArchiveManager.get_used_item(f) + root.get_node("Floor%s" % f).free() + root.add_child(next_floor) + for used_item in used_items: + print("path ",used_item) + var node = next_floor.get_node(used_item) + if node != null: + node.free() diff --git a/scripts/KeySprite.gd b/scripts/KeySprite.gd new file mode 100644 index 0000000..8ab10a6 --- /dev/null +++ b/scripts/KeySprite.gd @@ -0,0 +1,45 @@ +tool +extends Sprite + +class_name KeySprite + +enum KeyType { Yellow,Blue,Red,Green } + +# 钥匙类型 +export(KeyType) var key_type = KeyType.Yellow setget set_key_type + +func _init(): + self.texture = load("res://images/mota.png") + self.region_enabled = true + +func set_key_type(value): + key_type = value + match value: + KeyType.Yellow: + region_rect = Rect2(96,448,32,32) + KeyType.Blue: + region_rect = Rect2(128,448,32,32) + KeyType.Red: + region_rect = Rect2(160,448,32,32) + KeyType.Green: + region_rect = Rect2(192,448,32,32) + +# 触碰钥匙回调 +func _on_Area2D_body_entered(body): + if not body is PlayerKinematicBody2D: + return + match key_type: + KeyType.Yellow: + GameArchiveManager.player_info.yellow_key += 1 + $"/root/Main/UI/KeyBackground/YellowKeyCountLabel".text = GameArchiveManager.player_info.yellow_key as String + KeyType.Blue: + GameArchiveManager.player_info.blue_key += 1 + $"/root/Main/UI/KeyBackground/BlueKeyCountLabel".text = GameArchiveManager.player_info.blue_key as String + KeyType.Red: + GameArchiveManager.player_info.red_key += 1 + $"/root/Main/UI/KeyBackground/RedKeyCountLabel".text = GameArchiveManager.player_info.red_key as String + KeyType.Green: + GameArchiveManager.player_info.green_key += 1 + $"/root/Main/UI/KeyBackground/GreenKeyCountLabel".text = GameArchiveManager.player_info.green_key as String + queue_free() + GameArchiveManager.add_used_item(get_path()) diff --git a/scripts/LoadGameButton.gd b/scripts/LoadGameButton.gd new file mode 100644 index 0000000..80f3ed2 --- /dev/null +++ b/scripts/LoadGameButton.gd @@ -0,0 +1,5 @@ +extends Button + +func _on_LoadGameButton_pressed(): + GameArchiveManager.load_by_index(0) + pass # Replace with function body. diff --git a/scripts/PlayerKinematicBody2D.gd b/scripts/PlayerKinematicBody2D.gd index 0922207..cd6d8a1 100644 --- a/scripts/PlayerKinematicBody2D.gd +++ b/scripts/PlayerKinematicBody2D.gd @@ -39,5 +39,15 @@ func _on_ArrayTween_array_completed(): func _on_ArrayTween_array_value_step(step): var diff = step - position animation_tree["parameters/player/blend_position"] = diff - move_and_collide(diff) - get_viewport().get_texture() + var result = move_and_collide(diff) + call_collider(result) + +# 调用被碰撞对象的方法 +func call_collider(collision:KinematicCollision2D): + if collision == null or collision.collider == null: + return + var collider = collision.collider + if collider is TileMap: + return + if collider.has_method("on_player_touched"): + collider.on_player_touched() diff --git a/scripts/SaveGameButton.gd b/scripts/SaveGameButton.gd new file mode 100644 index 0000000..98e7134 --- /dev/null +++ b/scripts/SaveGameButton.gd @@ -0,0 +1,7 @@ +extends Button + +class_name SaveGameButton + +func _on_SaveGameButton_pressed(): + GameArchiveManager.save_to_index(0) + pass # Replace with function body.