Working conveyors
This commit is contained in:
parent
12136bacf6
commit
d46e98dda0
|
|
@ -10,6 +10,7 @@ export default class Game {
|
||||||
private world;
|
private world;
|
||||||
private ui;
|
private ui;
|
||||||
private prevWorldPos: Point | null = null;
|
private prevWorldPos: Point | null = null;
|
||||||
|
private prevFrame: number = performance.now();
|
||||||
|
|
||||||
constructor(private canvas: HTMLCanvasElement, controls: HTMLElement) {
|
constructor(private canvas: HTMLCanvasElement, controls: HTMLElement) {
|
||||||
window.addEventListener('resize', this.onResize);
|
window.addEventListener('resize', this.onResize);
|
||||||
|
|
@ -108,7 +109,11 @@ export default class Game {
|
||||||
}
|
}
|
||||||
|
|
||||||
private loop = () => {
|
private loop = () => {
|
||||||
this.world.update();
|
const now = performance.now();
|
||||||
|
const dt = now - this.prevFrame;
|
||||||
|
this.prevFrame = now;
|
||||||
|
|
||||||
|
this.world.update(dt);
|
||||||
|
|
||||||
this.graphics.clear();
|
this.graphics.clear();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,5 +52,9 @@ export const renderers: Renderers = {
|
||||||
ctx.fillRect(0.8, 0.2, 0.2, 0.6);
|
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.WEST]: [-1, 0],
|
||||||
[Direction.EAST]: [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 ALL_DIRECTIONS = [Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST];
|
||||||
export const movePoint = (point: Point, direction: Direction): Point => [
|
export const movePoint = (point: Point, direction: Direction): Point => [
|
||||||
point[0] + DIRECTION_VECTORS[direction][0],
|
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 {
|
export enum TileType {
|
||||||
DESTINATION,
|
DESTINATION,
|
||||||
|
|
@ -16,13 +16,15 @@ type Resource = number;
|
||||||
|
|
||||||
interface Port {
|
interface Port {
|
||||||
direction: PortDirection;
|
direction: PortDirection;
|
||||||
buffer?: Resource;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ports = Partial<Record<Direction, Port>>;
|
type Ports = Partial<Record<Direction, Port>>;
|
||||||
|
|
||||||
interface BaseTile {
|
interface BaseTile {
|
||||||
ports: Ports;
|
ports: Ports;
|
||||||
|
nextOutput?: Direction;
|
||||||
|
resource?: Resource;
|
||||||
|
timer?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TileDestination extends BaseTile {
|
interface TileDestination extends BaseTile {
|
||||||
|
|
@ -47,8 +49,25 @@ interface TileConveyor extends BaseTile {
|
||||||
export type Tile = TileDestination | TileSource | TileExtractor | TileConveyor;
|
export type Tile = TileDestination | TileSource | TileExtractor | TileConveyor;
|
||||||
|
|
||||||
const id = (point: Point) => ((Math.floor(point[0]) & 0xFFFF) << 16) | Math.floor(point[1]) & 0xFFFF;
|
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 {
|
export default class World {
|
||||||
private world = new Map<number, Tile>();
|
private world = new Map<number, Tile>();
|
||||||
|
|
@ -108,11 +127,11 @@ export default class World {
|
||||||
if (existingTile?.type === TileType.SOURCE) {
|
if (existingTile?.type === TileType.SOURCE) {
|
||||||
const ports: Ports = {};
|
const ports: Ports = {};
|
||||||
for (const direction of ALL_DIRECTIONS) {
|
for (const direction of ALL_DIRECTIONS) {
|
||||||
const oppositeDirection = getOppositeDirection(direction);
|
const [neighbour, oppositeDirection] = this.getNeighbour(position, direction);
|
||||||
const neighbourPos = movePoint(position, direction);
|
if (neighbour) {
|
||||||
const neighbour = this.getTile(neighbourPos);
|
if (!neighbour.ports[oppositeDirection]) {
|
||||||
if (neighbour && !neighbour.ports[oppositeDirection]) {
|
|
||||||
neighbour.ports[oppositeDirection] = { direction: PortDirection.INPUT };
|
neighbour.ports[oppositeDirection] = { direction: PortDirection.INPUT };
|
||||||
|
}
|
||||||
ports[direction] = { direction: PortDirection.OUTPUT };
|
ports[direction] = { direction: PortDirection.OUTPUT };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -141,22 +160,16 @@ export default class World {
|
||||||
const pid = id(position);
|
const pid = id(position);
|
||||||
const existingTile = this.world.get(pid);
|
const existingTile = this.world.get(pid);
|
||||||
const type = existingTile?.type;
|
const type = existingTile?.type;
|
||||||
if (type === TileType.DESTINATION || type === TileType.SOURCE) {
|
if (type === TileType.DESTINATION) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (existingTile) {
|
if (existingTile) {
|
||||||
for (const direction of getPortDirections(existingTile.ports)) {
|
for (const direction of getPortDirections(existingTile.ports)) {
|
||||||
const oppositeDirection = getOppositeDirection(direction);
|
const [neighbour, oppositeDirection] = this.getNeighbour(position, direction);
|
||||||
const neighbourPos = movePoint(position, direction);
|
|
||||||
const neighbour = this.getTile(neighbourPos);
|
|
||||||
if (neighbour) {
|
if (neighbour) {
|
||||||
delete neighbour.ports[oppositeDirection];
|
delete neighbour.ports[oppositeDirection];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (existingTile?.type === TileType.EXTRACTOR) {
|
|
||||||
this.world.set(pid, existingTile.source);
|
|
||||||
} else if (existingTile) {
|
|
||||||
this.world.delete(pid);
|
this.world.delete(pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -175,20 +188,65 @@ export default class World {
|
||||||
}
|
}
|
||||||
|
|
||||||
private genTile(position: Point): Tile | null {
|
private genTile(position: Point): Tile | null {
|
||||||
const pid = id(position);
|
|
||||||
const hash = cyrb32(this.seed, ...position);
|
const hash = cyrb32(this.seed, ...position);
|
||||||
|
|
||||||
if ((hash & 0xFF) === 42) {
|
if ((hash & 0xFF) === 42) {
|
||||||
const resource = (hash >> 12) & 0xF || 1;
|
const resource = (hash >> 12) & 0xF || 1;
|
||||||
const newTile: Tile = { type: TileType.SOURCE, resource, ports: {} };
|
const newTile: Tile = { type: TileType.SOURCE, resource, ports: {} };
|
||||||
this.world.set(pid, newTile);
|
|
||||||
return newTile;
|
return newTile;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
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