Learn You a Game Jam 2024 - Day 2


This is a Blog daily update for Learn You a Game Jam 2024

Goal of Day: Player movement control system

Video footage: https://www.twitch.tv/videos/2177846863

I started by copying the continuous movement control from the Creeps tutorial, but I wanted to alter it into tile-based movement, such that the player can move up, left, down or right from tile to tile only. Similar to Mystery Dungeon or grid-based Tactics games. It took me quite a while to get right, as I ran into various race conditions. Here's the current state:

extends Node2D
@onready var tile_map = $"../TileMap"
var MOVEMENT_SPEED = 8
var grid_position = Vector2.ZERO
var action_lock = false
var current_movement = null
var movement_queue = []
func _ready():
    position = tile_map.map_to_local(grid_position)
func _input(event):
    if event is InputEventKey and event.is_action_type():
        if event.is_pressed():
            # Add the movement to the queue if not already present
            if Input.is_action_pressed("left") and "left" not in movement_queue:
                movement_queue.append("left")
            elif Input.is_action_pressed("right") and "right" not in movement_queue:
                movement_queue.append("right")
            elif Input.is_action_pressed("up") and "up" not in movement_queue:
                movement_queue.append("up")
            elif Input.is_action_pressed("down") and "down" not in movement_queue:
                movement_queue.append("down")
        else:
            # Remove the movement from the queue if key is released
            if not Input.is_action_pressed("left") and "left" in movement_queue:
                movement_queue.erase("left")
            if not Input.is_action_pressed("right") and "right" in movement_queue:
                movement_queue.erase("right")
            if not Input.is_action_pressed("up") and "up" in movement_queue:
                movement_queue.erase("up")
            if not Input.is_action_pressed("down") and "down" in movement_queue:
                movement_queue.erase("down")
        # Start movement if not busy
        if not action_lock:
            handle_movement()
func handle_movement():
    if action_lock or not movement_queue:
        return
    current_movement = movement_queue[-1]
    action_lock = true
    update_grid_position(current_movement)
    if $AnimationPlayer.current_animation != current_movement:
        $AnimationPlayer.play(current_movement)
    var destination = tile_map.map_to_local(grid_position)
    var tween = create_tween()
    tween.tween_property(self, "position", destination, 1.0 / MOVEMENT_SPEED)
    tween.connect("finished", self._on_tween_finished)
func update_grid_position(direction):
    match direction:
        "left":
            grid_position.x -= 1
        "right":
            grid_position.x += 1
        "up":
            grid_position.y -= 1
        "down":
            grid_position.y += 1
func _on_tween_finished():
    $AnimationPlayer.pause()
    action_lock = false
    if movement_queue:
        handle_movement()

We use the concept of a Tween (something new I learned), which shifts the player's start position to a neighbouring tile position over a specified amount of time. And when _on_tween_finished() is called, we release the lock and are ready to accept new input from the user.

The movement_queue is used to keep track of what the most recent button held down was. Reason being, that if a user presses LEFT, then presses UP a short time before letting go of LEFT, then there is a brief period of time where both LEFT and UP are being held simultaneously. In that scenario, as a gamer I would rather have the character go UP, because it was most recently pressed and most likely to be my intended direction.

Maybe it was overkill to do it this way, as ultimately if I go for a turn-based game I might end up discarding some of this logic. But I did reach the goal of having the player move around smoothly, and having the walking animation loop nicely whilst he walks.


Leave a comment

Log in with itch.io to leave a comment.