Player throw back the ball from walk or idle state

This commit is contained in:
Mathilde Grapin 2023-06-18 20:30:25 +02:00
parent 1aff1c2e38
commit 332c0fb0e1
16 changed files with 165 additions and 25 deletions

View file

@ -56,8 +56,15 @@ move_down={
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
hit={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"echo":false,"script":null)
]
}
[layer_names]
2d_physics/layer_1="walls"
2d_physics/layer_2="player"
2d_physics/layer_1="player"
2d_physics/layer_2="enemy"
2d_physics/layer_3="wall"
2d_physics/layer_4="ball"

View file

@ -1,12 +1,16 @@
[gd_scene load_steps=3 format=3 uid="uid://cy0ko2cawudia"]
[gd_scene load_steps=4 format=3 uid="uid://cy0ko2cawudia"]
[ext_resource type="Script" path="res://scripts/ball/ball.gd" id="1_8tu7d"]
[ext_resource type="Texture2D" uid="uid://dl8qfp3u18nkx" path="res://art/objects/ball.png" id="1_un30v"]
[sub_resource type="CircleShape2D" id="CircleShape2D_srlvs"]
radius = 5.0
radius = 6.0
[node name="Ball" type="Area2D"]
[node name="Ball" type="CharacterBody2D"]
z_index = 1
collision_layer = 8
collision_mask = 7
script = ExtResource("1_8tu7d")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("1_un30v")

View file

@ -143,6 +143,8 @@ _data = {
size = Vector2(17, 10)
[node name="Enemy" type="CharacterBody2D"]
collision_layer = 2
collision_mask = 13
script = ExtResource("1_2uhn6")
[node name="Sprite2D" type="Sprite2D" parent="."]

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=12 format=3 uid="uid://b51tdt5kunai"]
[gd_scene load_steps=13 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"]
@ -8,6 +8,7 @@
[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/is_idle_condition.gd" id="9_vboat"]
[ext_resource type="Script" path="res://scripts/enemy/behavior_tree/get_random_destination_action.gd" id="10_f4jrw"]
[ext_resource type="Script" path="res://scripts/enemy/behavior_tree/move_to_destination_action.gd" id="11_tjc85"]
@ -37,6 +38,9 @@ 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")

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=16 format=3 uid="uid://ba1t35yyot4jl"]
[gd_scene load_steps=17 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,6 +8,7 @@
[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"]
[sub_resource type="Animation" id="Animation_rh7n7"]
length = 0.001
@ -97,7 +98,6 @@ tracks/2/keys = {
[sub_resource type="Animation" id="Animation_gswgu"]
resource_name = "throw"
length = 0.4
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
@ -186,14 +186,15 @@ _data = {
}
[sub_resource type="RectangleShape2D" id="RectangleShape2D_hocsq"]
size = Vector2(21, 7.5)
size = Vector2(21, 10)
[node name="Player" type="CharacterBody2D"]
collision_mask = 14
script = ExtResource("1_fmx2p")
[node name="Sprite2D" type="Sprite2D" parent="."]
position = Vector2(0, -16)
texture = ExtResource("4_orj3a")
texture = ExtResource("5_2s1mg")
hframes = 4
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
@ -203,7 +204,15 @@ libraries = {
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
y_sort_enabled = true
position = Vector2(-2.5, -3.75)
position = Vector2(-2.5, -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")
[node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("state")]
@ -215,3 +224,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")
[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="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"]

22
scripts/ball/ball.gd Normal file
View file

@ -0,0 +1,22 @@
class_name Ball
extends CharacterBody2D
const Y_OFFSET = -10
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)
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)

View file

@ -3,7 +3,7 @@ extends ActionLeaf
func tick(actor: Node, blackboard: Blackboard):
var rand_cell: Vector2i = actor.tile_map.get_random_top_cell()
actor.tile_map.set_cell(0, Vector2i(rand_cell.x, rand_cell.y), 2, Vector2i(0, 0), 0) # debug purpose
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

View file

@ -0,0 +1,12 @@
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

@ -14,3 +14,9 @@ func tick(actor: Node, blackboard: Blackboard):
if actor.position == destination:
return SUCCESS
return RUNNING
func after_run(actor, blackboard):
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

View file

@ -1,25 +1,26 @@
class_name ThrowBallAction
extends ActionLeaf
var has_animation_finished = false
var is_animation_finished = false
func before_run(actor, _blackboard):
actor.animation_player.animation_finished.connect(_on_animation_finished)
actor.animation_player.speed_scale = 0.8
func tick(actor, _blackboard):
func tick(actor, blackboard):
actor.animation_player.play("throw")
if !has_animation_finished:
if !is_animation_finished:
return RUNNING
else:
actor.throw_ball()
var target = blackboard.get_value("target")
actor.throw_ball(target)
actor.has_thrown_ball = true
return SUCCESS
func after_run(actor, _blackboard):
actor.animation_player.play("idle")
actor.animation_player.speed_scale = 1
actor.animation_player.play("idle")
func _on_animation_finished(_anim_name):
has_animation_finished = true
is_animation_finished = true

View file

@ -14,7 +14,8 @@ func _ready():
position = tile_map.map_to_local(spawn_cell)
position.y += Y_SPAWN_OFFSET
func throw_ball():
func throw_ball(target: Vector2):
var ball = ball_scene.instantiate()
ball.position = position
ball.target = target
tile_map.add_child(ball)

View file

@ -1,6 +1,8 @@
class_name Player
extends CharacterBody2D
signal hit
signal collide_with_ball
@export var speed = 120
var y_spawn_offset = -8
@onready var animation_player = $AnimationPlayer
@ -11,3 +13,9 @@ 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
func _on_area_2d_body_entered(body: Node2D):
# As players Area2D only collide with balls
# We only enter this function after colliding with a ball
collide_with_ball.emit()

View file

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

View file

@ -0,0 +1,20 @@
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

@ -4,13 +4,15 @@ extends PlayerState
func enter(_msg := {}):
player.animation_player.play("walk")
func physics_update(_delta):
func physics_update(delta):
var direction = get_input_direction()
player.velocity = direction * player.speed
var velocity = direction * player.speed
var collision = player.move_and_collide(velocity * delta)
if collision and Input.is_action_pressed("hit"):
state_machine.transition_to("Throw")
player.move_and_slide() # This method calculate with delta, we don't need to do it.
if player.velocity == Vector2.ZERO:
if velocity == Vector2.ZERO:
state_machine.transition_to("Idle")
func get_input_direction():

View file

@ -1,7 +1,12 @@
extends TileMap
@export var ground_tile_source_id = 0
@export var destination_tile_source_id = 2
@export var target_tile_source_id = 3
@export var map_width = 13 # keep to a odd value
@export var map_height = 19 # keep to a odd value
var current_destination_cell: Vector2i
var current_target_cell: Vector2i
func _ready():
draw_map()
@ -34,5 +39,25 @@ func get_random_top_cell() -> Vector2i:
var middle_height = floor(map_height / 2.0)
var rand_width = randi_range(0, map_width - 1)
var rand_height = randi_range(0, middle_height - 1)
#set_cell(0, Vector2i(rand_width, rand_height), 1, Vector2i(0, 0), 0)
return Vector2i(rand_width, rand_height)
func get_random_bottom_cell() -> Vector2i:
var middle_height = floor(map_height / 2.0)
var rand_width = randi_range(0, map_width - 1)
var rand_height = randi_range(middle_height + 1, map_height - 1)
return Vector2i(rand_width, rand_height)
# Debug helper functions
func reset_and_set_target_cell(cell: Vector2i):
reset_and_set_cell(current_target_cell, cell, target_tile_source_id)
func reset_and_set_destination_cell(cell: Vector2i):
reset_and_set_cell(current_destination_cell, cell, destination_tile_source_id)
func reset_and_set_cell(current_cell: Vector2i, cell: Vector2i, tile_source_id: int):
if current_cell != null:
set_cell(0, current_cell, ground_tile_source_id, Vector2i(0, 0), 0)
set_cell(0, cell, tile_source_id, Vector2i(0, 0), 0)
current_cell = cell