mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-20 04:05:06 -04:00
Made the "combo lost" text last 500ms instead of the pointless 150ms
This commit is contained in:
parent
da89cdb647
commit
23798c4e58
9 changed files with 262 additions and 265 deletions
109
Readme.md
109
Readme.md
|
@ -13,56 +13,75 @@ Break colourful bricks, catch bouncing coins and select powerful upgrades !
|
||||||
- [GitLab](https://gitlab.com/lecarore/breakout71)
|
- [GitLab](https://gitlab.com/lecarore/breakout71)
|
||||||
- [HackerNews thread](https://news.ycombinator.com/item?id=43183131)
|
- [HackerNews thread](https://news.ycombinator.com/item?id=43183131)
|
||||||
|
|
||||||
|
|
||||||
# Premium: allow looping
|
|
||||||
|
|
||||||
Allow players to loop the game :
|
|
||||||
- keep your score
|
|
||||||
- keep 1 perk, level it up beyond the max
|
|
||||||
- ban all other perks
|
|
||||||
- unlock all upgrades in loop 1+
|
|
||||||
|
|
||||||
Hard to scale :
|
|
||||||
- concave_puck
|
|
||||||
- instant_upgrade
|
|
||||||
- etherealcoins (0 grav, maybe then start floting like helium ? maybe less viscosity)
|
|
||||||
- shocks (maybe spawn balls during the explosion ? maybe bigger explosions for this)
|
|
||||||
- ghost_coins : pass through bricks will less friction ?
|
|
||||||
- clairvoyant
|
|
||||||
|
|
||||||
|
|
||||||
# Todo
|
|
||||||
- Make fullscreen an option and turn it back on when playing
|
|
||||||
- real time stats as the option says.
|
|
||||||
- weee sound when ball lost to side or sky
|
|
||||||
|
|
||||||
- [jaceys] Counters for coins lost, misses, and boundary bounces, as well as a timer.
|
|
||||||
|
|
||||||
- people assume unbounded allows for wrap around
|
|
||||||
- coin magnet and viscosity : only one level ~2.5
|
|
||||||
- Boost Ascetism : give +2 or even +3 combo per brick destroyed
|
|
||||||
- wind : move coins based on puck movement not position
|
|
||||||
- show -N points in red when combo resets
|
|
||||||
- reach is too punishing now, maybe only reset if you hit the lowest populate row of the level, if it's not a full width row
|
|
||||||
- respawn: N% of bricks respawn after N seconds
|
|
||||||
- [jaceys] Move the restart button out of the menu, so that it is more easily accessible
|
|
||||||
- [jaceys] A visual indication of whether a ball has hit a brick this serve
|
|
||||||
- [obigre] Offer to level ups perks separately
|
|
||||||
- bring back detailed help of perks as "intel"
|
|
||||||
- https://weblate.org/fr/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# System requirements
|
# System requirements
|
||||||
|
|
||||||
Breakout 71 can work offline (add it to home screen) and perform well even on low-end devices.
|
Breakout 71 can work offline (add it to home screen) and perform well even on low-end devices.
|
||||||
It's very lean and does not take much storage space (Roughly 0.1MB).
|
It's very lean and does not take much storage space (Roughly 0.1MB).
|
||||||
If the app stutters, turn on "fast mode" in the settings to render a simplified view that should be faster.
|
If the app stutters, turn on "fast mode" in the settings to render a simplified view that should be faster.
|
||||||
There's also an easy mode for kids (slower ball).
|
There's also an easy mode for kids (slower ball).
|
||||||
|
|
||||||
|
# Looping
|
||||||
|
|
||||||
|
Premium users can loop the game to continue player a harder and harder version of the game.
|
||||||
|
At the end of the last level of each run, they can start a new loop. They'll be taken back
|
||||||
|
to level 1, with only one of their perks, leveled up. All the other perks they used in the run
|
||||||
|
will be banned from the pool. The perk they decide to keep will gain one level, even if it was
|
||||||
|
already maxed out.
|
||||||
|
|
||||||
|
# Todo before next release
|
||||||
|
- b71 white border around dark coins
|
||||||
|
|
||||||
|
- [jaceys] Counters for coins lost, misses, and boundary bounces, as well as a timer.
|
||||||
|
- wind : move coins based on puck movement not position
|
||||||
|
- show -N points in red when combo resets
|
||||||
|
- Top down /read: punishing now, maybe only reset if you hit the lowest populate row of the level, if it's not a full width row
|
||||||
|
- [jaceys] Move the restart button out of the menu, so that it is more easily accessible
|
||||||
|
- [jaceys] A visual indication of whether a ball has hit a brick this serve
|
||||||
|
|
||||||
# UX
|
- scale concave_puck
|
||||||
|
- scale instant_upgrade
|
||||||
|
- scale etherealcoins (0 grav, maybe then start floting like helium ? maybe less viscosity)
|
||||||
|
- scale shocks (maybe spawn balls during the explosion ? maybe bigger explosions for this)
|
||||||
|
- scale ghost_coins : pass through bricks will less friction ?
|
||||||
|
- scale clairvoyant
|
||||||
|
|
||||||
|
# 29 march 2025
|
||||||
|
|
||||||
|
|
||||||
|
- Removed all previous loop only hazards
|
||||||
|
- Looping now bans all your perks except one. That one can level up beyond the normal max.
|
||||||
|
- Adjusted many perks to work beyond the max
|
||||||
|
- Split list of perks and levels in unlocks
|
||||||
|
- Asceticism now gives +3 combo per lvl
|
||||||
|
- Fortunate ball has a stronger effect
|
||||||
|
- Bigger puck : puck can now cover the whole screen at higher levels, but not more
|
||||||
|
- Corner shot : higher levels let you move further away from the play area
|
||||||
|
- Forgiving : level 2 halves the penalty, level 3 is a third ..
|
||||||
|
- Helium : stronger anti gravity at higher levels
|
||||||
|
- Implosions : works like bigger-explosions at higher levels
|
||||||
|
- Metamorphosis : coins can stain more bricks at higher levels
|
||||||
|
- Re-spawn : now delay based and probabilistic, to scale more easily with higher levels. no need to hit the puck
|
||||||
|
- sacrifice : at level 2+ the combo is doubles/tripled just before clearing the screen of any bricks
|
||||||
|
- shunt : changed the math keep 25% of combo at level 1,50% at level 2,63% at level 3,70% at level 4..
|
||||||
|
- soft reset : same math as shunt
|
||||||
|
- smaller puck : now the puck can get as small as a ball
|
||||||
|
- Unbounded : at level 2+, the top of the level is gone too
|
||||||
|
- Make fullscreen an option and turn it back on when playing
|
||||||
|
- Made the "combo lost" text last 500ms instead of the pointless 150ms
|
||||||
|
|
||||||
|
# 28 march 2025
|
||||||
|
|
||||||
|
- loop : added red/blue coins (red kill you, blue freeze puck) (removed later)
|
||||||
|
- added more hazard that were then removed
|
||||||
|
- add a toggle to switch between the “coin” design and colored bubbles
|
||||||
|
|
||||||
|
# UX / gameplay
|
||||||
|
|
||||||
|
- on mobile, relative movement of the touch would be amplified and added to the puck
|
||||||
|
- option : don't pause on mobile when lifting finger
|
||||||
|
- [obigre] Offer to level ups perks separately
|
||||||
|
- bring back detailed help of perks as "intel"
|
||||||
|
- https://weblate.org/fr/
|
||||||
- strict sample size red borders ?
|
- strict sample size red borders ?
|
||||||
- add some tutorial-like hints
|
- add some tutorial-like hints
|
||||||
- It's a bit confusing at first to grasp that one upgrade is applied randomly at the start of the game. Offer instead to skip lvl 1 and directly pick 4 perks, but only if you manage to clear lvl 1 with 4 upgrades.
|
- It's a bit confusing at first to grasp that one upgrade is applied randomly at the start of the game. Offer instead to skip lvl 1 and directly pick 4 perks, but only if you manage to clear lvl 1 with 4 upgrades.
|
||||||
|
@ -95,7 +114,7 @@ There's also an easy mode for kids (slower ball).
|
||||||
- Overgrowth — when the ball touches a bomb brick it turns into a regular green brick and spawns 1 more bricks near it (additional levels spawn 2 additional bricks)
|
- Overgrowth — when the ball touches a bomb brick it turns into a regular green brick and spawns 1 more bricks near it (additional levels spawn 2 additional bricks)
|
||||||
|
|
||||||
# graphics
|
# graphics
|
||||||
|
- Waterline under the puck, coins slow down a lot, reflections
|
||||||
- webgl rendering: background gradient light map, shinier coins
|
- webgl rendering: background gradient light map, shinier coins
|
||||||
- experiment with showing the combo somewhere else, maybe top center, maybe instead of score.
|
- experiment with showing the combo somewhere else, maybe top center, maybe instead of score.
|
||||||
|
|
||||||
|
@ -201,12 +220,6 @@ There's also an easy mode for kids (slower ball).
|
||||||
- animals
|
- animals
|
||||||
- countries flags and shapes
|
- countries flags and shapes
|
||||||
|
|
||||||
# extra settings
|
|
||||||
|
|
||||||
- add a toggle to switch between the “coin” design and colored bubbles
|
|
||||||
- on mobile, relative movement of the touch would be amplified and added to the puck
|
|
||||||
- option : don't pause on mobile when lifting finger
|
|
||||||
|
|
||||||
|
|
||||||
# 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..
|
||||||
|
|
171
dist/index.html
vendored
171
dist/index.html
vendored
File diff suppressed because one or more lines are too long
166
src/game.ts
166
src/game.ts
|
@ -43,6 +43,7 @@ import {hashCode} from "./getLevelBackground";
|
||||||
import {premiumMenuEntry} from "./premium";
|
import {premiumMenuEntry} from "./premium";
|
||||||
|
|
||||||
export function play() {
|
export function play() {
|
||||||
|
if (applyFullScreenChoice()) return;
|
||||||
if (gameState.running) return;
|
if (gameState.running) return;
|
||||||
gameState.running = true;
|
gameState.running = true;
|
||||||
gameState.ballStickToPuck = false;
|
gameState.ballStickToPuck = false;
|
||||||
|
@ -50,7 +51,6 @@ export function play() {
|
||||||
startRecordingGame(gameState);
|
startRecordingGame(gameState);
|
||||||
getAudioContext()?.resume();
|
getAudioContext()?.resume();
|
||||||
resumeRecording();
|
resumeRecording();
|
||||||
|
|
||||||
// document.body.classList[gameState.running ? 'add' : 'remove']('running')
|
// document.body.classList[gameState.running ? 'add' : 'remove']('running')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,36 +571,12 @@ async function openSettingsMenu() {
|
||||||
help: options[key].help,
|
help: options[key].help,
|
||||||
value: () => {
|
value: () => {
|
||||||
toggleOption(key);
|
toggleOption(key);
|
||||||
if (key === "mobile-mode") fitSize();
|
fitSize();
|
||||||
|
applyFullScreenChoice()
|
||||||
openSettingsMenu();
|
openSettingsMenu();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (document.fullscreenEnabled || document.webkitFullscreenEnabled) {
|
|
||||||
if (document.fullscreenElement !== null) {
|
|
||||||
actions.push({
|
|
||||||
text: t("main_menu.fullscreen_exit"),
|
|
||||||
help: t("main_menu.fullscreen_exit_help"),
|
|
||||||
icon: icons["icon:exit_fullscreen"],
|
|
||||||
value() {
|
|
||||||
toggleFullScreen();
|
|
||||||
openSettingsMenu();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
actions.push({
|
|
||||||
text: t("main_menu.fullscreen"),
|
|
||||||
help: t("main_menu.fullscreen_help"),
|
|
||||||
|
|
||||||
icon: icons["icon:fullscreen"],
|
|
||||||
value() {
|
|
||||||
toggleFullScreen();
|
|
||||||
openSettingsMenu();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions.push({
|
actions.push({
|
||||||
text: t("main_menu.reset"),
|
text: t("main_menu.reset"),
|
||||||
help: t("main_menu.reset_help"),
|
help: t("main_menu.reset_help"),
|
||||||
|
@ -818,51 +794,84 @@ async function openSettingsMenu() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function applyFullScreenChoice(): boolean {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!(document.fullscreenEnabled || document.webkitFullscreenEnabled)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.fullscreenElement !== null && !isOptionOn("fullscreen")) {
|
||||||
|
if (document.exitFullscreen) {
|
||||||
|
document.exitFullscreen();
|
||||||
|
return true
|
||||||
|
} else if (document.webkitCancelFullScreen) {
|
||||||
|
document.webkitCancelFullScreen();
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else if (isOptionOn("fullscreen") && !document.fullscreenElement) {
|
||||||
|
const docel = document.documentElement;
|
||||||
|
if (docel.requestFullscreen) {
|
||||||
|
docel.requestFullscreen();
|
||||||
|
return true
|
||||||
|
} else if (docel.webkitRequestFullscreen) {
|
||||||
|
docel.webkitRequestFullscreen();
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(e);
|
||||||
|
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async function openUnlocksList() {
|
async function openUnlocksList() {
|
||||||
const ts = getTotalScore();
|
const ts = getTotalScore();
|
||||||
const actions = [
|
const upgradeActions = upgrades
|
||||||
...upgrades
|
.sort((a, b) => a.threshold - b.threshold)
|
||||||
.sort((a, b) => a.threshold - b.threshold)
|
.map(({name, id, threshold, icon, help}) => ({
|
||||||
.map(({name, id, threshold, icon, help}) => ({
|
text: name,
|
||||||
text: name,
|
// help:
|
||||||
// help:
|
// ts >= threshold ? help(1) : t("unlocks.unlocks_at", { threshold }),
|
||||||
// ts >= threshold ? help(1) : t("unlocks.unlocks_at", { threshold }),
|
disabled: ts < threshold,
|
||||||
disabled: ts < threshold,
|
value: {perks: {[id]: 1}} as RunParams,
|
||||||
value: {perks: {[id]: 1}} as RunParams,
|
icon,
|
||||||
icon,
|
}))
|
||||||
})),
|
|
||||||
...allLevels
|
const levelActions = allLevels
|
||||||
.sort((a, b) => a.threshold - b.threshold)
|
.sort((a, b) => a.threshold - b.threshold)
|
||||||
.map((l) => {
|
.map((l) => {
|
||||||
const available = ts >= l.threshold;
|
const available = ts >= l.threshold;
|
||||||
return {
|
return {
|
||||||
text: l.name,
|
text: l.name,
|
||||||
// help: available
|
// help: available
|
||||||
// ? t("unlocks.level_description", {
|
// ? t("unlocks.level_description", {
|
||||||
// size: l.size,
|
// size: l.size,
|
||||||
// bricks: l.bricks.filter((i) => i).length,
|
// bricks: l.bricks.filter((i) => i).length,
|
||||||
// })
|
// })
|
||||||
// : t("unlocks.unlocks_at", { threshold: l.threshold }),
|
// : t("unlocks.unlocks_at", { threshold: l.threshold }),
|
||||||
disabled: !available,
|
disabled: !available,
|
||||||
value: {level: l.name} as RunParams,
|
value: {level: l.name} as RunParams,
|
||||||
icon: icons[l.name],
|
icon: icons[l.name],
|
||||||
};
|
};
|
||||||
}),
|
})
|
||||||
];
|
|
||||||
|
|
||||||
const percentUnlock = Math.round(
|
const percentUnlock = Math.round(
|
||||||
(actions.filter((a) => !a.disabled).length / actions.length) * 100,
|
([...upgradeActions, ...levelActions].filter((a) => !a.disabled).length / (upgradeActions.length +
|
||||||
|
levelActions.length)) * 100,
|
||||||
);
|
);
|
||||||
const tryOn = await asyncAlert<RunParams>({
|
const tryOn = await asyncAlert<RunParams>({
|
||||||
title: t("unlocks.title", {percentUnlock}),
|
title: t("unlocks.title", {percentUnlock}),
|
||||||
content: [
|
content: [
|
||||||
`<p>${t("unlocks.intro", {ts})}
|
`<p>${t("unlocks.intro", {ts, highScore: gameState.highScore})}
|
||||||
${percentUnlock < 100 ? t("unlocks.greyed_out_help") : ""}</p> `,
|
${percentUnlock < 100 ? t("unlocks.greyed_out_help") : ""}</p> `,
|
||||||
...actions,
|
...upgradeActions,
|
||||||
`<p>
|
t("unlocks.level"),
|
||||||
Your high score is ${gameState.highScore}.
|
...levelActions,
|
||||||
Click an item above to start a run with it.
|
|
||||||
</p>`,
|
|
||||||
],
|
],
|
||||||
allowClose: true,
|
allowClose: true,
|
||||||
actionsAsGrid: true,
|
actionsAsGrid: true,
|
||||||
|
@ -893,26 +902,6 @@ export async function confirmRestart(gameState) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toggleFullScreen() {
|
|
||||||
try {
|
|
||||||
if (document.fullscreenElement !== null) {
|
|
||||||
if (document.exitFullscreen) {
|
|
||||||
document.exitFullscreen();
|
|
||||||
} else if (document.webkitCancelFullScreen) {
|
|
||||||
document.webkitCancelFullScreen();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const docel = document.documentElement;
|
|
||||||
if (docel.requestFullscreen) {
|
|
||||||
docel.requestFullscreen();
|
|
||||||
} else if (docel.webkitRequestFullscreen) {
|
|
||||||
docel.webkitRequestFullscreen();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const pressed: { [k: string]: number } = {
|
const pressed: { [k: string]: number } = {
|
||||||
ArrowLeft: 0,
|
ArrowLeft: 0,
|
||||||
|
@ -931,7 +920,8 @@ export function setKeyPressed(key: string, on: 0 | 1) {
|
||||||
|
|
||||||
document.addEventListener("keydown", (e) => {
|
document.addEventListener("keydown", (e) => {
|
||||||
if (e.key.toLowerCase() === "f" && !e.ctrlKey && !e.metaKey) {
|
if (e.key.toLowerCase() === "f" && !e.ctrlKey && !e.metaKey) {
|
||||||
toggleFullScreen();
|
toggleOption('fullscreen');
|
||||||
|
applyFullScreenChoice()
|
||||||
} else if (e.key in pressed) {
|
} else if (e.key in pressed) {
|
||||||
setKeyPressed(e.key, 1);
|
setKeyPressed(e.key, 1);
|
||||||
}
|
}
|
||||||
|
@ -988,13 +978,15 @@ export function restart(params: RunParams) {
|
||||||
setLevel(gameState, 0);
|
setLevel(gameState, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
restart(
|
restart(
|
||||||
(window.location.search.includes("stressTest") && {
|
(window.location.search.includes("stressTest") && {
|
||||||
level: "Bird",
|
level: "Bird",
|
||||||
perks: {
|
perks: {
|
||||||
pierce:1,
|
pierce: 1,
|
||||||
sapper:1,
|
sapper: 1,
|
||||||
implosions: 3
|
implosions: 3,
|
||||||
|
streak_shots:1
|
||||||
},
|
},
|
||||||
levelsPerLoop: 2,
|
levelsPerLoop: 2,
|
||||||
}) ||
|
}) ||
|
||||||
|
|
|
@ -178,7 +178,8 @@ export function resetCombo(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (typeof x !== "undefined" && typeof y !== "undefined") {
|
if (typeof x !== "undefined" && typeof y !== "undefined") {
|
||||||
makeText(gameState, x, y, "red", "-" + lost, 20, 150);
|
|
||||||
|
makeText(gameState, x, y, "red", "-" + lost, 20, 500+clamp(lost, 0,500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lost;
|
return lost;
|
||||||
|
@ -197,7 +198,7 @@ export function decreaseCombo(
|
||||||
if (lost) {
|
if (lost) {
|
||||||
schedulGameSound(gameState, "comboDecrease", x, 1);
|
schedulGameSound(gameState, "comboDecrease", x, 1);
|
||||||
if (typeof x !== "undefined" && typeof y !== "undefined") {
|
if (typeof x !== "undefined" && typeof y !== "undefined") {
|
||||||
makeText(gameState, x, y, "red", "-" + lost, 20, 300);
|
makeText(gameState, x, y, "red", "-" + lost, 20, 400+lost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1709,7 +1710,7 @@ function makeText(
|
||||||
color: colorString,
|
color: colorString,
|
||||||
text: string,
|
text: string,
|
||||||
size = 20,
|
size = 20,
|
||||||
duration = 150,
|
duration = 500,
|
||||||
) {
|
) {
|
||||||
append(gameState.texts, (p: Partial<TextFlash>) => {
|
append(gameState.texts, (p: Partial<TextFlash>) => {
|
||||||
p.time = gameState.levelTime;
|
p.time = gameState.levelTime;
|
||||||
|
@ -1717,7 +1718,7 @@ function makeText(
|
||||||
p.y = y;
|
p.y = y;
|
||||||
p.color = color;
|
p.color = color;
|
||||||
p.size = size;
|
p.size = size;
|
||||||
p.duration = duration;
|
p.duration = clamp(duration,400,2000);
|
||||||
p.text = text;
|
p.text = text;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,6 +191,8 @@ export function countBricksBelow(gameState: GameState, index: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function comboKeepingRate(level:number){
|
export function comboKeepingRate(level:number){
|
||||||
if(level<=0) return 0
|
return clamp(1-1/(1+level)*1.5,0,1)
|
||||||
return 1-1/(1+level)*1.5
|
|
||||||
}
|
}
|
||||||
|
for(let i = 0;i<5;i++){
|
||||||
|
console.log(Math.round(comboKeepingRate(i)*100)+'%')
|
||||||
|
}
|
|
@ -837,36 +837,6 @@
|
||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
<concept_node>
|
|
||||||
<name>fullscreen_exit</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>fullscreen_exit_help</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>
|
<concept_node>
|
||||||
<name>fullscreen_help</name>
|
<name>fullscreen_help</name>
|
||||||
<description/>
|
<description/>
|
||||||
|
@ -2032,6 +2002,21 @@
|
||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>level</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>
|
<concept_node>
|
||||||
<name>level_description</name>
|
<name>level_description</name>
|
||||||
<description/>
|
<description/>
|
||||||
|
|
|
@ -51,9 +51,7 @@
|
||||||
"main_menu.download_save_file_help": "Get a save file",
|
"main_menu.download_save_file_help": "Get a save file",
|
||||||
"main_menu.footer_html": "<p> \n<span>Made in France by <a href=\"https://lecaro.me\">Renan LE CARO</a>.</span> \n<a href=\"https://paypal.me/renanlecaro\" target=\"_blank\">Donate</a>\n<a href=\"https://discord.gg/DZSPqyJkwP\" target=\"_blank\">Discord</a>\n<a href=\"https://f-droid.org/en/packages/me.lecaro.breakout/\" target=\"_blank\">F-Droid</a>\n<a href=\"https://play.google.com/store/apps/details?id=me.lecaro.breakout\" target=\"_blank\">Google Play</a>\n<a href=\"https://renanlecaro.itch.io/breakout71\" target=\"_blank\">itch.io</a> \n<a href=\"https://gitlab.com/lecarore/breakout71\" target=\"_blank\">Gitlab</a>\n<a href=\"https://breakout.lecaro.me/\" target=\"_blank\">Web version</a>\n<a href=\"https://news.ycombinator.com/item?id=43183131\" target=\"_blank\">HackerNews</a>\n<a href=\"https://breakout.lecaro.me/privacy.html\" target=\"_blank\">Privacy Policy</a>\n<span>v.{{appVersion}}</span>\n</p>\n",
|
"main_menu.footer_html": "<p> \n<span>Made in France by <a href=\"https://lecaro.me\">Renan LE CARO</a>.</span> \n<a href=\"https://paypal.me/renanlecaro\" target=\"_blank\">Donate</a>\n<a href=\"https://discord.gg/DZSPqyJkwP\" target=\"_blank\">Discord</a>\n<a href=\"https://f-droid.org/en/packages/me.lecaro.breakout/\" target=\"_blank\">F-Droid</a>\n<a href=\"https://play.google.com/store/apps/details?id=me.lecaro.breakout\" target=\"_blank\">Google Play</a>\n<a href=\"https://renanlecaro.itch.io/breakout71\" target=\"_blank\">itch.io</a> \n<a href=\"https://gitlab.com/lecarore/breakout71\" target=\"_blank\">Gitlab</a>\n<a href=\"https://breakout.lecaro.me/\" target=\"_blank\">Web version</a>\n<a href=\"https://news.ycombinator.com/item?id=43183131\" target=\"_blank\">HackerNews</a>\n<a href=\"https://breakout.lecaro.me/privacy.html\" target=\"_blank\">Privacy Policy</a>\n<span>v.{{appVersion}}</span>\n</p>\n",
|
||||||
"main_menu.fullscreen": "Fullscreen",
|
"main_menu.fullscreen": "Fullscreen",
|
||||||
"main_menu.fullscreen_exit": "Exit Fullscreen",
|
"main_menu.fullscreen_help": "Game will try to go full screen before starting",
|
||||||
"main_menu.fullscreen_exit_help": "Might not work on some machines",
|
|
||||||
"main_menu.fullscreen_help": "Might not work on some machines",
|
|
||||||
"main_menu.kid": "Kids mode",
|
"main_menu.kid": "Kids mode",
|
||||||
"main_menu.kid_help": "Start future runs with \"slower ball\".",
|
"main_menu.kid_help": "Start future runs with \"slower ball\".",
|
||||||
"main_menu.language": "Language",
|
"main_menu.language": "Language",
|
||||||
|
@ -128,9 +126,10 @@
|
||||||
"score_panel.upcoming_levels": "Upcoming levels :",
|
"score_panel.upcoming_levels": "Upcoming levels :",
|
||||||
"score_panel.upgrades_picked": "Upgrades picked so far : ",
|
"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.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.",
|
"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 run with it .Your high score is {{highScore}}.",
|
||||||
|
"unlocks.level": "Here are all the game levels, click one to start a run with that starting level. ",
|
||||||
"unlocks.level_description": "A {{size}}x{{size}} level with {{bricks}} bricks",
|
"unlocks.level_description": "A {{size}}x{{size}} level with {{bricks}} bricks",
|
||||||
"unlocks.title": "You unlocked {{percentUnlock}}% of the game.",
|
"unlocks.title": "You unlocked {{percentUnlock}}% of the game. ",
|
||||||
"unlocks.unlocks_at": "Unlocks at total score {{threshold}}.",
|
"unlocks.unlocks_at": "Unlocks at total score {{threshold}}.",
|
||||||
"upgrades.asceticism.fullHelp": "You'll need to store the coins somewhere while your combo climbs. ",
|
"upgrades.asceticism.fullHelp": "You'll need to store the coins somewhere while your combo climbs. ",
|
||||||
"upgrades.asceticism.help": "+{{combo}} combo / brick, combo resets on coin catch",
|
"upgrades.asceticism.help": "+{{combo}} combo / brick, combo resets on coin catch",
|
||||||
|
|
|
@ -51,9 +51,7 @@
|
||||||
"main_menu.download_save_file_help": "Obtenir un fichier de sauvegarde",
|
"main_menu.download_save_file_help": "Obtenir un fichier de sauvegarde",
|
||||||
"main_menu.footer_html": " <p> \n<span>Programmé en France par <a href=\"https://lecaro.me\">Renan LE CARO</a>.</span>\n<a href=\"https://paypal.me/renanlecaro\" target=\"_blank\">Donner</a>\n<a href=\"https://discord.gg/DZSPqyJkwP\" target=\"_blank\">Discord</a>\n<a href=\"https://f-droid.org/en/packages/me.lecaro.breakout/\" target=\"_blank\">F-Droid</a>\n<a href=\"https://play.google.com/store/apps/details?id=me.lecaro.breakout\" target=\"_blank\">Google Play</a>\n<a href=\"https://renanlecaro.itch.io/breakout71\" target=\"_blank\">itch.io</a>\n<a href=\"https://gitlab.com/lecarore/breakout71\" target=\"_blank\">Gitlab</a>\n<a href=\"https://breakout.lecaro.me/\" target=\"_blank\">Version web</a>\n<a href=\"https://news.ycombinator.com/item?id=43183131\" target=\"_blank\">HackerNews</a>\n<a href=\"https://breakout.lecaro.me/privacy.html\" target=\"_blank\">Politique de confidentialité</a> \n<span>v.{{appVersion}}</span>\n</p>",
|
"main_menu.footer_html": " <p> \n<span>Programmé en France par <a href=\"https://lecaro.me\">Renan LE CARO</a>.</span>\n<a href=\"https://paypal.me/renanlecaro\" target=\"_blank\">Donner</a>\n<a href=\"https://discord.gg/DZSPqyJkwP\" target=\"_blank\">Discord</a>\n<a href=\"https://f-droid.org/en/packages/me.lecaro.breakout/\" target=\"_blank\">F-Droid</a>\n<a href=\"https://play.google.com/store/apps/details?id=me.lecaro.breakout\" target=\"_blank\">Google Play</a>\n<a href=\"https://renanlecaro.itch.io/breakout71\" target=\"_blank\">itch.io</a>\n<a href=\"https://gitlab.com/lecarore/breakout71\" target=\"_blank\">Gitlab</a>\n<a href=\"https://breakout.lecaro.me/\" target=\"_blank\">Version web</a>\n<a href=\"https://news.ycombinator.com/item?id=43183131\" target=\"_blank\">HackerNews</a>\n<a href=\"https://breakout.lecaro.me/privacy.html\" target=\"_blank\">Politique de confidentialité</a> \n<span>v.{{appVersion}}</span>\n</p>",
|
||||||
"main_menu.fullscreen": "Plein écran",
|
"main_menu.fullscreen": "Plein écran",
|
||||||
"main_menu.fullscreen_exit": "Quitter le plein écran",
|
"main_menu.fullscreen_help": "Le jeu essaiera de passer en plein écran quand vous le démarrez",
|
||||||
"main_menu.fullscreen_exit_help": "Ne fonctionne pas toujours",
|
|
||||||
"main_menu.fullscreen_help": "Ne fonctionne pas toujours",
|
|
||||||
"main_menu.kid": "Mode enfants",
|
"main_menu.kid": "Mode enfants",
|
||||||
"main_menu.kid_help": "Balle plus lente",
|
"main_menu.kid_help": "Balle plus lente",
|
||||||
"main_menu.language": "Langue",
|
"main_menu.language": "Langue",
|
||||||
|
@ -128,7 +126,8 @@
|
||||||
"score_panel.upcoming_levels": "Niveaux de la parties : ",
|
"score_panel.upcoming_levels": "Niveaux de la parties : ",
|
||||||
"score_panel.upgrades_picked": "Améliorations choisies jusqu'à présent :",
|
"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.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.",
|
"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": "Voci 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",
|
"unlocks.level_description": "Un niveau {{size}}x{{size}} avec {{bricks}} briques",
|
||||||
"unlocks.title": "Vous avez débloqué {{percentUnlock}}% du jeu.",
|
"unlocks.title": "Vous avez débloqué {{percentUnlock}}% du jeu.",
|
||||||
"unlocks.unlocks_at": "Déverrouillé au score total {{threshold}}.",
|
"unlocks.unlocks_at": "Déverrouillé au score total {{threshold}}.",
|
||||||
|
|
|
@ -50,6 +50,11 @@ export const options = {
|
||||||
name: t("main_menu.record"),
|
name: t("main_menu.record"),
|
||||||
help: t("main_menu.record_help"),
|
help: t("main_menu.record_help"),
|
||||||
},
|
},
|
||||||
|
fullscreen: {
|
||||||
|
default: false,
|
||||||
|
name: t("main_menu.fullscreen"),
|
||||||
|
help: t("main_menu.fullscreen_help"),
|
||||||
|
},
|
||||||
} as const satisfies { [k: string]: OptionDef };
|
} as const satisfies { [k: string]: OptionDef };
|
||||||
|
|
||||||
export function isOptionOn(key: OptionId) {
|
export function isOptionOn(key: OptionId) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue