Compare commits
2 Commits
e1ba738ea0
...
bfb4979c6b
| Author | SHA1 | Date |
|---|---|---|
|
|
bfb4979c6b | |
|
|
9a1fb9b655 |
|
|
@ -65,7 +65,10 @@ export class Stat<T = {}> extends Component<StatState & T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@component
|
@component
|
||||||
export class Health extends Stat {
|
export class Health extends Stat<{ damageTypes?: string[]; priority?: number }> {
|
||||||
|
get damageTypes(): readonly string[] { return this.state.damageTypes ?? []; }
|
||||||
|
get priority(): number { return this.state.priority ?? 0; }
|
||||||
|
|
||||||
@action
|
@action
|
||||||
kill() {
|
kill() {
|
||||||
this.set(0);
|
this.set(0);
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ export class CombatSystem extends System {
|
||||||
let random: Random | undefined;
|
let random: Random | undefined;
|
||||||
|
|
||||||
for (const [target] of world.query(Attacked)) {
|
for (const [target] of world.query(Attacked)) {
|
||||||
const health = target.get(Health);
|
const healths = target.getAll(Health).sort((a, b) => b.priority - a.priority);
|
||||||
if (!health) {
|
if (healths.length === 0) {
|
||||||
console.warn(`[CombatSystem] Target ${target.id} has no Health component`);
|
console.warn(`[CombatSystem] Target ${target.id} has no Health component`);
|
||||||
for (const attack of target.getAll(Attacked)) target.remove(attack);
|
for (const attack of target.getAll(Attacked)) target.remove(attack);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -116,14 +116,43 @@ export class CombatSystem extends System {
|
||||||
|
|
||||||
if (damageSum === 0) continue;
|
if (damageSum === 0) continue;
|
||||||
|
|
||||||
const wasAlive = health.value > 0;
|
let totalBefore = 0;
|
||||||
health.update(-damageSum);
|
for (const pool of healths) totalBefore += pool.value;
|
||||||
|
|
||||||
|
for (const hit of hitEvents) {
|
||||||
|
let remaining = hit.amount;
|
||||||
|
|
||||||
|
if (hit.damageType) {
|
||||||
|
for (const pool of healths) {
|
||||||
|
if (remaining <= 0) break;
|
||||||
|
if (pool.value <= 0) continue;
|
||||||
|
if (!pool.damageTypes.includes(hit.damageType)) continue;
|
||||||
|
const take = Math.min(pool.value, remaining);
|
||||||
|
pool.update(-take);
|
||||||
|
remaining -= take;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remaining > 0) {
|
||||||
|
for (const pool of healths) {
|
||||||
|
if (remaining <= 0) break;
|
||||||
|
if (pool.value <= 0) continue;
|
||||||
|
if (pool.damageTypes.length > 0) continue;
|
||||||
|
const take = Math.min(pool.value, remaining);
|
||||||
|
pool.update(-take);
|
||||||
|
remaining -= take;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const info of hitEvents) {
|
for (const info of hitEvents) {
|
||||||
target.emit('Combat.hit', info);
|
target.emit('Combat.hit', info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wasAlive && health.value <= 0 && lastHit) {
|
let totalAfter = 0;
|
||||||
|
for (const pool of healths) totalAfter += pool.value;
|
||||||
|
|
||||||
|
if (totalBefore > 0 && totalAfter <= 0 && lastHit) {
|
||||||
target.emit('Combat.killed', lastHit);
|
target.emit('Combat.killed', lastHit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import UI from "./ui";
|
||||||
import World from "./world";
|
import World from "./world";
|
||||||
import { pointsEquals } from "./utils";
|
import { pointsEquals } from "./utils";
|
||||||
import { prevent } from "@common/utils";
|
import { prevent } from "@common/utils";
|
||||||
|
import { type Point } from "@common/geometry";
|
||||||
|
|
||||||
export default class Binario {
|
export default class Binario {
|
||||||
private running = false;
|
private running = false;
|
||||||
|
|
@ -52,7 +53,7 @@ export default class Binario {
|
||||||
scale = 1 / 1.1;
|
scale = 1 / 1.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.graphics.applyScale(scale, [event.clientX, event.clientY]);
|
this.graphics.applyScale(scale, { x: event.clientX, y: event.clientY });
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +67,7 @@ export default class Binario {
|
||||||
this.canvas.style.cursor = 'default';
|
this.canvas.style.cursor = 'default';
|
||||||
this.mouseDown = false;
|
this.mouseDown = false;
|
||||||
this.prevWorldPos = null;
|
this.prevWorldPos = null;
|
||||||
const mousePos: Point = [event.clientX, event.clientY];
|
const mousePos: Point = { x: event.clientX, y: event.clientY };
|
||||||
const worldPos = this.graphics.screenToWorld(mousePos);
|
const worldPos = this.graphics.screenToWorld(mousePos);
|
||||||
|
|
||||||
if (event.button === 0 && this.ui.selectedTool.tileType != null) {
|
if (event.button === 0 && this.ui.selectedTool.tileType != null) {
|
||||||
|
|
@ -79,8 +80,8 @@ export default class Binario {
|
||||||
}
|
}
|
||||||
|
|
||||||
private onMouseMove = (event: MouseEvent) => {
|
private onMouseMove = (event: MouseEvent) => {
|
||||||
const mousePos: Point = [event.clientX, event.clientY];
|
const mousePos: Point = { x: event.clientX, y: event.clientY };
|
||||||
const mouseDelta: Point = [event.movementX, event.movementY];
|
const mouseDelta: Point = { x: event.movementX, y: event.movementY };
|
||||||
const worldPos = this.graphics.screenToWorld(mousePos);
|
const worldPos = this.graphics.screenToWorld(mousePos);
|
||||||
|
|
||||||
if (this.mouseDown === 1) {
|
if (this.mouseDown === 1) {
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,15 @@ import { defaultRenderer, renderPorts, renderResource, renderers, type NullRende
|
||||||
import { ALL_DIRECTIONS, Direction, exp, trunc } from "./utils";
|
import { ALL_DIRECTIONS, Direction, exp, trunc } from "./utils";
|
||||||
import type World from "./world";
|
import type World from "./world";
|
||||||
import { type Tile } from "./world";
|
import { type Tile } from "./world";
|
||||||
|
import { type Point, type Rect } from "@common/geometry";
|
||||||
|
|
||||||
const initialTileSize = 32;
|
const initialTileSize = 32;
|
||||||
|
|
||||||
export default class Graphics {
|
export default class Graphics {
|
||||||
private context: CanvasRenderingContext2D;
|
private context: CanvasRenderingContext2D;
|
||||||
private tileSize = initialTileSize;
|
private tileSize = initialTileSize;
|
||||||
private offset: Point = [0, 0];
|
private offset: Point = { x: 0, y: 0 };
|
||||||
private highlighted: Point = [0, 0];
|
private highlighted: Point = { x: 0, y: 0 };
|
||||||
private tooltip: [Point, string] | null = null;
|
private tooltip: [Point, string] | null = null;
|
||||||
|
|
||||||
constructor(private canvas: HTMLCanvasElement) {
|
constructor(private canvas: HTMLCanvasElement) {
|
||||||
|
|
@ -25,7 +26,7 @@ export default class Graphics {
|
||||||
}
|
}
|
||||||
|
|
||||||
get size(): Point {
|
get size(): Point {
|
||||||
return [this.canvas.width, this.canvas.height];
|
return { x: this.canvas.width, y: this.canvas.height };
|
||||||
}
|
}
|
||||||
|
|
||||||
applyScale(scale: number, point: Point) {
|
applyScale(scale: number, point: Point) {
|
||||||
|
|
@ -93,16 +94,15 @@ export default class Graphics {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.context.fillStyle = 'white';
|
this.context.fillStyle = 'white';
|
||||||
this.context.fillRect(...pos, maxWidth + 10, maxHeight + 3);
|
this.context.fillRect(pos.x, pos.y, maxWidth + 10, maxHeight + 3);
|
||||||
this.context.strokeStyle = 'black';
|
this.context.strokeStyle = 'black';
|
||||||
this.context.strokeRect(...pos, maxWidth + 10, maxHeight + 3);
|
this.context.strokeRect(pos.x, pos.y, maxWidth + 10, maxHeight + 3);
|
||||||
this.context.font = '16px';
|
this.context.font = '16px';
|
||||||
this.context.fillStyle = 'black';
|
this.context.fillStyle = 'black';
|
||||||
|
|
||||||
let y = pos[1] + 18;
|
let y = pos.y + 18;
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
const measure = this.context.measureText(line);
|
this.context.fillText(line, pos.x + 5, y);
|
||||||
this.context.fillText(line, pos[0] + 5, y);
|
|
||||||
y += 18;
|
y += 18;
|
||||||
}
|
}
|
||||||
this.context.restore();
|
this.context.restore();
|
||||||
|
|
@ -112,15 +112,15 @@ export default class Graphics {
|
||||||
drawGrid() {
|
drawGrid() {
|
||||||
this.context.beginPath();
|
this.context.beginPath();
|
||||||
this.context.strokeStyle = 'gray';
|
this.context.strokeStyle = 'gray';
|
||||||
let [x0, y0, x1, y1] = this.visibleWorld;
|
const vw = this.visibleWorld;
|
||||||
[x0, y0] = this.worldToScreen([x0, y0]);
|
const topLeft = this.worldToScreen({ x: vw.x, y: vw.y });
|
||||||
[x1, y1] = this.worldToScreen([x1, y1]);
|
const bottomRight = this.worldToScreen({ x: vw.x + vw.width, y: vw.y + vw.height });
|
||||||
|
|
||||||
for (let x = x0; x < x1; x += this.tileSize) {
|
for (let x = topLeft.x; x < bottomRight.x; x += this.tileSize) {
|
||||||
this.context.moveTo(x, 0);
|
this.context.moveTo(x, 0);
|
||||||
this.context.lineTo(x, this.height);
|
this.context.lineTo(x, this.height);
|
||||||
}
|
}
|
||||||
for (let y = y0; y < y1; y += this.tileSize) {
|
for (let y = topLeft.y; y < bottomRight.y; y += this.tileSize) {
|
||||||
this.context.moveTo(0, y);
|
this.context.moveTo(0, y);
|
||||||
this.context.lineTo(this.width, y);
|
this.context.lineTo(this.width, y);
|
||||||
}
|
}
|
||||||
|
|
@ -144,7 +144,7 @@ export default class Graphics {
|
||||||
|
|
||||||
// TODO skip drawing if outside screen
|
// TODO skip drawing if outside screen
|
||||||
const screenPosition = this.worldToScreen(trunc(position));
|
const screenPosition = this.worldToScreen(trunc(position));
|
||||||
this.context.translate(screenPosition[0], screenPosition[1]);
|
this.context.translate(screenPosition.x, screenPosition.y);
|
||||||
this.context.scale(this.tileSize, this.tileSize);
|
this.context.scale(this.tileSize, this.tileSize);
|
||||||
|
|
||||||
if (tile) {
|
if (tile) {
|
||||||
|
|
@ -160,11 +160,12 @@ export default class Graphics {
|
||||||
}
|
}
|
||||||
|
|
||||||
drawWorld(world: World) {
|
drawWorld(world: World) {
|
||||||
const [x0, y0, x1, y1] = this.visibleWorld;
|
const vw = this.visibleWorld;
|
||||||
|
const x0 = vw.x, y0 = vw.y, x1 = vw.x + vw.width, y1 = vw.y + vw.height;
|
||||||
const resourceTiles: [Point, Tile][] = [];
|
const resourceTiles: [Point, Tile][] = [];
|
||||||
for (let y = y0; y <= y1; y++) {
|
for (let y = y0; y <= y1; y++) {
|
||||||
for (let x = x0; x <= x1; x++) {
|
for (let x = x0; x <= x1; x++) {
|
||||||
const pos: Point = [x, y];
|
const pos: Point = { x, y };
|
||||||
const tile = world.getTile(pos);
|
const tile = world.getTile(pos);
|
||||||
if (tile) {
|
if (tile) {
|
||||||
let renderer = renderers[tile.type] as Renderer<Tile>;
|
let renderer = renderers[tile.type] as Renderer<Tile>;
|
||||||
|
|
@ -186,17 +187,18 @@ export default class Graphics {
|
||||||
}
|
}
|
||||||
|
|
||||||
get visibleWorld(): Rect {
|
get visibleWorld(): Rect {
|
||||||
const [x0, y0] = this.screenToWorld([0, 0]);
|
const p0 = this.screenToWorld({ x: 0, y: 0 });
|
||||||
const [x1, y1] = this.screenToWorld([this.width, this.height]);
|
const p1 = this.screenToWorld({ x: this.width, y: this.height });
|
||||||
|
const x0 = Math.floor(p0.x), y0 = Math.floor(p0.y);
|
||||||
return [Math.floor(x0), Math.floor(y0), Math.ceil(x1), Math.ceil(y1)];
|
const x1 = Math.ceil(p1.x), y1 = Math.ceil(p1.y);
|
||||||
|
return { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
worldToScreen(point: Point): Point {
|
worldToScreen(point: Point): Point {
|
||||||
return [
|
return {
|
||||||
point[0] * this.tileSize + this.offset[0],
|
x: point.x * this.tileSize + this.offset.x,
|
||||||
point[1] * this.tileSize + this.offset[1],
|
y: point.y * this.tileSize + this.offset.y,
|
||||||
];
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
screenToWorld(point: Point): Point {
|
screenToWorld(point: Point): Point {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ export const renderResource = (ctx: CanvasRenderingContext2D, view: ViewConfig,
|
||||||
const [timer, timerMax] = tile.inputAnimations?.get(direction) ?? [0, 1];
|
const [timer, timerMax] = tile.inputAnimations?.get(direction) ?? [0, 1];
|
||||||
const amount = timer / timerMax;
|
const amount = timer / timerMax;
|
||||||
|
|
||||||
const [x, y] = movePoint([0.5, 0.52], direction, amount);
|
const { x, y } = movePoint({ x: 0.5, y: 0.52 }, direction, amount);
|
||||||
|
|
||||||
ctx.strokeStyle = 'white';
|
ctx.strokeStyle = 'white';
|
||||||
ctx.lineWidth = px * 2;
|
ctx.lineWidth = px * 2;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { type Point } from "@common/geometry";
|
||||||
|
|
||||||
export enum Direction {
|
export enum Direction {
|
||||||
NONE,
|
NONE,
|
||||||
NORTH,
|
NORTH,
|
||||||
|
|
@ -13,13 +15,20 @@ export function isDirection(obj: any): obj is Direction {
|
||||||
|
|
||||||
type Operand = Point | number;
|
type Operand = Point | number;
|
||||||
type Operation = (a: number, b: number) => number;
|
type Operation = (a: number, b: number) => number;
|
||||||
|
|
||||||
|
function isPoint(v: Operand): v is Point {
|
||||||
|
return typeof v === 'object';
|
||||||
|
}
|
||||||
|
|
||||||
function op(a: Operand, b: Operand, fn: Operation): Operand {
|
function op(a: Operand, b: Operand, fn: Operation): Operand {
|
||||||
const aArray = Array.isArray(a);
|
if (isPoint(a)) {
|
||||||
const bArray = Array.isArray(b);
|
return isPoint(b)
|
||||||
if (aArray) {
|
? { x: fn(a.x, b.x), y: fn(a.y, b.y) }
|
||||||
return (bArray ? a.map((x, i) => fn(x, b[i])) : a.map((x) => fn(x, b))) as Point;
|
: { x: fn(a.x, b as number), y: fn(a.y, b as number) };
|
||||||
}
|
}
|
||||||
return (bArray ? b.map((x) => fn(a, x)) : fn(a, b)) as Point;
|
return isPoint(b)
|
||||||
|
? { x: fn(a as number, b.x), y: fn(a as number, b.y) }
|
||||||
|
: fn(a as number, b as number);
|
||||||
}
|
}
|
||||||
|
|
||||||
const operations: Record<string, [Operation, number]> = {
|
const operations: Record<string, [Operation, number]> = {
|
||||||
|
|
@ -99,14 +108,16 @@ export function exp(strings: TemplateStringsArray, ...args: Operand[]): Operand
|
||||||
|
|
||||||
return calcStack[0];
|
return calcStack[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trunc(input: Point): Point {
|
export function trunc(input: Point): Point {
|
||||||
return op(input, 0, (x) => Math.floor(x)) as Point;
|
return { x: Math.floor(input.x), y: Math.floor(input.y) };
|
||||||
}
|
}
|
||||||
|
|
||||||
const EPS = 0.001;
|
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 pointsEquals = (a: Point, b: Point) => Math.abs(a.x - b.x) < EPS && Math.abs(a.y - b.y) < EPS;
|
||||||
|
|
||||||
export const getDirection = (point: Point): Direction => {
|
export const getDirection = (point: Point): Direction => {
|
||||||
const [x, y] = point;
|
const { x, y } = point;
|
||||||
const absX = Math.abs(x);
|
const absX = Math.abs(x);
|
||||||
const absY = Math.abs(y);
|
const absY = Math.abs(y);
|
||||||
if (absX === 0 && absY === 0) return Direction.NONE;
|
if (absX === 0 && absY === 0) return Direction.NONE;
|
||||||
|
|
@ -114,6 +125,7 @@ export const getDirection = (point: Point): Direction => {
|
||||||
else if (absY > absX) return y < 0 ? Direction.NORTH : Direction.SOUTH;
|
else if (absY > absX) return y < 0 ? Direction.NORTH : Direction.SOUTH;
|
||||||
else return Direction.NONE;
|
else return Direction.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getOppositeDirection = (dir: Direction): Direction => {
|
export const getOppositeDirection = (dir: Direction): Direction => {
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case Direction.NORTH: return Direction.SOUTH;
|
case Direction.NORTH: return Direction.SOUTH;
|
||||||
|
|
@ -123,13 +135,15 @@ export const getOppositeDirection = (dir: Direction): Direction => {
|
||||||
default: return Direction.NONE;
|
default: return Direction.NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DIRECTION_VECTORS: Record<Direction, Point> = {
|
export const DIRECTION_VECTORS: Record<Direction, Point> = {
|
||||||
[Direction.NONE]: [0, 0],
|
[Direction.NONE]: { x: 0, y: 0 },
|
||||||
[Direction.NORTH]: [0, -1],
|
[Direction.NORTH]: { x: 0, y: -1 },
|
||||||
[Direction.SOUTH]: [0, 1],
|
[Direction.SOUTH]: { x: 0, y: 1 },
|
||||||
[Direction.WEST]: [-1, 0],
|
[Direction.WEST]: { x: -1, y: 0 },
|
||||||
[Direction.EAST]: [1, 0],
|
[Direction.EAST]: { x: 1, y: 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NEXT_DIRECTION: Record<Direction, Direction> = {
|
export const NEXT_DIRECTION: Record<Direction, Direction> = {
|
||||||
[Direction.NONE]: Direction.NONE,
|
[Direction.NONE]: Direction.NONE,
|
||||||
[Direction.NORTH]: Direction.EAST,
|
[Direction.NORTH]: Direction.EAST,
|
||||||
|
|
@ -137,8 +151,10 @@ export const NEXT_DIRECTION: Record<Direction, Direction> = {
|
||||||
[Direction.WEST]: Direction.NORTH,
|
[Direction.WEST]: Direction.NORTH,
|
||||||
[Direction.EAST]: Direction.SOUTH,
|
[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, scale: number = 1): Point => [
|
|
||||||
point[0] + DIRECTION_VECTORS[direction][0] * scale,
|
export const movePoint = (point: Point, direction: Direction, scale: number = 1): Point => ({
|
||||||
point[1] + DIRECTION_VECTORS[direction][1] * scale,
|
x: point.x + DIRECTION_VECTORS[direction].x * scale,
|
||||||
];
|
y: point.y + DIRECTION_VECTORS[direction].y * scale,
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { intHash } from "@common/utils";
|
import { intHash } from "@common/utils";
|
||||||
|
import { type Point } from "@common/geometry";
|
||||||
import { ALL_DIRECTIONS, Direction, NEXT_DIRECTION, exp, getDirection, getOppositeDirection, isDirection, movePoint, pointsEquals, trunc } from "./utils";
|
import { ALL_DIRECTIONS, Direction, NEXT_DIRECTION, exp, getDirection, getOppositeDirection, isDirection, movePoint, pointsEquals, trunc } from "./utils";
|
||||||
|
|
||||||
export enum TileType {
|
export enum TileType {
|
||||||
|
|
@ -110,8 +111,8 @@ interface TileBinaryLogic extends BaseTile {
|
||||||
|
|
||||||
export type Tile = TileDestination | TileSource | TileExtractor | TileConveyor | TileUnaryLogic | TileBinaryLogic;
|
export type Tile = TileDestination | TileSource | TileExtractor | TileConveyor | TileUnaryLogic | TileBinaryLogic;
|
||||||
|
|
||||||
const id = (point: Point) => ((Math.floor(point[0]) & 0xFFFF) << 16) | Math.floor(point[1]) & 0xFFFF;
|
const id = (point: Point) => ((Math.floor(point.x) & 0xFFFF) << 16) | Math.floor(point.y) & 0xFFFF;
|
||||||
const deid = (pid: number): Point => [(pid >> 16) & 0xFFFF, pid & 0xFFFF];
|
const deid = (pid: number): Point => ({ x: (pid >> 16) & 0xFFFF, y: pid & 0xFFFF });
|
||||||
|
|
||||||
const rid = (resource: Resource): number => {
|
const rid = (resource: Resource): number => {
|
||||||
const idPart = (resource.type & 0xFFFF) << 16;
|
const idPart = (resource.type & 0xFFFF) << 16;
|
||||||
|
|
@ -196,7 +197,7 @@ export default class World {
|
||||||
if (x == 0) ports[Direction.WEST] = { direction: PortDirection.INPUT };
|
if (x == 0) ports[Direction.WEST] = { direction: PortDirection.INPUT };
|
||||||
if (x == 4) ports[Direction.EAST] = { direction: PortDirection.INPUT };
|
if (x == 4) ports[Direction.EAST] = { direction: PortDirection.INPUT };
|
||||||
|
|
||||||
this.setTile([x - 2, y - 2], {
|
this.setTile({ x: x - 2, y: y - 2 }, {
|
||||||
type: TileType.DESTINATION,
|
type: TileType.DESTINATION,
|
||||||
ports,
|
ports,
|
||||||
center: x == 2 && y == 2,
|
center: x == 2 && y == 2,
|
||||||
|
|
@ -331,7 +332,7 @@ export default class World {
|
||||||
}
|
}
|
||||||
|
|
||||||
getTile(position: Point): Tile | null {
|
getTile(position: Point): Tile | null {
|
||||||
const [x, y] = position;
|
const { x, y } = position;
|
||||||
const pid = id(position);
|
const pid = id(position);
|
||||||
const tile = this.world.get(pid);
|
const tile = this.world.get(pid);
|
||||||
if (tile) return tile;
|
if (tile) return tile;
|
||||||
|
|
@ -344,11 +345,11 @@ export default class World {
|
||||||
}
|
}
|
||||||
|
|
||||||
private genTile(position: Point): Tile | null {
|
private genTile(position: Point): Tile | null {
|
||||||
const hash = intHash(this.seed, ...position);
|
const hash = intHash(this.seed, position.x, position.y);
|
||||||
|
|
||||||
if ([42, 69, 0x42, 0x69].includes(hash & 0xFF)) {
|
if ([42, 69, 0x42, 0x69].includes(hash & 0xFF)) {
|
||||||
let mask = 1;
|
let mask = 1;
|
||||||
const dist = Math.log10(Math.hypot(...position));
|
const dist = Math.log10(Math.hypot(position.x, position.y));
|
||||||
for (let i = 1; i < dist; i++) {
|
for (let i = 1; i < dist; i++) {
|
||||||
mask = (mask << 1) | 1;
|
mask = (mask << 1) | 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue