Working conveyors
This commit is contained in:
parent
12136bacf6
commit
d46e98dda0
|
|
@ -10,6 +10,7 @@ export default class Game {
|
|||
private world;
|
||||
private ui;
|
||||
private prevWorldPos: Point | null = null;
|
||||
private prevFrame: number = performance.now();
|
||||
|
||||
constructor(private canvas: HTMLCanvasElement, controls: HTMLElement) {
|
||||
window.addEventListener('resize', this.onResize);
|
||||
|
|
@ -108,7 +109,11 @@ export default class Game {
|
|||
}
|
||||
|
||||
private loop = () => {
|
||||
this.world.update();
|
||||
const now = performance.now();
|
||||
const dt = now - this.prevFrame;
|
||||
this.prevFrame = now;
|
||||
|
||||
this.world.update(dt);
|
||||
|
||||
this.graphics.clear();
|
||||
|
||||
|
|
|
|||
|
|
@ -52,5 +52,9 @@ export const renderers: Renderers = {
|
|||
ctx.fillRect(0.8, 0.2, 0.2, 0.6);
|
||||
}
|
||||
}
|
||||
if (tile.resource) {
|
||||
ctx.fillStyle = 'blue';
|
||||
ctx.fillText(tile.resource.toString(2), 0.5, 0.65);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -141,6 +141,13 @@ export const DIRECTION_VECTORS: Record<Direction, Point> = {
|
|||
[Direction.WEST]: [-1, 0],
|
||||
[Direction.EAST]: [1, 0],
|
||||
};
|
||||
export const NEXT_DIRECTION: Record<Direction, Direction> = {
|
||||
[Direction.NONE]: Direction.NONE,
|
||||
[Direction.NORTH]: Direction.EAST,
|
||||
[Direction.SOUTH]: Direction.WEST,
|
||||
[Direction.WEST]: Direction.NORTH,
|
||||
[Direction.EAST]: Direction.SOUTH,
|
||||
};
|
||||
export const ALL_DIRECTIONS = [Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST];
|
||||
export const movePoint = (point: Point, direction: Direction): Point => [
|
||||
point[0] + DIRECTION_VECTORS[direction][0],
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ALL_DIRECTIONS, Direction, cyrb32, exp, getDirection, getOppositeDirection, movePoint, pointsEquals, trunc } from "./utils";
|
||||
import { ALL_DIRECTIONS, Direction, NEXT_DIRECTION, cyrb32, exp, getDirection, getOppositeDirection, movePoint, pointsEquals, trunc } from "./utils";
|
||||
|
||||
export enum TileType {
|
||||
DESTINATION,
|
||||
|
|
@ -16,13 +16,15 @@ type Resource = number;
|
|||
|
||||
interface Port {
|
||||
direction: PortDirection;
|
||||
buffer?: Resource;
|
||||
}
|
||||
|
||||
type Ports = Partial<Record<Direction, Port>>;
|
||||
|
||||
interface BaseTile {
|
||||
ports: Ports;
|
||||
nextOutput?: Direction;
|
||||
resource?: Resource;
|
||||
timer?: number;
|
||||
}
|
||||
|
||||
interface TileDestination extends BaseTile {
|
||||
|
|
@ -47,8 +49,25 @@ interface TileConveyor extends BaseTile {
|
|||
export type Tile = TileDestination | TileSource | TileExtractor | TileConveyor;
|
||||
|
||||
const id = (point: Point) => ((Math.floor(point[0]) & 0xFFFF) << 16) | Math.floor(point[1]) & 0xFFFF;
|
||||
const deid = (pid: number): Point => [(pid >> 16) & 0xFFFF, pid & 0xFFFF];
|
||||
|
||||
export const getPortDirections = (ports: Partial<Record<Direction, any>>) => Object.keys(ports).map(k => +k as Direction);
|
||||
export const getPortDirections = (ports: Ports) => Object.keys(ports).map(k => +k as Direction);
|
||||
|
||||
const findNextOutput = (ports: Ports, prevDirection?: Direction): Direction => {
|
||||
const outputs = getPortDirections(ports).filter(d => d && ports[d]?.direction === PortDirection.OUTPUT);
|
||||
if (outputs.length === 0) return Direction.NONE;
|
||||
|
||||
if (prevDirection) {
|
||||
let nextDirection = NEXT_DIRECTION[prevDirection];
|
||||
while (nextDirection !== prevDirection) {
|
||||
if (outputs.includes(nextDirection)) break;
|
||||
nextDirection = NEXT_DIRECTION[nextDirection]
|
||||
}
|
||||
return nextDirection;
|
||||
} else {
|
||||
return outputs[0];
|
||||
}
|
||||
}
|
||||
|
||||
export default class World {
|
||||
private world = new Map<number, Tile>();
|
||||
|
|
@ -108,11 +127,11 @@ export default class World {
|
|||
if (existingTile?.type === TileType.SOURCE) {
|
||||
const ports: Ports = {};
|
||||
for (const direction of ALL_DIRECTIONS) {
|
||||
const oppositeDirection = getOppositeDirection(direction);
|
||||
const neighbourPos = movePoint(position, direction);
|
||||
const neighbour = this.getTile(neighbourPos);
|
||||
if (neighbour && !neighbour.ports[oppositeDirection]) {
|
||||
neighbour.ports[oppositeDirection] = { direction: PortDirection.INPUT };
|
||||
const [neighbour, oppositeDirection] = this.getNeighbour(position, direction);
|
||||
if (neighbour) {
|
||||
if (!neighbour.ports[oppositeDirection]) {
|
||||
neighbour.ports[oppositeDirection] = { direction: PortDirection.INPUT };
|
||||
}
|
||||
ports[direction] = { direction: PortDirection.OUTPUT };
|
||||
}
|
||||
}
|
||||
|
|
@ -141,22 +160,16 @@ export default class World {
|
|||
const pid = id(position);
|
||||
const existingTile = this.world.get(pid);
|
||||
const type = existingTile?.type;
|
||||
if (type === TileType.DESTINATION || type === TileType.SOURCE) {
|
||||
if (type === TileType.DESTINATION) {
|
||||
return;
|
||||
}
|
||||
if (existingTile) {
|
||||
for (const direction of getPortDirections(existingTile.ports)) {
|
||||
const oppositeDirection = getOppositeDirection(direction);
|
||||
const neighbourPos = movePoint(position, direction);
|
||||
const neighbour = this.getTile(neighbourPos);
|
||||
const [neighbour, oppositeDirection] = this.getNeighbour(position, direction);
|
||||
if (neighbour) {
|
||||
delete neighbour.ports[oppositeDirection];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (existingTile?.type === TileType.EXTRACTOR) {
|
||||
this.world.set(pid, existingTile.source);
|
||||
} else if (existingTile) {
|
||||
this.world.delete(pid);
|
||||
}
|
||||
}
|
||||
|
|
@ -175,20 +188,65 @@ export default class World {
|
|||
}
|
||||
|
||||
private genTile(position: Point): Tile | null {
|
||||
const pid = id(position);
|
||||
const hash = cyrb32(this.seed, ...position);
|
||||
|
||||
if ((hash & 0xFF) === 42) {
|
||||
const resource = (hash >> 12) & 0xF || 1;
|
||||
const newTile: Tile = { type: TileType.SOURCE, resource, ports: {} };
|
||||
this.world.set(pid, newTile);
|
||||
return newTile;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
update() {
|
||||
private get tiles() {
|
||||
return this.world.entries();
|
||||
}
|
||||
|
||||
private getNeighbour(position: Point, direction: Direction): [Tile | null, Direction] {
|
||||
const neighbourPosition = movePoint(position, direction);
|
||||
const neighbour = this.getTile(neighbourPosition);
|
||||
const oppositeDirection = getOppositeDirection(direction);
|
||||
|
||||
return [neighbour, oppositeDirection];
|
||||
}
|
||||
|
||||
update(dt: number) {
|
||||
for (const [pid, tile] of this.tiles) {
|
||||
const position = deid(pid);
|
||||
if (tile.timer && tile.timer > 0) {
|
||||
tile.timer -= dt;
|
||||
}
|
||||
|
||||
if (!tile.timer || tile.timer <= 0) {
|
||||
switch (tile.type) {
|
||||
case TileType.EXTRACTOR:
|
||||
case TileType.CONVEYOR:
|
||||
if (tile.resource) {
|
||||
tile.nextOutput = findNextOutput(tile.ports, tile.nextOutput);
|
||||
if (tile.nextOutput) {
|
||||
const [neighbour, oppositeDirection] = this.getNeighbour(position, tile.nextOutput);
|
||||
|
||||
if (neighbour?.ports[oppositeDirection]?.direction === PortDirection.INPUT && !neighbour.resource) {
|
||||
neighbour.resource = tile.resource;
|
||||
neighbour.timer = 300; // TODO remove hardcode
|
||||
tile.resource = undefined;
|
||||
tile.timer = 500;
|
||||
} else {
|
||||
tile.timer = 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tile.type === TileType.EXTRACTOR && !tile.resource) {
|
||||
tile.resource = tile.source.resource;
|
||||
}
|
||||
break;
|
||||
case TileType.DESTINATION:
|
||||
// TODO count gathered
|
||||
tile.resource = undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue