Skip to content

GridMovement

namespace Griff.Scenes;
public sealed class GridMovement : Component

Steps tile by tile with no code, for puzzle games, roguelikes and old-school RPGs: as a player, each press of WASD, the arrow keys, the D-pad or the stick moves it one cell of the scene’s Tilemap, gliding there over StepTime, and holding a way keeps it walking. Solid tiles, solid colliders and other grid movers block it (it turns to face them instead). It starts on the middle of the cell it’s placed in. Plays its Animation’s Idle and Walk (or Run) clips if it has them (and IdleUp, WalkDown and so on, facing that way). Needs a Body and a collider, so pickups, doors and damage reach it; it ignores gravity. With a GridChase or a GridPatrol it’s an enemy or another mover instead, stepping on its own; with a Pushable it’s a crate that grid movers push a cell at a time by stepping into it. WalkTo (or its Destination) walks it to a cell, the nearest free one of several, or an entity, round walls and other movers: workers, villagers, units sent somewhere. On an isometric map it steps from diamond to diamond: up goes up to the right, right down to the right, down down to the left and left up to the left, and two ways held together go that way on the screen (with Diagonal, every way pressed goes that way on the screen). On a hex map it steps from hexagon to hexagon, six ways: left and right along the row, up or down with left or right held to the hexagon up or down that side, and up or down alone zigzagging straight up or down the screen.

This is a component: its saved properties are on its component page.

public string? ArrivedMessage { get; set; }

A message sent with Game.Send when a walk gets to its Destination, with this entity as its data.

public string? BlockedMessage { get; set; }

A message sent with Game.Send each time a walk has to stop and wait (see Blocked), with this entity as its data.

public string? BlockingLayers { get; set; }

Collision layers whose solid colliders are in its way, e.g. “Obstacle, Wall”; empty for every solid collider. Solid tiles and other grid movers always are. It goes for a step as for a walk, so a walk plans round what really blocks it.

public string? BumpSound { get; set; }

A sound played on trying to step into a wall, once per press.

public ValueTuple<int, int> Cell { get; }

The cell it’s in, or heading into while it moves: column then row on its Map, row 0 at the top (on no map, its whole-number position).

public bool Controllable { get; set; }

Untick it (from a script, in a cutscene) to ignore the player’s input; Step still works. Something with a GridChase, a GridPatrol or a Pushable never takes the player’s input. Its Focus action ticks it and unticks it on everything else the player plays (a board, another character).

public string? Destination { get; set; }

Where it’s walking to (see WalkTo): cells, as “column row” pairs separated by semicolons and counted as Cell is, e.g. “4 2; 5 2”, of which it goes to the nearest that’s free; or an entity’s name, whose cell it walks to (or next to it, when something solid is there). Empty while it isn’t walking. The game empties it on arriving; set it to send it off.

public bool Diagonal { get; set; }

Steps diagonally too, when two ways are held. It never cuts a wall’s corner. A hex map’s six ways are all along its hexagons’ sides, so there it changes nothing.

public Vector2 Facing { get; set; }

The way it faces, one cell’s step as a unit vector (diagonals are (±1, ±1)): down to start with. Like Step’s ways, it’s along the grid: on an isometric map, (0, 1) faces up to the right, and on a hex map (1, 1) faces the hexagon up to the right and (0, 1) straight up the screen.

public bool FlipSprite { get; set; }

Flip its sprite to face left or right as it moves (art should face right).

public Vector2 From { get; }

Where the step under way (see Stepping) started, in the world.

public float GiveWay { get; set; }

Seconds a walk waits, face to face with another walker that’s waiting for it (two in a one-cell aisle), before one of them steps aside to a free cell off the other’s way and lets it by: the one later in the scene, unless only the other has somewhere to go.

public ValueTuple<int, int>? Goal { get; }

The cell of its Destination it’s heading for now (it changes as cells fill and free up); null when it has none.

public bool IsMoving { get; }

True while it’s gliding from one cell to the next.

public bool IsWaiting { get; }

True while a walk is held up: another mover is in its way, there’s no way to its Destination just now, or it has stepped aside to let another by.

public bool IsWalking { get; }

True while it’s walking to its Destination, waiting on the way included.

public string? Map { get; set; }

The tilemap whose cells it steps between. Empty uses the first tilemap in the scene (not a layer); with none, it steps a world unit at a time, between whole-number positions.

public bool Repeat { get; set; }

Holding a way keeps stepping that way. Untick it to step once per press.

public float RepeatDelay { get; set; }

Seconds a way has to be held, after the first step, before it keeps walking: 0 walks straight on, about 0.25 lets a puzzle’s careful single steps come easily.

public bool Started { get; }

True once it has snapped onto its grid (it does as it first runs, and again after Unplace): until then its Cell isn’t known yet.

public bool StayOnMap { get; set; }

Never steps off the edge of its Map, even where there’s no wall.

public string? StepSound { get; set; }

A sound played with each step, e.g. “Sounds/step.wav”.

public float StepTime { get; set; }

Seconds each step takes to glide from one cell to the next.

public bool Stepping { get; }

True while it’s taking a step from one cell to the next.

public ValueTuple<int, int> CellAt(Vector2 world)

The cell of its grid a world position is in (see Cell).

public Vector2 CellCenter(ValueTuple<int, int> cell)

The world position of the middle of a cell of its grid.

public Tilemap? FindMap()

The tilemap it steps on: the one its Map names (a layer’s map, if it names a layer), else the first in its scene that isn’t a layer. Null for none: it steps a world unit at a time.

public void PlaceOn(ValueTuple<int, int> cell, Vector2 facing)

Stands it still in cell facing facing, dropping the step it was on and any step asked for or pressed: for something putting the board back as it was (a puzzle’s undo). It doesn’t move the entity; move it to the cell’s middle first.

public void Step(int x, int y)

Steps one cell x across and y up (each -1, 0 or 1) once the step under way ends, as if the player pressed that way, even when it isn’t Controllable. Blocked like a press is. On a hex map, (1, 1) is the hexagon up to the right and (0, 1) the one above that keeps it heading straight up.

public void StopWalking()

Stops walking, in the cell it’s in or stepping into.

public void Unplace()

Drops the step it was on and any asked for, and snaps onto the cell it’s over when it next runs: for something that moved it outright (a dungeon’s stairs).

public void WalkTo(IEnumerable<ValueTuple<int, int>> cells)

Walks to the nearest of cells that’s free (column then row, as Cell counts them), a step at a time, the shortest way: four ways, or eight if it’s Diagonal, round solid tiles, solid colliders (on its BlockingLayers, if it has any) and the cells other grid movers are in or stepping into. It plans again at every cell as things move, waits for a mover in its way, and steps aside when two walkers meet head on. Raises Arrived there; Blocked while it waits.

public void WalkTo(ValueTuple<int, int> cell)

Walks to one cell (see WalkTo).

public void WalkTo(Entity target)

Walks to target’s cell, or next to it when it’s in the way there (it’s solid, or a grid mover), following it as it moves.

public void WalkTo(string? place)

Walks to place: cells as “column row” pairs, e.g. “4 2; 5 2” (the nearest that’s free), or an entity’s name. Empty stops it. See Destination.

public event Action<GridMovement, ValueTuple<int, int>>? Arrived

Raised when a walk gets to its Destination, with the cell it arrived in. The walk is over.

public event Action<GridMovement>? Blocked

Raised each time a walk has to stop and wait: another mover is in its way, or there’s no way to its Destination just now. It keeps trying, as things move, until it gets there or StopWalking.

public event Action<GridMovement, Vector2>? Bumped

Raised on trying to step into a wall or anything else solid, with the way it tried.

public event Action<GridMovement, Vector2>? Stepped

Raised as each step starts, with the way it’s going.