commit 7038d29d873ed1dec9e6922f7a57ff5d8f0d73d6 Author: Mathilde Grapin Date: Sun Jun 11 23:38:54 2023 +0200 First commit Add simple player movement with a finite state machine. Add enemy that can move to target point. Add ground through a tilemap and wall that player and enemy cannot cross. diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4709183 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Godot 4+ specific ignores +.godot/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..6f64350 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Bovido diff --git a/art/Owlet_Monster_Idle_4.png b/art/Owlet_Monster_Idle_4.png new file mode 100644 index 0000000..f29b95b Binary files /dev/null and b/art/Owlet_Monster_Idle_4.png differ diff --git a/art/Owlet_Monster_Idle_4.png.import b/art/Owlet_Monster_Idle_4.png.import new file mode 100644 index 0000000..fd35759 --- /dev/null +++ b/art/Owlet_Monster_Idle_4.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bi7ceeuwhg5mp" +path="res://.godot/imported/Owlet_Monster_Idle_4.png-e97c7439f6908603cd036944f8ec35c0.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/Owlet_Monster_Idle_4.png" +dest_files=["res://.godot/imported/Owlet_Monster_Idle_4.png-e97c7439f6908603cd036944f8ec35c0.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/Owlet_Monster_Run_6.png b/art/Owlet_Monster_Run_6.png new file mode 100644 index 0000000..09abcc6 Binary files /dev/null and b/art/Owlet_Monster_Run_6.png differ diff --git a/art/Owlet_Monster_Run_6.png.import b/art/Owlet_Monster_Run_6.png.import new file mode 100644 index 0000000..24643c9 --- /dev/null +++ b/art/Owlet_Monster_Run_6.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cjxkidkeka7yp" +path="res://.godot/imported/Owlet_Monster_Run_6.png-91009248b6c6292786c9507b39f56504.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/Owlet_Monster_Run_6.png" +dest_files=["res://.godot/imported/Owlet_Monster_Run_6.png-91009248b6c6292786c9507b39f56504.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/Owlet_Monster_Throw_4.png b/art/Owlet_Monster_Throw_4.png new file mode 100644 index 0000000..7c87d8c Binary files /dev/null and b/art/Owlet_Monster_Throw_4.png differ diff --git a/art/Owlet_Monster_Throw_4.png.import b/art/Owlet_Monster_Throw_4.png.import new file mode 100644 index 0000000..fcbcaac --- /dev/null +++ b/art/Owlet_Monster_Throw_4.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dbrr63tv6i2ek" +path="res://.godot/imported/Owlet_Monster_Throw_4.png-b0e6d7a8b3f3e05fa0a65ca1d572b1b3.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/Owlet_Monster_Throw_4.png" +dest_files=["res://.godot/imported/Owlet_Monster_Throw_4.png-b0e6d7a8b3f3e05fa0a65ca1d572b1b3.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/Owlet_Monster_Walk_6.png b/art/Owlet_Monster_Walk_6.png new file mode 100644 index 0000000..870e571 Binary files /dev/null and b/art/Owlet_Monster_Walk_6.png differ diff --git a/art/Owlet_Monster_Walk_6.png.import b/art/Owlet_Monster_Walk_6.png.import new file mode 100644 index 0000000..c6fd6df --- /dev/null +++ b/art/Owlet_Monster_Walk_6.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bqkvmyqo86dtj" +path="res://.godot/imported/Owlet_Monster_Walk_6.png-f3db40d07a0bf1fd7998c83382ca48f1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/Owlet_Monster_Walk_6.png" +dest_files=["res://.godot/imported/Owlet_Monster_Walk_6.png-f3db40d07a0bf1fd7998c83382ca48f1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/Pink_Monster_Walk_6.png b/art/Pink_Monster_Walk_6.png new file mode 100644 index 0000000..30b1fc1 Binary files /dev/null and b/art/Pink_Monster_Walk_6.png differ diff --git a/art/Pink_Monster_Walk_6.png.import b/art/Pink_Monster_Walk_6.png.import new file mode 100644 index 0000000..926dcdf --- /dev/null +++ b/art/Pink_Monster_Walk_6.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bbwsdd0jddmck" +path="res://.godot/imported/Pink_Monster_Walk_6.png-56f137427307346e616efca3c76723df.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/Pink_Monster_Walk_6.png" +dest_files=["res://.godot/imported/Pink_Monster_Walk_6.png-56f137427307346e616efca3c76723df.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/pilko.png b/art/pilko.png new file mode 100644 index 0000000..4124f70 Binary files /dev/null and b/art/pilko.png differ diff --git a/art/pilko.png.import b/art/pilko.png.import new file mode 100644 index 0000000..402b5e3 --- /dev/null +++ b/art/pilko.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dl8qfp3u18nkx" +path="res://.godot/imported/pilko.png-8aabfc83bdded6cb5f6dd16640cb8b5e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/pilko.png" +dest_files=["res://.godot/imported/pilko.png-8aabfc83bdded6cb5f6dd16640cb8b5e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/tile.png b/art/tile.png new file mode 100644 index 0000000..ceaeded Binary files /dev/null and b/art/tile.png differ diff --git a/art/tile.png.import b/art/tile.png.import new file mode 100644 index 0000000..65c1e47 --- /dev/null +++ b/art/tile.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cm58s70te836m" +path="res://.godot/imported/tile.png-73ea3a56b72978ec382fa65704c5659d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/tile.png" +dest_files=["res://.godot/imported/tile.png-73ea3a56b72978ec382fa65704c5659d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/art/wall.png b/art/wall.png new file mode 100644 index 0000000..5cb1437 Binary files /dev/null and b/art/wall.png differ diff --git a/art/wall.png.import b/art/wall.png.import new file mode 100644 index 0000000..4519f2c --- /dev/null +++ b/art/wall.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://lnt0clkwms52" +path="res://.godot/imported/wall.png-a390048f5e12dd0b271d636d681186c9.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://art/wall.png" +dest_files=["res://.godot/imported/wall.png-a390048f5e12dd0b271d636d681186c9.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..adc26df --- /dev/null +++ b/icon.svg @@ -0,0 +1 @@ + diff --git a/icon.svg.import b/icon.svg.import new file mode 100644 index 0000000..072af45 --- /dev/null +++ b/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b4qf03u00t17v" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..1cf2cde --- /dev/null +++ b/project.godot @@ -0,0 +1,54 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="bovido" +run/main_scene="res://scenes/main.tscn" +config/features=PackedStringArray("4.0", "Forward Plus") +config/icon="res://icon.svg" + +[display] + +window/size/viewport_width=1280 +window/size/viewport_height=720 +window/stretch/scale=1.8 + +[input] + +move_right={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":105,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"echo":false,"script":null) +] +} +move_left={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"echo":false,"script":null) +] +} +move_up={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":233,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"echo":false,"script":null) +] +} +move_down={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":117,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"echo":false,"script":null) +] +} + +[layer_names] + +2d_physics/layer_1="walls" +2d_physics/layer_2="player" diff --git a/scenes/enemy.tscn b/scenes/enemy.tscn new file mode 100644 index 0000000..1c918e6 --- /dev/null +++ b/scenes/enemy.tscn @@ -0,0 +1,47 @@ +[gd_scene load_steps=6 format=3 uid="uid://bktg1ypaav3q3"] + +[ext_resource type="Texture2D" uid="uid://bbwsdd0jddmck" path="res://art/Pink_Monster_Walk_6.png" id="1_e5603"] +[ext_resource type="Script" path="res://scripts/enemy.gd" id="1_l5lyv"] + +[sub_resource type="Animation" id="Animation_etqki"] +resource_name = "walk" +length = 0.6 +loop_mode = 1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:frame") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1), +"update": 1, +"values": [0, 1, 2, 3, 4, 5] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_gnukq"] +_data = { +"walk": SubResource("Animation_etqki") +} + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_rlijp"] +size = Vector2(17, 10) + +[node name="Enemy" type="CharacterBody2D"] +script = ExtResource("1_l5lyv") + +[node name="Sprite2D" type="Sprite2D" parent="."] +position = Vector2(0, -16) +texture = ExtResource("1_e5603") +flip_h = true +hframes = 6 + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +libraries = { +"": SubResource("AnimationLibrary_gnukq") +} + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(-0.5, -5) +shape = SubResource("RectangleShape2D_rlijp") diff --git a/scenes/main.tscn b/scenes/main.tscn new file mode 100644 index 0000000..79eec7f --- /dev/null +++ b/scenes/main.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=4 format=3 uid="uid://cdwgmtyq2y8sm"] + +[ext_resource type="PackedScene" uid="uid://m8uyi35gr3qd" path="res://scenes/tile_map.tscn" id="2_c6bkg"] +[ext_resource type="PackedScene" uid="uid://ba1t35yyot4jl" path="res://scenes/player.tscn" id="2_idv37"] +[ext_resource type="PackedScene" uid="uid://bktg1ypaav3q3" path="res://scenes/enemy.tscn" id="3_2xcd4"] + +[node name="Main" type="Node2D"] +y_sort_enabled = true + +[node name="TileMap" parent="." instance=ExtResource("2_c6bkg")] +position = Vector2(324, 82) + +[node name="Enemy" parent="TileMap" instance=ExtResource("3_2xcd4")] +z_index = 1 +y_sort_enabled = true +position = Vector2(0, 40) + +[node name="Player" parent="TileMap" instance=ExtResource("2_idv37")] +z_index = 1 +z_as_relative = false +y_sort_enabled = true diff --git a/scenes/player.tscn b/scenes/player.tscn new file mode 100644 index 0000000..8b6b2b1 --- /dev/null +++ b/scenes/player.tscn @@ -0,0 +1,217 @@ +[gd_scene load_steps=16 format=3 uid="uid://ba1t35yyot4jl"] + +[ext_resource type="Texture2D" uid="uid://bqkvmyqo86dtj" path="res://art/Owlet_Monster_Walk_6.png" id="1_e23l4"] +[ext_resource type="Script" path="res://scripts/player.gd" id="1_fmx2p"] +[ext_resource type="Texture2D" uid="uid://cjxkidkeka7yp" path="res://art/Owlet_Monster_Run_6.png" id="2_qq5i7"] +[ext_resource type="Texture2D" uid="uid://bi7ceeuwhg5mp" path="res://art/Owlet_Monster_Idle_4.png" id="4_orj3a"] +[ext_resource type="Texture2D" uid="uid://dbrr63tv6i2ek" path="res://art/Owlet_Monster_Throw_4.png" id="5_2s1mg"] +[ext_resource type="Script" path="res://scripts/state_machine.gd" id="6_hl63m"] +[ext_resource type="Script" path="res://scripts/player_idle_state.gd" id="7_0nfrc"] +[ext_resource type="Script" path="res://scripts/player_walk_state.gd" id="7_gcd3q"] + +[sub_resource type="Animation" id="Animation_rh7n7"] +length = 0.001 + +[sub_resource type="Animation" id="Animation_7igie"] +resource_name = "idle" +length = 0.4 +loop_mode = 1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:texture") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [ExtResource("4_orj3a")] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite2D:hframes") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [4] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Sprite2D:frame") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 0.1, 0.2, 0.3), +"transitions": PackedFloat32Array(1, 1, 1, 1), +"update": 1, +"values": [0, 1, 2, 3] +} + +[sub_resource type="Animation" id="Animation_xfiuh"] +resource_name = "run" +length = 0.6 +loop_mode = 1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:texture") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [ExtResource("2_qq5i7")] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite2D:hframes") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [6] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Sprite2D:frame") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1), +"update": 1, +"values": [0, 1, 2, 3, 4, 5] +} + +[sub_resource type="Animation" id="Animation_gswgu"] +resource_name = "throw" +length = 0.4 +loop_mode = 1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:texture") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [ExtResource("5_2s1mg")] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite2D:hframes") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [4] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Sprite2D:frame") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 0.1, 0.2, 0.3), +"transitions": PackedFloat32Array(1, 1, 1, 1), +"update": 1, +"values": [0, 1, 2, 3] +} + +[sub_resource type="Animation" id="Animation_pjkea"] +resource_name = "walk" +length = 0.6 +loop_mode = 1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:texture") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [ExtResource("1_e23l4")] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite2D:hframes") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [6] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Sprite2D:frame") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1), +"update": 1, +"values": [0, 1, 2, 3, 4, 5] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_ldfyt"] +_data = { +"RESET": SubResource("Animation_rh7n7"), +"idle": SubResource("Animation_7igie"), +"run": SubResource("Animation_xfiuh"), +"throw": SubResource("Animation_gswgu"), +"walk": SubResource("Animation_pjkea") +} + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_hocsq"] +size = Vector2(21, 7.5) + +[node name="Player" type="CharacterBody2D"] +script = ExtResource("1_fmx2p") + +[node name="Sprite2D" type="Sprite2D" parent="."] +position = Vector2(0, -16) +texture = ExtResource("4_orj3a") +hframes = 4 + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +libraries = { +"": SubResource("AnimationLibrary_ldfyt") +} + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +y_sort_enabled = true +position = Vector2(-2.5, -3.75) +shape = SubResource("RectangleShape2D_hocsq") + +[node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("state")] +script = ExtResource("6_hl63m") +state = NodePath("Idle") + +[node name="Idle" type="Node" parent="StateMachine"] +script = ExtResource("7_0nfrc") + +[node name="Walk" type="Node" parent="StateMachine"] +script = ExtResource("7_gcd3q") diff --git a/scenes/tile_map.tscn b/scenes/tile_map.tscn new file mode 100644 index 0000000..4ed9434 --- /dev/null +++ b/scenes/tile_map.tscn @@ -0,0 +1,43 @@ +[gd_scene load_steps=7 format=3 uid="uid://m8uyi35gr3qd"] + +[ext_resource type="Texture2D" uid="uid://cm58s70te836m" path="res://art/tile.png" id="1_2goti"] +[ext_resource type="Texture2D" uid="uid://lnt0clkwms52" path="res://art/wall.png" id="2_xllgf"] +[ext_resource type="Script" path="res://scripts/tile_map.gd" id="3_067ya"] + +[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_wq1n0"] +texture = ExtResource("1_2goti") +texture_region_size = Vector2i(32, 32) +0:0/0 = 0 +0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:0/0/physics_layer_0/angular_velocity = 0.0 + +[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_u0t08"] +texture = ExtResource("2_xllgf") +texture_region_size = Vector2i(32, 32) +0:0/0 = 0 +0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0) +0:0/0/physics_layer_0/angular_velocity = 0.0 +0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 8.5, 0, 1.5, 15.5, 9, 0, 16) + +[sub_resource type="TileSet" id="TileSet_kwgeq"] +tile_shape = 1 +tile_layout = 5 +tile_size = Vector2i(32, 16) +physics_layer_0/collision_layer = 1 +sources/0 = SubResource("TileSetAtlasSource_wq1n0") +sources/1 = SubResource("TileSetAtlasSource_u0t08") + +[node name="TileMap" type="TileMap"] +y_sort_enabled = true +tile_set = SubResource("TileSet_kwgeq") +format = 2 +layer_0/name = "ground" +layer_0/y_sort_enabled = true +layer_1/name = "wall" +layer_1/enabled = true +layer_1/modulate = Color(1, 1, 1, 1) +layer_1/y_sort_enabled = true +layer_1/y_sort_origin = 0 +layer_1/z_index = 1 +layer_1/tile_data = PackedInt32Array() +script = ExtResource("3_067ya") diff --git a/scripts/enemy.gd b/scripts/enemy.gd new file mode 100644 index 0000000..5a2f488 --- /dev/null +++ b/scripts/enemy.gd @@ -0,0 +1,36 @@ +extends CharacterBody2D + +@onready var tile_map: TileMap = get_parent() +@onready var animation_player = $AnimationPlayer +@export var speed = 80 +var y_spawn_offset = -8 +var is_moving = false +var destination: Vector2 = Vector2.ZERO + + +func _ready(): + var spawn_cell: Vector2i = tile_map.get_top_spawn_cell() + position = tile_map.map_to_local(spawn_cell) + position.y += y_spawn_offset + +func _process(_delta): + if is_moving: + animation_player.play("walk") + else: + animation_player.stop() + +func _physics_process(delta): + move_to_rand_cell(delta) + +func move_to_rand_cell(delta): + if !is_moving: + var rand_cell: Vector2i = tile_map.get_random_top_cell() + tile_map.set_cell(0, Vector2i(rand_cell.x, rand_cell.y), 1, Vector2i(0, 0), 0) # debug purpose + destination = tile_map.map_to_local(rand_cell) + destination.y += y_spawn_offset + + is_moving = true + position = position.move_toward(destination, delta * speed) + + if position == destination: + is_moving = false diff --git a/scripts/player.gd b/scripts/player.gd new file mode 100644 index 0000000..6c40b44 --- /dev/null +++ b/scripts/player.gd @@ -0,0 +1,13 @@ +class_name Player +extends CharacterBody2D + +@export var speed = 120 +var y_spawn_offset = -8 +@onready var animation_player = $AnimationPlayer +@onready var sprite = $Sprite2D +@onready var tile_map: TileMap = get_parent() + +func _ready(): + var spawn_cell: Vector2i = tile_map.get_bottom_spawn_cell() + position = tile_map.map_to_local(spawn_cell) + position.y += y_spawn_offset diff --git a/scripts/player_idle_state.gd b/scripts/player_idle_state.gd new file mode 100644 index 0000000..2e86f14 --- /dev/null +++ b/scripts/player_idle_state.gd @@ -0,0 +1,13 @@ +class_name PlayerIdleState +extends PlayerState + +func enter(_msg := {}): + player.velocity = Vector2.ZERO + player.animation_player.play("idle") + +func update(_delta): + if get_input_direction() != Vector2.ZERO: + state_machine.transition_to("Walk") + +func get_input_direction(): + return Input.get_vector("move_left", "move_right", "move_up", "move_down") diff --git a/scripts/player_state.gd b/scripts/player_state.gd new file mode 100644 index 0000000..9f71b1a --- /dev/null +++ b/scripts/player_state.gd @@ -0,0 +1,9 @@ +class_name PlayerState +extends State + +var player: Player + +func _ready(): + await owner.ready + player = owner as Player + assert(player != null) diff --git a/scripts/player_walk_state.gd b/scripts/player_walk_state.gd new file mode 100644 index 0000000..c625b18 --- /dev/null +++ b/scripts/player_walk_state.gd @@ -0,0 +1,24 @@ +class_name PlayerWalkState +extends PlayerState + +func enter(_msg := {}): + player.animation_player.play("walk") + +func physics_update(_delta): + var direction = get_input_direction() + player.velocity = direction * player.speed + + player.move_and_slide() # this method calculate with delta, we don’t need to do it + + if player.velocity == Vector2.ZERO: + state_machine.transition_to("Idle") + +func get_input_direction(): + var direction = Input.get_vector("move_left", "move_right", "move_up", "move_down") + + if Input.is_action_pressed("move_left"): + player.sprite.flip_h = true + elif Input.is_action_pressed("move_right"): + player.sprite.flip_h = false + + return direction diff --git a/scripts/state.gd b/scripts/state.gd new file mode 100644 index 0000000..8b38f06 --- /dev/null +++ b/scripts/state.gd @@ -0,0 +1,19 @@ +class_name State +extends Node + +var state_machine = null + +func handle_input(_event: InputEvent): + pass + +func update(_delta: float): + pass + +func physics_update(_delta: float): + pass + +func enter(_msg: Dictionary = {}): + pass + +func exit(): + pass diff --git a/scripts/state_machine.gd b/scripts/state_machine.gd new file mode 100644 index 0000000..70f93a2 --- /dev/null +++ b/scripts/state_machine.gd @@ -0,0 +1,34 @@ +class_name StateMachine +extends Node + +signal transitioned(state_name) +@export var state: State + +func _ready(): + await owner.ready + + for child in get_children(): + child.state_machine = self + + state.enter() + +func _unhandled_input(event): + state.handle_input(event) + +func _process(delta): + state.update(delta) + +func _physics_process(delta): + state.physics_update(delta) + +func transition_to(target_state_name: String, msg: Dictionary = {}): + if not has_node(target_state_name): + push_warning("No state with name " + target_state_name) + return + + state.exit() + state = get_node(target_state_name) + state.enter(msg) + emit_signal("transitioned", state.name) + + diff --git a/scripts/tile_map.gd b/scripts/tile_map.gd new file mode 100644 index 0000000..815beab --- /dev/null +++ b/scripts/tile_map.gd @@ -0,0 +1,38 @@ +extends TileMap + +@export var map_width = 13 # keep to a odd value +@export var map_height = 19 # keep to a odd value + +func _ready(): + draw_map() + +func draw_map(): + draw_ground() + draw_separation() + get_random_top_cell() + +func draw_ground(): + for x in range(map_width): + for y in range(map_height): + set_cell(0, Vector2i(x, y), 0, Vector2i(0, 0), 0) + +# The tilemap is initially divided in two section +# One for the player (bottom section) +# One for the enemy (top section) +func draw_separation(): + var middle_height = floor(map_height / 2.0) + for x in range(map_width): + set_cell(1, Vector2i(x - 1, middle_height - 1), 1, Vector2i(0, 0), 0) # why have we to add -1? + +func get_top_spawn_cell() -> Vector2i: + return Vector2i(floor(map_width / 2.0), 1) + +func get_bottom_spawn_cell() -> Vector2i: + return Vector2i(floor(map_width / 2.0), map_height - 2) + +func get_random_top_cell() -> Vector2i: + var middle_height = floor(map_height / 2.0) + var rand_width = randi_range(0, map_width - 1) + var rand_height = randi_range(0, middle_height - 1) + #set_cell(0, Vector2i(rand_width, rand_height), 1, Vector2i(0, 0), 0) + return Vector2i(rand_width, rand_height)