breakout71/src/newGameState.ts

132 lines
3.5 KiB
TypeScript
Raw Normal View History

2025-03-27 10:52:31 +01:00
import { DebuffsMap, GameState, RunParams } from "./types";
2025-03-18 14:16:12 +01:00
import { getTotalScore } from "./settings";
import { allLevels, upgrades } from "./loadGameData";
import {
defaultSounds,
getPossibleUpgrades,
makeEmptyPerksMap,
2025-03-26 14:04:54 +01:00
sumOfValues,
2025-03-18 14:16:12 +01:00
} from "./game_utils";
import { dontOfferTooSoon, resetBalls } from "./gameStateMutators";
import { isOptionOn } from "./options";
2025-03-27 10:52:31 +01:00
import { debuffs } from "./debuffs";
2025-03-18 08:19:20 +01:00
export function newGameState(params: RunParams): GameState {
2025-03-16 17:45:29 +01:00
const totalScoreAtRunStart = getTotalScore();
const firstLevel = params?.level
? allLevels.filter((l) => l.name === params?.level)
: [];
2025-03-16 17:45:29 +01:00
const restInRandomOrder = allLevels
.filter((l) => totalScoreAtRunStart >= l.threshold)
.filter((l) => l.name !== params?.level)
.filter((l) => l.name !== params?.levelToAvoid)
.sort(() => Math.random() - 0.5);
2025-03-16 17:45:29 +01:00
const runLevels = firstLevel.concat(
restInRandomOrder.slice(0, 7 + 3).sort((a, b) => a.sortKey - b.sortKey),
);
2025-03-16 17:45:29 +01:00
const perks = { ...makeEmptyPerksMap(upgrades), ...(params?.perks || {}) };
2025-03-26 08:35:49 +01:00
const gameState: GameState = {
2025-03-16 17:45:29 +01:00
runLevels,
2025-03-27 10:52:31 +01:00
level: runLevels[0],
2025-03-16 17:45:29 +01:00
currentLevel: 0,
2025-03-20 23:11:42 +01:00
upgradesOfferedFor: -1,
2025-03-16 17:45:29 +01:00
perks,
2025-03-27 10:52:31 +01:00
debuffs: { ...emptyDebuffsMap(), ...(params?.debuffs || {}) },
2025-03-16 17:45:29 +01:00
puckWidth: 200,
baseSpeed: 12,
combo: 1,
gridSize: 12,
running: false,
2025-03-22 16:04:25 +01:00
isGameOver: false,
2025-03-18 14:16:12 +01:00
ballStickToPuck: true,
2025-03-16 17:45:29 +01:00
puckPosition: 400,
2025-03-25 08:22:58 +01:00
lastPuckPosition: 400,
2025-03-26 08:01:12 +01:00
lastPuckMove: 0,
2025-03-16 17:45:29 +01:00
pauseTimeout: null,
canvasWidth: 0,
canvasHeight: 0,
offsetX: 0,
offsetXRoundedDown: 0,
gameZoneWidth: 0,
gameZoneWidthRoundedUp: 0,
gameZoneHeight: 0,
brickWidth: 0,
score: 0,
lastScoreIncrease: -1000,
lastExplosion: -1000,
highScore: parseFloat(localStorage.getItem("breakout-3-hs") || "0"),
balls: [],
ballsColor: "white",
bricks: [],
brickHP: [],
2025-03-18 14:16:12 +01:00
lights: { indexMin: 0, total: 0, list: [] },
particles: { indexMin: 0, total: 0, list: [] },
texts: { indexMin: 0, total: 0, list: [] },
coins: { indexMin: 0, total: 0, list: [] },
2025-03-16 17:45:29 +01:00
levelStartScore: 0,
levelMisses: 0,
levelSpawnedCoins: 0,
puckColor: "#FFF",
ballSize: 20,
coinSize: 14,
puckHeight: 20,
totalScoreAtRunStart,
2025-03-26 14:04:54 +01:00
isCreativeModeRun: sumOfValues(perks) > 1,
2025-03-16 17:45:29 +01:00
pauseUsesDuringRun: 0,
keyboardPuckSpeed: 0,
lastTick: performance.now(),
lastTickDown: 0,
runStatistics: {
started: Date.now(),
levelsPlayed: 0,
runTime: 0,
coins_spawned: 0,
score: 0,
bricks_broken: 0,
misses: 0,
balls_lost: 0,
puck_bounces: 0,
wall_bounces: 0,
upgrades_picked: 1,
max_combo: 1,
max_level: 0,
},
lastOffered: {},
levelTime: 0,
2025-03-22 16:47:02 +01:00
winAt: 0,
2025-03-16 20:11:08 +01:00
levelWallBounces: 0,
needsRender: true,
2025-03-16 17:45:29 +01:00
autoCleanUses: 0,
2025-03-18 14:16:12 +01:00
...defaultSounds(),
2025-03-26 08:01:12 +01:00
2025-03-26 08:35:49 +01:00
isAdventureMode: !!params?.adventure,
rerolls: 0,
2025-03-16 17:45:29 +01:00
};
resetBalls(gameState);
2025-03-27 10:52:31 +01:00
if (!sumOfValues(gameState.perks) && !params?.adventure) {
2025-03-16 17:45:29 +01:00
const giftable = getPossibleUpgrades(gameState).filter((u) => u.giftable);
const randomGift =
(isOptionOn("easy") && "slow_down") ||
giftable[Math.floor(Math.random() * giftable.length)].id;
perks[randomGift] = 1;
dontOfferTooSoon(gameState, randomGift);
}
for (let perk of upgrades) {
if (gameState.perks[perk.id]) {
dontOfferTooSoon(gameState, perk.id);
}
2025-03-16 17:45:29 +01:00
}
return gameState;
}
2025-03-27 10:52:31 +01:00
export function emptyDebuffsMap(): DebuffsMap {
const map = {};
debuffs.forEach((d) => (map[d.id] = 0));
return map as DebuffsMap;
}