Tile placing
This commit is contained in:
parent
cdf915a779
commit
12136bacf6
|
|
@ -1,7 +1,7 @@
|
||||||
import Graphics from "./graphics";
|
import Graphics from "./graphics";
|
||||||
import UI from "./ui";
|
import UI from "./ui";
|
||||||
import World from "./world";
|
import World from "./world";
|
||||||
import { prevent } from "./utils";
|
import { pointsEquals, prevent } from "./utils";
|
||||||
|
|
||||||
export default class Game {
|
export default class Game {
|
||||||
private running = false;
|
private running = false;
|
||||||
|
|
@ -9,6 +9,7 @@ export default class Game {
|
||||||
private graphics;
|
private graphics;
|
||||||
private world;
|
private world;
|
||||||
private ui;
|
private ui;
|
||||||
|
private prevWorldPos: Point | null = null;
|
||||||
|
|
||||||
constructor(private canvas: HTMLCanvasElement, controls: HTMLElement) {
|
constructor(private canvas: HTMLCanvasElement, controls: HTMLElement) {
|
||||||
window.addEventListener('resize', this.onResize);
|
window.addEventListener('resize', this.onResize);
|
||||||
|
|
@ -42,7 +43,7 @@ export default class Game {
|
||||||
if (direction < 0) {
|
if (direction < 0) {
|
||||||
scale = 1.1;
|
scale = 1.1;
|
||||||
} else if (direction > 0) {
|
} else if (direction > 0) {
|
||||||
scale = 1/ 1.1;
|
scale = 1 / 1.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.graphics.applyScale(scale, [event.clientX, event.clientY]);
|
this.graphics.applyScale(scale, [event.clientX, event.clientY]);
|
||||||
|
|
@ -58,22 +59,37 @@ export default class Game {
|
||||||
private onMouseUp = (event: MouseEvent) => {
|
private onMouseUp = (event: MouseEvent) => {
|
||||||
this.canvas.style.cursor = 'default';
|
this.canvas.style.cursor = 'default';
|
||||||
this.mouseDown = false;
|
this.mouseDown = false;
|
||||||
|
this.prevWorldPos = null;
|
||||||
|
const mousePos: Point = [event.clientX, event.clientY];
|
||||||
|
const worldPos = this.graphics.screenToWorld(mousePos);
|
||||||
|
|
||||||
const pos = this.graphics.screenToWorld([event.clientX, event.clientY]);
|
if (event.button === 0 && this.ui.selectedTool.tileType != null) {
|
||||||
if (event.button === 0) {
|
const tileType = this.ui.selectedTool.tileType;
|
||||||
// this.world.placeTile(pos, TileType.CONVEYOR); TODO place selected tile from hotbar
|
this.world.placeTile(worldPos, tileType);
|
||||||
} else if (event.button === 2) {
|
} else if (event.button === 2) {
|
||||||
this.world.removeTile(pos);
|
this.world.removeTile(worldPos);
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
private onMouseMove = (event: MouseEvent) => {
|
private onMouseMove = (event: MouseEvent) => {
|
||||||
|
const mousePos: Point = [event.clientX, event.clientY];
|
||||||
|
const mouseDelta: Point = [event.movementX, event.movementY];
|
||||||
|
const worldPos = this.graphics.screenToWorld(mousePos);
|
||||||
|
|
||||||
if (this.mouseDown === 1) {
|
if (this.mouseDown === 1) {
|
||||||
this.canvas.style.cursor = 'grabbing';
|
this.canvas.style.cursor = 'grabbing';
|
||||||
this.graphics.pan([event.movementX, event.movementY]);
|
this.graphics.pan(mouseDelta);
|
||||||
|
} else if (this.mouseDown === 0 && this.ui.selectedTool.tileType != null) {
|
||||||
|
const tileType = this.ui.selectedTool.tileType;
|
||||||
|
this.world.placeTile(worldPos, tileType, this.prevWorldPos);
|
||||||
|
} else if (this.mouseDown === 2) {
|
||||||
|
this.world.removeTile(worldPos);
|
||||||
}
|
}
|
||||||
this.graphics.highlight([event.clientX, event.clientY])
|
if (!this.prevWorldPos || !pointsEquals(this.prevWorldPos, worldPos)) {
|
||||||
|
this.prevWorldPos = worldPos;
|
||||||
|
}
|
||||||
|
this.graphics.highlight(mousePos);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,6 +108,8 @@ export default class Game {
|
||||||
}
|
}
|
||||||
|
|
||||||
private loop = () => {
|
private loop = () => {
|
||||||
|
this.world.update();
|
||||||
|
|
||||||
this.graphics.clear();
|
this.graphics.clear();
|
||||||
|
|
||||||
this.graphics.drawGrid();
|
this.graphics.drawGrid();
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ export default class Graphics {
|
||||||
}
|
}
|
||||||
|
|
||||||
applyScale(scale: number, point: Point) {
|
applyScale(scale: number, point: Point) {
|
||||||
const newTileSize = Math.min(Math.max(this.tileSize * scale, 2), this.width / 2, this.height / 2);
|
const newTileSize = Math.min(Math.max(this.tileSize * scale, 16), this.width / 2, this.height / 2);
|
||||||
const realScale = newTileSize / this.tileSize;
|
const realScale = newTileSize / this.tileSize;
|
||||||
this.tileSize = newTileSize;
|
this.tileSize = newTileSize;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
import { type Tile, TileType } from "./world";
|
import { type Tile, TileType, getPortDirections, PortDirection } from "./world";
|
||||||
|
|
||||||
|
import extractorIcon from '../assets/img/extractor.png';
|
||||||
|
import { Direction, makeImage } from "./utils";
|
||||||
|
|
||||||
export type Renderer<T extends Tile> = (ctx: CanvasRenderingContext2D, tile: T) => void;
|
export type Renderer<T extends Tile> = (ctx: CanvasRenderingContext2D, tile: T) => void;
|
||||||
export type NullRenderer = (ctx: CanvasRenderingContext2D) => void;
|
export type NullRenderer = (ctx: CanvasRenderingContext2D) => void;
|
||||||
|
|
@ -7,6 +10,8 @@ type Renderers = {
|
||||||
[K in Tile['type']]: Renderer<Extract<Tile, { type: K }>>
|
[K in Tile['type']]: Renderer<Extract<Tile, { type: K }>>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const extractorImage = makeImage(extractorIcon);
|
||||||
|
|
||||||
export const renderers: Renderers = {
|
export const renderers: Renderers = {
|
||||||
[TileType.SOURCE]: (ctx, tile) => {
|
[TileType.SOURCE]: (ctx, tile) => {
|
||||||
ctx.fillStyle = '#bbffff7f';
|
ctx.fillStyle = '#bbffff7f';
|
||||||
|
|
@ -23,7 +28,29 @@ export const renderers: Renderers = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[TileType.EXTRACTOR]: (ctx, tile) => {
|
[TileType.EXTRACTOR]: (ctx, tile) => {
|
||||||
|
renderers[TileType.SOURCE](ctx, tile.source);
|
||||||
|
ctx.imageSmoothingEnabled = false;
|
||||||
|
ctx.drawImage(extractorImage, 0, 0, 1, 1);
|
||||||
},
|
},
|
||||||
[TileType.CONVEYOR]: (ctx, tile) => {
|
[TileType.CONVEYOR]: (ctx, tile) => {
|
||||||
|
ctx.fillStyle = 'lightgray';
|
||||||
|
ctx.fillRect(0.2, 0.2, 0.6, 0.6);
|
||||||
|
for (const direction of getPortDirections(tile.ports)) {
|
||||||
|
const portDirection = tile.ports[direction]?.direction;
|
||||||
|
if (portDirection === PortDirection.INPUT) {
|
||||||
|
ctx.fillStyle = 'lightgreen';
|
||||||
|
} else if (portDirection === PortDirection.OUTPUT) {
|
||||||
|
ctx.fillStyle = 'red';
|
||||||
|
}
|
||||||
|
if (direction === Direction.NORTH) {
|
||||||
|
ctx.fillRect(0.2, 0, 0.6, 0.2);
|
||||||
|
} else if (direction === Direction.SOUTH) {
|
||||||
|
ctx.fillRect(0.2, 0.8, 0.6, 0.2);
|
||||||
|
} else if (direction === Direction.WEST) {
|
||||||
|
ctx.fillRect(0, 0.2, 0.2, 0.6);
|
||||||
|
} else if (direction === Direction.EAST) {
|
||||||
|
ctx.fillRect(0.8, 0.2, 0.2, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -9,7 +9,7 @@ import conveyorIcon from '../assets/img/conveyor.png';
|
||||||
import extractorIcon from '../assets/img/extractor.png';
|
import extractorIcon from '../assets/img/extractor.png';
|
||||||
import trashIcon from '../assets/img/trash.png';
|
import trashIcon from '../assets/img/trash.png';
|
||||||
|
|
||||||
enum ToolType {
|
export enum ToolType {
|
||||||
SELECT,
|
SELECT,
|
||||||
EXTRACTOR,
|
EXTRACTOR,
|
||||||
CONVEYOR,
|
CONVEYOR,
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,20 @@
|
||||||
|
export enum Direction {
|
||||||
|
NONE,
|
||||||
|
NORTH,
|
||||||
|
EAST,
|
||||||
|
SOUTH,
|
||||||
|
WEST,
|
||||||
|
}
|
||||||
|
|
||||||
type Operand = Point | number;
|
type Operand = Point | number;
|
||||||
type Operation = (a: number, b: number) => number;
|
type Operation = (a: number, b: number) => number;
|
||||||
function op(a: Operand, b: Operand, fn: Operation): Operand {
|
function op(a: Operand, b: Operand, fn: Operation): Operand {
|
||||||
const aArray = Array.isArray(a);
|
const aArray = Array.isArray(a);
|
||||||
const bArray = Array.isArray(b);
|
const bArray = Array.isArray(b);
|
||||||
if (aArray) {
|
if (aArray) {
|
||||||
return (bArray ? a.map((x, i) => fn(x, b[i])): a.map((x) => fn(x, b))) as Point;
|
return (bArray ? a.map((x, i) => fn(x, b[i])) : a.map((x) => fn(x, b))) as Point;
|
||||||
}
|
}
|
||||||
return (bArray ? b.map((x) => fn(a, x)): fn(a, b)) as Point;
|
return (bArray ? b.map((x) => fn(a, x)) : fn(a, b)) as Point;
|
||||||
}
|
}
|
||||||
|
|
||||||
const operations: Record<string, [Operation, number]> = {
|
const operations: Record<string, [Operation, number]> = {
|
||||||
|
|
@ -89,6 +97,8 @@ export function exp(strings: TemplateStringsArray, ...args: Operand[]): Operand
|
||||||
export function trunc(input: Point): Point {
|
export function trunc(input: Point): Point {
|
||||||
return op(input, 0, (x) => Math.floor(x)) as Point;
|
return op(input, 0, (x) => Math.floor(x)) as Point;
|
||||||
}
|
}
|
||||||
|
const EPS = 0.001;
|
||||||
|
export const pointsEquals = (a: Point, b: Point) => Math.abs(a[0] - b[0]) < EPS && Math.abs(a[1] - b[1]) < EPS;
|
||||||
|
|
||||||
export const prevent = (e: Event) => (e.preventDefault(), false);
|
export const prevent = (e: Event) => (e.preventDefault(), false);
|
||||||
|
|
||||||
|
|
@ -105,3 +115,40 @@ export const cyrb32 = (seed: number, ...parts: number[]) => {
|
||||||
};
|
};
|
||||||
export const sinHash = (...data: number[]) => data.reduce((hash, n) => Math.sin((hash * 123.12 + n) * 756.12), 0) / 2 + 0.5;
|
export const sinHash = (...data: number[]) => data.reduce((hash, n) => Math.sin((hash * 123.12 + n) * 756.12), 0) / 2 + 0.5;
|
||||||
export const range = (size: number | string) => Object.keys((new Array(+size)).fill(0)).map(k => +k);
|
export const range = (size: number | string) => Object.keys((new Array(+size)).fill(0)).map(k => +k);
|
||||||
|
|
||||||
|
export const getDirection = (point: Point): Direction => {
|
||||||
|
const [x, y] = point;
|
||||||
|
const absX = Math.abs(x);
|
||||||
|
const absY = Math.abs(y);
|
||||||
|
if (absX === 0 && absY === 0) return Direction.NONE;
|
||||||
|
else if (absX > absY) return x < 0 ? Direction.WEST : Direction.EAST;
|
||||||
|
else if (absY > absX) return y < 0 ? Direction.NORTH : Direction.SOUTH;
|
||||||
|
else return Direction.NONE;
|
||||||
|
}
|
||||||
|
export const getOppositeDirection = (dir: Direction): Direction => {
|
||||||
|
switch (dir) {
|
||||||
|
case Direction.NORTH: return Direction.SOUTH;
|
||||||
|
case Direction.SOUTH: return Direction.NORTH;
|
||||||
|
case Direction.WEST: return Direction.EAST;
|
||||||
|
case Direction.EAST: return Direction.WEST;
|
||||||
|
default: return Direction.NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const DIRECTION_VECTORS: Record<Direction, Point> = {
|
||||||
|
[Direction.NONE]: [0, 0],
|
||||||
|
[Direction.NORTH]: [0, -1],
|
||||||
|
[Direction.SOUTH]: [0, 1],
|
||||||
|
[Direction.WEST]: [-1, 0],
|
||||||
|
[Direction.EAST]: [1, 0],
|
||||||
|
};
|
||||||
|
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],
|
||||||
|
point[1] + DIRECTION_VECTORS[direction][1],
|
||||||
|
];
|
||||||
|
|
||||||
|
export const makeImage = (src: string): HTMLImageElement => {
|
||||||
|
const image = new Image();
|
||||||
|
image.src = src;
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { cyrb32 } from "./utils";
|
import { ALL_DIRECTIONS, Direction, cyrb32, exp, getDirection, getOppositeDirection, movePoint, pointsEquals, trunc } from "./utils";
|
||||||
|
|
||||||
export enum TileType {
|
export enum TileType {
|
||||||
DESTINATION,
|
DESTINATION,
|
||||||
|
|
@ -7,24 +7,22 @@ export enum TileType {
|
||||||
CONVEYOR,
|
CONVEYOR,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Direction {
|
export enum PortDirection {
|
||||||
NONE,
|
INPUT,
|
||||||
NORTH,
|
OUTPUT
|
||||||
EAST,
|
|
||||||
SOUTH,
|
|
||||||
WEST,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Resource = number;
|
type Resource = number;
|
||||||
|
|
||||||
interface Port {
|
interface Port {
|
||||||
direction: Direction;
|
direction: PortDirection;
|
||||||
buffer?: Resource;
|
buffer?: Resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Ports = Partial<Record<Direction, Port>>;
|
||||||
|
|
||||||
interface BaseTile {
|
interface BaseTile {
|
||||||
outputs: Port[];
|
ports: Ports;
|
||||||
inputs: Port[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TileDestination extends BaseTile {
|
interface TileDestination extends BaseTile {
|
||||||
|
|
@ -32,7 +30,7 @@ interface TileDestination extends BaseTile {
|
||||||
center: boolean;
|
center: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TileSource {
|
interface TileSource extends BaseTile {
|
||||||
type: TileType.SOURCE;
|
type: TileType.SOURCE;
|
||||||
resource: Resource;
|
resource: Resource;
|
||||||
}
|
}
|
||||||
|
|
@ -50,36 +48,117 @@ 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;
|
||||||
|
|
||||||
|
export const getPortDirections = (ports: Partial<Record<Direction, any>>) => Object.keys(ports).map(k => +k as Direction);
|
||||||
|
|
||||||
export default class World {
|
export default class World {
|
||||||
private world = new Map<number, Tile>();
|
private world = new Map<number, Tile>();
|
||||||
constructor(private seed: number = Math.random() * 2e9) {
|
constructor(private seed: number = Math.random() * 2e9) {
|
||||||
|
|
||||||
for (let x = 0; x < 5; x++) {
|
for (let x = 0; x < 5; x++) {
|
||||||
for (let y = 0; y < 5; y++) {
|
for (let y = 0; y < 5; y++) {
|
||||||
const inputs: Port[] = [];
|
const ports: Ports = {};
|
||||||
if (y == 0) inputs.push({ direction: Direction.NORTH });
|
if (y == 0) ports[Direction.NORTH] = { direction: PortDirection.INPUT };
|
||||||
if (y == 4) inputs.push({ direction: Direction.SOUTH });
|
if (y == 4) ports[Direction.SOUTH] = { direction: PortDirection.INPUT };
|
||||||
if (x == 0) inputs.push({ direction: Direction.WEST });
|
if (x == 0) ports[Direction.WEST] = { direction: PortDirection.INPUT };
|
||||||
if (x == 4) inputs.push({ direction: Direction.EAST });
|
if (x == 4) ports[Direction.EAST] = { direction: PortDirection.INPUT };
|
||||||
|
|
||||||
this.placeTile([x - 2, y - 2], {
|
this.setTile([x - 2, y - 2], {
|
||||||
type: TileType.DESTINATION,
|
type: TileType.DESTINATION,
|
||||||
outputs: [],
|
ports,
|
||||||
inputs,
|
|
||||||
center: x == 2 && y == 2,
|
center: x == 2 && y == 2,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
placeTile(position: Point, tile: Tile) {
|
placeTile(position: Point, type: TileType, prevPosition: Point | null = null) {
|
||||||
// TODO select correct type
|
position = trunc(position);
|
||||||
|
if (prevPosition) {
|
||||||
|
prevPosition = trunc(prevPosition);
|
||||||
|
}
|
||||||
|
let tile: Tile | undefined;
|
||||||
|
const existingTile = this.getTile(position);
|
||||||
|
switch (type) {
|
||||||
|
case TileType.CONVEYOR:
|
||||||
|
if (prevPosition) {
|
||||||
|
const prevPositionTile = this.getTile(prevPosition);
|
||||||
|
const ports: Ports = {};
|
||||||
|
const direction = getDirection(exp`${position} - ${prevPosition}`);
|
||||||
|
const oppositeDirection = getOppositeDirection(direction);
|
||||||
|
|
||||||
|
if (prevPositionTile) {
|
||||||
|
if (!prevPositionTile.ports[direction]) {
|
||||||
|
prevPositionTile.ports[direction] = { direction: PortDirection.OUTPUT };
|
||||||
|
}
|
||||||
|
ports[oppositeDirection] = { direction: PortDirection.INPUT };
|
||||||
|
}
|
||||||
|
if (existingTile) {
|
||||||
|
if (!existingTile.ports[oppositeDirection]) {
|
||||||
|
existingTile.ports[oppositeDirection] = { direction: PortDirection.INPUT };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tile = {
|
||||||
|
type: TileType.CONVEYOR,
|
||||||
|
ports,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TileType.EXTRACTOR:
|
||||||
|
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 };
|
||||||
|
ports[direction] = { direction: PortDirection.OUTPUT };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tile = {
|
||||||
|
type: TileType.EXTRACTOR,
|
||||||
|
ports,
|
||||||
|
source: existingTile,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tile) {
|
||||||
|
this.setTile(position, tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private setTile(position: Point, tile: Tile) {
|
||||||
this.world.set(id(position), tile);
|
this.world.set(id(position), tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeTile(position: Point) {
|
removeTile(position: Point) {
|
||||||
// TODO restore correct type if needed
|
position = trunc(position);
|
||||||
this.world.delete(id(position));
|
const pid = id(position);
|
||||||
|
const existingTile = this.world.get(pid);
|
||||||
|
const type = existingTile?.type;
|
||||||
|
if (type === TileType.DESTINATION || type === TileType.SOURCE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (existingTile) {
|
||||||
|
for (const direction of getPortDirections(existingTile.ports)) {
|
||||||
|
const oppositeDirection = getOppositeDirection(direction);
|
||||||
|
const neighbourPos = movePoint(position, direction);
|
||||||
|
const neighbour = this.getTile(neighbourPos);
|
||||||
|
if (neighbour) {
|
||||||
|
delete neighbour.ports[oppositeDirection];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (existingTile?.type === TileType.EXTRACTOR) {
|
||||||
|
this.world.set(pid, existingTile.source);
|
||||||
|
} else if (existingTile) {
|
||||||
|
this.world.delete(pid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getTile(position: Point): Tile | null {
|
getTile(position: Point): Tile | null {
|
||||||
|
|
@ -89,16 +168,27 @@ export default class World {
|
||||||
if (tile) return tile;
|
if (tile) return tile;
|
||||||
|
|
||||||
if (Math.abs(x) >= 5 && Math.abs(y) >= 5) {
|
if (Math.abs(x) >= 5 && Math.abs(y) >= 5) {
|
||||||
const hash = cyrb32(this.seed, ...position);
|
return this.genTile(position);
|
||||||
|
|
||||||
if ((hash & 0xFF) === 42) {
|
|
||||||
const resource = (hash >> 12) & 0xF;
|
|
||||||
const newTile: Tile = { type: TileType.SOURCE, resource };
|
|
||||||
this.world.set(pid, newTile);
|
|
||||||
return newTile;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue