This commit is contained in:
Renan LE CARO 2025-03-23 16:11:12 +01:00
parent 2022b41937
commit a89a61e35b
12 changed files with 212 additions and 182 deletions

View file

@ -78,6 +78,15 @@ There's also an easy mode for kids (slower ball).
- the white outline on bricks associated with picky eater kinda works but i feel it's more distracting than anything. maybe try something different ? put a cross on matching coloured bricks, or the contrary, grey out other bricks. - the white outline on bricks associated with picky eater kinda works but i feel it's more distracting than anything. maybe try something different ? put a cross on matching coloured bricks, or the contrary, grey out other bricks.
# New perks ideas # New perks ideas
- [colin] Corner shot - the puck can go beyond the screen limits so as to make corner shots easier.
- [colin] Mental charge - the puck is divided into two smaller pucks, then 3 smaller ones at lvl 2
- [colin] Batteries - lvl1: recharge les pouvoirs du puck quand la balle touche le haut de l'écran (1 fois par lancer, se recharge en touchant le puck). lvl2: également après voir détruit 6 blocs. lvl3: également quand elle touche les bords de l'écran
- [colin] Combos extrêmes: lvl2 pour tous les combos, qui fait que le combo rapporte doubl ou triple, mais si sur un niveau la condition n'est pas respectée alors le perk ne donne plus de combo bonus pour ce niveau.
- [colin] Mytosis - les blocs bombe n'explosent pas mais relâchent une nouvelle balle à la place
- [colin] Juggle - au début du niveau, chaque balle est lancée l'une après au lieu de toutes à la fois
- [colin] Side-kick - briser un bloc par le côté génère plus de coins que par le dessus ou le dessous.
- [colin] Capital - les vies non perdues à la fin du niveau rapportent un bonus de points
- bricks are invisible, but .. - bricks are invisible, but ..
- second puck (symmetric to the first one) - second puck (symmetric to the first one)
- offer next level choice after upgrade pick - offer next level choice after upgrade pick
@ -159,9 +168,15 @@ There's also an easy mode for kids (slower ball).
- on mobile, relative movement of the touch would be amplified and added to the puck - on mobile, relative movement of the touch would be amplified and added to the puck
- option : don't pause on mobile when lifting finger - option : don't pause on mobile when lifting finger
# Unlockable infinite mode # Premium: infinite mode
Allow players to loop the game, adding one hasard per loop, making it harder and harder to exploit each strategy. The high score are separated from the main mode. The scores are added for unlock. You no longer get upgrades after the first 7 levels. The score you make in each level is instead multiplied by the number of "upgrades" and "choices" you would have had. Allow players to loop the game, adding one hasard per loop, making it harder and harder to exploit each strategy.
The high score are separated from the main mode. The scores are added for unlock. You no longer get upgrades after the first 7 levels.
The score you make in each level is instead multiplied by the number of "upgrades" and "choices" you would have had.
The score is your "fuel", and lets you pick the next level from a list. Each level has a cost, preview, and one or two downgrades.
Each downgrade acts as a score multiplier.
Your goal is no longer to score higher, but to go farther
Possible challenges : Possible challenges :
- Add negative coins that make the coin magnet less usage - Add negative coins that make the coin magnet less usage
@ -173,6 +188,17 @@ Possible challenges :
- graphical effects like trail, contrast, blur to make it harder to see what's going on - graphical effects like trail, contrast, blur to make it harder to see what's going on
- ball creates a draft behind itself that blows coins in odd patterns - ball creates a draft behind itself that blows coins in odd patterns
- add red anti-coins that apply downgrades
- destroy your combo
- hurt your score
- behave like heavier coins.
- deactivate a perk for this level
- reduce your number of coins
- destroy all coins on screen
- lowers your combo
- reduce your choice for your next perk
# extend re-playability # extend re-playability
- hard mode : bricks take many hits, perks more rare, missing clears level score, missing coins deducts score.. - hard mode : bricks take many hits, perks more rare, missing clears level score, missing coins deducts score..
- stats by lack of perk, like "best score without using hot start". - stats by lack of perk, like "best score without using hot start".
@ -186,19 +212,10 @@ This requires recording a bit more info about each run.
I could unlock the "pro stand" at $999 that just holds the play area higher. I could unlock the "pro stand" at $999 that just holds the play area higher.
# increase skill ceiling # increase skill ceiling
- reroll mechanic, rerolls are reward for better play - reroll mechanic, rerolls are reward for better play
- make puck smaller as combo increases ? - make puck smaller as combo increases ?
- add red anti-coins that apply downgrades
- destroy your combo
- hurt your score
- behave like heavier coins.
- deactivate a perk for this level
- reduce your number of coins
- destroy all coins on screen
- lowers your combo
- reduce your choice for your next perk
- final bosses (large vertical level that scrolls down faster and faster) - final bosses (large vertical level that scrolls down faster and faster)
- when the player reaches the last level, allow them to loop the run, unlocking a permanent bonus for this run. For example: +5 combo, +1 life per loop… the counterpart would be hazards that slowly populate the levels. - when the player reaches the last level, allow them to loop the run, unlocking a permanent bonus for this run. For example: +5 combo, +1 life per loop… the counterpart would be hazards that slowly populate the levels.

View file

@ -11,8 +11,8 @@ android {
applicationId = "me.lecaro.breakout" applicationId = "me.lecaro.breakout"
minSdk = 21 minSdk = 21
targetSdk = 34 targetSdk = 34
versionCode = 29044319 versionCode = 29045711
versionName = "29044319" versionName = "29045711"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { vectorDrawables {
useSupportLibrary = true useSupportLibrary = true

File diff suppressed because one or more lines are too long

39
dist/index.html vendored
View file

@ -642,7 +642,7 @@ function play() {
function pause(playerAskedForPause) { function pause(playerAskedForPause) {
if (!gameState.running) return; if (!gameState.running) return;
if (gameState.pauseTimeout) return; if (gameState.pauseTimeout) return;
gameState.pauseTimeout = setTimeout(()=>{ const stop = ()=>{
gameState.running = false; gameState.running = false;
setTimeout(()=>{ setTimeout(()=>{
if (!gameState.running) (0, _sounds.getAudioContext)()?.suspend(); if (!gameState.running) (0, _sounds.getAudioContext)()?.suspend();
@ -652,9 +652,12 @@ function pause(playerAskedForPause) {
// document.body.className = gameState.running ? " running " : " paused "; // document.body.className = gameState.running ? " running " : " paused ";
(0, _render.scoreDisplay).className = ""; (0, _render.scoreDisplay).className = "";
gameState.needsRender = true; gameState.needsRender = true;
}, Math.min(Math.max(0, gameState.pauseUsesDuringRun - 5) * 50, 500)); };
if (playerAskedForPause) // Pausing many times in a run will make pause slower if (playerAskedForPause) {
gameState.pauseUsesDuringRun++; // Pausing many times in a run will make pause slower
gameState.pauseUsesDuringRun++;
gameState.pauseTimeout = setTimeout(stop, Math.min(Math.max(0, gameState.pauseUsesDuringRun - 5) * 50, 500));
} else stop();
if (document.exitPointerLock) document.exitPointerLock(); if (document.exitPointerLock) document.exitPointerLock();
} }
const fitSize = ()=>{ const fitSize = ()=>{
@ -842,10 +845,10 @@ function tick() {
FPSCounter++; FPSCounter++;
} }
let FPSCounter = 0; let FPSCounter = 0;
let FPSDisplay = document.getElementById('FPSDisplay'); let FPSDisplay = document.getElementById("FPSDisplay");
setInterval(()=>{ setInterval(()=>{
if ((0, _options.isOptionOn)('show_fps')) FPSDisplay.innerText = FPSCounter + ' FPS ' + (0, _gameStateMutators.liveCount)(gameState.coins) + ' COINS ' + ((0, _gameStateMutators.liveCount)(gameState.particles) + (0, _gameStateMutators.liveCount)(gameState.texts) + (0, _gameStateMutators.liveCount)(gameState.lights)) + ' PARTICLES '; if ((0, _options.isOptionOn)("show_fps")) FPSDisplay.innerText = FPSCounter + " FPS " + (0, _gameStateMutators.liveCount)(gameState.coins) + " COINS " + ((0, _gameStateMutators.liveCount)(gameState.particles) + (0, _gameStateMutators.liveCount)(gameState.texts) + (0, _gameStateMutators.liveCount)(gameState.lights)) + " PARTICLES ";
else FPSDisplay.innerText = ''; else FPSDisplay.innerText = "";
FPSCounter = 0; FPSCounter = 0;
}, 1000); }, 1000);
window.addEventListener("visibilitychange", ()=>{ window.addEventListener("visibilitychange", ()=>{
@ -885,13 +888,13 @@ async function openMainMenu() {
{ {
text: (0, _i18N.t)("main_menu.settings_title"), text: (0, _i18N.t)("main_menu.settings_title"),
help: (0, _i18N.t)("main_menu.settings_help"), help: (0, _i18N.t)("main_menu.settings_help"),
icon: (0, _loadGameData.icons)['icon:settings'], icon: (0, _loadGameData.icons)["icon:settings"],
value () { value () {
openSettingsMenu(); openSettingsMenu();
} }
}, },
{ {
icon: (0, _loadGameData.icons)['icon:unlocks'], icon: (0, _loadGameData.icons)["icon:unlocks"],
text: (0, _i18N.t)("main_menu.unlocks"), text: (0, _i18N.t)("main_menu.unlocks"),
help: (0, _i18N.t)("main_menu.unlocks_help"), help: (0, _i18N.t)("main_menu.unlocks_help"),
value () { value () {
@ -899,7 +902,7 @@ async function openMainMenu() {
} }
}, },
{ {
icon: (0, _loadGameData.icons)['icon:sandbox'], icon: (0, _loadGameData.icons)["icon:sandbox"],
text: (0, _i18N.t)("sandbox.title"), text: (0, _i18N.t)("sandbox.title"),
help: (0, _settings.getTotalScore)() < creativeModeThreshold ? (0, _i18N.t)("sandbox.unlocks_at", { help: (0, _settings.getTotalScore)() < creativeModeThreshold ? (0, _i18N.t)("sandbox.unlocks_at", {
score: creativeModeThreshold score: creativeModeThreshold
@ -922,7 +925,7 @@ async function openMainMenu() {
{ {
text: (0, _i18N.t)("sandbox.start"), text: (0, _i18N.t)("sandbox.start"),
value: "start", value: "start",
icon: (0, _loadGameData.icons)['icon:continue'] icon: (0, _loadGameData.icons)["icon:continue"]
} }
] ]
})){ })){
@ -939,7 +942,7 @@ async function openMainMenu() {
} }
}, },
{ {
icon: (0, _loadGameData.icons)['icon:restart'], icon: (0, _loadGameData.icons)["icon:restart"],
text: (0, _i18N.t)("score_panel.restart"), text: (0, _i18N.t)("score_panel.restart"),
help: (0, _i18N.t)("score_panel.restart_help"), help: (0, _i18N.t)("score_panel.restart_help"),
value: ()=>{ value: ()=>{
@ -949,7 +952,7 @@ async function openMainMenu() {
} }
}, },
{ {
icon: (0, _loadGameData.icons)['icon:continue'], icon: (0, _loadGameData.icons)["icon:continue"],
text: (0, _i18N.t)("main_menu.resume"), text: (0, _i18N.t)("main_menu.resume"),
help: (0, _i18N.t)("main_menu.resume_help"), help: (0, _i18N.t)("main_menu.resume_help"),
value () {} value () {}
@ -1345,7 +1348,7 @@ const upgrades = (0, _upgrades.rawUpgrades).map((u)=>({
})); }));
},{"./data/palette.json":"ktRBU","./data/levels.json":"8JSUc","./data/version.json":"iyP6E","./upgrades":"1u3Dx","./getLevelBackground":"7OIPf","./levelIcon":"6rQoT","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"iyP6E":[function(require,module,exports,__globalThis) { },{"./data/palette.json":"ktRBU","./data/levels.json":"8JSUc","./data/version.json":"iyP6E","./upgrades":"1u3Dx","./getLevelBackground":"7OIPf","./levelIcon":"6rQoT","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"iyP6E":[function(require,module,exports,__globalThis) {
module.exports = JSON.parse("\"29044319\""); module.exports = JSON.parse("\"29045711\"");
},{}],"1u3Dx":[function(require,module,exports,__globalThis) { },{}],"1u3Dx":[function(require,module,exports,__globalThis) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
@ -1996,16 +1999,16 @@ function addToTotalScore(gameState, points) {
setSettingValue("breakout_71_total_score", getTotalScore() + points); setSettingValue("breakout_71_total_score", getTotalScore() + points);
} }
function getCurrentMaxCoins() { function getCurrentMaxCoins() {
return Math.pow(2, getSettingValue('max_coins', 1)) * 200; return Math.pow(2, getSettingValue("max_coins", 1)) * 200;
} }
function getCurrentMaxParticles() { function getCurrentMaxParticles() {
return Math.pow(2, getSettingValue('max_particles', 1)) * 200; return Math.pow(2, getSettingValue("max_particles", 1)) * 200;
} }
function cycleMaxCoins() { function cycleMaxCoins() {
setSettingValue('max_coins', (getSettingValue('max_coins', 1) + 1) % 6); setSettingValue("max_coins", (getSettingValue("max_coins", 1) + 1) % 6);
} }
function cycleMaxParticles() { function cycleMaxParticles() {
setSettingValue('max_particles', (getSettingValue('max_particles', 1) + 1) % 6); setSettingValue("max_particles", (getSettingValue("max_particles", 1) + 1) % 6);
} }
},{"@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"6rQoT":[function(require,module,exports,__globalThis) { },{"@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"6rQoT":[function(require,module,exports,__globalThis) {

View file

@ -1,5 +1,5 @@
// The version of the cache. // The version of the cache.
const VERSION = "29044319"; const VERSION = "29045711";
// The name of the cache // The name of the cache
const CACHE_NAME = `breakout-71-${VERSION}`; const CACHE_NAME = `breakout-71-${VERSION}`;

View file

@ -1 +1 @@
"29044319" "29045711"

View file

@ -67,7 +67,7 @@ body {
left: 0; left: 0;
} }
#FPSDisplay{ #FPSDisplay {
z-index: 1; z-index: 1;
white-space: nowrap; white-space: nowrap;
padding: 10px; padding: 10px;
@ -76,14 +76,14 @@ body {
user-select: none; user-select: none;
opacity: 0.8; opacity: 0.8;
color:white; color: white;
padding: 0; padding: 0;
position: fixed; position: fixed;
bottom: 0; bottom: 0;
left: 0; left: 0;
transform-origin: top left; transform-origin: top left;
transform: rotate(-90deg); transform: rotate(-90deg);
} }
body.has-alert-open { body.has-alert-open {

View file

@ -22,16 +22,18 @@ import {
import "./PWA/sw_loader"; import "./PWA/sw_loader";
import { getCurrentLang, t } from "./i18n/i18n"; import { getCurrentLang, t } from "./i18n/i18n";
import { import {
cycleMaxCoins, cycleMaxParticles, cycleMaxCoins,
cycleMaxParticles,
getCurrentMaxCoins, getCurrentMaxCoins,
getCurrentMaxParticles, getCurrentMaxParticles,
getSettingValue, getSettingValue,
getTotalScore, getTotalScore,
setSettingValue setSettingValue,
} from "./settings"; } from "./settings";
import { import {
forEachLiveOne, forEachLiveOne,
gameStateTick, liveCount, gameStateTick,
liveCount,
normalizeGameState, normalizeGameState,
pickRandomUpgrades, pickRandomUpgrades,
setLevel, setLevel,
@ -76,26 +78,29 @@ export function pause(playerAskedForPause: boolean) {
if (!gameState.running) return; if (!gameState.running) return;
if (gameState.pauseTimeout) return; if (gameState.pauseTimeout) return;
gameState.pauseTimeout = setTimeout( const stop = () => {
() => { gameState.running = false;
gameState.running = false;
setTimeout(() => { setTimeout(() => {
if (!gameState.running) getAudioContext()?.suspend(); if (!gameState.running) getAudioContext()?.suspend();
}, 1000); }, 1000);
pauseRecording(); pauseRecording();
gameState.pauseTimeout = null; gameState.pauseTimeout = null;
// document.body.className = gameState.running ? " running " : " paused "; // document.body.className = gameState.running ? " running " : " paused ";
scoreDisplay.className = ""; scoreDisplay.className = "";
gameState.needsRender = true; gameState.needsRender = true;
}, };
Math.min(Math.max(0, gameState.pauseUsesDuringRun - 5) * 50, 500),
);
if (playerAskedForPause) { if (playerAskedForPause) {
// Pausing many times in a run will make pause slower // Pausing many times in a run will make pause slower
gameState.pauseUsesDuringRun++; gameState.pauseUsesDuringRun++;
gameState.pauseTimeout = setTimeout(
stop,
Math.min(Math.max(0, gameState.pauseUsesDuringRun - 5) * 50, 500),
);
} else {
stop();
} }
if (document.exitPointerLock) { if (document.exitPointerLock) {
@ -143,6 +148,7 @@ export const fitSize = () => {
((item.x - past_off) / past_width) * gameState.gameZoneWidthRoundedUp; ((item.x - past_off) / past_width) * gameState.gameZoneWidthRoundedUp;
item.y = (item.y / past_heigh) * gameState.gameZoneHeight; item.y = (item.y / past_heigh) * gameState.gameZoneHeight;
} }
function mapXYPastCoord(coin: Coin | Ball) { function mapXYPastCoord(coin: Coin | Ball) {
coin.x = coin.x =
gameState.offsetXRoundedDown + gameState.offsetXRoundedDown +
@ -151,6 +157,7 @@ export const fitSize = () => {
coin.previousX = coin.x; coin.previousX = coin.x;
coin.previousY = coin.y; coin.previousY = coin.y;
} }
gameState.balls.forEach(mapXYPastCoord); gameState.balls.forEach(mapXYPastCoord);
forEachLiveOne(gameState.coins, mapXYPastCoord); forEachLiveOne(gameState.coins, mapXYPastCoord);
forEachLiveOne(gameState.particles, mapXY); forEachLiveOne(gameState.particles, mapXY);
@ -372,25 +379,27 @@ export function tick() {
} }
requestAnimationFrame(tick); requestAnimationFrame(tick);
FPSCounter++ FPSCounter++;
} }
let FPSCounter=0 let FPSCounter = 0;
let FPSDisplay=document.getElementById('FPSDisplay') as HTMLDivElement let FPSDisplay = document.getElementById("FPSDisplay") as HTMLDivElement;
setInterval(()=>{ setInterval(() => {
if(isOptionOn('show_fps')){ if (isOptionOn("show_fps")) {
FPSDisplay.innerText=FPSCounter+' FPS '+ FPSDisplay.innerText =
liveCount(gameState.coins)+' COINS '+ FPSCounter +
( " FPS " +
liveCount(gameState.particles)+ liveCount(gameState.coins) +
liveCount(gameState.texts)+ " COINS " +
liveCount(gameState.lights) (liveCount(gameState.particles) +
) + ' PARTICLES ' liveCount(gameState.texts) +
}else{ liveCount(gameState.lights)) +
FPSDisplay.innerText='' " PARTICLES ";
} else {
FPSDisplay.innerText = "";
} }
FPSCounter=0 FPSCounter = 0;
},1000) }, 1000);
window.addEventListener("visibilitychange", () => { window.addEventListener("visibilitychange", () => {
if (document.hidden) { if (document.hidden) {
@ -424,7 +433,7 @@ async function openScorePanel() {
<p>${t("score_panel.upgrades_picked")}</p> <p>${t("score_panel.upgrades_picked")}</p>
<p>${pickedUpgradesHTMl(gameState)}</p> <p>${pickedUpgradesHTMl(gameState)}</p>
`, `,
allowClose: true allowClose: true,
}); });
} }
@ -438,92 +447,90 @@ async function openScorePanel() {
}, },
); );
async function openMainMenu() { async function openMainMenu() {
pause(true); pause(true);
const creativeModeThreshold = Math.max(...upgrades.map((u) => u.threshold)); const creativeModeThreshold = Math.max(...upgrades.map((u) => u.threshold));
const actions:AsyncAlertAction<()=>void>[]=[{ const actions: AsyncAlertAction<() => void>[] = [
text: t("main_menu.settings_title"),
help: t("main_menu.settings_help"),
icon:icons['icon:settings'],
value() {
openSettingsMenu()
},
},{
icon:icons['icon:unlocks'],
text: t("main_menu.unlocks"),
help: t("main_menu.unlocks_help"),
value() {
openUnlocksList();
},
},{
icon:icons['icon:sandbox'],
text: t("sandbox.title"),
help:
getTotalScore() < creativeModeThreshold
? t("sandbox.unlocks_at", { score: creativeModeThreshold })
: t("sandbox.help"),
disabled: getTotalScore() < creativeModeThreshold,
async value() {
let creativeModePerks: Partial<{ [id in PerkId]: number }> =
getSettingValue("creativeModePerks", {}),
choice: "start" | Upgrade | void;
while (
(choice = await asyncAlert<"start" | Upgrade>({
title: t("sandbox.title"),
text: t("sandbox.instructions"),
actionsAsGrid: true,
actions: [
...upgrades.map((u) => ({
icon: u.icon,
text: u.name,
help: (creativeModePerks[u.id] || 0) + "/" + u.max,
value: u,
className: creativeModePerks[u.id]
? ""
: "grey-out-unless-hovered",
})),
{
text: t("sandbox.start"),
value: "start",
icon:icons['icon:continue'],
},
],
}))
) {
if (choice === "start") {
restart({ perks: creativeModePerks });
break
} else if (choice) {
creativeModePerks[choice.id] =
((creativeModePerks[choice.id] || 0) + 1) % (choice.max + 1);
setSettingValue("creativeModePerks", creativeModePerks);
}
}
},
},
{
icon:icons['icon:restart'],
text: t("score_panel.restart"),
help: t("score_panel.restart_help"),
value: () => {
restart({ levelToAvoid: currentLevelInfo(gameState).name });
},
},
{ {
icon:icons['icon:continue'], text: t("main_menu.settings_title"),
text: t("main_menu.resume"), help: t("main_menu.settings_help"),
help: t("main_menu.resume_help"), icon: icons["icon:settings"],
value() {}, value() {
}, openSettingsMenu();
] ; },
},
{
icon: icons["icon:unlocks"],
text: t("main_menu.unlocks"),
help: t("main_menu.unlocks_help"),
value() {
openUnlocksList();
},
},
{
icon: icons["icon:sandbox"],
text: t("sandbox.title"),
help:
getTotalScore() < creativeModeThreshold
? t("sandbox.unlocks_at", { score: creativeModeThreshold })
: t("sandbox.help"),
disabled: getTotalScore() < creativeModeThreshold,
async value() {
let creativeModePerks: Partial<{ [id in PerkId]: number }> =
getSettingValue("creativeModePerks", {}),
choice: "start" | Upgrade | void;
while (
(choice = await asyncAlert<"start" | Upgrade>({
title: t("sandbox.title"),
text: t("sandbox.instructions"),
actionsAsGrid: true,
actions: [
...upgrades.map((u) => ({
icon: u.icon,
text: u.name,
help: (creativeModePerks[u.id] || 0) + "/" + u.max,
value: u,
className: creativeModePerks[u.id]
? ""
: "grey-out-unless-hovered",
})),
{
text: t("sandbox.start"),
value: "start",
icon: icons["icon:continue"],
},
],
}))
) {
if (choice === "start") {
restart({ perks: creativeModePerks });
break;
} else if (choice) {
creativeModePerks[choice.id] =
((creativeModePerks[choice.id] || 0) + 1) % (choice.max + 1);
setSettingValue("creativeModePerks", creativeModePerks);
}
}
},
},
{
icon: icons["icon:restart"],
text: t("score_panel.restart"),
help: t("score_panel.restart_help"),
value: () => {
restart({ levelToAvoid: currentLevelInfo(gameState).name });
},
},
{
icon: icons["icon:continue"],
text: t("main_menu.resume"),
help: t("main_menu.resume_help"),
value() {},
},
];
const cb = await asyncAlert<() => void>({ const cb = await asyncAlert<() => void>({
title: t("main_menu.title"), title: t("main_menu.title"),
@ -764,21 +771,20 @@ async function openSettingsMenu() {
}, },
}); });
actions.push({ actions.push({
text: t("main_menu.max_coins",{max:getCurrentMaxCoins()}), text: t("main_menu.max_coins", { max: getCurrentMaxCoins() }),
help: t("main_menu.max_coins_help"), help: t("main_menu.max_coins_help"),
async value() { async value() {
cycleMaxCoins() cycleMaxCoins();
await openSettingsMenu() await openSettingsMenu();
}, },
}); });
actions.push({ actions.push({
text: t("main_menu.max_particles",{max:getCurrentMaxParticles()}), text: t("main_menu.max_particles", { max: getCurrentMaxParticles() }),
help: t("main_menu.max_particles_help"), help: t("main_menu.max_particles_help"),
async value() { async value() {
cycleMaxParticles() cycleMaxParticles();
await openSettingsMenu() await openSettingsMenu();
}, },
}); });
@ -789,9 +795,9 @@ async function openSettingsMenu() {
}); });
const cb = await asyncAlert<() => void>({ const cb = await asyncAlert<() => void>({
title: t("main_menu.settings_title"), title: t("main_menu.settings_title"),
text: t("main_menu.settings_help"), text: t("main_menu.settings_help"),
allowClose: true, allowClose: true,
actions actions,
}); });
if (cb) { if (cb) {
cb(); cb();

View file

@ -31,7 +31,11 @@ import {
import { t } from "./i18n/i18n"; import { t } from "./i18n/i18n";
import { icons } from "./loadGameData"; import { icons } from "./loadGameData";
import {addToTotalScore, getCurrentMaxCoins, getCurrentMaxParticles} from "./settings"; import {
addToTotalScore,
getCurrentMaxCoins,
getCurrentMaxParticles,
} from "./settings";
import { background } from "./render"; import { background } from "./render";
import { gameOver } from "./gameOver"; import { gameOver } from "./gameOver";
import { import {

View file

@ -1,8 +1,6 @@
import { Ball, GameState, PerkId, PerksMap } from "./types"; import { Ball, GameState, PerkId, PerksMap } from "./types";
import { icons, upgrades } from "./loadGameData"; import { icons, upgrades } from "./loadGameData";
export function getMajorityValue(arr: string[]): string { export function getMajorityValue(arr: string[]): string {
const count: { [k: string]: number } = {}; const count: { [k: string]: number } = {};
arr.forEach((v) => (count[v] = (count[v] || 0) + 1)); arr.forEach((v) => (count[v] = (count[v] || 0) + 1));

View file

@ -34,16 +34,18 @@ export function addToTotalScore(gameState: GameState, points: number) {
setSettingValue("breakout_71_total_score", getTotalScore() + points); setSettingValue("breakout_71_total_score", getTotalScore() + points);
} }
export function getCurrentMaxCoins() {
export function getCurrentMaxCoins(){ return Math.pow(2, getSettingValue("max_coins", 1)) * 200;
return Math.pow(2,getSettingValue('max_coins', 1))*200
} }
export function getCurrentMaxParticles(){ export function getCurrentMaxParticles() {
return Math.pow(2,getSettingValue('max_particles', 1))*200 return Math.pow(2, getSettingValue("max_particles", 1)) * 200;
} }
export function cycleMaxCoins(){ export function cycleMaxCoins() {
setSettingValue('max_coins', (getSettingValue('max_coins', 1)+1)%6) setSettingValue("max_coins", (getSettingValue("max_coins", 1) + 1) % 6);
} }
export function cycleMaxParticles(){ export function cycleMaxParticles() {
setSettingValue('max_particles', (getSettingValue('max_particles', 1)+1)%6) setSettingValue(
"max_particles",
(getSettingValue("max_particles", 1) + 1) % 6,
);
} }