diff --git a/prefab/Cursor.tscn b/prefab/Cursor.tscn
deleted file mode 100644
index 1202607..0000000
--- a/prefab/Cursor.tscn
+++ /dev/null
@@ -1,36 +0,0 @@
-[gd_scene load_steps=3 format=2]
-
-[ext_resource path="res://resource/sprite/effect/Cursor.png" type="Texture" id=1]
-[ext_resource path="res://src/effect/Cursor.cs" type="Script" id=2]
-
-[node name="Cursor" type="Node2D"]
-script = ExtResource( 2 )
-
-[node name="Center" type="Sprite" parent="."]
-texture = ExtResource( 1 )
-region_enabled = true
-region_rect = Rect2( 3, 3, 2, 2 )
-
-[node name="LT" type="Sprite" parent="."]
-texture = ExtResource( 1 )
-offset = Vector2( -0.5, -0.5 )
-region_enabled = true
-region_rect = Rect2( 0, 0, 3, 3 )
-
-[node name="LB" type="Sprite" parent="."]
-texture = ExtResource( 1 )
-offset = Vector2( -0.5, 0.5 )
-region_enabled = true
-region_rect = Rect2( 0, 5, 3, 3 )
-
-[node name="RT" type="Sprite" parent="."]
-texture = ExtResource( 1 )
-offset = Vector2( 0.5, -0.5 )
-region_enabled = true
-region_rect = Rect2( 5, 0, 3, 3 )
-
-[node name="RB" type="Sprite" parent="."]
-texture = ExtResource( 1 )
-offset = Vector2( 0.5, 0.5 )
-region_enabled = true
-region_rect = Rect2( 5, 5, 3, 3 )
diff --git a/prefab/Gun.tscn b/prefab/Gun.tscn
deleted file mode 100644
index 4c34c81..0000000
--- a/prefab/Gun.tscn
+++ /dev/null
@@ -1,35 +0,0 @@
-[gd_scene load_steps=5 format=2]
-
-[ext_resource path="res://resource/sprite/gun/gun1.png" type="Texture" id=1]
-[ext_resource path="res://src/gun/OrdinaryGun.cs" type="Script" id=2]
-[ext_resource path="res://prefab/bullet/OrdinaryBullets.tscn" type="PackedScene" id=3]
-
-[sub_resource type="RectangleShape2D" id=1]
-extents = Vector2( 9.5, 3.5 )
-
-[node name="Gun" type="Node2D"]
-z_index = 5
-script = ExtResource( 2 )
-bulletPacked = ExtResource( 3 )
-
-[node name="GunSprite" type="Sprite" parent="."]
-position = Vector2( 4, -3 )
-scale = Vector2( 0.8, 0.8 )
-texture = ExtResource( 1 )
-
-[node name="OriginPoint" type="Position2D" parent="."]
-position = Vector2( 0, -1.5 )
-scale = Vector2( 0.8, 0.8 )
-
-[node name="FirePoint" type="Position2D" parent="."]
-position = Vector2( 11, -1.5 )
-scale = Vector2( 0.8, 0.8 )
-
-[node name="Area" type="Area2D" parent="."]
-collision_layer = 4
-collision_mask = 0
-
-[node name="Collision" type="CollisionShape2D" parent="Area"]
-position = Vector2( 4.2, -0.199999 )
-shape = SubResource( 1 )
-disabled = true
diff --git a/prefab/Player.tscn b/prefab/Player.tscn
deleted file mode 100644
index 5432380..0000000
--- a/prefab/Player.tscn
+++ /dev/null
@@ -1,9 +0,0 @@
-[gd_scene load_steps=4 format=2]
-
-[ext_resource path="res://prefab/Role.tscn" type="PackedScene" id=1]
-[ext_resource path="res://src/role/Player.cs" type="Script" id=2]
-[ext_resource path="res://prefab/Gun.tscn" type="PackedScene" id=4]
-
-[node name="Player" instance=ExtResource( 1 )]
-script = ExtResource( 2 )
-GunPrefab = ExtResource( 4 )
diff --git a/prefab/Role.tscn b/prefab/Role.tscn
deleted file mode 100644
index ddc7240..0000000
--- a/prefab/Role.tscn
+++ /dev/null
@@ -1,102 +0,0 @@
-[gd_scene load_steps=19 format=2]
-
-[ext_resource path="res://resource/sprite/role/role1.png" type="Texture" id=1]
-[ext_resource path="res://src/role/Role.cs" type="Script" id=2]
-[ext_resource path="res://resource/sprite/role/role2.png" type="Texture" id=3]
-
-[sub_resource type="AtlasTexture" id=21]
-atlas = ExtResource( 1 )
-region = Rect2( 0, 48, 16, 24 )
-
-[sub_resource type="AtlasTexture" id=22]
-atlas = ExtResource( 1 )
-region = Rect2( 16, 48, 16, 24 )
-
-[sub_resource type="AtlasTexture" id=23]
-atlas = ExtResource( 1 )
-region = Rect2( 32, 48, 16, 24 )
-
-[sub_resource type="AtlasTexture" id=24]
-atlas = ExtResource( 1 )
-region = Rect2( 48, 48, 16, 24 )
-
-[sub_resource type="AtlasTexture" id=25]
-atlas = ExtResource( 1 )
-region = Rect2( 48, 48, 16, 24 )
-
-[sub_resource type="AtlasTexture" id=26]
-atlas = ExtResource( 1 )
-region = Rect2( 32, 48, 16, 24 )
-
-[sub_resource type="AtlasTexture" id=27]
-atlas = ExtResource( 1 )
-region = Rect2( 16, 48, 16, 24 )
-
-[sub_resource type="AtlasTexture" id=28]
-atlas = ExtResource( 1 )
-region = Rect2( 0, 48, 16, 24 )
-
-[sub_resource type="AtlasTexture" id=17]
-atlas = ExtResource( 1 )
-region = Rect2( 0, 24, 16, 24 )
-
-[sub_resource type="AtlasTexture" id=18]
-atlas = ExtResource( 1 )
-region = Rect2( 16, 24, 16, 24 )
-
-[sub_resource type="AtlasTexture" id=19]
-atlas = ExtResource( 1 )
-region = Rect2( 32, 24, 16, 24 )
-
-[sub_resource type="AtlasTexture" id=20]
-atlas = ExtResource( 1 )
-region = Rect2( 48, 24, 16, 24 )
-
-[sub_resource type="SpriteFrames" id=6]
-animations = [ {
-"frames": [ SubResource( 21 ), SubResource( 22 ), SubResource( 23 ), SubResource( 24 ) ],
-"loop": true,
-"name": "run",
-"speed": 10.0
-}, {
-"frames": [ SubResource( 25 ), SubResource( 26 ), SubResource( 27 ), SubResource( 28 ) ],
-"loop": true,
-"name": "reverseRun",
-"speed": 10.0
-}, {
-"frames": [ SubResource( 17 ), SubResource( 18 ), SubResource( 19 ), SubResource( 20 ) ],
-"loop": true,
-"name": "idle",
-"speed": 7.0
-} ]
-
-[sub_resource type="RectangleShape2D" id=29]
-extents = Vector2( 5, 7.5 )
-
-[sub_resource type="RectangleShape2D" id=16]
-extents = Vector2( 5, 4.5 )
-
-[node name="Role" type="KinematicBody2D"]
-collision_layer = 0
-script = ExtResource( 2 )
-Texture = ExtResource( 3 )
-
-[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
-position = Vector2( 0, -12 )
-frames = SubResource( 6 )
-animation = "idle"
-playing = true
-
-[node name="HitArea" type="Area2D" parent="."]
-
-[node name="CollisionShape2D" type="CollisionShape2D" parent="HitArea"]
-visible = false
-position = Vector2( 0, -7.5 )
-shape = SubResource( 29 )
-
-[node name="Collision" type="CollisionShape2D" parent="."]
-position = Vector2( 0, -4.5 )
-shape = SubResource( 16 )
-
-[node name="MountPoint" type="Position2D" parent="."]
-position = Vector2( 2, -4 )
diff --git a/prefab/bullet/HighSpeedBullet.tscn b/prefab/bullet/HighSpeedBullet.tscn
deleted file mode 100644
index e8ce680..0000000
--- a/prefab/bullet/HighSpeedBullet.tscn
+++ /dev/null
@@ -1,27 +0,0 @@
-[gd_scene load_steps=5 format=2]
-
-[ext_resource path="res://src/bullet/HighSpeedBullet.cs" type="Script" id=1]
-[ext_resource path="res://prefab/effect/Hit.tscn" type="PackedScene" id=2]
-
-[sub_resource type="Curve" id=1]
-_data = [ Vector2( 0, 0.781588 ), 0.0, 0.0, 0, 0, Vector2( 1, 1 ), 0.0, 0.0, 0, 0 ]
-
-[sub_resource type="Gradient" id=2]
-colors = PoolColorArray( 1, 1, 1, 0, 1, 1, 1, 0.705882 )
-
-[node name="HighSpeedBullet" type="Node2D"]
-script = ExtResource( 1 )
-Hit = ExtResource( 2 )
-
-[node name="Line" type="Line2D" parent="."]
-modulate = Color( 1, 0.937255, 0.843137, 1 )
-points = PoolVector2Array( 0, 0, 0, 10 )
-width = 1.0
-width_curve = SubResource( 1 )
-default_color = Color( 1, 1, 1, 1 )
-gradient = SubResource( 2 )
-begin_cap_mode = 2
-end_cap_mode = 2
-
-[node name="RayCast2D" type="RayCast2D" parent="."]
-visible = false
diff --git a/prefab/bullet/OrdinaryBullets.tscn b/prefab/bullet/OrdinaryBullets.tscn
deleted file mode 100644
index 2b67735..0000000
--- a/prefab/bullet/OrdinaryBullets.tscn
+++ /dev/null
@@ -1,16 +0,0 @@
-[gd_scene load_steps=4 format=2]
-
-[ext_resource path="res://src/bullet/OrdinaryBullets.cs" type="Script" id=1]
-[ext_resource path="res://resource/sprite/bullet/bullet.png" type="Texture" id=2]
-[ext_resource path="res://prefab/effect/Hit.tscn" type="PackedScene" id=3]
-
-[node name="OrdinaryBullets" type="RayCast2D"]
-enabled = true
-cast_to = Vector2( 8, 0 )
-script = ExtResource( 1 )
-Hit = ExtResource( 3 )
-
-[node name="Bullet" type="Sprite" parent="."]
-position = Vector2( 7, 0 )
-texture = ExtResource( 2 )
-offset = Vector2( -7.5, 0 )
diff --git a/prefab/common/ThrowNode.tscn b/prefab/common/ThrowNode.tscn
new file mode 100644
index 0000000..a35c9a7
--- /dev/null
+++ b/prefab/common/ThrowNode.tscn
@@ -0,0 +1,12 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://icon.png" type="Texture" id=1]
+[ext_resource path="res://src/weapon/ThrowNode.cs" type="Script" id=2]
+
+[node name="ThrowNode" type="Node2D"]
+position = Vector2( 140, 141 )
+script = ExtResource( 2 )
+
+[node name="Icon" type="Sprite" parent="."]
+scale = Vector2( 0.3, 0.3 )
+texture = ExtResource( 1 )
diff --git a/prefab/role/Player.tscn b/prefab/role/Player.tscn
new file mode 100644
index 0000000..06f381b
--- /dev/null
+++ b/prefab/role/Player.tscn
@@ -0,0 +1,9 @@
+[gd_scene load_steps=4 format=2]
+
+[ext_resource path="res://prefab/role/Role.tscn" type="PackedScene" id=1]
+[ext_resource path="res://src/role/Player.cs" type="Script" id=2]
+[ext_resource path="res://prefab/weapon/Gun.tscn" type="PackedScene" id=4]
+
+[node name="Player" instance=ExtResource( 1 )]
+script = ExtResource( 2 )
+GunPrefab = ExtResource( 4 )
diff --git a/prefab/role/Role.tscn b/prefab/role/Role.tscn
new file mode 100644
index 0000000..58b6905
--- /dev/null
+++ b/prefab/role/Role.tscn
@@ -0,0 +1,103 @@
+[gd_scene load_steps=19 format=2]
+
+[ext_resource path="res://src/role/Role.cs" type="Script" id=1]
+[ext_resource path="res://resource/sprite/role/role2.png" type="Texture" id=2]
+[ext_resource path="res://resource/sprite/role/role1.png" type="Texture" id=3]
+
+[sub_resource type="AtlasTexture" id=21]
+atlas = ExtResource( 3 )
+region = Rect2( 0, 48, 16, 24 )
+
+[sub_resource type="AtlasTexture" id=22]
+atlas = ExtResource( 3 )
+region = Rect2( 16, 48, 16, 24 )
+
+[sub_resource type="AtlasTexture" id=23]
+atlas = ExtResource( 3 )
+region = Rect2( 32, 48, 16, 24 )
+
+[sub_resource type="AtlasTexture" id=24]
+atlas = ExtResource( 3 )
+region = Rect2( 48, 48, 16, 24 )
+
+[sub_resource type="AtlasTexture" id=25]
+atlas = ExtResource( 3 )
+region = Rect2( 48, 48, 16, 24 )
+
+[sub_resource type="AtlasTexture" id=26]
+atlas = ExtResource( 3 )
+region = Rect2( 32, 48, 16, 24 )
+
+[sub_resource type="AtlasTexture" id=27]
+atlas = ExtResource( 3 )
+region = Rect2( 16, 48, 16, 24 )
+
+[sub_resource type="AtlasTexture" id=28]
+atlas = ExtResource( 3 )
+region = Rect2( 0, 48, 16, 24 )
+
+[sub_resource type="AtlasTexture" id=17]
+atlas = ExtResource( 3 )
+region = Rect2( 0, 24, 16, 24 )
+
+[sub_resource type="AtlasTexture" id=18]
+atlas = ExtResource( 3 )
+region = Rect2( 16, 24, 16, 24 )
+
+[sub_resource type="AtlasTexture" id=19]
+atlas = ExtResource( 3 )
+region = Rect2( 32, 24, 16, 24 )
+
+[sub_resource type="AtlasTexture" id=20]
+atlas = ExtResource( 3 )
+region = Rect2( 48, 24, 16, 24 )
+
+[sub_resource type="SpriteFrames" id=6]
+animations = [ {
+"frames": [ SubResource( 21 ), SubResource( 22 ), SubResource( 23 ), SubResource( 24 ) ],
+"loop": true,
+"name": "run",
+"speed": 10.0
+}, {
+"frames": [ SubResource( 25 ), SubResource( 26 ), SubResource( 27 ), SubResource( 28 ) ],
+"loop": true,
+"name": "reverseRun",
+"speed": 10.0
+}, {
+"frames": [ SubResource( 17 ), SubResource( 18 ), SubResource( 19 ), SubResource( 20 ) ],
+"loop": true,
+"name": "idle",
+"speed": 7.0
+} ]
+
+[sub_resource type="RectangleShape2D" id=29]
+extents = Vector2( 5, 7.5 )
+
+[sub_resource type="RectangleShape2D" id=16]
+extents = Vector2( 5, 4.5 )
+
+[node name="Role" type="KinematicBody2D"]
+collision_layer = 0
+script = ExtResource( 1 )
+Texture = ExtResource( 2 )
+
+[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
+position = Vector2( 0, -12 )
+frames = SubResource( 6 )
+animation = "idle"
+frame = 1
+playing = true
+
+[node name="HitArea" type="Area2D" parent="."]
+
+[node name="CollisionShape2D" type="CollisionShape2D" parent="HitArea"]
+visible = false
+position = Vector2( 0, -7.5 )
+shape = SubResource( 29 )
+
+[node name="Collision" type="CollisionShape2D" parent="."]
+position = Vector2( 0, -4.5 )
+shape = SubResource( 16 )
+
+[node name="MountPoint" type="Position2D" parent="."]
+position = Vector2( 2, -4 )
diff --git a/prefab/ui/Cursor.tscn b/prefab/ui/Cursor.tscn
new file mode 100644
index 0000000..1202607
--- /dev/null
+++ b/prefab/ui/Cursor.tscn
@@ -0,0 +1,36 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://resource/sprite/effect/Cursor.png" type="Texture" id=1]
+[ext_resource path="res://src/effect/Cursor.cs" type="Script" id=2]
+
+[node name="Cursor" type="Node2D"]
+script = ExtResource( 2 )
+
+[node name="Center" type="Sprite" parent="."]
+texture = ExtResource( 1 )
+region_enabled = true
+region_rect = Rect2( 3, 3, 2, 2 )
+
+[node name="LT" type="Sprite" parent="."]
+texture = ExtResource( 1 )
+offset = Vector2( -0.5, -0.5 )
+region_enabled = true
+region_rect = Rect2( 0, 0, 3, 3 )
+
+[node name="LB" type="Sprite" parent="."]
+texture = ExtResource( 1 )
+offset = Vector2( -0.5, 0.5 )
+region_enabled = true
+region_rect = Rect2( 0, 5, 3, 3 )
+
+[node name="RT" type="Sprite" parent="."]
+texture = ExtResource( 1 )
+offset = Vector2( 0.5, -0.5 )
+region_enabled = true
+region_rect = Rect2( 5, 0, 3, 3 )
+
+[node name="RB" type="Sprite" parent="."]
+texture = ExtResource( 1 )
+offset = Vector2( 0.5, 0.5 )
+region_enabled = true
+region_rect = Rect2( 5, 5, 3, 3 )
diff --git a/prefab/ui/RoomUI.tscn b/prefab/ui/RoomUI.tscn
new file mode 100644
index 0000000..727b74e
--- /dev/null
+++ b/prefab/ui/RoomUI.tscn
@@ -0,0 +1,8 @@
+[gd_scene load_steps=2 format=2]
+
+[ext_resource path="res://src/ui/RoomUI.cs" type="Script" id=1]
+
+[node name="RoomUI" type="Control"]
+anchor_right = 1.0
+anchor_bottom = 1.0
+script = ExtResource( 1 )
diff --git a/prefab/weapon/Gun.tscn b/prefab/weapon/Gun.tscn
new file mode 100644
index 0000000..3bbecf2
--- /dev/null
+++ b/prefab/weapon/Gun.tscn
@@ -0,0 +1,35 @@
+[gd_scene load_steps=5 format=2]
+
+[ext_resource path="res://src/weapon/gun/OrdinaryGun.cs" type="Script" id=1]
+[ext_resource path="res://prefab/weapon/bullet/OrdinaryBullets.tscn" type="PackedScene" id=2]
+[ext_resource path="res://resource/sprite/gun/gun1.png" type="Texture" id=3]
+
+[sub_resource type="RectangleShape2D" id=1]
+extents = Vector2( 9.5, 3.5 )
+
+[node name="Gun" type="Node2D"]
+z_index = 5
+script = ExtResource( 1 )
+bulletPacked = ExtResource( 2 )
+
+[node name="GunSprite" type="Sprite" parent="."]
+position = Vector2( 4, -3 )
+scale = Vector2( 0.8, 0.8 )
+texture = ExtResource( 3 )
+
+[node name="OriginPoint" type="Position2D" parent="."]
+position = Vector2( 0, -1.5 )
+scale = Vector2( 0.8, 0.8 )
+
+[node name="FirePoint" type="Position2D" parent="."]
+position = Vector2( 11, -1.5 )
+scale = Vector2( 0.8, 0.8 )
+
+[node name="Area" type="Area2D" parent="."]
+collision_layer = 4
+collision_mask = 0
+
+[node name="Collision" type="CollisionShape2D" parent="Area"]
+position = Vector2( 4.2, -0.199999 )
+shape = SubResource( 1 )
+disabled = true
diff --git a/prefab/weapon/bullet/HighSpeedBullet.tscn b/prefab/weapon/bullet/HighSpeedBullet.tscn
new file mode 100644
index 0000000..f3a97b6
--- /dev/null
+++ b/prefab/weapon/bullet/HighSpeedBullet.tscn
@@ -0,0 +1,27 @@
+[gd_scene load_steps=5 format=2]
+
+[ext_resource path="res://src/weapon/bullet/HighSpeedBullet.cs" type="Script" id=1]
+[ext_resource path="res://prefab/effect/Hit.tscn" type="PackedScene" id=2]
+
+[sub_resource type="Curve" id=1]
+_data = [ Vector2( 0, 0.781588 ), 0.0, 0.0, 0, 0, Vector2( 1, 1 ), 0.0, 0.0, 0, 0 ]
+
+[sub_resource type="Gradient" id=2]
+colors = PoolColorArray( 1, 1, 1, 0, 1, 1, 1, 0.705882 )
+
+[node name="HighSpeedBullet" type="Node2D"]
+script = ExtResource( 1 )
+Hit = ExtResource( 2 )
+
+[node name="Line" type="Line2D" parent="."]
+modulate = Color( 1, 0.937255, 0.843137, 1 )
+points = PoolVector2Array( 0, 0, 0, 10 )
+width = 1.0
+width_curve = SubResource( 1 )
+default_color = Color( 1, 1, 1, 1 )
+gradient = SubResource( 2 )
+begin_cap_mode = 2
+end_cap_mode = 2
+
+[node name="RayCast2D" type="RayCast2D" parent="."]
+visible = false
diff --git a/prefab/weapon/bullet/OrdinaryBullets.tscn b/prefab/weapon/bullet/OrdinaryBullets.tscn
new file mode 100644
index 0000000..f9d4848
--- /dev/null
+++ b/prefab/weapon/bullet/OrdinaryBullets.tscn
@@ -0,0 +1,18 @@
+[gd_scene load_steps=4 format=2]
+
+[ext_resource path="res://src/weapon/bullet/OrdinaryBullets.cs" type="Script" id=1]
+[ext_resource path="res://resource/sprite/bullet/bullet.png" type="Texture" id=2]
+[ext_resource path="res://prefab/effect/Hit.tscn" type="PackedScene" id=3]
+
+[node name="OrdinaryBullets" type="Node2D"]
+script = ExtResource( 1 )
+Hit = ExtResource( 3 )
+
+[node name="RayCast2D" type="RayCast2D" parent="."]
+enabled = true
+cast_to = Vector2( 18, 0 )
+
+[node name="Bullet" type="Sprite" parent="."]
+position = Vector2( 0.5, 0 )
+texture = ExtResource( 2 )
+offset = Vector2( -7.5, 0 )
diff --git a/project.godot b/project.godot
index 3040099..f339797 100644
--- a/project.godot
+++ b/project.godot
@@ -14,6 +14,10 @@
run/main_scene="res://scene/Room.tscn"
config/icon="res://icon.png"
+[autoload]
+
+GameManager="*res://src/manager/GameManager.cs"
+
[display]
window/size/width=480
diff --git a/resource/sprite/bullet/bullet.png b/resource/sprite/bullet/bullet.png
index e9c30ef..fb6ccea 100644
--- a/resource/sprite/bullet/bullet.png
+++ b/resource/sprite/bullet/bullet.png
Binary files differ
diff --git a/resource/tile/itch-io-DungeonTileset4.tres b/resource/tile/itch-io-DungeonTileset4.tres
deleted file mode 100644
index b2eceaa..0000000
--- a/resource/tile/itch-io-DungeonTileset4.tres
+++ /dev/null
@@ -1,540 +0,0 @@
-[gd_resource type="TileSet" load_steps=54 format=2]
-
-[ext_resource path="res://resource/sprite/package/itch-io-DungeonTileset4/16x16 dungeon ii wall reconfig v04 spritesheet.png" type="Texture" id=1]
-
-[sub_resource type="ConvexPolygonShape2D" id=1]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=2]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=3]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=4]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=5]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=6]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=7]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=8]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=9]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=10]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=11]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=12]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=13]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=14]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=15]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=16]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=17]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=18]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=19]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=20]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=21]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=22]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=23]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=24]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=25]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=26]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=27]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=28]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=29]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=30]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=31]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=32]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=33]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=34]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=35]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=36]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=37]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=38]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=39]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=40]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=41]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=42]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=43]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=44]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=45]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=46]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=47]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=48]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 16, 0, 16 )
-
-[sub_resource type="ConvexPolygonShape2D" id=51]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 12, 0, 12 )
-
-[sub_resource type="ConvexPolygonShape2D" id=52]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 12, 0, 12 )
-
-[sub_resource type="ConvexPolygonShape2D" id=53]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 12, 0, 12 )
-
-[sub_resource type="ConvexPolygonShape2D" id=54]
-points = PoolVector2Array( 0, 0, 16, 0, 16, 12, 0, 12 )
-
-[resource]
-0/name = "16x16 dungeon ii wall reconfig v04 spritesheet.png 0"
-0/texture = ExtResource( 1 )
-0/tex_offset = Vector2( 0, 0 )
-0/modulate = Color( 1, 1, 1, 1 )
-0/region = Rect2( 0, 0, 256, 128 )
-0/tile_mode = 1
-0/autotile/bitmask_mode = 2
-0/autotile/bitmask_flags = [ Vector2( 0, 0 ), 16, Vector2( 0, 2 ), 144, Vector2( 0, 3 ), 146, Vector2( 0, 6 ), 18, Vector2( 1, 0 ), 48, Vector2( 1, 2 ), 432, Vector2( 1, 3 ), 438, Vector2( 1, 6 ), 54, Vector2( 2, 0 ), 56, Vector2( 2, 2 ), 504, Vector2( 2, 3 ), 511, Vector2( 2, 6 ), 63, Vector2( 3, 0 ), 24, Vector2( 3, 2 ), 216, Vector2( 3, 3 ), 219, Vector2( 3, 6 ), 27, Vector2( 4, 0 ), 176, Vector2( 4, 4 ), 434, Vector2( 4, 6 ), 50, Vector2( 5, 4 ), 251, Vector2( 5, 6 ), 59, Vector2( 6, 0 ), 248, Vector2( 6, 1 ), 223, Vector2( 6, 3 ), 475, Vector2( 6, 4 ), 250, Vector2( 6, 6 ), 127, Vector2( 7, 0 ), 505, Vector2( 7, 2 ), 191, Vector2( 7, 4 ), 58, Vector2( 7, 6 ), 506, Vector2( 8, 0 ), 440, Vector2( 8, 1 ), 439, Vector2( 8, 3 ), 502, Vector2( 8, 4 ), 314, Vector2( 8, 6 ), 319, Vector2( 9, 4 ), 446, Vector2( 9, 6 ), 62, Vector2( 10, 0 ), 152, Vector2( 10, 4 ), 218, Vector2( 10, 6 ), 26, Vector2( 11, 0 ), 255, Vector2( 11, 2 ), 507, Vector2( 11, 7 ), 508, Vector2( 12, 7 ), 184, Vector2( 13, 0 ), 447, Vector2( 13, 2 ), 510, Vector2( 14, 1 ), 151, Vector2( 15, 1 ), 466 ]
-0/autotile/icon_coordinate = Vector2( 0, 0 )
-0/autotile/tile_size = Vector2( 16, 16 )
-0/autotile/spacing = 0
-0/autotile/occluder_map = [ ]
-0/autotile/navpoly_map = [ ]
-0/autotile/priority_map = [ ]
-0/autotile/z_index_map = [ ]
-0/occluder_offset = Vector2( 0, 0 )
-0/navigation_offset = Vector2( 0, 0 )
-0/shape_offset = Vector2( 0, 0 )
-0/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-0/shape = SubResource( 1 )
-0/shape_one_way = false
-0/shape_one_way_margin = 1.0
-0/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 1 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 1, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 2 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 2, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 3 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 3, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 4 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 0, 2 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 5 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 0, 3 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 6 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 0, 6 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 7 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 1, 2 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 8 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 2, 2 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 9 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 3, 2 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 10 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 1, 3 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 11 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 3, 3 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 12 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 2, 3 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 13 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 1, 6 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 14 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 2, 6 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 15 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 3, 6 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 16 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 4, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 17 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 4, 6 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 18 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 4, 4 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 19 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 5, 4 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 20 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 5, 6 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 21 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 6, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 22 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 7, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 23 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 8, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 24 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 10, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 25 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 6, 1 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 26 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 8, 1 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 27 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 7, 2 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 28 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 6, 3 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 29 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 8, 3 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 30 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 6, 4 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 31 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 7, 4 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 32 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 8, 4 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 33 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 9, 4 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 34 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 10, 4 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 35 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 6, 6 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 36 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 7, 6 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 37 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 9, 6 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 38 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 8, 6 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 39 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 10, 6 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 40 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 11, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 41 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 13, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 42 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 11, 2 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 43 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 13, 2 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 44 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 14, 1 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 45 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 15, 1 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 46 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 11, 7 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 47 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 12, 7 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 48 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-0/z_index = 0
-5/name = "16x16 dungeon ii wall reconfig v04 spritesheet.png 5"
-5/texture = ExtResource( 1 )
-5/tex_offset = Vector2( 0, 0 )
-5/modulate = Color( 1, 1, 1, 1 )
-5/region = Rect2( 0, 128, 64, 32 )
-5/tile_mode = 2
-5/autotile/icon_coordinate = Vector2( 0, 0 )
-5/autotile/tile_size = Vector2( 16, 16 )
-5/autotile/spacing = 0
-5/autotile/occluder_map = [ ]
-5/autotile/navpoly_map = [ ]
-5/autotile/priority_map = [ ]
-5/autotile/z_index_map = [ ]
-5/occluder_offset = Vector2( 0, 0 )
-5/navigation_offset = Vector2( 0, 0 )
-5/shape_offset = Vector2( 0, 0 )
-5/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-5/shape_one_way = false
-5/shape_one_way_margin = 0.0
-5/shapes = [ ]
-5/z_index = 0
-7/name = "16x16 dungeon ii wall reconfig v04 spritesheet.png 7"
-7/texture = ExtResource( 1 )
-7/tex_offset = Vector2( 0, 0 )
-7/modulate = Color( 1, 1, 1, 1 )
-7/region = Rect2( 0, 16, 64, 16 )
-7/tile_mode = 2
-7/autotile/icon_coordinate = Vector2( 0, 0 )
-7/autotile/tile_size = Vector2( 16, 16 )
-7/autotile/spacing = 0
-7/autotile/occluder_map = [ ]
-7/autotile/navpoly_map = [ ]
-7/autotile/priority_map = [ ]
-7/autotile/z_index_map = [ ]
-7/occluder_offset = Vector2( 0, 0 )
-7/navigation_offset = Vector2( 0, 0 )
-7/shape_offset = Vector2( 0, 0 )
-7/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
-7/shape = SubResource( 51 )
-7/shape_one_way = false
-7/shape_one_way_margin = 1.0
-7/shapes = [ {
-"autotile_coord": Vector2( 0, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 51 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 1, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 52 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 2, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 53 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-}, {
-"autotile_coord": Vector2( 3, 0 ),
-"one_way": false,
-"one_way_margin": 1.0,
-"shape": SubResource( 54 ),
-"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
-} ]
-7/z_index = 0
diff --git a/scene/Room.tscn b/scene/Room.tscn
index db8a22c..5900efa 100644
--- a/scene/Room.tscn
+++ b/scene/Room.tscn
@@ -1,14 +1,16 @@
-[gd_scene load_steps=5 format=2]
+[gd_scene load_steps=6 format=2]
-[ext_resource path="res://prefab/Player.tscn" type="PackedScene" id=1]
+[ext_resource path="res://prefab/role/Player.tscn" type="PackedScene" id=1]
[ext_resource path="res://resource/map/dungeon_test.tmx" type="PackedScene" id=2]
-[ext_resource path="res://src/RoomManager.cs" type="Script" id=3]
-[ext_resource path="res://prefab/Cursor.tscn" type="PackedScene" id=4]
+[ext_resource path="res://src/room/RoomManager.cs" type="Script" id=3]
+[ext_resource path="res://prefab/ui/Cursor.tscn" type="PackedScene" id=4]
+[ext_resource path="res://prefab/common/ThrowNode.tscn" type="PackedScene" id=5]
[node name="Room" type="Node2D"]
script = ExtResource( 3 )
MouseCursor = ExtResource( 4 )
UIPath = NodePath("")
+ThrowNode = ExtResource( 5 )
[node name="MapRoot" type="Node2D" parent="."]
diff --git a/src/MathUtils.cs b/src/MathUtils.cs
deleted file mode 100644
index 9c6033a..0000000
--- a/src/MathUtils.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using Godot;
-
-public static class MathUtils
-{
- ///
- /// 返回一个区间内的随机小数
- ///
- public static float RandRange(float min, float max)
- {
- if (min == max) return min;
- if (min > max)
- return GD.Randf() * (min - max) + max;
- return GD.Randf() * (max - min) + min;
- }
-
- ///
- /// 返回一个区间内的随机整数
- ///
- public static int RandRangeInt(int min, int max)
- {
- if (min == max) return min;
- if (min > max)
- return Mathf.FloorToInt(GD.Randf() * (min - max + 1) + max);
- return Mathf.FloorToInt(GD.Randf() * (max - min + 1) + min);
- }
-}
\ No newline at end of file
diff --git a/src/RoomManager.cs b/src/RoomManager.cs
deleted file mode 100644
index 7c2d6a0..0000000
--- a/src/RoomManager.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using Godot;
-
-///
-/// 房间管理器
-///
-public class RoomManager : Node2D
-{
- ///
- /// 鼠标指针
- ///
- [Export] public PackedScene MouseCursor;
-
- [Export] public NodePath UIPath;
-
- public static RoomManager Current { get; private set; }
-
- public CanvasLayer UI;
- public Cursor Cursor { get; private set; }
-
- public override void _EnterTree()
- {
- Current = this;
- Input.SetMouseMode(Input.MouseMode.Hidden);
- // 初始化鼠标
- Cursor = MouseCursor.Instance();
- AddChild(Cursor);
-
- //初始化地图
- var node = GetNode("MapRoot").GetChild(0).GetNode("Config");
- Color color = (Color) node.GetMeta("ClearColor");
- VisualServer.SetDefaultClearColor(color);
- }
-}
\ No newline at end of file
diff --git a/src/bullet/Bullet.cs b/src/bullet/Bullet.cs
deleted file mode 100644
index ec5ac06..0000000
--- a/src/bullet/Bullet.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using Godot;
-
-///
-/// 子弹接口
-///
-public interface IBullet
-{
- ///
- /// 攻击目标阵营
- ///
- CampEnum TargetCamp { get; }
- ///
- /// 发射该子弹的武器
- ///
- Gun Gun { get; }
- ///
- /// 发射该子弹的物体对象
- ///
- Node2D Master { get; }
- ///
- /// 初始化基础数据
- ///
- /// 攻击的目标阵营
- /// 发射该子弹的枪对象
- /// 发射该子弹的角色
- void Init(CampEnum target, Gun gun, Node2D master);
-}
\ No newline at end of file
diff --git a/src/bullet/HighSpeedBullet.cs b/src/bullet/HighSpeedBullet.cs
deleted file mode 100644
index 039c416..0000000
--- a/src/bullet/HighSpeedBullet.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using Godot;
-
-///
-/// 高速子弹
-///
-public class HighSpeedBullet : Node2D, IBullet
-{
- public CampEnum TargetCamp { get; private set; }
-
- public Gun Gun { get; private set; }
-
- public Node2D Master { get; private set; }
-
- ///
- /// 碰撞物体后产生的火花
- ///
- [Export] public PackedScene Hit;
-
- //射线检测节点
- private RayCast2D RayCast2D;
- private Line2D Line;
- private float ca = 1;
-
- public void Init(CampEnum target, Gun gun, Node2D master)
- {
- TargetCamp = target;
- Gun = gun;
- Master = master;
-
- //飞行距离
- var distance = MathUtils.RandRange(gun.Attribute.MinDistance, gun.Attribute.MaxDistance);
-
- //初始化子弹数据
- RayCast2D = GetNode("RayCast2D");
- Line = GetNode("Line");
- Modulate = Colors.White;
-
- // 目标点
- Vector2 targetPos = new Vector2(distance, 0);
- RayCast2D.CastTo = targetPos;
- RayCast2D.ForceRaycastUpdate();
- if (RayCast2D.IsColliding())
- {
- //碰到物体
- Vector2 collPosition = RayCast2D.GetCollisionPoint();
- Node2D hit = Hit.Instance();
- hit.RotationDegrees = MathUtils.RandRangeInt(0, 360);
- hit.GlobalPosition = collPosition;
- GetTree().CurrentScene.AddChild(hit);
- //划线的点坐标
- Line.SetPointPosition(1, new Vector2(Line.GlobalPosition.DistanceTo(collPosition), 0));
- }
- else
- {
- //划线的点坐标
- Line.SetPointPosition(1, targetPos);
- }
- RayCast2D.Enabled = false;
- }
-
- public override void _Process(float delta)
- {
- ca -= 12 * delta;
- if (ca <= 0) {
- QueueFree();
- return;
- }
- Color c = Modulate;
- c.a = ca;
- Modulate = c;
- }
-}
\ No newline at end of file
diff --git a/src/bullet/OrdinaryBullets.cs b/src/bullet/OrdinaryBullets.cs
deleted file mode 100644
index 34b0d71..0000000
--- a/src/bullet/OrdinaryBullets.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using Godot;
-
-///
-/// 普通的子弹
-///
-public class OrdinaryBullets : RayCast2D, IBullet
-{
- public CampEnum TargetCamp { get; private set; }
-
- public Gun Gun { get; private set; }
-
- public Node2D Master { get; private set; }
-
- ///
- /// 碰撞物体后产生的火花
- ///
- [Export] public PackedScene Hit;
-
- // 起始点坐标
- private Vector2 StartPosition;
- // 最大飞行距离
- private float MaxDistance;
- // 子弹飞行速度
- private float FlySpeed = 1500;
- //当前子弹已经飞行的距离
- private float CurrFlyDistance = 0;
-
- //子弹的精灵
- private Sprite BulletSprite;
-
- public void Init(CampEnum target, Gun gun, Node2D master)
- {
- TargetCamp = target;
- Gun = gun;
- Master = master;
-
- MaxDistance = MathUtils.RandRange(gun.Attribute.MinDistance, gun.Attribute.MaxDistance);
- StartPosition = GlobalPosition;
- //Scale = new Vector2(0, 1);
- BulletSprite = GetNode("Bullet");
- // BulletSprite.Visible = false;
-
- Scale = new Vector2(1.8f, 1);
- }
-
- public override void _PhysicsProcess(float delta)
- {
-
- if (IsColliding())
- {
- var pos = GetCollisionPoint();
- GlobalPosition = pos;
- Node2D hit = Hit.Instance();
- hit.RotationDegrees = MathUtils.RandRangeInt(0, 360);
- hit.GlobalPosition = pos;
- GetTree().CurrentScene.AddChild(hit);
- QueueFree();
- }
- else
- {
- Position += new Vector2(FlySpeed * delta, 0).Rotated(Rotation);
-
- if (CurrFlyDistance == 0)
- {
- BulletSprite.Visible = true;
- }
-
- CurrFlyDistance += FlySpeed * delta;
- if (CurrFlyDistance >= MaxDistance)
- {
- QueueFree();
- }
- }
- }
-
-}
\ No newline at end of file
diff --git a/src/common/CommonNodeManager.cs b/src/common/CommonNodeManager.cs
new file mode 100644
index 0000000..6d0f516
--- /dev/null
+++ b/src/common/CommonNodeManager.cs
@@ -0,0 +1,11 @@
+using Godot;
+
+public static class CommonNodeManager
+{
+ public const string ThrowNodeResPath = "";
+
+ public static ThrowNode CreateThrowNode(Vector2 start, Vector2 target, float startHeight, float targetHeight, float moveSpeed, float rotationSpeed)
+ {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/common/MathUtils.cs b/src/common/MathUtils.cs
new file mode 100644
index 0000000..9c6033a
--- /dev/null
+++ b/src/common/MathUtils.cs
@@ -0,0 +1,26 @@
+using Godot;
+
+public static class MathUtils
+{
+ ///
+ /// 返回一个区间内的随机小数
+ ///
+ public static float RandRange(float min, float max)
+ {
+ if (min == max) return min;
+ if (min > max)
+ return GD.Randf() * (min - max) + max;
+ return GD.Randf() * (max - min) + min;
+ }
+
+ ///
+ /// 返回一个区间内的随机整数
+ ///
+ public static int RandRangeInt(int min, int max)
+ {
+ if (min == max) return min;
+ if (min > max)
+ return Mathf.FloorToInt(GD.Randf() * (min - max + 1) + max);
+ return Mathf.FloorToInt(GD.Randf() * (max - min + 1) + min);
+ }
+}
\ No newline at end of file
diff --git a/src/gun/Gun.cs b/src/gun/Gun.cs
deleted file mode 100644
index a511109..0000000
--- a/src/gun/Gun.cs
+++ /dev/null
@@ -1,336 +0,0 @@
-using Godot;
-using System;
-
-///
-/// 枪的基类
-///
-public abstract class Gun : Node2D
-{
- ///
- /// 开火回调事件
- ///
- public event Action FireEvent;
-
- ///
- /// 属性数据
- ///
- public GunAttribute Attribute
- {
- get
- {
- if (_attribute == null)
- {
- throw new Exception("请先调用Init来初始化枪的属性");
- }
- return _attribute;
- }
- private set => _attribute = value;
- }
- private GunAttribute _attribute;
-
- ///
- /// 枪的图片
- ///
- public Sprite GunSprite { get; private set; }
-
- ///
- /// 枪攻击的目标阵营
- ///
- public CampEnum TargetCamp { get; set; }
- ///
- /// 枪管的开火点
- ///
- public Position2D FirePoint { get; private set; }
- ///
- /// 枪管的原点
- ///
- public Position2D OriginPoint { get; private set; }
- ///
- /// 枪的当前散射半径
- ///
- public float CurrScatteringRange { get; private set; } = 0;
-
- //是否按下
- private bool triggerFlag = false;
- //扳机计时器
- private float triggerTimer = 0;
- //开火前延时时间
- private float delayedTime = 0;
- //开火间隙时间
- private float fireInterval = 0;
- //开火枪口角度
- private float fireAngle = 0;
- //攻击冷却计时
- private float attackTimer = 0;
- //攻击状态
- private bool attackFlag = false;
- //按下的时间
- private float downTimer = 0;
- //松开的时间
- private float upTimer = 0;
- //连发次数
- private float continuousCount = 0;
- private bool continuousShootFlag = false;
-
- public override void _EnterTree()
- {
- GunSprite = GetNode("GunSprite");
- FirePoint = GetNode("FirePoint");
- OriginPoint = GetNode("OriginPoint");
- }
-
- public override void _Process(float delta)
- {
- if (triggerFlag)
- {
- if (upTimer > 0) //第一帧按下扳机
- {
- upTimer = 0;
- DownTrigger();
- }
- downTimer += delta;
- }
- else
- {
- if (downTimer > 0) //第一帧松开扳机
- {
- downTimer = 0;
- UpTriggern();
- }
- upTimer += delta;
- }
-
- // 攻击的计时器
- if (attackTimer > 0)
- {
- attackTimer -= delta;
- if (attackTimer < 0)
- {
- delayedTime += attackTimer;
- attackTimer = 0;
- }
- }
- else if (delayedTime > 0) //攻击延时
- {
- delayedTime -= delta;
- if (attackTimer < 0)
- {
- delayedTime = 0;
- }
- }
-
- //连发判断
- if (continuousCount > 0 && delayedTime <= 0 && attackTimer <= 0)
- {
- TriggernFire();
- }
-
- if (!attackFlag && attackTimer <= 0)
- {
- CurrScatteringRange = Mathf.Max(CurrScatteringRange - Attribute.ScatteringRangeBackSpeed * delta, Attribute.StartScatteringRange);
- }
- triggerTimer = triggerTimer > 0 ? triggerTimer - delta : 0;
- triggerFlag = false;
- attackFlag = false;
-
- //枪身回归
- Position = Position.MoveToward(Vector2.Zero, 35 * delta);
- if (fireInterval == 0)
- {
- RotationDegrees = 0;
- }
- else
- {
- RotationDegrees = Mathf.Lerp(0, fireAngle, attackTimer / fireInterval);
- }
- }
-
- public void Init(GunAttribute attribute)
- {
- if (_attribute != null)
- {
- throw new Exception("当前武器已经初始化过了!");
- }
-
- Attribute = attribute;
- //更新图片
- var texture = ResourceLoader.Load(attribute.Sprite);
- GunSprite.Texture = texture;
- //开火位置
- FirePoint.Position = new Vector2(attribute.FirePosition.x, -attribute.FirePosition.y);
- OriginPoint.Position = new Vector2(0, -attribute.FirePosition.y);
- //握把位置
- GunSprite.Position = attribute.HoldPosition;
-
- Init();
- }
-
- ///
- /// 扳机函数, 调用即视为扣动扳机
- ///
- public void Trigger()
- {
- //是否第一帧按下
- var justDown = downTimer == 0;
- //是否能发射
- var flag = false;
- if (continuousCount <= 0) //不能处于连发状态下
- {
- if (Attribute.ContinuousShoot) //自动射击
- {
- if (triggerTimer > 0)
- {
- if (continuousShootFlag)
- {
- flag = true;
- }
- }
- else
- {
- flag = true;
- if (delayedTime <= 0 && attackTimer <= 0)
- {
- continuousShootFlag = true;
- }
- }
- }
- else //半自动
- {
- if (justDown && triggerTimer <= 0)
- {
- flag = true;
- }
- }
- }
-
- if (flag)
- {
- if (justDown)
- {
- //开火前延时
- delayedTime = Attribute.DelayedTime;
- //扳机按下间隔
- triggerTimer = Attribute.TriggerInterval;
- //连发数量
- if (!Attribute.ContinuousShoot)
- {
- continuousCount = MathUtils.RandRangeInt(Attribute.MinContinuousCount, Attribute.MaxContinuousCount);
- }
- }
- if (delayedTime <= 0 && attackTimer <= 0)
- {
- TriggernFire();
- }
- attackFlag = true;
- }
- triggerFlag = true;
- }
-
- ///
- /// 刚按下扳机
- ///
- private void DownTrigger()
- {
-
- }
-
- ///
- /// 刚松开扳机
- ///
- private void UpTriggern()
- {
- continuousShootFlag = false;
- if (delayedTime > 0)
- {
- continuousCount = 0;
- }
- }
-
- ///
- /// 触发开火
- ///
- private void TriggernFire()
- {
- continuousCount = continuousCount > 0 ? continuousCount - 1 : 0;
- fireInterval = 60 / Attribute.StartFiringSpeed;
- attackTimer += fireInterval;
-
- //触发开火函数
- Fire();
-
- //开火发射的子弹数量
- var bulletCount = MathUtils.RandRangeInt(Attribute.MaxFireBulletCount, Attribute.MinFireBulletCount);
- //枪口角度
- var angle = new Vector2(GameConfig.ScatteringDistance, CurrScatteringRange).Angle();
-
- //创建子弹
- for (int i = 0; i < bulletCount; i++)
- {
- //先算枪口方向
- Rotation = (float)GD.RandRange(-angle, angle);
- //发射子弹
- ShootBullet();
- }
-
- //当前的散射半径
- CurrScatteringRange = Mathf.Min(CurrScatteringRange + Attribute.ScatteringRangeAddValue, Attribute.FinalScatteringRange);
- //枪的旋转角度
- RotationDegrees -= Attribute.UpliftAngle;
- fireAngle = RotationDegrees;
- //枪身位置
- Position = new Vector2(Mathf.Max(-Attribute.MaxBacklash, Position.x - MathUtils.RandRange(Attribute.MinBacklash, Attribute.MaxBacklash)), Position.y);
-
- if (FireEvent != null)
- {
- FireEvent(this);
- }
- }
-
- ///
- /// 初始化时调用
- ///
- protected abstract void Init();
-
- ///
- /// 单次开火时调用的函数
- ///
- protected abstract void Fire();
-
- ///
- /// 发射子弹时调用的函数, 每发射一枚子弹调用一次,
- /// 如果做霰弹枪效果, 一次开火发射5枚子弹, 则该函数调用5次
- ///
- protected abstract void ShootBullet();
-
- ///
- /// 实例化并返回子弹对象
- ///
- /// 子弹的预制体
- protected T CreateBullet(PackedScene bulletPack, Vector2 globalPostion, float globalRotation, Node parent = null) where T : Node2D, IBullet
- {
- return (T) CreateBullet(bulletPack, globalPostion, globalRotation, parent);
- }
-
-
- protected IBullet CreateBullet(PackedScene bulletPack, Vector2 globalPostion, float globalRotation, Node parent = null)
- {
- // 实例化子弹
- Node2D bullet = bulletPack.Instance();
- // 设置坐标
- bullet.GlobalPosition = globalPostion;
- // 旋转角度
- bullet.GlobalRotation = globalRotation;
- if (parent == null)
- {
- GetTree().CurrentScene.AddChild(bullet);
- }
- else
- {
- parent.AddChild(bullet);
- }
- // 调用初始化
- IBullet result = (IBullet)bullet;
- result.Init(TargetCamp, this, null);
- return result;
- }
-}
\ No newline at end of file
diff --git a/src/gun/GunAttribute.cs b/src/gun/GunAttribute.cs
deleted file mode 100644
index aaeab64..0000000
--- a/src/gun/GunAttribute.cs
+++ /dev/null
@@ -1,117 +0,0 @@
-using Godot;
-
-///
-/// 枪上的属性
-///
-public class GunAttribute
-{
- ///
- /// 枪的图片
- ///
- public string Sprite = "res://resource/sprite/gun/gun1.png";
- ///
- /// 是否连续发射, 如果为false, 则每次发射都需要扣动扳机
- ///
- public bool ContinuousShoot = true;
- ///
- /// 是否为松发开火, 也就是松开扳机才开火, 若要启用该属性, 必须将 'ContinuousShoot' 设置为 false
- ///
- public bool LooseShoot = false;
- ///
- /// 连续发射最小次数, 仅当ContinuousShoot为false时生效
- ///
- public int MinContinuousCount = 3;
- ///
- /// 连续发射最大次数, 仅当ContinuousShoot为false时生效
- ///
- public int MaxContinuousCount = 3;
- ///
- /// 按下一次扳机后需要多长时间才能再次按下
- ///
- public float TriggerInterval = 0;
- ///
- /// 初始射速, 初始每秒分钟能发射多少发子弹
- ///
- public float StartFiringSpeed = 300;
- ///
- /// 最终射速, 最终每秒分钟能发射多少发子弹
- ///
- public float FinalFiringSpeed = 300;
- ///
- /// 按下扳机并开火后射速增加速率
- ///
- public float FiringSpeedAddSpeed = 2;
- ///
- /// 松开扳机后射速消散速率
- ///
- public float FiringSpeedBackSpeed = 10;
- ///
- /// 单次开火发射子弹最小数量
- ///
- public int MinFireBulletCount = 1;
- ///
- /// 单次开火发射子弹最大数量
- ///
- public int MaxFireBulletCount = 1;
- ///
- /// 开火前延时
- ///
- public float DelayedTime = 0f;
- ///
- /// 初始散射半径
- ///
- public float StartScatteringRange = 0;
- ///
- /// 最终散射半径
- ///
- public float FinalScatteringRange = 20;
- ///
- /// 每次发射后散射增加值
- ///
- public float ScatteringRangeAddValue = 2;
- ///
- /// 松开扳机后散射销退速率
- ///
- public float ScatteringRangeBackSpeed = 10;
- ///
- /// 子弹飞行最大距离
- ///
- public float MaxDistance = 600;
- ///
- /// 子弹飞行最小距离
- ///
- public float MinDistance = 800;
- ///
- /// 开火位置
- ///
- public Vector2 FirePosition = new Vector2(11, 0);
- ///
- /// 握把位置
- ///
- public Vector2 HoldPosition = new Vector2(4, -3);
- ///
- /// 重量
- ///
- public float Weight = 11;
- ///
- /// 最大后坐力 (仅用于开火后枪身抖动)
- ///
- public float MaxBacklash = 4;
- ///
- /// 最小后坐力 (仅用于开火后枪身抖动)
- ///
- public float MinBacklash = 2;
- ///
- /// 开火后枪口上抬角度
- ///
- public float UpliftAngle = 30;
- ///
- /// 开火后枪口角度恢复速度倍数
- ///
- public float UpliftAngleRestore = 1;
-
- public GunAttribute()
- {
-
- }
-}
\ No newline at end of file
diff --git a/src/gun/OrdinaryGun.cs b/src/gun/OrdinaryGun.cs
deleted file mode 100644
index 1bb47c5..0000000
--- a/src/gun/OrdinaryGun.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using Godot;
-
-
-///
-/// 普通的枪
-///
-public class OrdinaryGun : Gun
-{
-
- [Export] public PackedScene bulletPacked;
-
- protected override void Init()
- {
-
- }
-
- protected override void Fire()
- {
-
- }
-
- protected override void ShootBullet()
- {
- //创建子弹
- CreateBullet(bulletPacked, FirePoint.GlobalPosition, (FirePoint.GlobalPosition - OriginPoint.GlobalPosition).Angle());
- }
-}
\ No newline at end of file
diff --git a/src/manager/GameManager.cs b/src/manager/GameManager.cs
new file mode 100644
index 0000000..24462e8
--- /dev/null
+++ b/src/manager/GameManager.cs
@@ -0,0 +1,9 @@
+using Godot;
+
+///
+/// 游戏主管理器, 自动加载
+///
+public class GameManager : Node2D
+{
+
+}
\ No newline at end of file
diff --git a/src/role/Player.cs b/src/role/Player.cs
index 9c97124..63d8ec3 100644
--- a/src/role/Player.cs
+++ b/src/role/Player.cs
@@ -29,7 +29,7 @@
CurrGun = gun;
var attr = new GunAttribute();
- attr.StartFiringSpeed = 360;
+ attr.StartFiringSpeed = 480;
attr.StartScatteringRange = 5;
attr.FinalScatteringRange = 60;
attr.ScatteringRangeAddValue = 2f;
diff --git a/src/room/RoomManager.cs b/src/room/RoomManager.cs
new file mode 100644
index 0000000..4896dad
--- /dev/null
+++ b/src/room/RoomManager.cs
@@ -0,0 +1,48 @@
+using Godot;
+
+///
+/// 房间管理器
+///
+public class RoomManager : Node2D
+{
+ ///
+ /// 鼠标指针
+ ///
+ [Export] public PackedScene MouseCursor;
+
+ [Export] public NodePath UIPath;
+
+ [Export] public PackedScene ThrowNode;
+
+ public static RoomManager Current { get; private set; }
+
+ public CanvasLayer UI;
+ public Cursor Cursor { get; private set; }
+
+ public override void _EnterTree()
+ {
+ Current = this;
+ Input.SetMouseMode(Input.MouseMode.Hidden);
+ // 初始化鼠标
+ Cursor = MouseCursor.Instance();
+ AddChild(Cursor);
+
+ //初始化地图
+ var node = GetNode("MapRoot").GetChild(0).GetNode("Config");
+ Color color = (Color) node.GetMeta("ClearColor");
+ VisualServer.SetDefaultClearColor(color);
+ }
+
+ public override void _Draw()
+ {
+ DrawLine(new Vector2(100, 100), new Vector2(200, 200), Colors.White);
+ }
+
+ public override void _Process(float delta)
+ {
+ if (Input.IsActionJustPressed("fire"))
+ {
+ //CommonNodeManager.CreateThrowNode();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/weapon/ThrowNode.cs b/src/weapon/ThrowNode.cs
new file mode 100644
index 0000000..17a2e87
--- /dev/null
+++ b/src/weapon/ThrowNode.cs
@@ -0,0 +1,47 @@
+using System;
+using Godot;
+
+///
+/// 模拟抛出的物体, 使用时将对象挂载到该节点上即可
+///
+public class ThrowNode : Node2D
+{
+ public float MaxHeight = 30;
+ public float TargetHeight = 0;
+ public float StartHeight = 0;
+
+ public Vector2 StartPos;
+ public Vector2 TargetPos = new Vector2(120, 100);
+ public Vector2 RealPosition = Vector2.Zero;
+
+
+ public override void _Ready()
+ {
+ StartPos = GlobalPosition;
+ RealPosition = StartPos;
+ }
+
+ public override void _Process(float delta)
+ {
+ if (RealPosition.DistanceSquaredTo(TargetPos) > 1)
+ {
+ float v = (StartPos.DistanceTo(RealPosition)) / (StartPos.DistanceTo(TargetPos));
+ float progress = Mathf.Sin(v * Mathf.Pi);
+
+ float y = 0;
+ if (v <= 0.5f)
+ {
+ y = Mathf.Lerp(StartHeight, MaxHeight, progress);
+ }
+ else
+ {
+ y = Mathf.Lerp(TargetHeight, MaxHeight, progress);
+ }
+
+ RealPosition = RealPosition.MoveToward(TargetPos, 100 * delta);
+ GlobalPosition = RealPosition - new Vector2(0, y);
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/weapon/bullet/Bullet.cs b/src/weapon/bullet/Bullet.cs
new file mode 100644
index 0000000..ec5ac06
--- /dev/null
+++ b/src/weapon/bullet/Bullet.cs
@@ -0,0 +1,27 @@
+using Godot;
+
+///
+/// 子弹接口
+///
+public interface IBullet
+{
+ ///
+ /// 攻击目标阵营
+ ///
+ CampEnum TargetCamp { get; }
+ ///
+ /// 发射该子弹的武器
+ ///
+ Gun Gun { get; }
+ ///
+ /// 发射该子弹的物体对象
+ ///
+ Node2D Master { get; }
+ ///
+ /// 初始化基础数据
+ ///
+ /// 攻击的目标阵营
+ /// 发射该子弹的枪对象
+ /// 发射该子弹的角色
+ void Init(CampEnum target, Gun gun, Node2D master);
+}
\ No newline at end of file
diff --git a/src/weapon/bullet/HighSpeedBullet.cs b/src/weapon/bullet/HighSpeedBullet.cs
new file mode 100644
index 0000000..039c416
--- /dev/null
+++ b/src/weapon/bullet/HighSpeedBullet.cs
@@ -0,0 +1,72 @@
+using Godot;
+
+///
+/// 高速子弹
+///
+public class HighSpeedBullet : Node2D, IBullet
+{
+ public CampEnum TargetCamp { get; private set; }
+
+ public Gun Gun { get; private set; }
+
+ public Node2D Master { get; private set; }
+
+ ///
+ /// 碰撞物体后产生的火花
+ ///
+ [Export] public PackedScene Hit;
+
+ //射线检测节点
+ private RayCast2D RayCast2D;
+ private Line2D Line;
+ private float ca = 1;
+
+ public void Init(CampEnum target, Gun gun, Node2D master)
+ {
+ TargetCamp = target;
+ Gun = gun;
+ Master = master;
+
+ //飞行距离
+ var distance = MathUtils.RandRange(gun.Attribute.MinDistance, gun.Attribute.MaxDistance);
+
+ //初始化子弹数据
+ RayCast2D = GetNode("RayCast2D");
+ Line = GetNode("Line");
+ Modulate = Colors.White;
+
+ // 目标点
+ Vector2 targetPos = new Vector2(distance, 0);
+ RayCast2D.CastTo = targetPos;
+ RayCast2D.ForceRaycastUpdate();
+ if (RayCast2D.IsColliding())
+ {
+ //碰到物体
+ Vector2 collPosition = RayCast2D.GetCollisionPoint();
+ Node2D hit = Hit.Instance();
+ hit.RotationDegrees = MathUtils.RandRangeInt(0, 360);
+ hit.GlobalPosition = collPosition;
+ GetTree().CurrentScene.AddChild(hit);
+ //划线的点坐标
+ Line.SetPointPosition(1, new Vector2(Line.GlobalPosition.DistanceTo(collPosition), 0));
+ }
+ else
+ {
+ //划线的点坐标
+ Line.SetPointPosition(1, targetPos);
+ }
+ RayCast2D.Enabled = false;
+ }
+
+ public override void _Process(float delta)
+ {
+ ca -= 12 * delta;
+ if (ca <= 0) {
+ QueueFree();
+ return;
+ }
+ Color c = Modulate;
+ c.a = ca;
+ Modulate = c;
+ }
+}
\ No newline at end of file
diff --git a/src/weapon/bullet/OrdinaryBullets.cs b/src/weapon/bullet/OrdinaryBullets.cs
new file mode 100644
index 0000000..cefd904
--- /dev/null
+++ b/src/weapon/bullet/OrdinaryBullets.cs
@@ -0,0 +1,78 @@
+using Godot;
+
+///
+/// 普通的子弹
+///
+public class OrdinaryBullets : Node2D, IBullet
+{
+ public CampEnum TargetCamp { get; private set; }
+
+ public Gun Gun { get; private set; }
+
+ public Node2D Master { get; private set; }
+
+ ///
+ /// 碰撞物体后产生的火花
+ ///
+ [Export] public PackedScene Hit;
+
+ // 起始点坐标
+ private Vector2 StartPosition;
+ // 最大飞行距离
+ private float MaxDistance;
+ // 子弹飞行速度
+ private float FlySpeed = 1500;
+ //当前子弹已经飞行的距离
+ private float CurrFlyDistance = 0;
+ //射线碰撞节点
+ private RayCast2D RayCast;
+ //子弹的精灵
+ private Sprite BulletSprite;
+
+ private int frame = 0;
+
+ public void Init(CampEnum target, Gun gun, Node2D master)
+ {
+ TargetCamp = target;
+ Gun = gun;
+ Master = master;
+
+ MaxDistance = MathUtils.RandRange(gun.Attribute.MinDistance, gun.Attribute.MaxDistance);
+ StartPosition = GlobalPosition;
+ BulletSprite = GetNode("Bullet");
+ BulletSprite.Visible = false;
+ RayCast = GetNode("RayCast2D");
+
+ }
+
+ public override void _PhysicsProcess(float delta)
+ {
+ if (frame++ == 0)
+ {
+ BulletSprite.Visible = true;
+ }
+ //碰到墙壁
+ if (RayCast.IsColliding())
+ {
+ //var target = RayCast.GetCollider();
+ var pos = RayCast.GetCollisionPoint();
+ //播放受击动画
+ Node2D hit = Hit.Instance();
+ hit.RotationDegrees = MathUtils.RandRangeInt(0, 360);
+ hit.GlobalPosition = pos;
+ GetTree().CurrentScene.AddChild(hit);
+ QueueFree();
+ }
+ else //没有碰到, 继续移动
+ {
+ Position += new Vector2(FlySpeed * delta, 0).Rotated(Rotation);
+
+ CurrFlyDistance += FlySpeed * delta;
+ if (CurrFlyDistance >= MaxDistance)
+ {
+ QueueFree();
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/weapon/gun/Gun.cs b/src/weapon/gun/Gun.cs
new file mode 100644
index 0000000..a511109
--- /dev/null
+++ b/src/weapon/gun/Gun.cs
@@ -0,0 +1,336 @@
+using Godot;
+using System;
+
+///
+/// 枪的基类
+///
+public abstract class Gun : Node2D
+{
+ ///
+ /// 开火回调事件
+ ///
+ public event Action FireEvent;
+
+ ///
+ /// 属性数据
+ ///
+ public GunAttribute Attribute
+ {
+ get
+ {
+ if (_attribute == null)
+ {
+ throw new Exception("请先调用Init来初始化枪的属性");
+ }
+ return _attribute;
+ }
+ private set => _attribute = value;
+ }
+ private GunAttribute _attribute;
+
+ ///
+ /// 枪的图片
+ ///
+ public Sprite GunSprite { get; private set; }
+
+ ///
+ /// 枪攻击的目标阵营
+ ///
+ public CampEnum TargetCamp { get; set; }
+ ///
+ /// 枪管的开火点
+ ///
+ public Position2D FirePoint { get; private set; }
+ ///
+ /// 枪管的原点
+ ///
+ public Position2D OriginPoint { get; private set; }
+ ///
+ /// 枪的当前散射半径
+ ///
+ public float CurrScatteringRange { get; private set; } = 0;
+
+ //是否按下
+ private bool triggerFlag = false;
+ //扳机计时器
+ private float triggerTimer = 0;
+ //开火前延时时间
+ private float delayedTime = 0;
+ //开火间隙时间
+ private float fireInterval = 0;
+ //开火枪口角度
+ private float fireAngle = 0;
+ //攻击冷却计时
+ private float attackTimer = 0;
+ //攻击状态
+ private bool attackFlag = false;
+ //按下的时间
+ private float downTimer = 0;
+ //松开的时间
+ private float upTimer = 0;
+ //连发次数
+ private float continuousCount = 0;
+ private bool continuousShootFlag = false;
+
+ public override void _EnterTree()
+ {
+ GunSprite = GetNode("GunSprite");
+ FirePoint = GetNode("FirePoint");
+ OriginPoint = GetNode("OriginPoint");
+ }
+
+ public override void _Process(float delta)
+ {
+ if (triggerFlag)
+ {
+ if (upTimer > 0) //第一帧按下扳机
+ {
+ upTimer = 0;
+ DownTrigger();
+ }
+ downTimer += delta;
+ }
+ else
+ {
+ if (downTimer > 0) //第一帧松开扳机
+ {
+ downTimer = 0;
+ UpTriggern();
+ }
+ upTimer += delta;
+ }
+
+ // 攻击的计时器
+ if (attackTimer > 0)
+ {
+ attackTimer -= delta;
+ if (attackTimer < 0)
+ {
+ delayedTime += attackTimer;
+ attackTimer = 0;
+ }
+ }
+ else if (delayedTime > 0) //攻击延时
+ {
+ delayedTime -= delta;
+ if (attackTimer < 0)
+ {
+ delayedTime = 0;
+ }
+ }
+
+ //连发判断
+ if (continuousCount > 0 && delayedTime <= 0 && attackTimer <= 0)
+ {
+ TriggernFire();
+ }
+
+ if (!attackFlag && attackTimer <= 0)
+ {
+ CurrScatteringRange = Mathf.Max(CurrScatteringRange - Attribute.ScatteringRangeBackSpeed * delta, Attribute.StartScatteringRange);
+ }
+ triggerTimer = triggerTimer > 0 ? triggerTimer - delta : 0;
+ triggerFlag = false;
+ attackFlag = false;
+
+ //枪身回归
+ Position = Position.MoveToward(Vector2.Zero, 35 * delta);
+ if (fireInterval == 0)
+ {
+ RotationDegrees = 0;
+ }
+ else
+ {
+ RotationDegrees = Mathf.Lerp(0, fireAngle, attackTimer / fireInterval);
+ }
+ }
+
+ public void Init(GunAttribute attribute)
+ {
+ if (_attribute != null)
+ {
+ throw new Exception("当前武器已经初始化过了!");
+ }
+
+ Attribute = attribute;
+ //更新图片
+ var texture = ResourceLoader.Load(attribute.Sprite);
+ GunSprite.Texture = texture;
+ //开火位置
+ FirePoint.Position = new Vector2(attribute.FirePosition.x, -attribute.FirePosition.y);
+ OriginPoint.Position = new Vector2(0, -attribute.FirePosition.y);
+ //握把位置
+ GunSprite.Position = attribute.HoldPosition;
+
+ Init();
+ }
+
+ ///
+ /// 扳机函数, 调用即视为扣动扳机
+ ///
+ public void Trigger()
+ {
+ //是否第一帧按下
+ var justDown = downTimer == 0;
+ //是否能发射
+ var flag = false;
+ if (continuousCount <= 0) //不能处于连发状态下
+ {
+ if (Attribute.ContinuousShoot) //自动射击
+ {
+ if (triggerTimer > 0)
+ {
+ if (continuousShootFlag)
+ {
+ flag = true;
+ }
+ }
+ else
+ {
+ flag = true;
+ if (delayedTime <= 0 && attackTimer <= 0)
+ {
+ continuousShootFlag = true;
+ }
+ }
+ }
+ else //半自动
+ {
+ if (justDown && triggerTimer <= 0)
+ {
+ flag = true;
+ }
+ }
+ }
+
+ if (flag)
+ {
+ if (justDown)
+ {
+ //开火前延时
+ delayedTime = Attribute.DelayedTime;
+ //扳机按下间隔
+ triggerTimer = Attribute.TriggerInterval;
+ //连发数量
+ if (!Attribute.ContinuousShoot)
+ {
+ continuousCount = MathUtils.RandRangeInt(Attribute.MinContinuousCount, Attribute.MaxContinuousCount);
+ }
+ }
+ if (delayedTime <= 0 && attackTimer <= 0)
+ {
+ TriggernFire();
+ }
+ attackFlag = true;
+ }
+ triggerFlag = true;
+ }
+
+ ///
+ /// 刚按下扳机
+ ///
+ private void DownTrigger()
+ {
+
+ }
+
+ ///
+ /// 刚松开扳机
+ ///
+ private void UpTriggern()
+ {
+ continuousShootFlag = false;
+ if (delayedTime > 0)
+ {
+ continuousCount = 0;
+ }
+ }
+
+ ///
+ /// 触发开火
+ ///
+ private void TriggernFire()
+ {
+ continuousCount = continuousCount > 0 ? continuousCount - 1 : 0;
+ fireInterval = 60 / Attribute.StartFiringSpeed;
+ attackTimer += fireInterval;
+
+ //触发开火函数
+ Fire();
+
+ //开火发射的子弹数量
+ var bulletCount = MathUtils.RandRangeInt(Attribute.MaxFireBulletCount, Attribute.MinFireBulletCount);
+ //枪口角度
+ var angle = new Vector2(GameConfig.ScatteringDistance, CurrScatteringRange).Angle();
+
+ //创建子弹
+ for (int i = 0; i < bulletCount; i++)
+ {
+ //先算枪口方向
+ Rotation = (float)GD.RandRange(-angle, angle);
+ //发射子弹
+ ShootBullet();
+ }
+
+ //当前的散射半径
+ CurrScatteringRange = Mathf.Min(CurrScatteringRange + Attribute.ScatteringRangeAddValue, Attribute.FinalScatteringRange);
+ //枪的旋转角度
+ RotationDegrees -= Attribute.UpliftAngle;
+ fireAngle = RotationDegrees;
+ //枪身位置
+ Position = new Vector2(Mathf.Max(-Attribute.MaxBacklash, Position.x - MathUtils.RandRange(Attribute.MinBacklash, Attribute.MaxBacklash)), Position.y);
+
+ if (FireEvent != null)
+ {
+ FireEvent(this);
+ }
+ }
+
+ ///
+ /// 初始化时调用
+ ///
+ protected abstract void Init();
+
+ ///
+ /// 单次开火时调用的函数
+ ///
+ protected abstract void Fire();
+
+ ///
+ /// 发射子弹时调用的函数, 每发射一枚子弹调用一次,
+ /// 如果做霰弹枪效果, 一次开火发射5枚子弹, 则该函数调用5次
+ ///
+ protected abstract void ShootBullet();
+
+ ///
+ /// 实例化并返回子弹对象
+ ///
+ /// 子弹的预制体
+ protected T CreateBullet(PackedScene bulletPack, Vector2 globalPostion, float globalRotation, Node parent = null) where T : Node2D, IBullet
+ {
+ return (T) CreateBullet(bulletPack, globalPostion, globalRotation, parent);
+ }
+
+
+ protected IBullet CreateBullet(PackedScene bulletPack, Vector2 globalPostion, float globalRotation, Node parent = null)
+ {
+ // 实例化子弹
+ Node2D bullet = bulletPack.Instance();
+ // 设置坐标
+ bullet.GlobalPosition = globalPostion;
+ // 旋转角度
+ bullet.GlobalRotation = globalRotation;
+ if (parent == null)
+ {
+ GetTree().CurrentScene.AddChild(bullet);
+ }
+ else
+ {
+ parent.AddChild(bullet);
+ }
+ // 调用初始化
+ IBullet result = (IBullet)bullet;
+ result.Init(TargetCamp, this, null);
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/src/weapon/gun/GunAttribute.cs b/src/weapon/gun/GunAttribute.cs
new file mode 100644
index 0000000..aaeab64
--- /dev/null
+++ b/src/weapon/gun/GunAttribute.cs
@@ -0,0 +1,117 @@
+using Godot;
+
+///
+/// 枪上的属性
+///
+public class GunAttribute
+{
+ ///
+ /// 枪的图片
+ ///
+ public string Sprite = "res://resource/sprite/gun/gun1.png";
+ ///
+ /// 是否连续发射, 如果为false, 则每次发射都需要扣动扳机
+ ///
+ public bool ContinuousShoot = true;
+ ///
+ /// 是否为松发开火, 也就是松开扳机才开火, 若要启用该属性, 必须将 'ContinuousShoot' 设置为 false
+ ///
+ public bool LooseShoot = false;
+ ///
+ /// 连续发射最小次数, 仅当ContinuousShoot为false时生效
+ ///
+ public int MinContinuousCount = 3;
+ ///
+ /// 连续发射最大次数, 仅当ContinuousShoot为false时生效
+ ///
+ public int MaxContinuousCount = 3;
+ ///
+ /// 按下一次扳机后需要多长时间才能再次按下
+ ///
+ public float TriggerInterval = 0;
+ ///
+ /// 初始射速, 初始每秒分钟能发射多少发子弹
+ ///
+ public float StartFiringSpeed = 300;
+ ///
+ /// 最终射速, 最终每秒分钟能发射多少发子弹
+ ///
+ public float FinalFiringSpeed = 300;
+ ///
+ /// 按下扳机并开火后射速增加速率
+ ///
+ public float FiringSpeedAddSpeed = 2;
+ ///
+ /// 松开扳机后射速消散速率
+ ///
+ public float FiringSpeedBackSpeed = 10;
+ ///
+ /// 单次开火发射子弹最小数量
+ ///
+ public int MinFireBulletCount = 1;
+ ///
+ /// 单次开火发射子弹最大数量
+ ///
+ public int MaxFireBulletCount = 1;
+ ///
+ /// 开火前延时
+ ///
+ public float DelayedTime = 0f;
+ ///
+ /// 初始散射半径
+ ///
+ public float StartScatteringRange = 0;
+ ///
+ /// 最终散射半径
+ ///
+ public float FinalScatteringRange = 20;
+ ///
+ /// 每次发射后散射增加值
+ ///
+ public float ScatteringRangeAddValue = 2;
+ ///
+ /// 松开扳机后散射销退速率
+ ///
+ public float ScatteringRangeBackSpeed = 10;
+ ///
+ /// 子弹飞行最大距离
+ ///
+ public float MaxDistance = 600;
+ ///
+ /// 子弹飞行最小距离
+ ///
+ public float MinDistance = 800;
+ ///
+ /// 开火位置
+ ///
+ public Vector2 FirePosition = new Vector2(11, 0);
+ ///
+ /// 握把位置
+ ///
+ public Vector2 HoldPosition = new Vector2(4, -3);
+ ///
+ /// 重量
+ ///
+ public float Weight = 11;
+ ///
+ /// 最大后坐力 (仅用于开火后枪身抖动)
+ ///
+ public float MaxBacklash = 4;
+ ///
+ /// 最小后坐力 (仅用于开火后枪身抖动)
+ ///
+ public float MinBacklash = 2;
+ ///
+ /// 开火后枪口上抬角度
+ ///
+ public float UpliftAngle = 30;
+ ///
+ /// 开火后枪口角度恢复速度倍数
+ ///
+ public float UpliftAngleRestore = 1;
+
+ public GunAttribute()
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/src/weapon/gun/OrdinaryGun.cs b/src/weapon/gun/OrdinaryGun.cs
new file mode 100644
index 0000000..1bb47c5
--- /dev/null
+++ b/src/weapon/gun/OrdinaryGun.cs
@@ -0,0 +1,27 @@
+using Godot;
+
+
+///
+/// 普通的枪
+///
+public class OrdinaryGun : Gun
+{
+
+ [Export] public PackedScene bulletPacked;
+
+ protected override void Init()
+ {
+
+ }
+
+ protected override void Fire()
+ {
+
+ }
+
+ protected override void ShootBullet()
+ {
+ //创建子弹
+ CreateBullet(bulletPacked, FirePoint.GlobalPosition, (FirePoint.GlobalPosition - OriginPoint.GlobalPosition).Angle());
+ }
+}
\ No newline at end of file
diff --git a/ui/RoomUI.tscn b/ui/RoomUI.tscn
deleted file mode 100644
index 727b74e..0000000
--- a/ui/RoomUI.tscn
+++ /dev/null
@@ -1,8 +0,0 @@
-[gd_scene load_steps=2 format=2]
-
-[ext_resource path="res://src/ui/RoomUI.cs" type="Script" id=1]
-
-[node name="RoomUI" type="Control"]
-anchor_right = 1.0
-anchor_bottom = 1.0
-script = ExtResource( 1 )