First commit
Add simple player movement with a finite state machine. Add enemy that can move to target point. Add ground through a tilemap and wall that player and enemy cannot cross.
This commit is contained in:
commit
7038d29d87
34 changed files with 883 additions and 0 deletions
36
scripts/enemy.gd
Normal file
36
scripts/enemy.gd
Normal file
|
@ -0,0 +1,36 @@
|
|||
extends CharacterBody2D
|
||||
|
||||
@onready var tile_map: TileMap = get_parent()
|
||||
@onready var animation_player = $AnimationPlayer
|
||||
@export var speed = 80
|
||||
var y_spawn_offset = -8
|
||||
var is_moving = false
|
||||
var destination: Vector2 = Vector2.ZERO
|
||||
|
||||
|
||||
func _ready():
|
||||
var spawn_cell: Vector2i = tile_map.get_top_spawn_cell()
|
||||
position = tile_map.map_to_local(spawn_cell)
|
||||
position.y += y_spawn_offset
|
||||
|
||||
func _process(_delta):
|
||||
if is_moving:
|
||||
animation_player.play("walk")
|
||||
else:
|
||||
animation_player.stop()
|
||||
|
||||
func _physics_process(delta):
|
||||
move_to_rand_cell(delta)
|
||||
|
||||
func move_to_rand_cell(delta):
|
||||
if !is_moving:
|
||||
var rand_cell: Vector2i = tile_map.get_random_top_cell()
|
||||
tile_map.set_cell(0, Vector2i(rand_cell.x, rand_cell.y), 1, Vector2i(0, 0), 0) # debug purpose
|
||||
destination = tile_map.map_to_local(rand_cell)
|
||||
destination.y += y_spawn_offset
|
||||
|
||||
is_moving = true
|
||||
position = position.move_toward(destination, delta * speed)
|
||||
|
||||
if position == destination:
|
||||
is_moving = false
|
13
scripts/player.gd
Normal file
13
scripts/player.gd
Normal file
|
@ -0,0 +1,13 @@
|
|||
class_name Player
|
||||
extends CharacterBody2D
|
||||
|
||||
@export var speed = 120
|
||||
var y_spawn_offset = -8
|
||||
@onready var animation_player = $AnimationPlayer
|
||||
@onready var sprite = $Sprite2D
|
||||
@onready var tile_map: TileMap = get_parent()
|
||||
|
||||
func _ready():
|
||||
var spawn_cell: Vector2i = tile_map.get_bottom_spawn_cell()
|
||||
position = tile_map.map_to_local(spawn_cell)
|
||||
position.y += y_spawn_offset
|
13
scripts/player_idle_state.gd
Normal file
13
scripts/player_idle_state.gd
Normal file
|
@ -0,0 +1,13 @@
|
|||
class_name PlayerIdleState
|
||||
extends PlayerState
|
||||
|
||||
func enter(_msg := {}):
|
||||
player.velocity = Vector2.ZERO
|
||||
player.animation_player.play("idle")
|
||||
|
||||
func update(_delta):
|
||||
if get_input_direction() != Vector2.ZERO:
|
||||
state_machine.transition_to("Walk")
|
||||
|
||||
func get_input_direction():
|
||||
return Input.get_vector("move_left", "move_right", "move_up", "move_down")
|
9
scripts/player_state.gd
Normal file
9
scripts/player_state.gd
Normal file
|
@ -0,0 +1,9 @@
|
|||
class_name PlayerState
|
||||
extends State
|
||||
|
||||
var player: Player
|
||||
|
||||
func _ready():
|
||||
await owner.ready
|
||||
player = owner as Player
|
||||
assert(player != null)
|
24
scripts/player_walk_state.gd
Normal file
24
scripts/player_walk_state.gd
Normal file
|
@ -0,0 +1,24 @@
|
|||
class_name PlayerWalkState
|
||||
extends PlayerState
|
||||
|
||||
func enter(_msg := {}):
|
||||
player.animation_player.play("walk")
|
||||
|
||||
func physics_update(_delta):
|
||||
var direction = get_input_direction()
|
||||
player.velocity = direction * player.speed
|
||||
|
||||
player.move_and_slide() # this method calculate with delta, we don’t need to do it
|
||||
|
||||
if player.velocity == Vector2.ZERO:
|
||||
state_machine.transition_to("Idle")
|
||||
|
||||
func get_input_direction():
|
||||
var direction = Input.get_vector("move_left", "move_right", "move_up", "move_down")
|
||||
|
||||
if Input.is_action_pressed("move_left"):
|
||||
player.sprite.flip_h = true
|
||||
elif Input.is_action_pressed("move_right"):
|
||||
player.sprite.flip_h = false
|
||||
|
||||
return direction
|
19
scripts/state.gd
Normal file
19
scripts/state.gd
Normal file
|
@ -0,0 +1,19 @@
|
|||
class_name State
|
||||
extends Node
|
||||
|
||||
var state_machine = null
|
||||
|
||||
func handle_input(_event: InputEvent):
|
||||
pass
|
||||
|
||||
func update(_delta: float):
|
||||
pass
|
||||
|
||||
func physics_update(_delta: float):
|
||||
pass
|
||||
|
||||
func enter(_msg: Dictionary = {}):
|
||||
pass
|
||||
|
||||
func exit():
|
||||
pass
|
34
scripts/state_machine.gd
Normal file
34
scripts/state_machine.gd
Normal file
|
@ -0,0 +1,34 @@
|
|||
class_name StateMachine
|
||||
extends Node
|
||||
|
||||
signal transitioned(state_name)
|
||||
@export var state: State
|
||||
|
||||
func _ready():
|
||||
await owner.ready
|
||||
|
||||
for child in get_children():
|
||||
child.state_machine = self
|
||||
|
||||
state.enter()
|
||||
|
||||
func _unhandled_input(event):
|
||||
state.handle_input(event)
|
||||
|
||||
func _process(delta):
|
||||
state.update(delta)
|
||||
|
||||
func _physics_process(delta):
|
||||
state.physics_update(delta)
|
||||
|
||||
func transition_to(target_state_name: String, msg: Dictionary = {}):
|
||||
if not has_node(target_state_name):
|
||||
push_warning("No state with name " + target_state_name)
|
||||
return
|
||||
|
||||
state.exit()
|
||||
state = get_node(target_state_name)
|
||||
state.enter(msg)
|
||||
emit_signal("transitioned", state.name)
|
||||
|
||||
|
38
scripts/tile_map.gd
Normal file
38
scripts/tile_map.gd
Normal file
|
@ -0,0 +1,38 @@
|
|||
extends TileMap
|
||||
|
||||
@export var map_width = 13 # keep to a odd value
|
||||
@export var map_height = 19 # keep to a odd value
|
||||
|
||||
func _ready():
|
||||
draw_map()
|
||||
|
||||
func draw_map():
|
||||
draw_ground()
|
||||
draw_separation()
|
||||
get_random_top_cell()
|
||||
|
||||
func draw_ground():
|
||||
for x in range(map_width):
|
||||
for y in range(map_height):
|
||||
set_cell(0, Vector2i(x, y), 0, Vector2i(0, 0), 0)
|
||||
|
||||
# The tilemap is initially divided in two section
|
||||
# One for the player (bottom section)
|
||||
# One for the enemy (top section)
|
||||
func draw_separation():
|
||||
var middle_height = floor(map_height / 2.0)
|
||||
for x in range(map_width):
|
||||
set_cell(1, Vector2i(x - 1, middle_height - 1), 1, Vector2i(0, 0), 0) # why have we to add -1?
|
||||
|
||||
func get_top_spawn_cell() -> Vector2i:
|
||||
return Vector2i(floor(map_width / 2.0), 1)
|
||||
|
||||
func get_bottom_spawn_cell() -> Vector2i:
|
||||
return Vector2i(floor(map_width / 2.0), map_height - 2)
|
||||
|
||||
func get_random_top_cell() -> Vector2i:
|
||||
var middle_height = floor(map_height / 2.0)
|
||||
var rand_width = randi_range(0, map_width - 1)
|
||||
var rand_height = randi_range(0, middle_height - 1)
|
||||
#set_cell(0, Vector2i(rand_width, rand_height), 1, Vector2i(0, 0), 0)
|
||||
return Vector2i(rand_width, rand_height)
|
Loading…
Add table
Add a link
Reference in a new issue