Skip to content

Conveyor

namespace Griff.Scenes;
public sealed class Conveyor : Component, IDrawable

Belts on a grid that carry items: a factory’s lines from machine to machine. Each cell of Belts points one way and holds one item at a time; items glide along at Speed cells a second (or a cell’s own speed, for a slow chute dropping onto a fast belt) while the cell ahead is free and wait when it isn’t, so a full end backs the line up. With a Spacing items glide on smoothly several to a cell, each that far behind the one ahead, and bunch up into a pile at a full end. A belt that runs into another’s side merges, the two taking turns; a Split cell hands items to the belts leading out of it in turn (by item, with Filters), and an Under cell lets a crossing line pass under it. At a belt’s end a ConveyorPort takes what arrives into a machine, and another puts what the machine makes onto a belt; a script can put items on, take them off and read any cell.

It lies on the cells of its Map (as a grid mover steps on them), so belts line up with the floor and the walls. Items move in fixed steps of game time, so a line plays out the same at any game speed, sped up with Time.FastForward or Time.Scale. Its items are drawn by the conveyor itself, a quad or an image each, so hundreds cost no more than the sprites they look like. While it’s Solid, belts and splitters are walls to grid movers (WalkTo goes round them), and crossings and unders aren’t. It’s saved with the scene, items too, so it rewinds with everything else; in a network game the host moves the items and the players see them.

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

public Color BeltColor { get; set; }

The color ShowBelts draws belts in; its arrows are lighter.

public string? BeltTiles { get; set; }

A tilemap (a layer of its own, say) whose animated tiles are belts: they step with this conveyor’s items instead of with time, a run’s frames making up one cell of travel, so belt art moves as fast as the items and stops with the line.

public IReadOnlyList<string> Belts { get; set; }

Its cells, one a row: the column and row (counted as a tilemap’s are, row 0 at the top), the way it carries (right, left, up or down) and, for one that isn’t a plain belt, crossing or split, e.g. “4 2 right”, “5 2 right crossing”, “9 2 down split”. A number after the way is the cell’s own speed in cells a second, for a slow chute or a fast run in the same line: “4 2 right 0.5”, “9 2 down split 3”. Lay them from a script with Lay and LayPath, and set speeds with SetSpeed and SetRunSpeed.

public IReadOnlyList<ConveyorCell> Cells { get; }

Its cells, in the order they were laid.

public IReadOnlyList<ValueTuple<int, int, string>> Contents { get; }

Every item on it and its cell, in the order the cells were laid (the one furthest on first, with several on a cell).

public int Count { get; }

How many items are on it.

public IReadOnlyList<string> Filters { get; set; }

What a splitter sends onto each belt leading out of it, one a row: that belt’s column and row and the items, e.g. “10 4 Deck, Box”. An item goes to the belts whose filter names it (“Deck” lets “Deck 17” by), else to those with none, in turn; one with nowhere to go waits in the splitter’s middle. Set them from a script with Filter.

public GridCells Grid { get; }

The cells it lies on (see Map).

public Color ItemColor { get; set; }

The color an item is drawn in when ItemImages has nothing for it.

public IReadOnlyList<string> ItemImages { get; set; }

What items look like, one a row: the item, a colon, and an image (relative to Assets) or a color, e.g. “Deck: Sprites/deck.png”, “Report: #FFA300”. An item not named here uses its first word’s (“Deck 17” looks like “Deck”), else ItemColor.

public float ItemSize { get; set; }

How big an item is drawn, as a share of a cell.

public IReadOnlyList<string> Items { get; set; }

What’s on it, one a row: the cell’s column and row and the item, e.g. “4 2 Deck”. Set it to start with items on the belts; the game keeps it up to date as they move. With a Spacing a cell can hold several, and one between cells’ middles has a part column or row: “4.25 2 Deck” is a quarter cell right of (4, 2)’s middle.

public string? Layer { get; set; }

The collision layer its belts are on, like a collider’s: a grid mover with Blocking Layers is stopped only by the layers it names, e.g. “Obstacle”. Empty is “Default”.

public string? Map { get; set; }

The tilemap whose cells it lies on. Empty uses the tilemap on its own entity or the one it’s inside, else the first in the scene; with none, cells are world units centered on whole numbers, as for a grid mover.

public bool MovingArrows { get; set; }

Slides ShowBelts’ arrows along with the items while the line runs, so the belts look like they move.

public int Order { get; set; }

Higher draws on top, like Order.

public IReadOnlyList<ValueTuple<int, int, string, Vector2>> Positions { get; }

Every item on it, its cell and where it is in the world now, in the order Contents lists them.

public bool Running { get; set; }

While ticked, items move and ports take and put; untick it (or switch it off) to stop the line where it is.

public bool ShowBelts { get; set; }

Draws each cell as a plain belt with an arrow the way it carries (crossings lighter, splitters with two arrows), for a line with no art of its own yet. Untick it when a tilemap draws the belts.

public bool Solid { get; set; }

Belts and splitters are walls to grid movers, as solid colliders are: one walking somewhere goes round them, and crosses at a crossing. Untick it to let them walk over every belt.

public bool SortByY { get; set; }

Sorts each item by its own height, when the camera sorts by Y: an item lower down the screen is drawn in front of a worker standing behind it.

public float Spacing { get; set; }

How close an item follows the one ahead, in cells, up to 1: with 0.25 a belt carries up to four items a cell, gliding on smoothly while there’s room ahead and closing up a quarter cell apart behind a full end, a pile you can see. 0 keeps one item a cell, each waiting in its cell’s middle until the cell ahead is free.

public float Speed { get; set; }

Cells an item moves a second, up to one a step of the game: every cell’s but those with a speed of their own (a number in its Belts row). An item crossing from a cell of one speed into another’s changes speed at the edge between them.

public bool BlocksWalking(ValueTuple<int, int> cell)

True if a belt or splitter (not a crossing or an under) is at the cell: what stops a grid mover while it’s Solid.

public ConveyorCell? CellAt(int x, int y)

The cell at column x, row y, or null if there’s none.

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

The cell a world position is in.

public void Clear()

Takes up every cell, and the items on them.

public void Filter(int x, int y, string? items)

Sets what the splitter behind the belt at column x, row y sends onto it, e.g. “Deck, Box” (see Filters); null or empty takes the filter off.

public string? FilterAt(int x, int y)

The items the splitter behind the belt at column x, row y sends onto it, or null for any.

public Tilemap? FindMap()

The tilemap whose cells it lies on (see Map), or null for world units.

public bool IsWaiting(int x, int y)

True if an item on the cell has reached its middle and couldn’t move on: the line is backed up there, or it’s at an end with nothing taking it.

public string? ItemAt(int x, int y)

The item on the cell at column x, row y (the one furthest on, with several), or null.

public Vector2? ItemPosition(int x, int y)

Where the item on the cell (the one furthest on, with several) is in the world now (it glides from cell to cell), or null if there’s none.

public IReadOnlyList<string> ItemsAt(int x, int y)

The items on the cell at column x, row y, the one furthest on first.

public void Lay(IEnumerable<ConveyorCell> cells)

Lays cells all at once (each as Lay does, turning a cell already there, which keeps its speed unless the new one has one): a line from a LineTool, gaps and all.

public void Lay(ValueTuple<int, int> cell, ValueTuple<int, int> way, ConveyorCellKind kind = ConveyorCellKind.Belt)

Lays a cell at cell carrying way (see Lay).

public void Lay(int x, int y, int wayX, int wayY, ConveyorCellKind kind = ConveyorCellKind.Belt)

Lays a cell at column x, row y carrying the way (wayX, wayY): (1, 0) right, (0, 1) up, (-1, 0) left, (0, -1) down. A cell already there is turned (an item on it stays, and its speed).

public void LayPath(IReadOnlyList<ValueTuple<int, int>> points, ConveyorCellKind kind = ConveyorCellKind.Belt, ValueTuple<int, int>? lastWay = default, float speed = 0f)

Lays a belt through points, each cell carrying on to the next: between two points that aren’t next to each other it goes along the row first, then up or down the column, so the corners of a line are its points, e.g. LayPath([(2, 4), (9, 4), (9, 8)]). The last cell carries on the way the one before it does (or lastWay). Cells already there are turned to follow it. With a speed every cell of it carries at that many cells a second (a slow chute, a fast belt); 0 keeps their speeds, the conveyor’s Speed for new ones.

public bool Put(int x, int y, string item)

Puts item in the middle of the cell at column x, row y, to move on from there: false if there’s no belt there, something’s on it, or the item that just left it isn’t a cell away yet (with a Spacing: an item is nearer its middle than that).

public string? Remove(int x, int y)

Takes up the cell at column x, row y: returns the item that was on it, if any.

public IReadOnlyList<ValueTuple<int, int>> RunThrough(int x, int y)

The run through the cell at column x, row y, from its first cell to its last: the cells leading into it and on from it one to one, up to a splitter, a merge, or a cell going at another speed.

public int SetRunSpeed(int x, int y, float speed)

Gives the run through the cell at column x, row y a speed of its own (see SetSpeed): the cells leading into it and on from it one to one, up to a splitter, a merge, or a cell going at another speed than it does. Returns how many cells that was.

public int SetSpeed(IEnumerable<ValueTuple<int, int>> cells, float speed)

Gives each of cells a speed of its own (see SetSpeed): returns how many there were.

public bool SetSpeed(int x, int y, float speed)

Gives the cell at column x, row y a speed of its own, in cells a second (0 for the conveyor’s Speed again): false if there’s no cell there. An item on it goes on from where it is.

public float SpeedAt(int x, int y)

Cells a second the cell at column x, row y carries items at: its own speed, else the conveyor’s Speed; 0 if there’s no cell there.

public string? Take(int x, int y)

Takes the item off the cell at column x, row y (the one furthest on, with several): returns it, or null if there was none.

public event Action<Conveyor, ValueTuple<int, int>, string>? ReachedEnd

Raised once the step is over for each item that reached the end of a belt with nothing there to take it: its cell and the item. It waits there, holding the line up, until something takes it (Take).