mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-22 04:56:15 -04:00
wip
This commit is contained in:
parent
0cef60f90d
commit
bdbf8b846c
19 changed files with 1306 additions and 1591 deletions
|
@ -2,47 +2,36 @@ import { GameState, Level, PerkId, Upgrade } from "./types";
|
|||
import { allLevels, icons, upgrades } from "./loadGameData";
|
||||
import { t } from "./i18n/i18n";
|
||||
import { getSettingValue, getTotalScore, setSettingValue } from "./settings";
|
||||
import { confirmRestart, creativeModeThreshold, restart } from "./game";
|
||||
import { requiredAsyncAlert } from "./asyncAlert";
|
||||
import { describeLevel, highScoreForMode, sumOfValues } from "./game_utils";
|
||||
import {confirmRestart, creativeModeThreshold, gameState, restart} from "./game";
|
||||
import {asyncAlert, requiredAsyncAlert} from "./asyncAlert";
|
||||
import { describeLevel, highScoreText, sumOfValues } from "./game_utils";
|
||||
|
||||
export function creativeMode(gameState: GameState) {
|
||||
return {
|
||||
icon: icons["icon:sandbox"],
|
||||
text: t("lab.menu_entry"),
|
||||
help:
|
||||
highScoreForMode("creative") ||
|
||||
// highScoreForMode("creative") ||
|
||||
(getTotalScore() < creativeModeThreshold &&
|
||||
t("lab.unlocks_at", { score: creativeModeThreshold })) ||
|
||||
t("lab.help"),
|
||||
disabled: getTotalScore() < creativeModeThreshold,
|
||||
async value() {
|
||||
if (await confirmRestart(gameState)) {
|
||||
restart({ mode: "creative" });
|
||||
}
|
||||
openCreativeModePerksPicker()
|
||||
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function openCreativeModePerksPicker(
|
||||
gameState,
|
||||
currentLevel: number,
|
||||
) {
|
||||
gameState.readyToRender = false;
|
||||
export async function openCreativeModePerksPicker() {
|
||||
|
||||
|
||||
let creativeModePerks: Partial<{ [id in PerkId]: number }> = getSettingValue(
|
||||
"creativeModePerks_" + currentLevel,
|
||||
"creativeModePerks" ,
|
||||
{},
|
||||
),
|
||||
choice: Upgrade | Level | "reset" | void;
|
||||
|
||||
upgrades.forEach((u) => {
|
||||
creativeModePerks[u.id] = Math.min(
|
||||
creativeModePerks[u.id] || 0,
|
||||
u.max - gameState.bannedPerks[u.id],
|
||||
);
|
||||
});
|
||||
|
||||
let noCreative: PerkId[] = [
|
||||
"extra_levels",
|
||||
"shunt",
|
||||
|
@ -51,8 +40,8 @@ export async function openCreativeModePerksPicker(
|
|||
];
|
||||
|
||||
while (
|
||||
(choice = await requiredAsyncAlert<Upgrade | Level | "reset">({
|
||||
title: t("lab.title", { lvl: currentLevel + 1 }),
|
||||
(choice = await asyncAlert<Upgrade | Level | "reset">({
|
||||
title: t("lab.menu_entry"),
|
||||
className: "actionsAsGrid",
|
||||
content: [
|
||||
t("lab.instructions"),
|
||||
|
@ -69,9 +58,8 @@ export async function openCreativeModePerksPicker(
|
|||
help:
|
||||
(creativeModePerks[u.id] || 0) +
|
||||
"/" +
|
||||
(u.max - gameState.bannedPerks[u.id]),
|
||||
u.max,
|
||||
value: u,
|
||||
disabled: u.max - gameState.bannedPerks[u.id] <= 0,
|
||||
className: creativeModePerks[u.id]
|
||||
? "sandbox"
|
||||
: "sandbox grey-out-unless-hovered",
|
||||
|
@ -92,17 +80,18 @@ export async function openCreativeModePerksPicker(
|
|||
creativeModePerks[u.id] = 0;
|
||||
});
|
||||
} else if ("bricks" in choice) {
|
||||
setSettingValue("creativeModePerks_" + currentLevel, creativeModePerks);
|
||||
upgrades.forEach((u) => {
|
||||
gameState.perks[u.id] = creativeModePerks[u.id];
|
||||
gameState.bannedPerks[u.id] += creativeModePerks[u.id];
|
||||
});
|
||||
gameState.runLevels[currentLevel] = choice;
|
||||
break;
|
||||
setSettingValue("creativeModePerks" , creativeModePerks);
|
||||
if (await confirmRestart(gameState)) {
|
||||
restart({ perks:creativeModePerks, level:choice.name});
|
||||
}
|
||||
return
|
||||
} else if (choice) {
|
||||
creativeModePerks[choice.id] =
|
||||
((creativeModePerks[choice.id] || 0) + 1) %
|
||||
(choice.max - gameState.bannedPerks[choice.id] + 1);
|
||||
(choice.max +1);
|
||||
}else{
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1293,4 +1293,4 @@
|
|||
"svg": null,
|
||||
"color": ""
|
||||
}
|
||||
]
|
||||
]
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_": "",
|
||||
"B": "black",
|
||||
"W": "white",
|
||||
"W": "#FFFFFF",
|
||||
"g": "#231f20",
|
||||
"y": "#ffd300",
|
||||
"b": "#6262EA",
|
||||
|
@ -21,4 +21,4 @@
|
|||
"k": "#618227",
|
||||
"e": "#e1c8b4",
|
||||
"l": "#9b9fa4"
|
||||
}
|
||||
}
|
67
src/game.ts
67
src/game.ts
|
@ -16,7 +16,7 @@ import {
|
|||
currentLevelInfo,
|
||||
describeLevel,
|
||||
getRowColIndex,
|
||||
highScoreForMode,
|
||||
highScoreText,
|
||||
levelsListHTMl,
|
||||
max_levels,
|
||||
pickedUpgradesHTMl,
|
||||
|
@ -72,6 +72,7 @@ import { creativeMode } from "./creative";
|
|||
import { setupTooltips } from "./tooltip";
|
||||
import { startingPerkMenuButton } from "./startingPerks";
|
||||
import "./migrations";
|
||||
import {getCreativeModeWarning} from "./gameOver";
|
||||
|
||||
export async function play() {
|
||||
if (await applyFullScreenChoice()) return;
|
||||
|
@ -441,20 +442,15 @@ async function openScorePanel() {
|
|||
pause(true);
|
||||
|
||||
const cb = await asyncAlert({
|
||||
title: gameState.loop
|
||||
? t("score_panel.title_looped", {
|
||||
loop: gameState.loop,
|
||||
score: gameState.score,
|
||||
level: gameState.currentLevel + 1,
|
||||
max: max_levels(gameState),
|
||||
})
|
||||
: t("score_panel.title", {
|
||||
title: t("score_panel.title", {
|
||||
score: gameState.score,
|
||||
level: gameState.currentLevel + 1,
|
||||
max: max_levels(gameState),
|
||||
}),
|
||||
|
||||
content: [
|
||||
|
||||
getCreativeModeWarning(gameState),
|
||||
pickedUpgradesHTMl(gameState),
|
||||
levelsListHTMl(gameState, gameState.currentLevel),
|
||||
gameState.rerolls
|
||||
|
@ -486,31 +482,13 @@ export async function openMainMenu() {
|
|||
{
|
||||
icon: icons["icon:7_levels_run"],
|
||||
text: t("main_menu.normal"),
|
||||
help: highScoreForMode("short") || t("main_menu.normal_help"),
|
||||
help: highScoreText() || t("main_menu.normal_help"),
|
||||
value: () => {
|
||||
restart({
|
||||
levelToAvoid: currentLevelInfo(gameState).name,
|
||||
mode: "short",
|
||||
levelToAvoid: currentLevelInfo(gameState).name
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: icons["icon:loop"],
|
||||
text: t("main_menu.loop_run"),
|
||||
help:
|
||||
highScoreForMode("long") ||
|
||||
(getTotalScore() < creativeModeThreshold &&
|
||||
t("lab.unlocks_at", { score: creativeModeThreshold })) ||
|
||||
t("main_menu.loop_run_help"),
|
||||
|
||||
value: () => {
|
||||
restart({
|
||||
levelToAvoid: currentLevelInfo(gameState).name,
|
||||
mode: "long",
|
||||
});
|
||||
},
|
||||
disabled: getTotalScore() < creativeModeThreshold,
|
||||
},
|
||||
creativeMode(gameState),
|
||||
{
|
||||
icon: icons["icon:unlocks"],
|
||||
|
@ -880,15 +858,16 @@ async function openUnlocksList() {
|
|||
});
|
||||
if (tryOn) {
|
||||
if (await confirmRestart(gameState)) {
|
||||
restart({ ...tryOn, mode: "short" });
|
||||
restart({ ...tryOn });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function confirmRestart(gameState) {
|
||||
|
||||
if (!gameState.currentLevel) return true;
|
||||
if (alertsOpen) return true;
|
||||
|
||||
pause(true)
|
||||
return asyncAlert({
|
||||
title: t("confirmRestart.title"),
|
||||
content: [
|
||||
|
@ -970,8 +949,7 @@ document.addEventListener("keyup", async (e) => {
|
|||
// When doing ctrl + R in dev to refresh, i don't want to instantly restart a run
|
||||
if (await confirmRestart(gameState)) {
|
||||
restart({
|
||||
levelToAvoid: currentLevelInfo(gameState).name,
|
||||
mode: gameState.mode,
|
||||
levelToAvoid: currentLevelInfo(gameState).name
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
@ -980,7 +958,7 @@ document.addEventListener("keyup", async (e) => {
|
|||
e.preventDefault();
|
||||
});
|
||||
|
||||
export const gameState = newGameState({ mode: "short" });
|
||||
export const gameState = newGameState({});
|
||||
|
||||
export function restart(params: RunParams) {
|
||||
fitSize();
|
||||
|
@ -989,26 +967,7 @@ export function restart(params: RunParams) {
|
|||
setLevel(gameState, 0);
|
||||
}
|
||||
|
||||
restart(
|
||||
(window.location.search.includes("stressTest") && {
|
||||
// level: "Bird",
|
||||
perks: {
|
||||
// shocks: 10,
|
||||
// multiball: 6,
|
||||
// telekinesis: 2,
|
||||
// ghost_coins: 1,
|
||||
pierce: 2,
|
||||
// clairvoyant: 2,
|
||||
// sturdy_bricks:2,
|
||||
bigger_explosions: 10,
|
||||
sapper: 3,
|
||||
// unbounded: 1,
|
||||
},
|
||||
mode: "long",
|
||||
}) || {
|
||||
mode: "short",
|
||||
},
|
||||
);
|
||||
restart({ });
|
||||
|
||||
tick();
|
||||
setupTooltips();
|
||||
|
|
|
@ -118,11 +118,12 @@ export function gameOver(title: string, intro: string) {
|
|||
allowClose: true,
|
||||
title,
|
||||
content: [
|
||||
getCreativeModeWarning(gameState),
|
||||
`
|
||||
<p>${intro}</p>
|
||||
<p>${t("gameOver.cumulative_total", { startTs, endTs })}</p>
|
||||
${unlocksInfo}
|
||||
<p>${t("gameOver.cumulative_total", { startTs, endTs })}</p>
|
||||
`,
|
||||
unlocksInfo,
|
||||
{
|
||||
value: null,
|
||||
text: t("gameOver.restart"),
|
||||
|
@ -135,13 +136,19 @@ export function gameOver(title: string, intro: string) {
|
|||
],
|
||||
}).then(() =>
|
||||
restart({
|
||||
levelToAvoid: currentLevelInfo(gameState).name,
|
||||
mode: gameState.mode,
|
||||
levelToAvoid: currentLevelInfo(gameState).name
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export function getCreativeModeWarning(gameState: GameState){
|
||||
if(gameState.creative){
|
||||
return '<p>'+t('gameOver.creative')+'</p>'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
export function getHistograms(gameState: GameState) {
|
||||
if(gameState.creative) return ''
|
||||
let runStats = "";
|
||||
try {
|
||||
// Stores only top 100 runs
|
||||
|
@ -155,7 +162,6 @@ export function getHistograms(gameState: GameState) {
|
|||
runsHistory.push({
|
||||
...gameState.runStatistics,
|
||||
perks: gameState.perks,
|
||||
mode: gameState.mode,
|
||||
appVersion,
|
||||
});
|
||||
|
||||
|
@ -172,7 +178,6 @@ export function getHistograms(gameState: GameState) {
|
|||
unit: string,
|
||||
) => {
|
||||
let values = runsHistory
|
||||
.filter((h) => (h.mode || "short") === gameState.mode)
|
||||
.map((h) => getter(h) || 0);
|
||||
let min = Math.min(...values);
|
||||
let max = Math.max(...values);
|
||||
|
|
|
@ -76,10 +76,10 @@ export function resetBalls(gameState: GameState) {
|
|||
const count = 1 + (gameState.perks?.multiball || 0);
|
||||
const perBall = gameState.puckWidth / (count + 1);
|
||||
gameState.balls = [];
|
||||
gameState.ballsColor = "#FFF";
|
||||
gameState.ballsColor = "#FFFFFF";
|
||||
if (gameState.perks.picky_eater || gameState.perks.pierce_color) {
|
||||
gameState.ballsColor =
|
||||
getMajorityValue(gameState.bricks.filter((i) => i)) || "#FFF";
|
||||
getMajorityValue(gameState.bricks.filter((i) => i)) || "#FFFFFF";
|
||||
}
|
||||
for (let i = 0; i < count; i++) {
|
||||
const x =
|
||||
|
@ -131,8 +131,7 @@ export function normalizeGameState(gameState: GameState) {
|
|||
gameState.gameZoneWidth / 12 / 10 +
|
||||
gameState.currentLevel / 3 +
|
||||
gameState.levelTime / (30 * 1000) -
|
||||
gameState.perks.slow_down * 2 +
|
||||
gameState.loop,
|
||||
gameState.perks.slow_down * 2
|
||||
);
|
||||
|
||||
gameState.puckWidth = Math.max(
|
||||
|
@ -174,7 +173,7 @@ export function normalizeGameState(gameState: GameState) {
|
|||
|
||||
export function baseCombo(gameState: GameState) {
|
||||
return (
|
||||
gameState.baseCombo +
|
||||
1 +
|
||||
gameState.perks.base_combo * 3 +
|
||||
gameState.perks.smaller_puck * 5
|
||||
);
|
||||
|
@ -206,7 +205,7 @@ export function resetCombo(
|
|||
gameState,
|
||||
x,
|
||||
y,
|
||||
"red",
|
||||
"#FF0000",
|
||||
"-" + lost,
|
||||
20,
|
||||
500 + clamp(lost, 0, 500),
|
||||
|
@ -231,7 +230,7 @@ export function increaseCombo(
|
|||
typeof x !== "undefined" &&
|
||||
typeof y !== "undefined"
|
||||
) {
|
||||
makeText(gameState, x, y, "gold", "+" + by, 25, 400 + by);
|
||||
makeText(gameState, x, y, "#ffd300", "+" + by, 25, 400 + by);
|
||||
}
|
||||
}
|
||||
export function decreaseCombo(
|
||||
|
@ -247,7 +246,7 @@ export function decreaseCombo(
|
|||
if (lost) {
|
||||
schedulGameSound(gameState, "comboDecrease", x, 1);
|
||||
if (typeof x !== "undefined" && typeof y !== "undefined") {
|
||||
makeText(gameState, x, y, "red", "-" + lost, 20, 400 + lost);
|
||||
makeText(gameState, x, y, "#FF0000", "-" + lost, 20, 400 + lost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -342,11 +341,10 @@ export function explosionAt(
|
|||
});
|
||||
gameState.lastExplosion = Date.now();
|
||||
|
||||
// makeLight(gameState, x, y, "white", gameState.brickWidth * 2, 150);
|
||||
if (gameState.perks.implosions) {
|
||||
spawnImplosion(gameState, 7 * size, x, y, "white");
|
||||
spawnImplosion(gameState, 7 * size, x, y, "#FFFFFF");
|
||||
} else {
|
||||
spawnExplosion(gameState, 7 * size, x, y, "white");
|
||||
spawnExplosion(gameState, 7 * size, x, y, "#FFFFFF");
|
||||
}
|
||||
|
||||
gameState.runStatistics.bricks_broken++;
|
||||
|
@ -566,13 +564,14 @@ export function schedulGameSound(
|
|||
}
|
||||
|
||||
export function addToScore(gameState: GameState, coin: Coin) {
|
||||
|
||||
gameState.score += coin.points;
|
||||
gameState.lastScoreIncrease = gameState.levelTime;
|
||||
addToTotalScore(gameState, coin.points);
|
||||
if (gameState.score > gameState.highScore) {
|
||||
if (gameState.score > gameState.highScore && !gameState.creative) {
|
||||
gameState.highScore = gameState.score;
|
||||
localStorage.setItem(
|
||||
"breakout-3-hs-" + gameState.mode,
|
||||
"breakout-3-hs-short" ,
|
||||
gameState.score.toString(),
|
||||
);
|
||||
}
|
||||
|
@ -585,7 +584,7 @@ export function addToScore(gameState: GameState, coin: Coin) {
|
|||
-coin.y / 100,
|
||||
gameState.perks.metamorphosis || isOptionOn("colorful_coins")
|
||||
? coin.color
|
||||
: "gold",
|
||||
: "#ffd300",
|
||||
|
||||
true,
|
||||
gameState.coinSize / 2,
|
||||
|
@ -605,62 +604,6 @@ export function addToScore(gameState: GameState, coin: Coin) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function gotoNextLoop(gameState: GameState) {
|
||||
pause(false);
|
||||
gameState.loop++;
|
||||
gameState.runStatistics.loops++;
|
||||
gameState.runLevels = getRunLevels(gameState.totalScoreAtRunStart, {});
|
||||
gameState.upgradesOfferedFor = -1;
|
||||
|
||||
let comboText = "";
|
||||
if (gameState.rerolls) {
|
||||
comboText = t("loop.converted_rerolls", { n: gameState.rerolls });
|
||||
gameState.baseCombo += gameState.rerolls;
|
||||
gameState.rerolls = 0;
|
||||
} else {
|
||||
comboText = t("loop.no_rerolls");
|
||||
}
|
||||
|
||||
const userPerks = upgrades.filter((u) => gameState.perks[u.id]);
|
||||
|
||||
const keep = await requiredAsyncAlert<PerkId>({
|
||||
title: t("loop.title", { loop: gameState.loop }),
|
||||
content: [
|
||||
t("loop.instructions"),
|
||||
comboText,
|
||||
...userPerks
|
||||
.filter((u) => u.id !== "instant_upgrade")
|
||||
.map((u) => {
|
||||
return {
|
||||
text:
|
||||
u.name +
|
||||
t("level_up.upgrade_perk_to_level", {
|
||||
level: gameState.perks[u.id] + 1,
|
||||
}),
|
||||
icon: u.icon,
|
||||
value: u.id,
|
||||
help: u.help(gameState.perks[u.id] + 1),
|
||||
};
|
||||
}),
|
||||
],
|
||||
});
|
||||
// Decrease max level of all perks
|
||||
userPerks.forEach((u) => {
|
||||
if (u.id !== keep) {
|
||||
gameState.bannedPerks[u.id] += gameState.perks[u.id];
|
||||
}
|
||||
});
|
||||
|
||||
// Increase max level of kept perk by 2
|
||||
gameState.bannedPerks[keep] -= 2;
|
||||
|
||||
// Increase current level of kept perk by 1
|
||||
Object.assign(gameState.perks, makeEmptyPerksMap(upgrades), {
|
||||
[keep]: gameState.perks[keep] + 1,
|
||||
});
|
||||
|
||||
await setLevel(gameState, 0);
|
||||
}
|
||||
function recordBestWorstLevelScore(gameState: GameState) {
|
||||
const levelScore = gameState.score - gameState.levelStartScore;
|
||||
const { runStatistics } = gameState;
|
||||
|
@ -689,9 +632,7 @@ export async function setLevel(gameState: GameState, l: number) {
|
|||
stopRecording();
|
||||
recordBestWorstLevelScore(gameState);
|
||||
|
||||
if (gameState.mode === "creative") {
|
||||
await openCreativeModePerksPicker(gameState, l);
|
||||
} else if (l > 0) {
|
||||
if (l > 0) {
|
||||
await openUpgradesPicker(gameState);
|
||||
}
|
||||
gameState.currentLevel = l;
|
||||
|
@ -749,7 +690,6 @@ export async function setLevel(gameState: GameState, l: number) {
|
|||
background.src = "data:image/svg+xml;UTF8," + lvl.svg;
|
||||
|
||||
document.body.style.setProperty("--level-background", lvl.color || "#000");
|
||||
gameState.readyToRender = true;
|
||||
}
|
||||
|
||||
function setBrick(gameState: GameState, index: number, color: string) {
|
||||
|
@ -760,8 +700,17 @@ function setBrick(gameState: GameState, index: number, color: string) {
|
|||
0;
|
||||
}
|
||||
|
||||
const rainbow=[
|
||||
'#ff2e2e',
|
||||
'#ffe02e',
|
||||
'#70ff33',
|
||||
'#33ffa7',
|
||||
'#38acff',
|
||||
'#7038ff',
|
||||
'#ff3de5',
|
||||
]
|
||||
export function rainbowColor(): colorString {
|
||||
return `hsl(${(Math.round(gameState.levelTime / 4) * 2) % 360},100%,70%)`;
|
||||
return rainbow[Math.floor(gameState.levelTime / 50) %rainbow.length ]
|
||||
}
|
||||
|
||||
export function repulse(
|
||||
|
@ -1050,12 +999,10 @@ export function gameStateTick(
|
|||
) {
|
||||
if (gameState.currentLevel + 1 < max_levels(gameState)) {
|
||||
setLevel(gameState, gameState.currentLevel + 1);
|
||||
} else if (gameState.loop < (gameState.mode === "long" ? 7 : 0)) {
|
||||
gotoNextLoop(gameState);
|
||||
} else {
|
||||
} else {
|
||||
gameOver(
|
||||
t("gameOver.7_loop.title", { loop: gameState.loop }),
|
||||
t("gameOver.7_loop.summary", { score: gameState.score }),
|
||||
t("gameOver.win.title" ),
|
||||
t("gameOver.win.summary", { score: gameState.score }),
|
||||
);
|
||||
}
|
||||
} else if (gameState.running || gameState.levelTime) {
|
||||
|
@ -1091,7 +1038,7 @@ export function gameStateTick(
|
|||
|
||||
const ratio =
|
||||
1 -
|
||||
((gameState.perks.viscosity * 0.03 + 0.005) * frames) /
|
||||
((gameState.perks.viscosity * 0.03 + 0.002) * frames) /
|
||||
(1 + gameState.perks.etherealcoins);
|
||||
|
||||
coin.vy *= ratio;
|
||||
|
@ -1121,7 +1068,7 @@ export function gameStateTick(
|
|||
gameState.baseSpeed,
|
||||
gameState.perks.metamorphosis || isOptionOn("colorful_coins")
|
||||
? coin.color
|
||||
: "gold",
|
||||
: "#ffd300",
|
||||
true,
|
||||
5,
|
||||
250,
|
||||
|
@ -1300,7 +1247,7 @@ export function gameStateTick(
|
|||
0,
|
||||
(Math.random() - 0.5) * 10,
|
||||
5,
|
||||
"red",
|
||||
"#FF0000",
|
||||
true,
|
||||
gameState.coinSize / 2,
|
||||
100 * (Math.random() + 1),
|
||||
|
@ -1314,7 +1261,7 @@ export function gameStateTick(
|
|||
Math.random() * gameState.gameZoneHeight,
|
||||
5,
|
||||
(Math.random() - 0.5) * 10,
|
||||
"red",
|
||||
"#FF0000",
|
||||
true,
|
||||
gameState.coinSize / 2,
|
||||
100 * (Math.random() + 1),
|
||||
|
@ -1328,7 +1275,7 @@ export function gameStateTick(
|
|||
Math.random() * gameState.gameZoneHeight,
|
||||
-5,
|
||||
(Math.random() - 0.5) * 10,
|
||||
"red",
|
||||
"#FF0000",
|
||||
true,
|
||||
gameState.coinSize / 2,
|
||||
100 * (Math.random() + 1),
|
||||
|
@ -1354,7 +1301,7 @@ export function gameStateTick(
|
|||
gameState.gameZoneHeight,
|
||||
(Math.random() - 0.5) * 10,
|
||||
-5,
|
||||
"red",
|
||||
"#FF0000",
|
||||
true,
|
||||
gameState.coinSize / 2,
|
||||
100 * (Math.random() + 1),
|
||||
|
@ -1368,7 +1315,7 @@ export function gameStateTick(
|
|||
gameState.gameZoneHeight - gameState.puckHeight,
|
||||
pos * 10,
|
||||
-5,
|
||||
"red",
|
||||
"#FF0000",
|
||||
true,
|
||||
gameState.coinSize / 2,
|
||||
100 * (Math.random() + 1),
|
||||
|
@ -1593,7 +1540,7 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
|||
gameState,
|
||||
gameState.puckPosition,
|
||||
gameState.gameZoneHeight - gameState.puckHeight * 2,
|
||||
"red",
|
||||
"#FF0000",
|
||||
t("play.missed_ball"),
|
||||
gameState.puckHeight,
|
||||
500,
|
||||
|
@ -1706,7 +1653,7 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
|||
gameState,
|
||||
brickCenterX(gameState, hitBrick),
|
||||
brickCenterY(gameState, hitBrick),
|
||||
"white",
|
||||
"#FFFFFF",
|
||||
gameState.brickWidth + 2,
|
||||
50 * gameState.brickHP[hitBrick],
|
||||
);
|
||||
|
@ -1726,8 +1673,8 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
|||
(extraCombo && Math.random() > 0.1 / (1 + extraCombo))
|
||||
) {
|
||||
const color =
|
||||
(remainingSapper && (Math.random() > 0.5 ? "orange" : "red")) ||
|
||||
(willMiss && "red") ||
|
||||
(remainingSapper && (Math.random() > 0.5 ? "#ffb92a" : "#FF0000")) ||
|
||||
(willMiss && "#FF0000") ||
|
||||
gameState.ballsColor;
|
||||
|
||||
makeParticle(
|
||||
|
@ -1770,7 +1717,7 @@ function justLostALife(gameState: GameState, ball: Ball, x: number, y: number) {
|
|||
y,
|
||||
Math.random() * gameState.baseSpeed * 3,
|
||||
gameState.baseSpeed * 3,
|
||||
"red",
|
||||
"#FF0000",
|
||||
false,
|
||||
gameState.coinSize / 2,
|
||||
150,
|
||||
|
@ -1784,7 +1731,7 @@ function makeCoin(
|
|||
y: number,
|
||||
vx: number,
|
||||
vy: number,
|
||||
color = "gold",
|
||||
color = "#ffd300",
|
||||
points = 1,
|
||||
) {
|
||||
let weight = 0.8 + Math.random() * 0.2 + Math.min(2, points * 0.01);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { Ball, GameState, Level, PerkId, PerksMap } from "./types";
|
||||
import {Ball, Coin, GameState, Level, PerkId, PerksMap} from "./types";
|
||||
import { icons, upgrades } from "./loadGameData";
|
||||
import { t } from "./i18n/i18n";
|
||||
import { brickAt } from "./level_editor/levels_editor_util";
|
||||
import { clamp } from "./pure_functions";
|
||||
import {isOptionOn} from "./options";
|
||||
|
||||
export function describeLevel(level: Level) {
|
||||
let bricks = 0,
|
||||
|
@ -78,8 +79,8 @@ export function getPossibleUpgrades(gameState: GameState) {
|
|||
}
|
||||
|
||||
export function max_levels(gameState: GameState) {
|
||||
if (gameState.mode === "creative") return 3;
|
||||
return Math.max(7 + gameState.perks.extra_levels - gameState.loop, 1);
|
||||
if (gameState.creative ) return 1;
|
||||
return 7 + gameState.perks.extra_levels
|
||||
}
|
||||
|
||||
export function pickedUpgradesHTMl(gameState: GameState) {
|
||||
|
@ -122,7 +123,7 @@ export function pickedUpgradesHTMl(gameState: GameState) {
|
|||
|
||||
export function levelsListHTMl(gameState: GameState, level: number) {
|
||||
if (!gameState.perks.clairvoyant) return "";
|
||||
if (gameState.mode === "creative") return "";
|
||||
if (gameState.creative) return "";
|
||||
let list = "";
|
||||
for (let i = 0; i < max_levels(gameState); i++) {
|
||||
list += `<span style="opacity: ${i >= level ? 1 : 0.2}" title="${gameState.runLevels[i].name}">${icons[gameState.runLevels[i].name]}</span>`;
|
||||
|
@ -255,15 +256,19 @@ export function isMovingWhilePassiveIncome(gameState: GameState) {
|
|||
);
|
||||
}
|
||||
|
||||
export function highScoreForMode(mode: GameState["mode"]) {
|
||||
try {
|
||||
const score = parseInt(
|
||||
localStorage.getItem("breakout-3-hs-" + mode) || "0",
|
||||
export function getHighScore(){
|
||||
try {
|
||||
return parseInt(
|
||||
localStorage.getItem("breakout-3-hs-short" ) || "0",
|
||||
);
|
||||
if (score) {
|
||||
return t("main_menu.high_score", { score });
|
||||
}
|
||||
} catch (e) {}
|
||||
return 0
|
||||
}
|
||||
|
||||
export function highScoreText( ) {
|
||||
|
||||
if (getHighScore()) {
|
||||
return t("main_menu.high_score", { score:getHighScore() });
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -87,41 +87,6 @@
|
|||
<folder_node>
|
||||
<name>gameOver</name>
|
||||
<children>
|
||||
<folder_node>
|
||||
<name>7_loop</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>summary</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>title</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<concept_node>
|
||||
<name>cumulative_total</name>
|
||||
<description/>
|
||||
|
@ -450,6 +415,21 @@
|
|||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>title</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
</children>
|
||||
|
@ -532,21 +512,6 @@
|
|||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>title</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>unlocks_at</name>
|
||||
<description/>
|
||||
|
@ -1312,21 +1277,6 @@
|
|||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>loop_run</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>true</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>loop_run_help</name>
|
||||
<description/>
|
||||
|
@ -1462,36 +1412,6 @@
|
|||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>opaque_coins</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>opaque_coins_help</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>pointer_lock</name>
|
||||
<description/>
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
"confirmRestart.text": "You're about to start a new game, is that really what you wanted ?",
|
||||
"confirmRestart.title": "Start a new game ?",
|
||||
"confirmRestart.yes": "Restart game",
|
||||
"gameOver.7_loop.summary": "This game is over. You stashed {{score}} coins. ",
|
||||
"gameOver.7_loop.title": "You completed this game",
|
||||
"gameOver.cumulative_total": "Your total cumulative score went from {{startTs}} to {{endTs}}.",
|
||||
"gameOver.lost.summary": "You dropped the ball after catching {{score}} coins.",
|
||||
"gameOver.lost.title": "Game Over",
|
||||
|
@ -25,13 +23,13 @@
|
|||
"gameOver.stats.upgrades_applied": "Upgrades applied",
|
||||
"gameOver.test_run": "This is a test game, its score is not recorded.",
|
||||
"gameOver.unlocked_count": "You unlocked {{count}} items :",
|
||||
"gameOver.win.summary": "You cleared all levels for this game, catching {{score}} coins in total.",
|
||||
"lab.help": "Try to come up with 3 good builds",
|
||||
"lab.instructions": "Select upgrades below, then pick the level to play. Each time you upgrade a perk, it cannot be upgraded as much in the following levels. ",
|
||||
"lab.menu_entry": "New lab game",
|
||||
"gameOver.win.summary": "This game is over. You stashed {{score}} coins. ",
|
||||
"gameOver.win.title": "You completed this game",
|
||||
"lab.help": "Try any build you want",
|
||||
"lab.instructions": "Select upgrades below, then pick the level to play. ",
|
||||
"lab.menu_entry": "Creative mode",
|
||||
"lab.reset": "Reset all to 0",
|
||||
"lab.select_level": "Select a level for this build",
|
||||
"lab.title": "Choose perks for level {{lvl}}/3",
|
||||
"lab.select_level": "Select a level to play on",
|
||||
"lab.unlocks_at": "Unlocks at total score {{score}}",
|
||||
"level_up.after_buttons": "You just finished level {{level}}/{{max}}.",
|
||||
"level_up.before_buttons": "You caught {{score}} coins {{catchGain}} out of {{levelSpawnedCoins}} in {{time}} seconds {{timeGain}}.\n\nYou missed {{levelMisses}} times {{missesGain}} and hit the walls or ceiling {{levelWallBounces}} times{{wallHitsGain}}.\n\n{{compliment}}",
|
||||
|
@ -82,7 +80,6 @@
|
|||
"main_menu.language_help": "Choose the game's language",
|
||||
"main_menu.load_save_file": "Load save file",
|
||||
"main_menu.load_save_file_help": "Select a save file on your device",
|
||||
"main_menu.loop_run": "New long game",
|
||||
"main_menu.loop_run_help": "Allows you to loop up to 7 times",
|
||||
"main_menu.max_coins": " {{max}} coins on screen maximum",
|
||||
"main_menu.max_coins_help": "Cosmetic only, no effect on score",
|
||||
|
@ -90,10 +87,8 @@
|
|||
"main_menu.max_particles_help": "Limits the number of particles show on screen for visual effect. ",
|
||||
"main_menu.mobile": "Mobile mode",
|
||||
"main_menu.mobile_help": "Leaves space under the puck.",
|
||||
"main_menu.normal": "New short game",
|
||||
"main_menu.normal": "New game",
|
||||
"main_menu.normal_help": "Play 7 levels with a random starting perk",
|
||||
"main_menu.opaque_coins": "Opaque coins with white border",
|
||||
"main_menu.opaque_coins_help": "Less pretty but more readable",
|
||||
"main_menu.pointer_lock": "Mouse pointer lock",
|
||||
"main_menu.pointer_lock_help": "Locks and hides the mouse cursor.",
|
||||
"main_menu.record": "Record gameplay videos",
|
||||
|
@ -143,7 +138,7 @@
|
|||
"score_panel.upcoming_levels": "Upcoming levels :",
|
||||
"score_panel.upgrades_picked": "Upgrades picked so far : ",
|
||||
"unlocks.greyed_out_help": "The greyed out ones can be unlocked by increasing your total score. The total score increases every time you score in game.",
|
||||
"unlocks.intro": "Your total score is {{ts}}. Below are all the upgrades and levels the games has to offer. Click an upgrade or level below to start a short game with it.",
|
||||
"unlocks.intro": "Your total score is {{ts}}. Below are all the upgrades and levels the games has to offer. Click an upgrade or level below to start a game with it.",
|
||||
"unlocks.level": "Here are all the game levels, click one to start a game with that starting level. ",
|
||||
"unlocks.level_description": "A {{size}}x{{size}} level with {{bricks}} bricks, {{colors}} colors and {{bombs}} bombs.",
|
||||
"unlocks.title": "You unlocked {{percentUnlock}}% of the game. ",
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
"confirmRestart.text": "Vous êtes sur le point de commencer une nouvelle partie, est-ce vraiment ce que vous vouliez ?",
|
||||
"confirmRestart.title": "Démarrer une nouvelle partie ?",
|
||||
"confirmRestart.yes": "Commencer une nouvelle partie",
|
||||
"gameOver.7_loop.summary": "Cette partie est terminée. Vous avez accumulé {{score}} pièces. ",
|
||||
"gameOver.7_loop.title": "Vous avez terminé cette partie",
|
||||
"gameOver.cumulative_total": "Votre score total cumulé est passé de {{startTs}} à {{endTs}}.",
|
||||
"gameOver.lost.summary": "Vous avez fait tomber la balle après avoir attrapé {{score}} pièces.",
|
||||
"gameOver.lost.title": "Balle perdue",
|
||||
|
@ -25,13 +23,13 @@
|
|||
"gameOver.stats.upgrades_applied": "Mises à jour appliquées",
|
||||
"gameOver.test_run": "Cette partie de test et son score ne sont pas enregistrés.",
|
||||
"gameOver.unlocked_count": "Vous avez débloqué {{count}} objet(s) :",
|
||||
"gameOver.win.summary": "Vous avez nettoyé tous les niveaux pour cette partie, en attrapant {{score}} pièces au total.",
|
||||
"lab.help": "Créez trois bonnes combinaisons d'améliorations",
|
||||
"lab.instructions": "Sélectionnez les améliorations ci-dessous, puis choisissez le niveau à jouer. Chaque amélioration d'un avantage ne peut pas être améliorée autant dans les niveaux suivants.",
|
||||
"lab.menu_entry": "Nouvelle partie \"lab\" ",
|
||||
"gameOver.win.summary": "Cette partie est terminée. Vous avez accumulé {{score}} pièces. ",
|
||||
"gameOver.win.title": "Vous avez terminé cette partie",
|
||||
"lab.help": "Essayez n'importe quel build",
|
||||
"lab.instructions": "Sélectionnez les améliorations ci-dessous, puis choisissez le niveau à jouer. ",
|
||||
"lab.menu_entry": "Mode créatif",
|
||||
"lab.reset": "RAZ toutes les améliorations",
|
||||
"lab.select_level": "Sélectionnez un niveau pour continue",
|
||||
"lab.title": "Choisissez les avantages pour le niveau {{lvl}}/3",
|
||||
"lab.select_level": "Sélectionnez un niveau sur lequel jouer",
|
||||
"lab.unlocks_at": "Déverrouillé à partir d'un score total de {{score}}",
|
||||
"level_up.after_buttons": "Vous venez de terminer le niveau {{level}}/{{max}}.",
|
||||
"level_up.before_buttons": "Vous avez attrapé {{score}} pièces {{catchGain}} sur {{levelSpawnedCoins}} en {{time}} secondes {{timeGain}}.\n\nVous avez raté les briques {{levelMisses}} fois {{missesGain}} et touché les bords de la zone de jeu {{levelWallBounces}} fois {{wallHitsGain}}.\n\n{{compliment}}",
|
||||
|
@ -82,7 +80,6 @@
|
|||
"main_menu.language_help": "Changer la langue d'affichage",
|
||||
"main_menu.load_save_file": "Charger une sauvegarde",
|
||||
"main_menu.load_save_file_help": "Depuis un fichier ",
|
||||
"main_menu.loop_run": "Nouvelle partie longue ",
|
||||
"main_menu.loop_run_help": "Permet de boucler le jeu jusqu'à 7 fois",
|
||||
"main_menu.max_coins": "{{max}} pièces affichées maximum",
|
||||
"main_menu.max_coins_help": "Visuel uniquement, pas d'impact sur le score",
|
||||
|
@ -90,10 +87,8 @@
|
|||
"main_menu.max_particles_help": "Limite le nombre de particules affichées à l'écran pour les effets visuels",
|
||||
"main_menu.mobile": "Mode mobile",
|
||||
"main_menu.mobile_help": "Laisse un espace sous le palet.",
|
||||
"main_menu.normal": "Nouvelle partie rapide",
|
||||
"main_menu.normal": "Nouvelle partie",
|
||||
"main_menu.normal_help": "Avec un avantage de départ aléatoire",
|
||||
"main_menu.opaque_coins": "Pièces opaques avec bordure blanche",
|
||||
"main_menu.opaque_coins_help": "Moins joli mais plus lisible",
|
||||
"main_menu.pointer_lock": "Verrouillage du pointeur",
|
||||
"main_menu.pointer_lock_help": "Cache aussi le curseur de la souris.",
|
||||
"main_menu.record": "Enregistrer des vidéos de jeu",
|
||||
|
@ -143,7 +138,7 @@
|
|||
"score_panel.upcoming_levels": "Niveaux de la parties : ",
|
||||
"score_panel.upgrades_picked": "Améliorations choisies jusqu'à présent :",
|
||||
"unlocks.greyed_out_help": "Les éléments grisées peuvent être débloquées en augmentant votre score total. Le score total augmente à chaque fois que vous marquez des points dans le jeu.",
|
||||
"unlocks.intro": "Votre score total est de {{ts}}. Vous trouverez ci-dessous toutes les améliorations et tous les niveaux que le jeu peut offrir. Cliquez sur l'un d'entre eux pour commencer une nouvelle partie rapide. ",
|
||||
"unlocks.intro": "Votre score total est de {{ts}}. Vous trouverez ci-dessous toutes les améliorations et tous les niveaux que le jeu peut offrir. Cliquez sur l'un d'entre eux pour commencer une nouvelle partie. ",
|
||||
"unlocks.level": "Voici tous les niveaux du jeu. Cliquez sur un niveau pour commencer une nouvelle partie avec ce niveau de départ. ",
|
||||
"unlocks.level_description": "Un niveau {{size}}x{{size}} avec {{bricks}} briques, {{colors}} couleurs et {{bombs}} bombes.",
|
||||
"unlocks.title": "Vous avez débloqué {{percentUnlock}}% du jeu.",
|
||||
|
|
|
@ -35,3 +35,23 @@ migrate("recover_high_scores", () => {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
migrate("remove_long_and_creative_mode_data", () => {
|
||||
let runsHistory = JSON.parse(
|
||||
localStorage.getItem("breakout_71_runs_history") || "[]",
|
||||
) as RunHistoryItem[];
|
||||
|
||||
let cleaned=runsHistory.filter(r=> {
|
||||
if('mode' in r){
|
||||
if(r.mode !== 'short'){
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
if(cleaned.length!==runsHistory.length)
|
||||
localStorage.setItem(
|
||||
"breakout_71_runs_history",
|
||||
JSON.stringify(cleaned),
|
||||
);
|
||||
});
|
||||
|
|
|
@ -2,8 +2,8 @@ import { GameState, RunParams } from "./types";
|
|||
import { getTotalScore } from "./settings";
|
||||
import { allLevels, upgrades } from "./loadGameData";
|
||||
import {
|
||||
defaultSounds,
|
||||
getPossibleUpgrades,
|
||||
defaultSounds, getHighScore,
|
||||
getPossibleUpgrades, highScoreText,
|
||||
makeEmptyPerksMap,
|
||||
sumOfValues,
|
||||
} from "./game_utils";
|
||||
|
@ -63,11 +63,9 @@ export function newGameState(params: RunParams): GameState {
|
|||
lastScoreIncrease: -1000,
|
||||
lastExplosion: -1000,
|
||||
lastBrickBroken: 0,
|
||||
highScore: parseFloat(
|
||||
localStorage.getItem("breakout-3-hs-" + params?.mode || "short") || "0",
|
||||
),
|
||||
highScore: getHighScore(),
|
||||
balls: [],
|
||||
ballsColor: "white",
|
||||
ballsColor: "#FFFFFF",
|
||||
bricks: [],
|
||||
brickHP: [],
|
||||
lights: { indexMin: 0, total: 0, list: [] },
|
||||
|
@ -78,7 +76,7 @@ export function newGameState(params: RunParams): GameState {
|
|||
levelStartScore: 0,
|
||||
levelMisses: 0,
|
||||
levelSpawnedCoins: 0,
|
||||
puckColor: "#FFF",
|
||||
puckColor: "#FFFFFF",
|
||||
ballSize: 20,
|
||||
coinSize: 14,
|
||||
puckHeight: 20,
|
||||
|
@ -112,10 +110,7 @@ export function newGameState(params: RunParams): GameState {
|
|||
autoCleanUses: 0,
|
||||
...defaultSounds(),
|
||||
rerolls: 0,
|
||||
loop: 0,
|
||||
baseCombo: 1,
|
||||
mode: params?.mode || "short",
|
||||
readyToRender: true,
|
||||
creative: sumOfValues(params.perks)>1
|
||||
};
|
||||
resetBalls(gameState);
|
||||
|
||||
|
|
|
@ -25,11 +25,6 @@ export const options = {
|
|||
name: t("main_menu.colorful_coins"),
|
||||
help: t("main_menu.colorful_coins_help"),
|
||||
},
|
||||
opaque_coins: {
|
||||
default: true,
|
||||
name: t("main_menu.opaque_coins"),
|
||||
help: t("main_menu.opaque_coins_help"),
|
||||
},
|
||||
extra_bright: {
|
||||
default: true,
|
||||
name: t("main_menu.extra_bright"),
|
||||
|
|
|
@ -40,7 +40,7 @@ export function drawMainCanvasOnSmallCanvas(gameState: GameState) {
|
|||
);
|
||||
|
||||
// Here we don't use drawText as we don't want to cache a picture for each distinct value of score
|
||||
recordCanvasCtx.fillStyle = "#FFF";
|
||||
recordCanvasCtx.fillStyle = "#FFFFFF";
|
||||
recordCanvasCtx.textBaseline = "top";
|
||||
recordCanvasCtx.font = "12px monospace";
|
||||
recordCanvasCtx.textAlign = "right";
|
||||
|
|
1832
src/render.ts
1832
src/render.ts
File diff suppressed because it is too large
Load diff
|
@ -30,6 +30,7 @@ export function getTotalScore() {
|
|||
}
|
||||
|
||||
export function addToTotalScore(gameState: GameState, points: number) {
|
||||
if(!gameState.creative)
|
||||
setSettingValue("breakout_71_total_score", getTotalScore() + points);
|
||||
}
|
||||
|
||||
|
|
7
src/types.d.ts
vendored
7
src/types.d.ts
vendored
|
@ -167,7 +167,6 @@ export type ReusableArray<T> = {
|
|||
|
||||
export type RunHistoryItem = RunStats & {
|
||||
perks?: PerksMap;
|
||||
mode: GameState["mode"];
|
||||
appVersion?: string;
|
||||
};
|
||||
export type GameState = {
|
||||
|
@ -286,17 +285,13 @@ export type GameState = {
|
|||
colorChange: { vol: number; x: number };
|
||||
};
|
||||
rerolls: number;
|
||||
loop: number;
|
||||
baseCombo: number;
|
||||
mode: "short" | "long" | "creative";
|
||||
readyToRender: boolean;
|
||||
creative:boolean;
|
||||
};
|
||||
|
||||
export type RunParams = {
|
||||
level?: string;
|
||||
levelToAvoid?: string;
|
||||
perks?: Partial<PerksMap>;
|
||||
mode: "short" | "long" | "creative";
|
||||
};
|
||||
export type OptionDef = {
|
||||
default: boolean;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue