mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-20 04:05:06 -04:00
Build 29045711
This commit is contained in:
parent
2022b41937
commit
a89a61e35b
12 changed files with 212 additions and 182 deletions
41
Readme.md
41
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,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.
|
||||
|
||||
# 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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because one or more lines are too long
39
dist/index.html
vendored
39
dist/index.html
vendored
|
@ -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) {
|
||||
|
|
|
@ -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}`;
|
||||
|
|
|
@ -1 +1 @@
|
|||
"29044319"
|
||||
"29045711"
|
||||
|
|
|
@ -67,7 +67,7 @@ body {
|
|||
left: 0;
|
||||
}
|
||||
|
||||
#FPSDisplay{
|
||||
#FPSDisplay {
|
||||
z-index: 1;
|
||||
white-space: nowrap;
|
||||
padding: 10px;
|
||||
|
@ -76,14 +76,14 @@ body {
|
|||
user-select: none;
|
||||
opacity: 0.8;
|
||||
|
||||
color:white;
|
||||
padding: 0;
|
||||
position: fixed;
|
||||
color: white;
|
||||
padding: 0;
|
||||
position: fixed;
|
||||
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
transform-origin: top left;
|
||||
transform: rotate(-90deg);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
transform-origin: top left;
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
body.has-alert-open {
|
||||
|
|
252
src/game.ts
252
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() {
|
|||
<p>${t("score_panel.upgrades_picked")}</p>
|
||||
<p>${pickedUpgradesHTMl(gameState)}</p>
|
||||
`,
|
||||
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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue