From a89a61e35bb674c5cefa3d7fa799c04d030504d0 Mon Sep 17 00:00:00 2001 From: Renan LE CARO Date: Sun, 23 Mar 2025 16:11:12 +0100 Subject: [PATCH] Build 29045711 --- Readme.md | 43 ++++-- app/build.gradle.kts | 4 +- app/src/main/assets/index.html | 2 +- dist/index.html | 39 ++--- src/PWA/sw-b71.js | 2 +- src/data/levels.json | 2 +- src/data/version.json | 2 +- src/game.less | 18 +-- src/game.ts | 252 +++++++++++++++++---------------- src/gameStateMutators.ts | 6 +- src/game_utils.ts | 2 - src/settings.ts | 22 +-- 12 files changed, 212 insertions(+), 182 deletions(-) diff --git a/Readme.md b/Readme.md index 6d94ee0..7c9ecb8 100644 --- a/Readme.md +++ b/Readme.md @@ -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. # 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 .. - second puck (symmetric to the first one) - 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 - 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 : - 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 - 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 - 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". @@ -186,23 +212,14 @@ 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. # increase skill ceiling + - reroll mechanic, rerolls are reward for better play - 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) - 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. - + # Colin's feedback (cwpute/obigre) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f15043b..c0a5e67 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -11,8 +11,8 @@ android { applicationId = "me.lecaro.breakout" minSdk = 21 targetSdk = 34 - versionCode = 29044319 - versionName = "29044319" + versionCode = 29045711 + versionName = "29045711" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true diff --git a/app/src/main/assets/index.html b/app/src/main/assets/index.html index c3c03fb..608b2f6 100644 --- a/app/src/main/assets/index.html +++ b/app/src/main/assets/index.html @@ -1 +1 @@ -Breakout 71 \ No newline at end of file +Breakout 71
\ No newline at end of file diff --git a/dist/index.html b/dist/index.html index 632037a..bc3a963 100644 --- a/dist/index.html +++ b/dist/index.html @@ -642,7 +642,7 @@ function play() { function pause(playerAskedForPause) { if (!gameState.running) return; if (gameState.pauseTimeout) return; - gameState.pauseTimeout = setTimeout(()=>{ + const stop = ()=>{ gameState.running = false; setTimeout(()=>{ if (!gameState.running) (0, _sounds.getAudioContext)()?.suspend(); @@ -652,9 +652,12 @@ function pause(playerAskedForPause) { // document.body.className = gameState.running ? " running " : " paused "; (0, _render.scoreDisplay).className = ""; 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 - gameState.pauseUsesDuringRun++; + }; + if (playerAskedForPause) { + // 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(); } const fitSize = ()=>{ @@ -842,10 +845,10 @@ function tick() { FPSCounter++; } let FPSCounter = 0; -let FPSDisplay = document.getElementById('FPSDisplay'); +let FPSDisplay = document.getElementById("FPSDisplay"); 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 '; - else FPSDisplay.innerText = ''; + 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 = ""; FPSCounter = 0; }, 1000); window.addEventListener("visibilitychange", ()=>{ @@ -885,13 +888,13 @@ async function openMainMenu() { { text: (0, _i18N.t)("main_menu.settings_title"), help: (0, _i18N.t)("main_menu.settings_help"), - icon: (0, _loadGameData.icons)['icon:settings'], + icon: (0, _loadGameData.icons)["icon:settings"], value () { openSettingsMenu(); } }, { - icon: (0, _loadGameData.icons)['icon:unlocks'], + icon: (0, _loadGameData.icons)["icon:unlocks"], text: (0, _i18N.t)("main_menu.unlocks"), help: (0, _i18N.t)("main_menu.unlocks_help"), 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"), help: (0, _settings.getTotalScore)() < creativeModeThreshold ? (0, _i18N.t)("sandbox.unlocks_at", { score: creativeModeThreshold @@ -922,7 +925,7 @@ async function openMainMenu() { { text: (0, _i18N.t)("sandbox.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"), help: (0, _i18N.t)("score_panel.restart_help"), 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"), help: (0, _i18N.t)("main_menu.resume_help"), 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) { -module.exports = JSON.parse("\"29044319\""); +module.exports = JSON.parse("\"29045711\""); },{}],"1u3Dx":[function(require,module,exports,__globalThis) { 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); } function getCurrentMaxCoins() { - return Math.pow(2, getSettingValue('max_coins', 1)) * 200; + return Math.pow(2, getSettingValue("max_coins", 1)) * 200; } function getCurrentMaxParticles() { - return Math.pow(2, getSettingValue('max_particles', 1)) * 200; + return Math.pow(2, getSettingValue("max_particles", 1)) * 200; } function cycleMaxCoins() { - setSettingValue('max_coins', (getSettingValue('max_coins', 1) + 1) % 6); + setSettingValue("max_coins", (getSettingValue("max_coins", 1) + 1) % 6); } 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) { diff --git a/src/PWA/sw-b71.js b/src/PWA/sw-b71.js index da13334..1d03647 100644 --- a/src/PWA/sw-b71.js +++ b/src/PWA/sw-b71.js @@ -1,5 +1,5 @@ // The version of the cache. -const VERSION = "29044319"; +const VERSION = "29045711"; // The name of the cache const CACHE_NAME = `breakout-71-${VERSION}`; diff --git a/src/data/levels.json b/src/data/levels.json index 7ceea9a..10e5291 100644 --- a/src/data/levels.json +++ b/src/data/levels.json @@ -990,4 +990,4 @@ "svg": null, "color": "" } -] \ No newline at end of file +] diff --git a/src/data/version.json b/src/data/version.json index 4b6c968..8848037 100644 --- a/src/data/version.json +++ b/src/data/version.json @@ -1 +1 @@ -"29044319" +"29045711" diff --git a/src/game.less b/src/game.less index 0122fee..939c7a5 100644 --- a/src/game.less +++ b/src/game.less @@ -67,7 +67,7 @@ body { left: 0; } -#FPSDisplay{ +#FPSDisplay { z-index: 1; white-space: nowrap; padding: 10px; @@ -75,15 +75,15 @@ body { pointer-events: none; user-select: none; opacity: 0.8; - - color:white; - padding: 0; - position: fixed; - bottom: 0; - left: 0; - transform-origin: top left; - transform: rotate(-90deg); + color: white; + padding: 0; + position: fixed; + + bottom: 0; + left: 0; + transform-origin: top left; + transform: rotate(-90deg); } body.has-alert-open { diff --git a/src/game.ts b/src/game.ts index 59c30f5..56abe0a 100644 --- a/src/game.ts +++ b/src/game.ts @@ -22,16 +22,18 @@ import { import "./PWA/sw_loader"; import { getCurrentLang, t } from "./i18n/i18n"; import { - cycleMaxCoins, cycleMaxParticles, + cycleMaxCoins, + cycleMaxParticles, getCurrentMaxCoins, getCurrentMaxParticles, getSettingValue, getTotalScore, - setSettingValue + setSettingValue, } from "./settings"; import { forEachLiveOne, - gameStateTick, liveCount, + gameStateTick, + liveCount, normalizeGameState, pickRandomUpgrades, setLevel, @@ -76,26 +78,29 @@ export function pause(playerAskedForPause: boolean) { if (!gameState.running) return; if (gameState.pauseTimeout) return; - gameState.pauseTimeout = setTimeout( - () => { - gameState.running = false; + const stop = () => { + gameState.running = false; - setTimeout(() => { - if (!gameState.running) getAudioContext()?.suspend(); - }, 1000); + setTimeout(() => { + if (!gameState.running) getAudioContext()?.suspend(); + }, 1000); - pauseRecording(); - gameState.pauseTimeout = null; - // document.body.className = gameState.running ? " running " : " paused "; - scoreDisplay.className = ""; - gameState.needsRender = true; - }, - Math.min(Math.max(0, gameState.pauseUsesDuringRun - 5) * 50, 500), - ); + pauseRecording(); + gameState.pauseTimeout = null; + // document.body.className = gameState.running ? " running " : " paused "; + scoreDisplay.className = ""; + gameState.needsRender = true; + }; if (playerAskedForPause) { // 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) { @@ -143,6 +148,7 @@ export const fitSize = () => { ((item.x - past_off) / past_width) * gameState.gameZoneWidthRoundedUp; item.y = (item.y / past_heigh) * gameState.gameZoneHeight; } + function mapXYPastCoord(coin: Coin | Ball) { coin.x = gameState.offsetXRoundedDown + @@ -151,6 +157,7 @@ export const fitSize = () => { coin.previousX = coin.x; coin.previousY = coin.y; } + gameState.balls.forEach(mapXYPastCoord); forEachLiveOne(gameState.coins, mapXYPastCoord); forEachLiveOne(gameState.particles, mapXY); @@ -372,25 +379,27 @@ export function tick() { } requestAnimationFrame(tick); - FPSCounter++ + FPSCounter++; } -let FPSCounter=0 -let FPSDisplay=document.getElementById('FPSDisplay') as HTMLDivElement -setInterval(()=>{ - if(isOptionOn('show_fps')){ - FPSDisplay.innerText=FPSCounter+' FPS '+ - liveCount(gameState.coins)+' COINS '+ - ( - liveCount(gameState.particles)+ - liveCount(gameState.texts)+ - liveCount(gameState.lights) - ) + ' PARTICLES ' - }else{ - FPSDisplay.innerText='' +let FPSCounter = 0; +let FPSDisplay = document.getElementById("FPSDisplay") as HTMLDivElement; +setInterval(() => { + if (isOptionOn("show_fps")) { + FPSDisplay.innerText = + FPSCounter + + " FPS " + + liveCount(gameState.coins) + + " COINS " + + (liveCount(gameState.particles) + + liveCount(gameState.texts) + + liveCount(gameState.lights)) + + " PARTICLES "; + } else { + FPSDisplay.innerText = ""; } - FPSCounter=0 -},1000) + FPSCounter = 0; +}, 1000); window.addEventListener("visibilitychange", () => { if (document.hidden) { @@ -424,7 +433,7 @@ async function openScorePanel() {

${t("score_panel.upgrades_picked")}

${pickedUpgradesHTMl(gameState)}

`, - allowClose: true + allowClose: true, }); } @@ -438,92 +447,90 @@ async function openScorePanel() { }, ); - async function openMainMenu() { pause(true); - const creativeModeThreshold = Math.max(...upgrades.map((u) => u.threshold)); - 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 }); - }, - }, + const actions: AsyncAlertAction<() => void>[] = [ { - icon:icons['icon:continue'], - text: t("main_menu.resume"), - help: t("main_menu.resume_help"), - value() {}, - }, - ] ; + 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.resume"), + help: t("main_menu.resume_help"), + value() {}, + }, + ]; const cb = await asyncAlert<() => void>({ title: t("main_menu.title"), @@ -764,21 +771,20 @@ async function openSettingsMenu() { }, }); - 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"), async value() { - cycleMaxCoins() - await openSettingsMenu() + cycleMaxCoins(); + await openSettingsMenu(); }, }); 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"), async value() { - cycleMaxParticles() - await openSettingsMenu() + cycleMaxParticles(); + await openSettingsMenu(); }, }); @@ -789,9 +795,9 @@ async function openSettingsMenu() { }); const cb = await asyncAlert<() => void>({ title: t("main_menu.settings_title"), - text: t("main_menu.settings_help"), + text: t("main_menu.settings_help"), allowClose: true, - actions + actions, }); if (cb) { cb(); diff --git a/src/gameStateMutators.ts b/src/gameStateMutators.ts index 7dcb3d1..b80abe7 100644 --- a/src/gameStateMutators.ts +++ b/src/gameStateMutators.ts @@ -31,7 +31,11 @@ import { import { t } from "./i18n/i18n"; import { icons } from "./loadGameData"; -import {addToTotalScore, getCurrentMaxCoins, getCurrentMaxParticles} from "./settings"; +import { + addToTotalScore, + getCurrentMaxCoins, + getCurrentMaxParticles, +} from "./settings"; import { background } from "./render"; import { gameOver } from "./gameOver"; import { diff --git a/src/game_utils.ts b/src/game_utils.ts index a796dd2..7d44f4a 100644 --- a/src/game_utils.ts +++ b/src/game_utils.ts @@ -1,8 +1,6 @@ import { Ball, GameState, PerkId, PerksMap } from "./types"; import { icons, upgrades } from "./loadGameData"; - - export function getMajorityValue(arr: string[]): string { const count: { [k: string]: number } = {}; arr.forEach((v) => (count[v] = (count[v] || 0) + 1)); diff --git a/src/settings.ts b/src/settings.ts index 790fa30..c8f4d8a 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -34,16 +34,18 @@ export function addToTotalScore(gameState: GameState, points: number) { setSettingValue("breakout_71_total_score", getTotalScore() + points); } - -export function getCurrentMaxCoins(){ - return Math.pow(2,getSettingValue('max_coins', 1))*200 +export function getCurrentMaxCoins() { + return Math.pow(2, getSettingValue("max_coins", 1)) * 200; } -export function getCurrentMaxParticles(){ - return Math.pow(2,getSettingValue('max_particles', 1))*200 +export function getCurrentMaxParticles() { + return Math.pow(2, getSettingValue("max_particles", 1)) * 200; } -export function cycleMaxCoins(){ - setSettingValue('max_coins', (getSettingValue('max_coins', 1)+1)%6) +export function cycleMaxCoins() { + setSettingValue("max_coins", (getSettingValue("max_coins", 1) + 1) % 6); +} +export function cycleMaxParticles() { + setSettingValue( + "max_particles", + (getSettingValue("max_particles", 1) + 1) % 6, + ); } -export function cycleMaxParticles(){ - setSettingValue('max_particles', (getSettingValue('max_particles', 1)+1)%6) -} \ No newline at end of file