Player throw back the ball from walk or idle state
This commit is contained in:
parent
1aff1c2e38
commit
332c0fb0e1
16 changed files with 165 additions and 25 deletions
22
scripts/ball/ball.gd
Normal file
22
scripts/ball/ball.gd
Normal 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)
|
||||
|
|
@ -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
|
||||
|
|
12
scripts/enemy/behavior_tree/get_random_target_action.gd
Normal file
12
scripts/enemy/behavior_tree/get_random_target_action.gd
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 player’s Area2D only collide with balls
|
||||
# We only enter this function after colliding with a ball
|
||||
collide_with_ball.emit()
|
||||
|
|
|
@ -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
|
||||
|
|
20
scripts/player/states/player_throw_state.gd
Normal file
20
scripts/player/states/player_throw_state.gd
Normal 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
|
|
@ -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():
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue