0 votes

Hey guys, I've read an interesting article about how movement in old zelda games was crafted, which in short used a half tile grid and four directions to move to, while moving in any of these directions the player was frame by frame aligned into the center of the grid cell in the direction of movement. So I took a stab at it and tried to come up with such a system myself. I used tilemap to create a grid and compared player vs cell position, but it came out quite buggy and not really usable (still had fun).

I just wanted to ask if any of you did something like this before or have an idea how this could work, or could suggest me a different approach for this particular thing, any help would be really appreciated.

The article : http://troygilbert.com/deconstructing-zelda/movement-mechanics/

My code:

extends KinematicBody2D

var GridTileMap
var PlayerSpeed = 50
var PlayerDirection = Vector2(0,0)
var Velocity
var PlayerPosition
var GridBoundaries
var ActiveGridCell
var CellSize
var HalfCellSize

func _ready():
    GridTileMap = get_node("../GridTileMap")
    GridBoundaries = GridTileMap.get_used_cells()
    CellSize = GridTileMap.get_cell_size()
    HalfCellSize = CellSize.x / 2

    func _process(delta):

ActiveGridCell = GridTileMap.world_to_map(PlayerPosition)
PlayerPosition = self.get_global_position()

if Input.is_action_pressed("ui_up"):
    PlayerDirection.y = -1
    if int(PlayerPosition.x) > int(ActiveGridCell.x * CellSize.x + HalfCellSize):
        self.global_position.x -= PlayerSpeed * delta
    elif int(PlayerPosition.x) < int(ActiveGridCell.x * CellSize.x + HalfCellSize):
        self.global_position.x += PlayerSpeed * delta
elif Input.is_action_pressed("ui_right"):
    PlayerDirection = Vector2(1,0)
    if int(PlayerPosition.y) > int(ActiveGridCell.y * CellSize.y + HalfCellSize):
        self.global_position.y -= PlayerSpeed * delta
    elif int(PlayerPosition.y) < int(ActiveGridCell.y * CellSize.y + HalfCellSize):
        self.global_position.y += PlayerSpeed * delta
elif Input.is_action_pressed("ui_down"):
    PlayerDirection = Vector2(0,1)
    if int(PlayerPosition.x) > int(ActiveGridCell.x * CellSize.x + HalfCellSize):
        self.global_position.x -= PlayerSpeed * delta
    elif int(PlayerPosition.x) < int(ActiveGridCell.x * CellSize.x + HalfCellSize):
        self.global_position.x += PlayerSpeed * delta
elif Input.is_action_pressed("ui_left"):
    PlayerDirection = Vector2(-1,0)
    if int(PlayerPosition.y) > int(ActiveGridCell.y * CellSize.y + HalfCellSize):
        self.global_position.y -= PlayerSpeed * delta
    elif int(PlayerPosition.y) < int(ActiveGridCell.y * CellSize.y + HalfCellSize):
        self.global_position.y += PlayerSpeed * delta
else:
    PlayerDirection = Vector2(0,0)

if PlayerDirection != Vector2(0,0):

    Velocity = PlayerDirection.normalized() * PlayerSpeed
    move_and_collide(Velocity * delta)
in Engine by (128 points)

2 Answers

+2 votes
Best answer

Godot have some really handy function called stepify and the Vector2/3 equivalent snapped, that allows to fit elements in a grid.

These methods can be called when motion ends, give-take some epsilon as distance from previous-next grid part.

by (7,832 points)
selected by
+1 vote

You might find this helpful:
http://kidscancode.org/blog/2018/01/godot3_inheritance/

It's an article I wrote on Godot's inheritance system, but the example game uses grid-based movement.

GDQuest also has an example here (done in Godot 2.1, but the concepts still apply): https://www.youtube.com/watch?v=A7xcmDeIoLY

by (19,645 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.