Compare commits

...

10 commits

46 changed files with 593 additions and 286 deletions

Binary file not shown.

View file

@ -0,0 +1,33 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://8guv2d1fgna7"
path="res://.godot/imported/DraftingMono-Regular.ttf-2613f107ee7cfa148009be1dfb779785.fontdata"
[deps]
source_file="res://art/fonts/DraftingMono-Regular.ttf"
dest_files=["res://.godot/imported/DraftingMono-Regular.ttf-2613f107ee7cfa148009be1dfb779785.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
hinting=1
subpixel_positioning=1
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}

View file

Before

Width:  |  Height:  |  Size: 323 B

After

Width:  |  Height:  |  Size: 323 B

View file

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://d265li1k63anm" uid="uid://d265li1k63anm"
path="res://.godot/imported/target_tile.png-8889c881dce8d973f9cccb76e30928fa.ctex" path="res://.godot/imported/ball_target.png-420e9ad20dd0b28420ac9e18f85c8839.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://art/tiles/target_tile.png" source_file="res://art/tiles/ball_target.png"
dest_files=["res://.godot/imported/target_tile.png-8889c881dce8d973f9cccb76e30928fa.ctex"] dest_files=["res://.godot/imported/ball_target.png-420e9ad20dd0b28420ac9e18f85c8839.ctex"]
[params] [params]

View file

Before

Width:  |  Height:  |  Size: 313 B

After

Width:  |  Height:  |  Size: 313 B

View file

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://b7565sd31qorm" uid="uid://b7565sd31qorm"
path="res://.godot/imported/destination_tile.png-6f95af7bf74b60a839485c30677f4a21.ctex" path="res://.godot/imported/destination.png-6d8060cc8ba13cfb8eb5a86e36773f7a.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://art/tiles/destination_tile.png" source_file="res://art/tiles/destination.png"
dest_files=["res://.godot/imported/destination_tile.png-6f95af7bf74b60a839485c30677f4a21.ctex"] dest_files=["res://.godot/imported/destination.png-6d8060cc8ba13cfb8eb5a86e36773f7a.ctex"]
[params] [params]

View file

Before

Width:  |  Height:  |  Size: 323 B

After

Width:  |  Height:  |  Size: 323 B

View file

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://cm58s70te836m" uid="uid://cm58s70te836m"
path="res://.godot/imported/ground_tile.png-a0838c31e75c33807f6e9b010d97f31b.ctex" path="res://.godot/imported/ground.png-ce6ec90789aee5a940b6b4beb4661e80.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://art/tiles/ground_tile.png" source_file="res://art/tiles/ground.png"
dest_files=["res://.godot/imported/ground_tile.png-a0838c31e75c33807f6e9b010d97f31b.ctex"] dest_files=["res://.godot/imported/ground.png-ce6ec90789aee5a940b6b4beb4661e80.ctex"]
[params] [params]

BIN
art/tiles/ground_bottom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bpa4fpmkhv6ao"
path="res://.godot/imported/ground_bottom.png-d8a2059588952b722104cd772c3c3a06.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/tiles/ground_bottom.png"
dest_files=["res://.godot/imported/ground_bottom.png-d8a2059588952b722104cd772c3c3a06.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

BIN
art/tiles/ground_left.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bwv5d4umos2we"
path="res://.godot/imported/ground_left.png-f29085d700bb612e942e2167f26ccb98.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/tiles/ground_left.png"
dest_files=["res://.godot/imported/ground_left.png-f29085d700bb612e942e2167f26ccb98.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cs7y54h6hd148"
path="res://.godot/imported/ground_left_bottom.png-ed5178aa269f950377859b107753d505.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/tiles/ground_left_bottom.png"
dest_files=["res://.godot/imported/ground_left_bottom.png-ed5178aa269f950377859b107753d505.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

BIN
art/tiles/ground_right.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cibnnq23akjqa"
path="res://.godot/imported/ground_right.png-5294f2bc13ed7d1f06582c289081850a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/tiles/ground_right.png"
dest_files=["res://.godot/imported/ground_right.png-5294f2bc13ed7d1f06582c289081850a.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://rc351wxc3821"
path="res://.godot/imported/ground_right_bottom.png-fd8508008a93bd4abfb6ce8b6ac148ec.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/tiles/ground_right_bottom.png"
dest_files=["res://.godot/imported/ground_right_bottom.png-fd8508008a93bd4abfb6ce8b6ac148ec.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

View file

Before

Width:  |  Height:  |  Size: 318 B

After

Width:  |  Height:  |  Size: 318 B

View file

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://lnt0clkwms52" uid="uid://lnt0clkwms52"
path="res://.godot/imported/wall_tile.png-943542e63eb98fa5c2f8ba381f7ef7b8.ctex" path="res://.godot/imported/wall.png-b444f5cdb367a6f2116effa1c0667bcc.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://art/tiles/wall_tile.png" source_file="res://art/tiles/wall.png"
dest_files=["res://.godot/imported/wall_tile.png-943542e63eb98fa5c2f8ba381f7ef7b8.ctex"] dest_files=["res://.godot/imported/wall.png-b444f5cdb367a6f2116effa1c0667bcc.ctex"]
[params] [params]

View file

@ -9,10 +9,9 @@
[sub_resource type="Animation" id="Animation_ouyrp"] [sub_resource type="Animation" id="Animation_ouyrp"]
length = 0.001 length = 0.001
[sub_resource type="Animation" id="Animation_6vdwd"] [sub_resource type="Animation" id="Animation_jt5bg"]
resource_name = "idle" resource_name = "hit_ball"
length = 0.4 length = 0.4
loop_mode = 1
tracks/0/type = "value" tracks/0/type = "value"
tracks/0/imported = false tracks/0/imported = false
tracks/0/enabled = true tracks/0/enabled = true
@ -23,7 +22,7 @@ tracks/0/keys = {
"times": PackedFloat32Array(0), "times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1), "transitions": PackedFloat32Array(1),
"update": 1, "update": 1,
"values": [ExtResource("3_5xsrd")] "values": [ExtResource("2_5t5q0")]
} }
tracks/1/type = "value" tracks/1/type = "value"
tracks/1/imported = false tracks/1/imported = false
@ -50,9 +49,10 @@ tracks/2/keys = {
"values": [0, 1, 2, 3] "values": [0, 1, 2, 3]
} }
[sub_resource type="Animation" id="Animation_jt5bg"] [sub_resource type="Animation" id="Animation_6vdwd"]
resource_name = "throw" resource_name = "idle"
length = 0.4 length = 0.4
loop_mode = 1
tracks/0/type = "value" tracks/0/type = "value"
tracks/0/imported = false tracks/0/imported = false
tracks/0/enabled = true tracks/0/enabled = true
@ -63,7 +63,7 @@ tracks/0/keys = {
"times": PackedFloat32Array(0), "times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1), "transitions": PackedFloat32Array(1),
"update": 1, "update": 1,
"values": [ExtResource("2_5t5q0")] "values": [ExtResource("3_5xsrd")]
} }
tracks/1/type = "value" tracks/1/type = "value"
tracks/1/imported = false tracks/1/imported = false
@ -134,8 +134,8 @@ tracks/2/keys = {
[sub_resource type="AnimationLibrary" id="AnimationLibrary_gnukq"] [sub_resource type="AnimationLibrary" id="AnimationLibrary_gnukq"]
_data = { _data = {
"RESET": SubResource("Animation_ouyrp"), "RESET": SubResource("Animation_ouyrp"),
"hit_ball": SubResource("Animation_jt5bg"),
"idle": SubResource("Animation_6vdwd"), "idle": SubResource("Animation_6vdwd"),
"throw": SubResource("Animation_jt5bg"),
"walk": SubResource("Animation_etqki") "walk": SubResource("Animation_etqki")
} }
@ -172,6 +172,5 @@ shape = SubResource("RectangleShape2D_rlijp")
[node name="EnemyBehaviorTree" parent="." instance=ExtResource("3_jk76t")] [node name="EnemyBehaviorTree" parent="." instance=ExtResource("3_jk76t")]
[connection signal="go_to_ball" from="." to="EnemyBehaviorTree" method="_on_enemy_go_to_ball"]
[connection signal="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"] [connection signal="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"]
[connection signal="body_exited" from="Area2D" to="." method="_on_area_2d_body_exited"] [connection signal="body_exited" from="Area2D" to="." method="_on_area_2d_body_exited"]

View file

@ -1,14 +1,10 @@
[gd_scene load_steps=15 format=3 uid="uid://b51tdt5kunai"] [gd_scene load_steps=11 format=3 uid="uid://b51tdt5kunai"]
[ext_resource type="Script" path="res://addons/beehave/nodes/beehave_tree.gd" id="1_b2pc4"] [ext_resource type="Script" path="res://addons/beehave/nodes/beehave_tree.gd" id="1_b2pc4"]
[ext_resource type="Script" path="res://addons/beehave/nodes/composites/sequence.gd" id="2_80fm4"] [ext_resource type="Script" path="res://addons/beehave/nodes/composites/sequence.gd" id="2_80fm4"]
[ext_resource type="Script" path="res://addons/beehave/nodes/composites/selector.gd" id="2_xkd41"] [ext_resource type="Script" path="res://addons/beehave/nodes/composites/selector.gd" id="2_xkd41"]
[ext_resource type="Script" path="res://scripts/enemy/behavior_tree/can_wait_condition.gd" id="4_0jr1a"]
[ext_resource type="Script" path="res://addons/beehave/nodes/decorators/time_limiter.gd" id="5_012bh"]
[ext_resource type="Script" path="res://scripts/enemy/behavior_tree/wait_action.gd" id="6_eyknc"]
[ext_resource type="Script" path="res://scripts/enemy/behavior_tree/can_throw_ball_condition.gd" id="7_k5qlq"] [ext_resource type="Script" path="res://scripts/enemy/behavior_tree/can_throw_ball_condition.gd" id="7_k5qlq"]
[ext_resource type="Script" path="res://scripts/enemy/behavior_tree/throw_ball_action.gd" id="8_wytqf"] [ext_resource type="Script" path="res://scripts/enemy/behavior_tree/throw_ball_action.gd" id="8_wytqf"]
[ext_resource type="Script" path="res://scripts/enemy/behavior_tree/get_random_target_action.gd" id="8_y68xp"]
[ext_resource type="Script" path="res://scripts/enemy/behavior_tree/can_go_to_ball_condition.gd" id="10_3puvl"] [ext_resource type="Script" path="res://scripts/enemy/behavior_tree/can_go_to_ball_condition.gd" id="10_3puvl"]
[ext_resource type="Script" path="res://scripts/enemy/behavior_tree/get_ball_destination_action.gd" id="11_bvy6m"] [ext_resource type="Script" path="res://scripts/enemy/behavior_tree/get_ball_destination_action.gd" id="11_bvy6m"]
[ext_resource type="Script" path="res://scripts/enemy/behavior_tree/move_to_destination_action.gd" id="11_tjc85"] [ext_resource type="Script" path="res://scripts/enemy/behavior_tree/move_to_destination_action.gd" id="11_tjc85"]
@ -21,28 +17,12 @@ script = ExtResource("1_b2pc4")
[node name="MainSelector" type="Node" parent="."] [node name="MainSelector" type="Node" parent="."]
script = ExtResource("2_xkd41") script = ExtResource("2_xkd41")
[node name="WaitSequence" type="Node" parent="MainSelector"]
script = ExtResource("2_80fm4")
[node name="CanWait" type="Node" parent="MainSelector/WaitSequence"]
script = ExtResource("4_0jr1a")
[node name="TimeLimiterDecorator" type="Node" parent="MainSelector/WaitSequence"]
script = ExtResource("5_012bh")
wait_time = 2.0
[node name="Wait" type="Node" parent="MainSelector/WaitSequence/TimeLimiterDecorator"]
script = ExtResource("6_eyknc")
[node name="ThrowBallSequence" type="Node" parent="MainSelector"] [node name="ThrowBallSequence" type="Node" parent="MainSelector"]
script = ExtResource("2_80fm4") script = ExtResource("2_80fm4")
[node name="CanThrowBall" type="Node" parent="MainSelector/ThrowBallSequence"] [node name="CanThrowBall" type="Node" parent="MainSelector/ThrowBallSequence"]
script = ExtResource("7_k5qlq") script = ExtResource("7_k5qlq")
[node name="GetRandomTarget" type="Node" parent="MainSelector/ThrowBallSequence"]
script = ExtResource("8_y68xp")
[node name="ThrowBall" type="Node" parent="MainSelector/ThrowBallSequence"] [node name="ThrowBall" type="Node" parent="MainSelector/ThrowBallSequence"]
script = ExtResource("8_wytqf") script = ExtResource("8_wytqf")
@ -64,8 +44,5 @@ script = ExtResource("2_80fm4")
[node name="CanReturnBall" type="Node" parent="MainSelector/SequenceComposite"] [node name="CanReturnBall" type="Node" parent="MainSelector/SequenceComposite"]
script = ExtResource("13_lrd2w") script = ExtResource("13_lrd2w")
[node name="GetRandomTarget2" type="Node" parent="MainSelector/SequenceComposite"]
script = ExtResource("8_y68xp")
[node name="ReturnBall" type="Node" parent="MainSelector/SequenceComposite"] [node name="ReturnBall" type="Node" parent="MainSelector/SequenceComposite"]
script = ExtResource("14_qbh47") script = ExtResource("14_qbh47")

18
scenes/hud.tscn Normal file
View file

@ -0,0 +1,18 @@
[gd_scene load_steps=3 format=3 uid="uid://bxj8v34v1igyc"]
[ext_resource type="Script" path="res://scripts/hud.gd" id="1_glf76"]
[ext_resource type="FontFile" uid="uid://8guv2d1fgna7" path="res://art/fonts/DraftingMono-Regular.ttf" id="1_xr1ih"]
[node name="HUD" type="CanvasLayer"]
script = ExtResource("1_glf76")
[node name="ScoreLabel" type="Label" parent="."]
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -60.0
offset_bottom = 41.0
grow_horizontal = 0
theme_override_fonts/font = ExtResource("1_xr1ih")
theme_override_font_sizes/font_size = 30
text = "0"

View file

@ -1,11 +1,14 @@
[gd_scene load_steps=4 format=3 uid="uid://cdwgmtyq2y8sm"] [gd_scene load_steps=6 format=3 uid="uid://cdwgmtyq2y8sm"]
[ext_resource type="Script" path="res://scripts/main.gd" id="1_1xo8b"]
[ext_resource type="PackedScene" uid="uid://m8uyi35gr3qd" path="res://scenes/tile_map.tscn" id="2_c6bkg"] [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://ba1t35yyot4jl" path="res://scenes/player.tscn" id="2_idv37"]
[ext_resource type="PackedScene" uid="uid://bktg1ypaav3q3" path="res://scenes/enemy.tscn" id="3_2xcd4"] [ext_resource type="PackedScene" uid="uid://bktg1ypaav3q3" path="res://scenes/enemy.tscn" id="3_2xcd4"]
[ext_resource type="PackedScene" uid="uid://bxj8v34v1igyc" path="res://scenes/hud.tscn" id="4_ealqo"]
[node name="Main" type="Node2D"] [node name="Main" type="Node2D"]
y_sort_enabled = true y_sort_enabled = true
script = ExtResource("1_1xo8b")
[node name="TileMap" parent="." instance=ExtResource("2_c6bkg")] [node name="TileMap" parent="." instance=ExtResource("2_c6bkg")]
position = Vector2(324, 82) position = Vector2(324, 82)
@ -19,3 +22,7 @@ position = Vector2(0, 40)
z_index = 1 z_index = 1
z_as_relative = false z_as_relative = false
y_sort_enabled = true y_sort_enabled = true
[node name="HUD" parent="." instance=ExtResource("4_ealqo")]
[connection signal="hit_ball" from="TileMap/Player" to="." method="_on_player_hit_ball"]

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=17 format=3 uid="uid://ba1t35yyot4jl"] [gd_scene load_steps=18 format=3 uid="uid://ba1t35yyot4jl"]
[ext_resource type="Texture2D" uid="uid://bqkvmyqo86dtj" path="res://art/characters/Owlet_Monster_Walk_6.png" id="1_e23l4"] [ext_resource type="Texture2D" uid="uid://bqkvmyqo86dtj" path="res://art/characters/Owlet_Monster_Walk_6.png" id="1_e23l4"]
[ext_resource type="Script" path="res://scripts/player/player.gd" id="1_fmx2p"] [ext_resource type="Script" path="res://scripts/player/player.gd" id="1_fmx2p"]
@ -8,11 +8,51 @@
[ext_resource type="Script" path="res://scripts/state_machine/state_machine.gd" id="6_hl63m"] [ext_resource type="Script" path="res://scripts/state_machine/state_machine.gd" id="6_hl63m"]
[ext_resource type="Script" path="res://scripts/player/states/player_idle_state.gd" id="7_0nfrc"] [ext_resource type="Script" path="res://scripts/player/states/player_idle_state.gd" id="7_0nfrc"]
[ext_resource type="Script" path="res://scripts/player/states/player_walk_state.gd" id="7_gcd3q"] [ext_resource type="Script" path="res://scripts/player/states/player_walk_state.gd" id="7_gcd3q"]
[ext_resource type="Script" path="res://scripts/player/states/player_throw_state.gd" id="9_atm3r"] [ext_resource type="Script" path="res://scripts/player/states/player_hit_ball_state.gd" id="9_aqfsh"]
[sub_resource type="Animation" id="Animation_rh7n7"] [sub_resource type="Animation" id="Animation_rh7n7"]
length = 0.001 length = 0.001
[sub_resource type="Animation" id="Animation_gswgu"]
resource_name = "hit_ball"
length = 0.4
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_7igie"] [sub_resource type="Animation" id="Animation_7igie"]
resource_name = "idle" resource_name = "idle"
length = 0.4 length = 0.4
@ -95,46 +135,6 @@ tracks/2/keys = {
"values": [0, 1, 2, 3, 4, 5] "values": [0, 1, 2, 3, 4, 5]
} }
[sub_resource type="Animation" id="Animation_gswgu"]
resource_name = "throw"
length = 0.4
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"] [sub_resource type="Animation" id="Animation_pjkea"]
resource_name = "walk" resource_name = "walk"
length = 0.6 length = 0.6
@ -179,17 +179,20 @@ tracks/2/keys = {
[sub_resource type="AnimationLibrary" id="AnimationLibrary_ldfyt"] [sub_resource type="AnimationLibrary" id="AnimationLibrary_ldfyt"]
_data = { _data = {
"RESET": SubResource("Animation_rh7n7"), "RESET": SubResource("Animation_rh7n7"),
"hit_ball": SubResource("Animation_gswgu"),
"idle": SubResource("Animation_7igie"), "idle": SubResource("Animation_7igie"),
"run": SubResource("Animation_xfiuh"), "run": SubResource("Animation_xfiuh"),
"throw": SubResource("Animation_gswgu"),
"walk": SubResource("Animation_pjkea") "walk": SubResource("Animation_pjkea")
} }
[sub_resource type="RectangleShape2D" id="RectangleShape2D_hocsq"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_hocsq"]
size = Vector2(21, 10) size = Vector2(24, 7)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_i54nm"]
size = Vector2(17, 10)
[node name="Player" type="CharacterBody2D"] [node name="Player" type="CharacterBody2D"]
collision_mask = 14 collision_mask = 6
script = ExtResource("1_fmx2p") script = ExtResource("1_fmx2p")
[node name="Sprite2D" type="Sprite2D" parent="."] [node name="Sprite2D" type="Sprite2D" parent="."]
@ -204,16 +207,15 @@ libraries = {
[node name="CollisionShape2D" type="CollisionShape2D" parent="."] [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
y_sort_enabled = true y_sort_enabled = true
position = Vector2(-2.5, -5) position = Vector2(-3, -3.5)
shape = SubResource("RectangleShape2D_hocsq") shape = SubResource("RectangleShape2D_hocsq")
[node name="Area2D" type="Area2D" parent="."] [node name="Area2D" type="Area2D" parent="."]
collision_mask = 8 collision_mask = 8
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] [node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
y_sort_enabled = true position = Vector2(-1.5, -5)
position = Vector2(-2.5, -5) shape = SubResource("RectangleShape2D_i54nm")
shape = SubResource("RectangleShape2D_hocsq")
[node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("state")] [node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("state")]
script = ExtResource("6_hl63m") script = ExtResource("6_hl63m")
@ -225,9 +227,10 @@ script = ExtResource("7_0nfrc")
[node name="Walk" type="Node" parent="StateMachine"] [node name="Walk" type="Node" parent="StateMachine"]
script = ExtResource("7_gcd3q") script = ExtResource("7_gcd3q")
[node name="Throw" type="Node" parent="StateMachine"] [node name="HitBall" type="Node" parent="StateMachine"]
script = ExtResource("9_atm3r") script = ExtResource("9_aqfsh")
[connection signal="collide_with_ball" from="." to="StateMachine/Idle" method="_on_player_collide_with_ball"] [connection signal="ball_starts_colliding" from="." to="StateMachine/Idle" method="_on_player_ball_starts_colliding"]
[connection signal="animation_finished" from="AnimationPlayer" to="StateMachine/Throw" method="_on_animation_player_animation_finished"] [connection signal="ball_stops_colliding" from="." to="StateMachine/Idle" method="_on_player_ball_stops_colliding"]
[connection signal="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"] [connection signal="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"]
[connection signal="body_exited" from="Area2D" to="." method="_on_area_2d_body_exited"]

View file

@ -1,52 +1,123 @@
[gd_scene load_steps=11 format=3 uid="uid://m8uyi35gr3qd"] [gd_scene load_steps=21 format=3 uid="uid://m8uyi35gr3qd"]
[ext_resource type="Texture2D" uid="uid://cm58s70te836m" path="res://art/tiles/ground_tile.png" id="1_set62"] [ext_resource type="Texture2D" uid="uid://cm58s70te836m" path="res://art/tiles/ground.png" id="1_kvtof"]
[ext_resource type="Texture2D" uid="uid://lnt0clkwms52" path="res://art/tiles/wall_tile.png" id="2_iitec"] [ext_resource type="Texture2D" uid="uid://lnt0clkwms52" path="res://art/tiles/wall.png" id="2_odoye"]
[ext_resource type="Texture2D" uid="uid://b7565sd31qorm" path="res://art/tiles/destination_tile.png" id="3_ca0hc"] [ext_resource type="Texture2D" uid="uid://b7565sd31qorm" path="res://art/tiles/destination.png" id="3_plcvy"]
[ext_resource type="Texture2D" uid="uid://d265li1k63anm" path="res://art/tiles/target_tile.png" id="4_w73lj"] [ext_resource type="Texture2D" uid="uid://d265li1k63anm" path="res://art/tiles/ball_target.png" id="4_k2ia8"]
[ext_resource type="Script" path="res://scripts/tile_map/tile_map.gd" id="5_hxvn0"] [ext_resource type="Script" path="res://scripts/tile_map/tile_map.gd" id="5_hxvn0"]
[ext_resource type="Texture2D" uid="uid://bwv5d4umos2we" path="res://art/tiles/ground_left.png" id="5_uwsf1"]
[ext_resource type="Texture2D" uid="uid://cibnnq23akjqa" path="res://art/tiles/ground_right.png" id="6_tgb06"]
[ext_resource type="Texture2D" uid="uid://bpa4fpmkhv6ao" path="res://art/tiles/ground_bottom.png" id="7_ffh6f"]
[ext_resource type="Texture2D" uid="uid://cs7y54h6hd148" path="res://art/tiles/ground_left_bottom.png" id="8_c76ky"]
[ext_resource type="Texture2D" uid="uid://rc351wxc3821" path="res://art/tiles/ground_right_bottom.png" id="9_mdsbd"]
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_wq1n0"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_wq1n0"]
texture = ExtResource("1_set62") texture = ExtResource("1_kvtof")
texture_region_size = Vector2i(32, 32) texture_region_size = Vector2i(32, 32)
0:0/0 = 0 0:0/0 = 0
0:0/0/physics_layer_0/linear_velocity = Vector2(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/angular_velocity = 0.0
0:0/0/physics_layer_1/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_1/angular_velocity = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_u0t08"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_u0t08"]
texture = ExtResource("2_iitec") texture = ExtResource("2_odoye")
texture_region_size = Vector2i(32, 32) texture_region_size = Vector2i(32, 32)
0:0/0 = 0 0:0/0 = 0
0:0/0/physics_layer_0/linear_velocity = Vector2(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/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) 0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 9.5, -16, -7.5, 0, 0.5, 16.5, -7.5, 16.5, 9, -0.5, 17)
0:0/0/physics_layer_1/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_1/angular_velocity = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_x1mdb"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_x1mdb"]
texture = ExtResource("3_ca0hc") texture = ExtResource("3_plcvy")
texture_region_size = Vector2i(32, 32) texture_region_size = Vector2i(32, 32)
0:0/0 = 0 0:0/0 = 0
0:0/0/physics_layer_0/linear_velocity = Vector2(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/angular_velocity = 0.0
0:0/0/physics_layer_1/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_1/angular_velocity = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_hm0kl"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_hm0kl"]
texture = ExtResource("4_w73lj") texture = ExtResource("4_k2ia8")
texture_region_size = Vector2i(32, 32) texture_region_size = Vector2i(32, 32)
0:0/0 = 0 0:0/0 = 0
0:0/0/physics_layer_0/linear_velocity = Vector2(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/angular_velocity = 0.0
0:0/0/physics_layer_1/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_1/angular_velocity = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_8npvn"]
texture = ExtResource("5_uwsf1")
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(-3.5, -19.5, -19.5, -11, -22.5, -13, -7, -21.5)
0:0/0/physics_layer_1/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_1/angular_velocity = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_f47wg"]
texture = ExtResource("6_tgb06")
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(1, 0.5, 16.5, -7, 21, -4.5, 6, 3)
0:0/0/physics_layer_1/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_1/angular_velocity = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_trdpm"]
texture = ExtResource("7_ffh6f")
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(-18, -6, -2.5, 2, -6.5, 4.5, -22, -4)
0:0/0/physics_layer_1/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_1/angular_velocity = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_aht32"]
texture = ExtResource("8_c76ky")
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(-2.5, -18.5, -21, -10, -1, 1.5, -7, 2, -29, -10, -5.5, -21)
0:0/0/physics_layer_1/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_1/angular_velocity = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_cx4es"]
texture = ExtResource("9_mdsbd")
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.5, -7.5, -0.5, 2, -18, -6.5, -22.5, -5, 0, 8, 21, -5.5)
0:0/0/physics_layer_1/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_1/angular_velocity = 0.0
[sub_resource type="TileSet" id="TileSet_kwgeq"] [sub_resource type="TileSet" id="TileSet_kwgeq"]
tile_shape = 1 tile_shape = 1
tile_layout = 5 tile_layout = 5
tile_size = Vector2i(32, 16) tile_size = Vector2i(32, 16)
physics_layer_0/collision_layer = 1 physics_layer_0/collision_layer = 4
physics_layer_0/collision_mask = 3
physics_layer_1/collision_layer = 4
sources/0 = SubResource("TileSetAtlasSource_wq1n0") sources/0 = SubResource("TileSetAtlasSource_wq1n0")
sources/1 = SubResource("TileSetAtlasSource_u0t08") sources/1 = SubResource("TileSetAtlasSource_u0t08")
sources/2 = SubResource("TileSetAtlasSource_x1mdb") sources/2 = SubResource("TileSetAtlasSource_x1mdb")
sources/3 = SubResource("TileSetAtlasSource_hm0kl") sources/3 = SubResource("TileSetAtlasSource_hm0kl")
sources/4 = SubResource("TileSetAtlasSource_8npvn")
sources/5 = SubResource("TileSetAtlasSource_f47wg")
sources/6 = SubResource("TileSetAtlasSource_trdpm")
sources/7 = SubResource("TileSetAtlasSource_aht32")
sources/8 = SubResource("TileSetAtlasSource_cx4es")
[node name="TileMap" type="TileMap"] [node name="TileMap" type="TileMap"]
y_sort_enabled = true y_sort_enabled = true
position = Vector2(-1, 1)
tile_set = SubResource("TileSet_kwgeq") tile_set = SubResource("TileSet_kwgeq")
format = 2 format = 2
layer_0/name = "ground" layer_0/name = "ground"

View file

@ -1,26 +1,43 @@
class_name Ball class_name Ball
extends CharacterBody2D extends CharacterBody2D
signal notify_enemy const y_offset = -10
const Y_OFFSET = -10 const player_path = "/root/Main/TileMap/Player"
const enemy_path = "/root/Main/TileMap/Enemy"
signal notify_enemy(ball_target: Vector2i)
var speed = 100 var speed = 100
var target = Vector2.ZERO var target = Vector2.ZERO
@onready var tile_map: TileMap = get_parent() @onready var tile_map: TileMap = get_parent()
func _ready(): func _ready():
target.y += Y_OFFSET target.y += y_offset
var player = get_node("/root/Main/TileMap/Player") connect_player()
assert(player) connect_enemy()
player.hit.connect(_on_player_hit)
func _physics_process(delta): func _physics_process(delta):
position = position.move_toward(target, delta * speed) position = position.move_toward(target, delta * speed)
func _on_player_hit(): func update_target(new_target: Vector2i):
var rand_cell: Vector2i = tile_map.get_random_top_cell() target = tile_map.map_to_local(new_target) + Vector2(0, y_offset)
tile_map.reset_and_set_target_cell(rand_cell) # Debug
target = tile_map.map_to_local(rand_cell) + Vector2(0, Y_OFFSET) tile_map.reset_and_set_target_cell(new_target)
notify_enemy.emit()
func aim_to_bottom() -> bool: func _on_player_hit_ball():
return tile_map.is_in_bottom_area(target) var new_target: Vector2i = tile_map.get_random_top_cell()
update_target(new_target)
notify_enemy.emit(new_target)
func _on_enemy_hit_ball():
var new_target: Vector2i = tile_map.get_random_bottom_cell()
update_target(new_target)
notify_enemy.emit(new_target)
func connect_player():
var player = get_node(player_path)
assert(player)
player.hit_ball.connect(_on_player_hit_ball)
func connect_enemy():
var enemy = get_node(enemy_path)
assert(enemy)
enemy.hit_ball.connect(_on_enemy_hit_ball)

View file

@ -2,6 +2,10 @@ class_name CanGoToBallCondition
extends ConditionLeaf extends ConditionLeaf
func tick(actor, _blackboard): func tick(actor, _blackboard):
if actor.next_target != null && actor.has_thrown_ball && !actor.collide_with_ball: if (
actor.ball_in_game() &&
actor.next_destination != null &&
!actor.collide_with_ball
):
return SUCCESS return SUCCESS
return FAILURE return FAILURE

View file

@ -3,10 +3,9 @@ extends ConditionLeaf
func tick(actor, _blackboard): func tick(actor, _blackboard):
if ( if (
actor.has_thrown_ball actor.ball_in_game() &&
&& actor.next_target != null actor.collide_with_ball &&
&& actor.collide_with_ball !actor.ball_aims_to_bottom
&& !actor.current_ball.aim_to_bottom()
): ):
return SUCCESS return SUCCESS
return FAILURE return FAILURE

View file

@ -2,6 +2,6 @@ class_name CanThrowBallCondition
extends ConditionLeaf extends ConditionLeaf
func tick(actor, _blackboard): func tick(actor, _blackboard):
if !actor.has_thrown_ball: if !actor.ball_in_game():
return SUCCESS return SUCCESS
return FAILURE return FAILURE

View file

@ -1,11 +0,0 @@
class_name CanWaitCodition
extends ConditionLeaf
func tick(actor, _blackboard):
if actor.next_target != null:
return FAILURE
var num = randi_range(0, 1)
if num == 1:
return FAILURE
return SUCCESS

View file

@ -2,12 +2,5 @@ class_name GetBallDestinationAction
extends ActionLeaf extends ActionLeaf
func tick(actor: Node, blackboard: Blackboard): func tick(actor: Node, blackboard: Blackboard):
# var rand_cell: Vector2i = actor.tile_map.get_random_top_cell() blackboard.set_value("destination", actor.next_destination)
# actor.tile_map.reset_and_set_destination_cell(rand_cell)
#
# var destination = actor.tile_map.map_to_local(rand_cell)
# destination.y += actor.Y_SPAWN_OFFSET
#
blackboard.set_value("destination", actor.next_target)
return SUCCESS return SUCCESS

View file

@ -1,12 +0,0 @@
class_name GetRandomTargetAction
extends ActionLeaf
func tick(actor, blackboard):
var rand_cell: Vector2i = actor.tile_map.get_random_bottom_cell()
actor.tile_map.reset_and_set_target_cell(rand_cell)
var target = actor.tile_map.map_to_local(rand_cell)
blackboard.set_value("target", target)
return SUCCESS

View file

@ -3,20 +3,20 @@ extends ActionLeaf
func before_run(actor, blackboard): func before_run(actor, blackboard):
var destination = blackboard.get_value("destination") var destination = blackboard.get_value("destination")
actor.sprite.flip_h = actor.position.x > destination.x actor.flip_sprite(destination)
actor.animation_player.play("walk") actor.play_walk_animation()
func tick(actor: Node, blackboard: Blackboard): func tick(actor: Node, blackboard: Blackboard):
var destination = blackboard.get_value("destination") var destination = blackboard.get_value("destination")
var delta = get_physics_process_delta_time() actor.move_to(destination)
actor.position = actor.position.move_toward(destination, delta * actor.speed)
if actor.position == destination: if actor.position == destination:
actor.next_destination = null
return SUCCESS return SUCCESS
return RUNNING return RUNNING
func after_run(actor, blackboard): func after_run(actor, blackboard):
actor.play_idle_animation()
# Debug
var destination = blackboard.get_value("destination") var destination = blackboard.get_value("destination")
destination.y -= actor.Y_SPAWN_OFFSET actor.reset_tile(destination)
var cell = actor.tile_map.local_to_map(destination)
actor.tile_map.set_cell(0, cell, 0, Vector2i(0, 0), 0) # debug purpose

View file

@ -2,14 +2,12 @@ class_name ReturnBallAction
extends ActionLeaf extends ActionLeaf
func before_run(actor, _blackboard): func before_run(actor, _blackboard):
actor.play_throw_animation() actor.play_hit_ball_animation()
func tick(actor, blackboard): func tick(actor, _blackboard):
if !actor.is_throw_animation_finished: if !actor.hit_ball_animation_finished:
return RUNNING return RUNNING
else: actor.return_ball()
var target = blackboard.get_value("target")
actor.return_ball(target)
return SUCCESS return SUCCESS
func after_run(actor, _blackboard): func after_run(actor, _blackboard):

View file

@ -2,16 +2,13 @@ class_name ThrowBallAction
extends ActionLeaf extends ActionLeaf
func before_run(actor, _blackboard): func before_run(actor, _blackboard):
actor.play_throw_animation() actor.play_hit_ball_animation()
func tick(actor, blackboard): func tick(actor, _blackboard):
if !actor.is_throw_animation_finished: if !actor.hit_ball_animation_finished:
return RUNNING return RUNNING
else: actor.throw_ball()
var target = blackboard.get_value("target")
actor.throw_ball(target)
actor.has_thrown_ball = true
return SUCCESS return SUCCESS
func after_run(actor, _blackboard): func after_run(actor, _blackboard):
actor.animation_player.play("idle") actor.play_idle_animation()

View file

@ -1,8 +0,0 @@
class_name WaitAction
extends ActionLeaf
func before_run(actor, _blackboard):
actor.animation_player.play("idle")
func tick(_actor, _blackboard):
return RUNNING

View file

@ -1,50 +1,76 @@
class_name Enemy class_name Enemy
extends CharacterBody2D extends CharacterBody2D
signal go_to_ball const ball_scene = preload("res://scenes/ball.tscn")
const Y_SPAWN_OFFSET = -8 const ball_name = "Ball"
@export var speed = 80 const y_spawn_offset = -8
var has_thrown_ball = false signal hit_ball
var ball_scene = preload("res://scenes/ball.tscn") var speed = 80
var current_ball: Ball var next_destination
var next_target
var collide_with_ball = false var collide_with_ball = false
var is_throw_animation_finished = false var hit_ball_animation_finished = false
var ball_aims_to_bottom = false
@onready var tile_map: TileMap = get_parent() @onready var tile_map: TileMap = get_parent()
@onready var animation_player = $AnimationPlayer @onready var animation_player = $AnimationPlayer
@onready var sprite = $Sprite2D @onready var sprite = $Sprite2D
func _ready(): func _ready():
var spawn_cell: Vector2i = tile_map.get_top_spawn_cell() var spawn_cell = tile_map.get_top_spawn_cell()
position = tile_map.map_to_local(spawn_cell) position = tile_map.map_to_local(spawn_cell) + Vector2(0, y_spawn_offset)
position.y += Y_SPAWN_OFFSET animation_player.animation_finished.connect(_on_hit_ball_animation_finished)
animation_player.animation_finished.connect(_on_animation_finished)
func throw_ball(target: Vector2): func move_to(destination):
var delta = get_physics_process_delta_time()
position = position.move_toward(destination, delta * speed)
func throw_ball():
var ball = ball_scene.instantiate() var ball = ball_scene.instantiate()
ball.name = ball_name
ball.position = position ball.position = position
ball.target = target ball.notify_enemy.connect(_on_notify_enemy)
tile_map.add_child(ball) tile_map.add_child(ball)
current_ball = ball hit_ball.emit()
current_ball.notify_enemy.connect(_on_notify_enemy)
func play_throw_animation(): func return_ball():
is_throw_animation_finished = false hit_ball.emit()
func flip_sprite(destination):
sprite.flip_h = position.x > destination.x
func play_hit_ball_animation():
hit_ball_animation_finished = false
animation_player.speed_scale = 0.8 animation_player.speed_scale = 0.8
animation_player.play("throw") animation_player.play("hit_ball")
animation_player.speed_scale = 1 animation_player.speed_scale = 1
func return_ball(target: Vector2): func play_idle_animation():
current_ball.target = target animation_player.play("idle")
func _on_animation_finished(_anim_name): func play_walk_animation():
is_throw_animation_finished = true animation_player.play("walk")
func _on_notify_enemy(): func _on_hit_ball_animation_finished(_anim_name):
next_target = current_ball.target hit_ball_animation_finished = true
func _on_notify_enemy(ball_target: Vector2i):
if tile_map.is_in_bottom_area(ball_target):
ball_aims_to_bottom = true
else:
ball_aims_to_bottom = false
# TODO: add to ball_target an offset depending from where the enemy come from
next_destination = tile_map.map_to_local(ball_target)
func _on_area_2d_body_entered(_body): func _on_area_2d_body_entered(_body):
collide_with_ball = true collide_with_ball = true
func _on_area_2d_body_exited(_body): func _on_area_2d_body_exited(_body):
collide_with_ball = false collide_with_ball = false
func ball_in_game() -> bool:
return tile_map.has_node(ball_name)
# Debug functions
func reset_tile(destination):
destination.y -= y_spawn_offset
var cell = tile_map.local_to_map(destination)
tile_map.set_cell(0, cell, 0, Vector2i(0, 0), 0)

4
scripts/hud.gd Normal file
View file

@ -0,0 +1,4 @@
extends CanvasLayer
func update_score(score):
$ScoreLabel.text = str(score)

7
scripts/main.gd Normal file
View file

@ -0,0 +1,7 @@
extends Node2D
var score = 0
func _on_player_hit_ball():
score += 1
$HUD.update_score(score)

View file

@ -1,21 +1,42 @@
class_name Player class_name Player
extends CharacterBody2D extends CharacterBody2D
signal hit const y_spawn_offset = -8
signal collide_with_ball signal hit_ball
signal ball_starts_colliding
signal ball_stops_colliding
@export var speed = 120 @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() @onready var tile_map: TileMap = get_parent()
func _ready(): func _ready():
var spawn_cell: Vector2i = tile_map.get_bottom_spawn_cell() var spawn_cell = tile_map.get_bottom_spawn_cell()
position = tile_map.map_to_local(spawn_cell) position = tile_map.map_to_local(spawn_cell) + Vector2(0, y_spawn_offset)
position.y += y_spawn_offset
func get_input_direction():
return Input.get_vector("move_left", "move_right", "move_up", "move_down")
func _on_area_2d_body_entered(_body: Node2D): func flip_sprite():
if Input.is_action_pressed("move_left"):
$Sprite2D.flip_h = true
elif Input.is_action_pressed("move_right"):
$Sprite2D.flip_h = false
func play_idle_animation():
$AnimationPlayer.play("idle")
func play_walk_animation():
$AnimationPlayer.play("walk")
func play_hit_ball_animation():
$AnimationPlayer.speed_scale = 0.8
$AnimationPlayer.play("hit_ball")
await $AnimationPlayer.animation_finished
$AnimationPlayer.speed_scale = 1
func _on_area_2d_body_entered(_body):
# As players Area2D only collide with balls # As players Area2D only collide with balls
# We only enter this function after colliding with a ball # We only enter this function after colliding with a ball
collide_with_ball.emit() ball_starts_colliding.emit()
func _on_area_2d_body_exited(_body):
ball_stops_colliding.emit()

View file

@ -0,0 +1,7 @@
class_name PlayerHitBallState
extends PlayerState
func enter(_msg := {}):
player.hit_ball.emit()
await player.play_hit_ball_animation()
state_machine.transition_to("Idle")

View file

@ -1,23 +1,21 @@
class_name PlayerIdleState class_name PlayerIdleState
extends PlayerState extends PlayerState
var collide_with_ball = false var player_collide_with_ball = false
func enter(_msg := {}): func enter(_msg := {}):
player.velocity = Vector2.ZERO player.velocity = Vector2.ZERO
player.animation_player.play("idle") player.play_idle_animation()
func update(_delta): func update(_delta):
if collide_with_ball && Input.is_action_pressed("hit"): if player_collide_with_ball && Input.is_action_pressed("hit"):
collide_with_ball = false state_machine.transition_to("HitBall")
state_machine.transition_to("Throw")
if get_input_direction() != Vector2.ZERO: if player.get_input_direction() != Vector2.ZERO:
state_machine.transition_to("Walk") state_machine.transition_to("Walk")
func get_input_direction(): func _on_player_ball_starts_colliding():
return Input.get_vector("move_left", "move_right", "move_up", "move_down") player_collide_with_ball = true
func _on_player_ball_stops_colliding():
func _on_player_collide_with_ball(): player_collide_with_ball = false
collide_with_ball = true

View file

@ -1,20 +0,0 @@
class_name PlayerThrowState
extends PlayerState
var is_animation_finished = false
func enter(_msg := {}):
player.animation_player.speed_scale = 0.8
player.animation_player.play("throw")
player.hit.emit()
func update(_delta: float):
if is_animation_finished:
state_machine.transition_to("Idle")
func exit():
is_animation_finished = false
player.animation_player.speed_scale = 1
func _on_animation_player_animation_finished(_anim_name):
is_animation_finished = true

View file

@ -2,25 +2,17 @@ class_name PlayerWalkState
extends PlayerState extends PlayerState
func enter(_msg := {}): func enter(_msg := {}):
player.animation_player.play("walk") player.play_walk_animation()
func physics_update(delta): func physics_update(delta):
var direction = get_input_direction() var direction = player.get_input_direction()
var velocity = direction * player.speed var velocity = direction * player.speed
player.flip_sprite()
var collision = player.move_and_collide(velocity * delta) var collision = player.move_and_collide(velocity * delta)
if collision and Input.is_action_pressed("hit"): if collision and Input.is_action_pressed("hit"):
state_machine.transition_to("Throw") state_machine.transition_to("HitBall")
if velocity == Vector2.ZERO: if velocity == Vector2.ZERO:
state_machine.transition_to("Idle") 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

View file

@ -4,6 +4,11 @@ extends TileMap
@export var wall_tile_source_id = 1 @export var wall_tile_source_id = 1
@export var destination_tile_source_id = 2 @export var destination_tile_source_id = 2
@export var target_tile_source_id = 3 @export var target_tile_source_id = 3
@export var ground_left_tile_source_id = 4
@export var ground_right_tile_source_id = 5
@export var ground_bottom_tile_source_id = 6
@export var ground_left_bottom_tile_source_id = 7
@export var ground_right_bottom_tile_source_id = 8
@export var map_width = 13 # keep to a odd value @export var map_width = 13 # keep to a odd value
@export var map_height = 19 # keep to a odd value @export var map_height = 19 # keep to a odd value
# Debug variables # Debug variables
@ -22,47 +27,59 @@ func draw_map():
draw_wall() draw_wall()
func draw_ground(): func draw_ground():
var tile_source_id = ground_tile_source_id
var height = get_bottom_area_height()
for x in range(map_width): for x in range(map_width):
for y in range(map_height): for y in range(map_height):
set_cell(0, Vector2i(x, y), ground_tile_source_id, Vector2i(0, 0), 0) if x == 0 && y == map_height - 1:
tile_source_id = ground_left_bottom_tile_source_id
elif x == map_width - 1 && y == map_height - 1:
tile_source_id = ground_right_bottom_tile_source_id
elif x == 0 && y >= height.x:
tile_source_id = ground_left_tile_source_id
elif x == map_width - 1 && y >= height.x:
tile_source_id = ground_right_tile_source_id
elif y == height.y:
tile_source_id = ground_bottom_tile_source_id
else:
tile_source_id = ground_tile_source_id
set_cell(0, Vector2i(x, y), tile_source_id, Vector2i(0, 0), 0)
func draw_wall(): func draw_wall():
var middle_height = floor(map_height / 2.0) var middle_height = floor(map_height / 2.0)
for x in range(map_width): for x in range(map_width):
set_cell(1, Vector2i(x - 1, middle_height - 1), wall_tile_source_id, Vector2i(0, 0), 0) # why have we to add -1? set_cell(1, Vector2i(x - 1, middle_height - 1), wall_tile_source_id, Vector2i(0, 0), 0) # why have we to add -1?
func get_top_spawn_cell(): func get_top_spawn_cell() -> Vector2i:
return Vector2i(floor(map_width / 2.0), 1) return Vector2i(floor(map_width / 2.0), 1)
func get_bottom_spawn_cell(): func get_bottom_spawn_cell() -> Vector2i:
return Vector2i(floor(map_width / 2.0), map_height - 2) return Vector2i(floor(map_width / 2.0), map_height - 2)
func get_random_top_cell(): func get_random_top_cell() -> Vector2i:
var w = get_area_width() var w = get_area_width()
var h = get_top_area_height() var h = get_top_area_height()
return Vector2i(randi_range(w.x, w.y), randi_range(h.x, h.y)) return Vector2i(randi_range(w.x, w.y), randi_range(h.x, h.y))
func get_random_bottom_cell(): func get_random_bottom_cell() -> Vector2i:
var w = get_area_width() var w = get_area_width()
var h = get_bottom_area_height() var h = get_bottom_area_height()
return Vector2i(randi_range(w.x, w.y), randi_range(h.x, h.y)) return Vector2i(randi_range(w.x, w.y), randi_range(h.x, h.y))
func is_in_bottom_area(local_position: Vector2): func is_in_bottom_area(cell: Vector2i) -> bool:
var map_position = local_to_map(local_position)
var height = get_bottom_area_height() var height = get_bottom_area_height()
return cell.y >= height.x && cell.y <= height.y
return map_position.y >= height.x && map_position.y <= height.y func get_area_width() -> Vector2i:
func get_area_width():
return Vector2i(0, map_width - 1) return Vector2i(0, map_width - 1)
func get_top_area_height(): func get_top_area_height() -> Vector2i:
var middle_height = floor(map_height / 2.0) var middle_height = floor(map_height / 2.0)
return Vector2i(0, middle_height - 1) return Vector2i(0, middle_height - 1)
func get_bottom_area_height(): func get_bottom_area_height() -> Vector2i:
var middle_height = floor(map_height / 2.0) var middle_height = floor(map_height / 2.0)
return Vector2i(middle_height + 1, map_height - 1) return Vector2i(middle_height + 1, map_height - 1)