Arbitrary infinite factory size

This commit is contained in:
ducdat0507 2022-12-20 21:00:07 +07:00
parent 6b9a53685b
commit 4f496765a9
2 changed files with 243 additions and 242 deletions

View file

@ -10,7 +10,7 @@ import cursor from "./factory-components/cursor.jpg";
import square from "./factory-components/square.jpg"; import square from "./factory-components/square.jpg";
import { computed, ComputedRef, reactive, Ref, ref, watchEffect } from "vue"; import { computed, ComputedRef, reactive, Ref, ref, watchEffect } from "vue";
import { Direction } from "util/common"; import { Direction } from "util/common";
import { persistent } from "game/persistence"; import { Persistent, persistent, State } from "game/persistence";
import player from "game/player"; import player from "game/player";
import "./styles/factory.css"; import "./styles/factory.css";
import { globalBus } from "game/events"; import { globalBus } from "game/events";
@ -25,8 +25,8 @@ const day = 20;
// TODO: unhardcode stuff // TODO: unhardcode stuff
enum FactoryDirections { enum FactoryDirections {
Any, Any = "ANY",
None None = "NONE"
} }
type FactoryDirection = FactoryDirections | Direction; type FactoryDirection = FactoryDirections | Direction;
@ -76,8 +76,8 @@ function getDirection(dir: Direction) {
} }
const factorySize = { const factorySize = {
width: 50, width: 6,
height: 50 height: 6
}; };
const blockSize = 50; const blockSize = 50;
@ -128,7 +128,7 @@ const factory = createLayer(id, () => {
type FactoryCompNames = keyof typeof FACTORY_COMPONENTS; type FactoryCompNames = keyof typeof FACTORY_COMPONENTS;
type BuildableCompName = Exclude<FactoryCompNames, "cursor">; type BuildableCompName = Exclude<FactoryCompNames, "cursor">;
interface FactoryComponentProducers { interface FactoryComponentProducers extends Record<string, State> {
type: Exclude<BuildableCompName, "conveyor">; type: Exclude<BuildableCompName, "conveyor">;
consumptionStock: Record<string, number>; consumptionStock: Record<string, number>;
@ -136,7 +136,7 @@ const factory = createLayer(id, () => {
productionStock: Record<string, number>; productionStock: Record<string, number>;
ticksDone: number; ticksDone: number;
} }
interface FactoryComponentConveyor { interface FactoryComponentConveyor extends Record<string, State> {
type: "conveyor"; type: "conveyor";
directionOut: Direction; directionOut: Direction;
} }
@ -147,18 +147,18 @@ const factory = createLayer(id, () => {
name: string; name: string;
description: string; description: string;
// amount it consumes /** amount it consumes */
consumption: Record<string, number>; consumption: Record<string, number>;
// maximum stock of consumption /** maximum stock of consumption */
consumptionStock: Record<string, number>; consumptionStock: Record<string, number>;
// amount it produces /** amount it produces */
production: Record<string, number>; production: Record<string, number>;
// maximum stock of production /** maximum stock of production */
productionStock: Record<string, number>; productionStock: Record<string, number>;
// on produce, do something /** on produce, do something */
onProduce?: (times: number) => void; onProduce?: (times: number) => void;
// can it produce? (in addtion to the stock check) /** can it produce? (in addtion to the stock check) */
canProduce?: ComputedRef<boolean>; canProduce?: ComputedRef<boolean>;
} }
@ -202,14 +202,8 @@ const factory = createLayer(id, () => {
const isMouseHoverShown = ref(false); const isMouseHoverShown = ref(false);
const whatIsHovered = ref<FactoryCompNames | "">(""); const whatIsHovered = ref<FactoryCompNames | "">("");
const compSelected = ref<FactoryCompNames>("cursor"); const compSelected = ref<FactoryCompNames>("cursor");
const components: Ref<(FactoryComponent | null)[][]> = persistent( const components: Persistent<{ [key: string]: FactoryComponent }> = persistent({});
Array(factorySize.width) const compInternalData: Record<string, FactoryInternal> = {};
.fill(undefined)
.map(() => Array(factorySize.height).fill(null))
);
const compInternalData: (FactoryInternal | null)[][] = Array(factorySize.width)
.fill(undefined)
.map(() => Array(factorySize.height).fill(null));
// pixi // pixi
const app = new Application({ const app = new Application({
@ -219,31 +213,54 @@ const factory = createLayer(id, () => {
let spriteContainer = new Container(); let spriteContainer = new Container();
const movingBlocks = new Container(); const movingBlocks = new Container();
graphicContainer.zIndex = 1; spriteContainer.zIndex = 0;
movingBlocks.zIndex = 2; movingBlocks.zIndex = 1;
graphicContainer.zIndex = 2;
app.stage.addChild(graphicContainer, spriteContainer, movingBlocks); app.stage.addChild(graphicContainer, spriteContainer, movingBlocks);
app.stage.sortableChildren = true; app.stage.sortableChildren = true;
let loaded = false; let loaded = false;
globalBus.on("onLoad", async () => { globalBus.on("onLoad", async () => {
loaded = false; loaded = false;
spriteContainer.destroy({ spriteContainer.destroy({
children: true children: true
}); });
spriteContainer = new Container(); spriteContainer = new Container();
app.stage.addChild(spriteContainer); app.stage.addChild(spriteContainer);
for (const y of components.value.keys()) {
for (const x of components.value[y].keys()) { const floorGraphics = new Graphics();
const data = components.value[y][x]; floorGraphics.beginFill(0x70645d);
if (data === null) continue; floorGraphics.drawRect(
await addFactoryComp(x, y, data.type); -factorySize.width * blockSize,
-factorySize.height * blockSize,
factorySize.width * 2 * blockSize,
factorySize.height * 2 * blockSize
);
floorGraphics.endFill();
spriteContainer.addChild(floorGraphics);
// load every sprite here so pixi doesn't complain about loading multiple times
await Assets.load(Object.values(FACTORY_COMPONENTS).map(x => x.imageSrc));
if (Array.isArray(components.value)) components.value = {};
else
for (const id in components.value) {
const data = components.value[id];
console.log(id, data);
if (data?.type === undefined) {
delete components.value[id];
continue;
} }
const [x, y] = id.split("x").map(p => +p);
addFactoryComp(x, y, data.type);
} }
loaded = true; loaded = true;
}); });
window.internal = compInternalData; (window as any).internal = compInternalData;
window.comp = components; (window as any).comp = components;
window.blocks = movingBlocks; (window as any).blocks = movingBlocks;
let taskIsRunning = false; let taskIsRunning = false;
globalBus.on("update", async diff => { globalBus.on("update", async diff => {
@ -253,12 +270,12 @@ const factory = createLayer(id, () => {
// will change soon:tm: // will change soon:tm:
const tick = diff; const tick = diff;
// make them produce // make them produce
for (const y of components.value.keys()) { for (const id in components.value) {
for (const x of components.value[y].keys()) { const [x, y] = id.split("x").map(p => +p);
const data = components.value[y][x]; const data = components.value[id];
const compData = compInternalData[y][x]; const compData = compInternalData[id];
//console.log(compData, data) //console.log(compData, data)
if (data === null || compData === null) continue; if (data === undefined || compData === undefined) continue;
const factoryData = FACTORY_COMPONENTS[data.type]; const factoryData = FACTORY_COMPONENTS[data.type];
//debugger; //debugger;
if (data.type === "conveyor") { if (data.type === "conveyor") {
@ -273,18 +290,15 @@ const factory = createLayer(id, () => {
const dirAmt = directionToNum(data.directionOut); const dirAmt = directionToNum(data.directionOut);
if (dirType === "h") { if (dirType === "h") {
if (block.x <= block.lastX + dirAmt) { if (block.x <= block.lastX + dirAmt) {
// hit border const compBehind = compInternalData[x + dirAmt + "x" + y];
if ( const storedComp = components.value[x + dirAmt + "x" + y];
(dirAmt === -1 && x === 0) ||
(dirAmt === 1 && x === components.value[y].length - 1)
)
continue;
const compBehind = compInternalData[y][x + dirAmt];
const storedComp = components.value[y][x + dirAmt];
// empty spot // empty spot
if (compBehind === null) continue; if (compBehind === undefined) {
if (compBehind.type === "conveyor") { // just delete it
movingBlocks.removeChild(block.sprite);
compData.packages.splice(key, 1);
} else if (compBehind.type === "conveyor") {
// push it to the next conveyor, kill it from the // push it to the next conveyor, kill it from the
// curent conveyor // curent conveyor
block.lastX += dirAmt; block.lastX += dirAmt;
@ -307,18 +321,15 @@ const factory = createLayer(id, () => {
} }
} else { } else {
if (block.y <= block.lastY + dirAmt) { if (block.y <= block.lastY + dirAmt) {
// hit border const compBehind = compInternalData[x + "x" + (y + dirAmt)];
if ( const storedComp = components.value[x + "x" + (y + dirAmt)];
(dirAmt === -1 && y === 0) ||
(dirAmt === 1 && y === components.value.length - 1)
)
continue;
const compBehind = compInternalData[y + dirAmt][x];
const storedComp = components.value[y + dirAmt][x];
// empty spot // empty spot
if (compBehind === null) continue; if (compBehind === undefined) {
if (compBehind.type === "conveyor") { // just delete it
movingBlocks.removeChild(block.sprite);
compData.packages.splice(key, 1);
} else if (compBehind.type === "conveyor") {
// push it to the next conveyor, kill it from the // push it to the next conveyor, kill it from the
// curent conveyor // curent conveyor
block.lastY += dirAmt; block.lastY += dirAmt;
@ -333,8 +344,7 @@ const factory = createLayer(id, () => {
compData.packages.splice(key, 1); compData.packages.splice(key, 1);
} }
} else { } else {
const change = const change = dirAmt * Math.min(Math.abs(block.y - block.lastY), tick);
dirAmt * Math.min(Math.abs(block.y - block.lastY), tick);
block.y += change; block.y += change;
block.sprite.y += change * blockSize; block.sprite.y += change * blockSize;
} }
@ -364,30 +374,26 @@ const factory = createLayer(id, () => {
let xInc = 0; let xInc = 0;
//debugger; //debugger;
if ( if (
y < components.value.length - 1 && components.value[x + "x" + (y + 1)]?.type === "conveyor" &&
components.value[y + 1][x]?.type === "conveyor" && (compInternalData[x + "x" + (y + 1)] as FactoryInternalProducer)
(compInternalData[y + 1][x] as FactoryInternalProducer).startingFrom === .startingFrom === "up"
"up"
) { ) {
yInc = 1; yInc = 1;
} else if ( } else if (
y > 0 && components.value[x + "x" + (y - 1)]?.type === "conveyor" &&
components.value[y - 1][x]?.type === "conveyor" && (compInternalData[x + "x" + (y - 1)] as FactoryInternalProducer)
(compInternalData[y - 1][x] as FactoryInternalProducer).startingFrom === .startingFrom === "down"
"down"
) { ) {
yInc = -1; yInc = -1;
} else if ( } else if (
x < components.value[y].length - 1 && components.value[x + 1 + "x" + y]?.type === "conveyor" &&
components.value[y][x + 1]?.type === "conveyor" && (compInternalData[x + 1 + "x" + y] as FactoryInternalProducer).startingFrom ===
(compInternalData[y][x + 1] as FactoryInternalProducer).startingFrom ===
"right" "right"
) { ) {
xInc = 1; xInc = 1;
} else if ( } else if (
x > 0 && components.value[x - 1 + "x" + y]?.type === "conveyor" &&
components.value[y][x - 1]?.type === "conveyor" && (compInternalData[x - 1 + "x" + y] as FactoryInternalProducer).startingFrom ===
(compInternalData[y][x - 1] as FactoryInternalProducer).startingFrom ===
"left" "left"
) { ) {
xInc = -1; xInc = -1;
@ -406,7 +412,7 @@ const factory = createLayer(id, () => {
} }
// there is nothing to move // there is nothing to move
if (itemToMove === undefined) continue; if (itemToMove === undefined) continue;
const texture = await Assets.load(RESOURCES[itemToMove[0]]); const texture = Assets.get(RESOURCES[itemToMove[0]]);
const sprite = new Sprite(texture); const sprite = new Sprite(texture);
/* /*
@ -440,25 +446,27 @@ const factory = createLayer(id, () => {
}; };
( (
compInternalData[y + yInc][x + xInc] as FactoryInternalConveyor compInternalData[x + xInc + "x" + (y + yInc)] as FactoryInternalConveyor
).nextPackages.push(block); ).nextPackages.push(block);
movingBlocks.addChild(sprite); movingBlocks.addChild(sprite);
} }
} }
}
taskIsRunning = false; taskIsRunning = false;
}); });
async function addFactoryComp(x: number, y: number, type: BuildableCompName) { function addFactoryComp(x: number, y: number, type: BuildableCompName) {
if (x < -factorySize.width || x >= factorySize.width) return;
if (y < -factorySize.height || y >= factorySize.height) return;
const factoryBaseData = FACTORY_COMPONENTS[type]; const factoryBaseData = FACTORY_COMPONENTS[type];
const sheet = await Assets.load(factoryBaseData.imageSrc); const sheet = Assets.get(factoryBaseData.imageSrc);
const sprite = new Sprite(sheet); const sprite = new Sprite(sheet);
sprite.x = x * blockSize; sprite.x = x * blockSize;
sprite.y = y * blockSize; sprite.y = y * blockSize;
sprite.width = blockSize; sprite.width = blockSize;
sprite.height = blockSize; sprite.height = blockSize;
components.value[y][x] = { components.value[x + "x" + y] = {
type, type,
ticksDone: 0, ticksDone: 0,
directionIn: type === "conveyor" ? Direction.Right : undefined, directionIn: type === "conveyor" ? Direction.Right : undefined,
@ -477,7 +485,7 @@ const factory = createLayer(id, () => {
) )
} as FactoryComponent; } as FactoryComponent;
const isConveyor = type === "conveyor"; const isConveyor = type === "conveyor";
compInternalData[y][x] = { compInternalData[x + "x" + y] = {
type, type,
packages: isConveyor ? [] : undefined, packages: isConveyor ? [] : undefined,
nextPackages: isConveyor ? [] : undefined, nextPackages: isConveyor ? [] : undefined,
@ -486,7 +494,7 @@ const factory = createLayer(id, () => {
if (type === "conveyor") return true; if (type === "conveyor") return true;
if (!(factoryBaseData.canProduce?.value ?? true)) return false; if (!(factoryBaseData.canProduce?.value ?? true)) return false;
// this should NEVER be null // this should NEVER be null
const compData = components.value[y][x] as FactoryComponentProducers; const compData = components.value[x + "x" + y] as FactoryComponentProducers;
for (const [key, res] of Object.entries(compData.productionStock)) { for (const [key, res] of Object.entries(compData.productionStock)) {
// if the current stock + production is more than you can handle // if the current stock + production is more than you can handle
if ( if (
@ -510,14 +518,12 @@ const factory = createLayer(id, () => {
function updateGraphics() { function updateGraphics() {
app.resize(); app.resize();
graphicContainer.clear(); graphicContainer.clear();
// I honestly have no clue how this works // make (0, 0) the center of the screen
const calculatedX = mapOffset.x * blockSize; const calculatedX = mapOffset.x * blockSize + app.view.width / 2;
const calculatedY = mapOffset.y * blockSize; const calculatedY = mapOffset.y * blockSize + app.view.height / 2;
movingBlocks.x = calculatedX; spriteContainer.x = movingBlocks.x = calculatedX;
movingBlocks.y = calculatedY; spriteContainer.y = movingBlocks.y = calculatedY;
spriteContainer.x = calculatedX;
spriteContainer.y = calculatedY;
if (isMouseHoverShown.value && compSelected.value !== "cursor") { if (isMouseHoverShown.value && compSelected.value !== "cursor") {
const { tx, ty } = spriteContainer.localTransform; const { tx, ty } = spriteContainer.localTransform;
@ -534,7 +540,7 @@ const factory = createLayer(id, () => {
const pointerDown = ref(false), const pointerDown = ref(false),
pointerDrag = ref(false), pointerDrag = ref(false),
compHovered = ref<FactoryComponent | null>(null); compHovered = ref<FactoryComponent | undefined>(undefined);
function onFactoryPointerMove(e: PointerEvent) { function onFactoryPointerMove(e: PointerEvent) {
const { x, y } = getRelativeCoords(e); const { x, y } = getRelativeCoords(e);
@ -551,28 +557,24 @@ const factory = createLayer(id, () => {
mapOffset.y += e.movementY / blockSize; mapOffset.y += e.movementY / blockSize;
// the maximum you can see currently // the maximum you can see currently
// total size of blocks - current size = amount you should move // total size of blocks - current size = amount you should move
mapOffset.x = Math.min( mapOffset.x = Math.min(Math.max(mapOffset.x, -factorySize.width), factorySize.width);
Math.max(mapOffset.x, 0), mapOffset.y = Math.min(Math.max(mapOffset.y, -factorySize.height), factorySize.height);
blockSize * factorySize.width - app.screen.width
);
mapOffset.y = Math.min(
Math.max(mapOffset.y, 0),
blockSize * factorySize.height - app.screen.height
);
} }
if (!pointerDown.value && !pointerDrag.value && compSelected.value === "cursor") { if (!pointerDown.value && !pointerDrag.value && compSelected.value === "cursor") {
const { tx, ty } = spriteContainer.localTransform; const { tx, ty } = spriteContainer.localTransform;
compHovered.value = compHovered.value =
components.value[roundDownTo(y - ty, blockSize) / blockSize][ components.value[
roundDownTo(x - tx, blockSize) / blockSize Math.round(roundDownTo(x - tx, blockSize) / blockSize) +
"x" +
Math.round(roundDownTo(y - ty, blockSize) / blockSize)
]; ];
} }
} }
async function onFactoryPointerDown() { function onFactoryPointerDown() {
window.addEventListener("pointerup", onFactoryPointerUp); window.addEventListener("pointerup", onFactoryPointerUp);
pointerDown.value = true; pointerDown.value = true;
} }
async function onFactoryPointerUp(e: PointerEvent) { function onFactoryPointerUp(e: PointerEvent) {
// make sure they're not dragging and that // make sure they're not dragging and that
// they aren't trying to put down a cursor // they aren't trying to put down a cursor
if (!pointerDrag.value) { if (!pointerDrag.value) {
@ -582,13 +584,13 @@ const factory = createLayer(id, () => {
y = roundDownTo(y - ty, blockSize) / blockSize; y = roundDownTo(y - ty, blockSize) / blockSize;
if (e.button === 0) { if (e.button === 0) {
if (compSelected.value !== "cursor") { if (compSelected.value !== "cursor") {
await addFactoryComp(x, y, compSelected.value); if (!components.value[x + "x" + y]) addFactoryComp(x, y, compSelected.value);
} }
} else if (e.button === 2) { } else if (e.button === 2) {
const data = compInternalData[y][x]; const data = compInternalData[x + "x" + y];
if (data === null) return; if (data === undefined) return;
components.value[y][x] = null; delete components.value[x + "x" + y];
compInternalData[y][x] = null; delete compInternalData[x + "x" + y];
spriteContainer.removeChild(data.sprite); spriteContainer.removeChild(data.sprite);
} }
} }
@ -607,7 +609,6 @@ const factory = createLayer(id, () => {
player.tabs.splice(0, Infinity, "main"); player.tabs.splice(0, Infinity, "main");
} }
function onComponentHover(name: FactoryCompNames | "") { function onComponentHover(name: FactoryCompNames | "") {
if (compSelected.value !== "cursor") return;
whatIsHovered.value = name; whatIsHovered.value = name;
} }
function onCompClick(name: FactoryCompNames) { function onCompClick(name: FactoryCompNames) {
@ -635,7 +636,7 @@ const factory = createLayer(id, () => {
onContextmenu={(e: MouseEvent) => e.preventDefault()} onContextmenu={(e: MouseEvent) => e.preventDefault()}
/> />
<div class="info-container"> <div class="info-container">
{compHovered.value !== null ? ( {compHovered.value !== undefined ? (
<> <>
<b>{FACTORY_COMPONENTS[compHovered.value.type].name}</b> <b>{FACTORY_COMPONENTS[compHovered.value.type].name}</b>
<br /> <br />
@ -649,9 +650,9 @@ const factory = createLayer(id, () => {
...compHovered.value.consumptionStock ...compHovered.value.consumptionStock
}).map(i => { }).map(i => {
return `${i[0]}: ${i[1]}/${ return `${i[0]}: ${i[1]}/${
FACTORY_COMPONENTS[compHovered.value.type] FACTORY_COMPONENTS[compHovered.value?.type ?? "cursor"]
.consumptionStock[i[0]] ?? .consumptionStock[i[0]] ??
FACTORY_COMPONENTS[compHovered.value.type] FACTORY_COMPONENTS[compHovered.value?.type ?? "cursor"]
.productionStock[i[0]] .productionStock[i[0]]
}`; }`;
})} })}

View file

@ -19,9 +19,9 @@ export function isFunction<T, S extends ReadonlyArray<unknown>, R>(
} }
export enum Direction { export enum Direction {
Up = "Up", Up = "UP",
Down = "Down", Down = "DOWN",
Left = "Left", Left = "LEFT",
Right = "Right", Right = "RIGHT",
Default = "Up" Default = "UP"
} }