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"
type="CompressedTexture2D"
uid="uid://d265li1k63anm"
path="res://.godot/imported/target_tile.png-8889c881dce8d973f9cccb76e30928fa.ctex"
path="res://.godot/imported/ball_target.png-420e9ad20dd0b28420ac9e18f85c8839.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/tiles/target_tile.png"
dest_files=["res://.godot/imported/target_tile.png-8889c881dce8d973f9cccb76e30928fa.ctex"]
source_file="res://art/tiles/ball_target.png"
dest_files=["res://.godot/imported/ball_target.png-420e9ad20dd0b28420ac9e18f85c8839.ctex"]
[params]

View file

Before

Width:  |  Height:  |  Size: 313 B

After

Width:  |  Height:  |  Size: 313 B

View file

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

View file

Before

Width:  |  Height:  |  Size: 323 B

After

Width:  |  Height:  |  Size: 323 B

View file

@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://cm58s70te836m"
path="res://.godot/imported/ground_tile.png-a0838c31e75c33807f6e9b010d97f31b.ctex"
path="res://.godot/imported/ground.png-ce6ec90789aee5a940b6b4beb4661e80.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/tiles/ground_tile.png"
dest_files=["res://.godot/imported/ground_tile.png-a0838c31e75c33807f6e9b010d97f31b.ctex"]
source_file="res://art/tiles/ground.png"
dest_files=["res://.godot/imported/ground.png-ce6ec90789aee5a940b6b4beb4661e80.ctex"]
[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"
type="CompressedTexture2D"
uid="uid://lnt0clkwms52"
path="res://.godot/imported/wall_tile.png-943542e63eb98fa5c2f8ba381f7ef7b8.ctex"
path="res://.godot/imported/wall.png-b444f5cdb367a6f2116effa1c0667bcc.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/tiles/wall_tile.png"
dest_files=["res://.godot/imported/wall_tile.png-943542e63eb98fa5c2f8ba381f7ef7b8.ctex"]
source_file="res://art/tiles/wall.png"
dest_files=["res://.godot/imported/wall.png-b444f5cdb367a6f2116effa1c0667bcc.ctex"]
[params]

View file

@ -9,10 +9,9 @@
[sub_resource type="Animation" id="Animation_ouyrp"]
length = 0.001
[sub_resource type="Animation" id="Animation_6vdwd"]
resource_name = "idle"
[sub_resource type="Animation" id="Animation_jt5bg"]
resource_name = "hit_ball"
length = 0.4
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
@ -23,7 +22,7 @@ tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("3_5xsrd")]
"values": [ExtResource("2_5t5q0")]
}
tracks/1/type = "value"
tracks/1/imported = false
@ -50,9 +49,10 @@ tracks/2/keys = {
"values": [0, 1, 2, 3]
}
[sub_resource type="Animation" id="Animation_jt5bg"]
resource_name = "throw"
[sub_resource type="Animation" id="Animation_6vdwd"]
resource_name = "idle"
length = 0.4
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
@ -63,7 +63,7 @@ tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("2_5t5q0")]
"values": [ExtResource("3_5xsrd")]
}
tracks/1/type = "value"
tracks/1/imported = false
@ -134,8 +134,8 @@ tracks/2/keys = {
[sub_resource type="AnimationLibrary" id="AnimationLibrary_gnukq"]
_data = {
"RESET": SubResource("Animation_ouyrp"),
"hit_ball": SubResource("Animation_jt5bg"),
"idle": SubResource("Animation_6vdwd"),
"throw": SubResource("Animation_jt5bg"),
"walk": SubResource("Animation_etqki")
}
@ -172,6 +172,5 @@ shape = SubResource("RectangleShape2D_rlijp")
[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_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/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://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/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/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"]
@ -21,28 +17,12 @@ script = ExtResource("1_b2pc4")
[node name="MainSelector" type="Node" parent="."]
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"]
script = ExtResource("2_80fm4")
[node name="CanThrowBall" type="Node" parent="MainSelector/ThrowBallSequence"]
script = ExtResource("7_k5qlq")
[node name="GetRandomTarget" type="Node" parent="MainSelector/ThrowBallSequence"]
script = ExtResource("8_y68xp")
[node name="ThrowBall" type="Node" parent="MainSelector/ThrowBallSequence"]
script = ExtResource("8_wytqf")
@ -64,8 +44,5 @@ script = ExtResource("2_80fm4")
[node name="CanReturnBall" type="Node" parent="MainSelector/SequenceComposite"]
script = ExtResource("13_lrd2w")
[node name="GetRandomTarget2" type="Node" parent="MainSelector/SequenceComposite"]
script = ExtResource("8_y68xp")
[node name="ReturnBall" type="Node" parent="MainSelector/SequenceComposite"]
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://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://bxj8v34v1igyc" path="res://scenes/hud.tscn" id="4_ealqo"]
[node name="Main" type="Node2D"]
y_sort_enabled = true
script = ExtResource("1_1xo8b")
[node name="TileMap" parent="." instance=ExtResource("2_c6bkg")]
position = Vector2(324, 82)
@ -19,3 +22,7 @@ position = Vector2(0, 40)
z_index = 1
z_as_relative = false
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="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/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_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"]
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"]
resource_name = "idle"
length = 0.4
@ -95,46 +135,6 @@ tracks/2/keys = {
"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"]
resource_name = "walk"
length = 0.6
@ -179,17 +179,20 @@ tracks/2/keys = {
[sub_resource type="AnimationLibrary" id="AnimationLibrary_ldfyt"]
_data = {
"RESET": SubResource("Animation_rh7n7"),
"hit_ball": SubResource("Animation_gswgu"),
"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, 10)
size = Vector2(24, 7)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_i54nm"]
size = Vector2(17, 10)
[node name="Player" type="CharacterBody2D"]
collision_mask = 14
collision_mask = 6
script = ExtResource("1_fmx2p")
[node name="Sprite2D" type="Sprite2D" parent="."]
@ -204,16 +207,15 @@ libraries = {
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
y_sort_enabled = true
position = Vector2(-2.5, -5)
position = Vector2(-3, -3.5)
shape = SubResource("RectangleShape2D_hocsq")
[node name="Area2D" type="Area2D" parent="."]
collision_mask = 8
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
y_sort_enabled = true
position = Vector2(-2.5, -5)
shape = SubResource("RectangleShape2D_hocsq")
position = Vector2(-1.5, -5)
shape = SubResource("RectangleShape2D_i54nm")
[node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("state")]
script = ExtResource("6_hl63m")
@ -225,9 +227,10 @@ script = ExtResource("7_0nfrc")
[node name="Walk" type="Node" parent="StateMachine"]
script = ExtResource("7_gcd3q")
[node name="Throw" type="Node" parent="StateMachine"]
script = ExtResource("9_atm3r")
[node name="HitBall" type="Node" parent="StateMachine"]
script = ExtResource("9_aqfsh")
[connection signal="collide_with_ball" from="." to="StateMachine/Idle" method="_on_player_collide_with_ball"]
[connection signal="animation_finished" from="AnimationPlayer" to="StateMachine/Throw" method="_on_animation_player_animation_finished"]
[connection signal="ball_starts_colliding" from="." to="StateMachine/Idle" method="_on_player_ball_starts_colliding"]
[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_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://lnt0clkwms52" path="res://art/tiles/wall_tile.png" id="2_iitec"]
[ext_resource type="Texture2D" uid="uid://b7565sd31qorm" path="res://art/tiles/destination_tile.png" id="3_ca0hc"]
[ext_resource type="Texture2D" uid="uid://d265li1k63anm" path="res://art/tiles/target_tile.png" id="4_w73lj"]
[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.png" id="2_odoye"]
[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/ball_target.png" id="4_k2ia8"]
[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"]
texture = ExtResource("1_set62")
texture = ExtResource("1_kvtof")
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_1/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_1/angular_velocity = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_u0t08"]
texture = ExtResource("2_iitec")
texture = ExtResource("2_odoye")
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)
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"]
texture = ExtResource("3_ca0hc")
texture = ExtResource("3_plcvy")
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_1/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_1/angular_velocity = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_hm0kl"]
texture = ExtResource("4_w73lj")
texture = ExtResource("4_k2ia8")
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_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"]
tile_shape = 1
tile_layout = 5
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/1 = SubResource("TileSetAtlasSource_u0t08")
sources/2 = SubResource("TileSetAtlasSource_x1mdb")
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"]
y_sort_enabled = true
position = Vector2(-1, 1)
tile_set = SubResource("TileSet_kwgeq")
format = 2
layer_0/name = "ground"

View file

@ -1,26 +1,43 @@
class_name Ball
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 target = Vector2.ZERO
@onready var tile_map: TileMap = get_parent()
func _ready():
target.y += Y_OFFSET
var player = get_node("/root/Main/TileMap/Player")
assert(player)
player.hit.connect(_on_player_hit)
target.y += y_offset
connect_player()
connect_enemy()
func _physics_process(delta):
position = position.move_toward(target, delta * speed)
func _on_player_hit():
var rand_cell: Vector2i = tile_map.get_random_top_cell()
tile_map.reset_and_set_target_cell(rand_cell)
target = tile_map.map_to_local(rand_cell) + Vector2(0, Y_OFFSET)
notify_enemy.emit()
func update_target(new_target: Vector2i):
target = tile_map.map_to_local(new_target) + Vector2(0, y_offset)
# Debug
tile_map.reset_and_set_target_cell(new_target)
func aim_to_bottom() -> bool:
return tile_map.is_in_bottom_area(target)
func _on_player_hit_ball():
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
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 FAILURE

View file

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

View file

@ -2,6 +2,6 @@ class_name CanThrowBallCondition
extends ConditionLeaf
func tick(actor, _blackboard):
if !actor.has_thrown_ball:
if !actor.ball_in_game():
return SUCCESS
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
func tick(actor: Node, blackboard: Blackboard):
# var rand_cell: Vector2i = actor.tile_map.get_random_top_cell()
# 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)
blackboard.set_value("destination", actor.next_destination)
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):
var destination = blackboard.get_value("destination")
actor.sprite.flip_h = actor.position.x > destination.x
actor.animation_player.play("walk")
actor.flip_sprite(destination)
actor.play_walk_animation()
func tick(actor: Node, blackboard: Blackboard):
var destination = blackboard.get_value("destination")
var delta = get_physics_process_delta_time()
actor.position = actor.position.move_toward(destination, delta * actor.speed)
actor.move_to(destination)
if actor.position == destination:
actor.next_destination = null
return SUCCESS
return RUNNING
func after_run(actor, blackboard):
actor.play_idle_animation()
# Debug
var destination = blackboard.get_value("destination")
destination.y -= actor.Y_SPAWN_OFFSET
var cell = actor.tile_map.local_to_map(destination)
actor.tile_map.set_cell(0, cell, 0, Vector2i(0, 0), 0) # debug purpose
actor.reset_tile(destination)

View file

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

View file

@ -2,16 +2,13 @@ class_name ThrowBallAction
extends ActionLeaf
func before_run(actor, _blackboard):
actor.play_throw_animation()
actor.play_hit_ball_animation()
func tick(actor, blackboard):
if !actor.is_throw_animation_finished:
func tick(actor, _blackboard):
if !actor.hit_ball_animation_finished:
return RUNNING
else:
var target = blackboard.get_value("target")
actor.throw_ball(target)
actor.has_thrown_ball = true
actor.throw_ball()
return SUCCESS
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
extends CharacterBody2D
signal go_to_ball
const Y_SPAWN_OFFSET = -8
@export var speed = 80
var has_thrown_ball = false
var ball_scene = preload("res://scenes/ball.tscn")
var current_ball: Ball
var next_target
const ball_scene = preload("res://scenes/ball.tscn")
const ball_name = "Ball"
const y_spawn_offset = -8
signal hit_ball
var speed = 80
var next_destination
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 animation_player = $AnimationPlayer
@onready var sprite = $Sprite2D
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
animation_player.animation_finished.connect(_on_animation_finished)
var spawn_cell = tile_map.get_top_spawn_cell()
position = tile_map.map_to_local(spawn_cell) + Vector2(0, y_spawn_offset)
animation_player.animation_finished.connect(_on_hit_ball_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()
ball.name = ball_name
ball.position = position
ball.target = target
ball.notify_enemy.connect(_on_notify_enemy)
tile_map.add_child(ball)
current_ball = ball
current_ball.notify_enemy.connect(_on_notify_enemy)
hit_ball.emit()
func play_throw_animation():
is_throw_animation_finished = false
func return_ball():
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.play("throw")
animation_player.play("hit_ball")
animation_player.speed_scale = 1
func return_ball(target: Vector2):
current_ball.target = target
func play_idle_animation():
animation_player.play("idle")
func _on_animation_finished(_anim_name):
is_throw_animation_finished = true
func play_walk_animation():
animation_player.play("walk")
func _on_notify_enemy():
next_target = current_ball.target
func _on_hit_ball_animation_finished(_anim_name):
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):
collide_with_ball = true
func _on_area_2d_body_exited(_body):
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
extends CharacterBody2D
signal hit
signal collide_with_ball
const y_spawn_offset = -8
signal hit_ball
signal ball_starts_colliding
signal ball_stops_colliding
@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
var spawn_cell = tile_map.get_bottom_spawn_cell()
position = tile_map.map_to_local(spawn_cell) + Vector2(0, 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
# 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
extends PlayerState
var collide_with_ball = false
var player_collide_with_ball = false
func enter(_msg := {}):
player.velocity = Vector2.ZERO
player.animation_player.play("idle")
player.play_idle_animation()
func update(_delta):
if collide_with_ball && Input.is_action_pressed("hit"):
collide_with_ball = false
state_machine.transition_to("Throw")
if player_collide_with_ball && Input.is_action_pressed("hit"):
state_machine.transition_to("HitBall")
if get_input_direction() != Vector2.ZERO:
if player.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")
func _on_player_ball_starts_colliding():
player_collide_with_ball = true
func _on_player_collide_with_ball():
collide_with_ball = true
func _on_player_ball_stops_colliding():
player_collide_with_ball = false

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
func enter(_msg := {}):
player.animation_player.play("walk")
player.play_walk_animation()
func physics_update(delta):
var direction = get_input_direction()
var direction = player.get_input_direction()
var velocity = direction * player.speed
player.flip_sprite()
var collision = player.move_and_collide(velocity * delta)
if collision and Input.is_action_pressed("hit"):
state_machine.transition_to("Throw")
state_machine.transition_to("HitBall")
if 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

View file

@ -4,6 +4,11 @@ extends TileMap
@export var wall_tile_source_id = 1
@export var destination_tile_source_id = 2
@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_height = 19 # keep to a odd value
# Debug variables
@ -22,47 +27,59 @@ func draw_map():
draw_wall()
func draw_ground():
var tile_source_id = ground_tile_source_id
var height = get_bottom_area_height()
for x in range(map_width):
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():
var middle_height = floor(map_height / 2.0)
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?
func get_top_spawn_cell():
func get_top_spawn_cell() -> Vector2i:
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)
func get_random_top_cell():
func get_random_top_cell() -> Vector2i:
var w = get_area_width()
var h = get_top_area_height()
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 h = get_bottom_area_height()
return Vector2i(randi_range(w.x, w.y), randi_range(h.x, h.y))
func is_in_bottom_area(local_position: Vector2):
var map_position = local_to_map(local_position)
func is_in_bottom_area(cell: Vector2i) -> bool:
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():
func get_area_width() -> Vector2i:
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)
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)
return Vector2i(middle_height + 1, map_height - 1)