Build 29184940

This commit is contained in:
Renan LE CARO 2025-06-28 09:41:02 +02:00
parent 7b9c21a47a
commit 2563e23a0f
15 changed files with 107 additions and 44 deletions

View file

@ -15,11 +15,16 @@ Break colourful bricks, catch bouncing coins and select powerful upgrades !
# Changelog
## To do
- add check for translation variable present in one language but not english
- remove mentions of "pcuk" from store descriptions : fdroid, play store, itchio
- remove mentions of "puck" from itchio descriptions
## Done
- fixed a tricky bug where multiple level ups would happen at once
- add check for unbalanced number of braces in translations
- add check for translation variable present in one language but not english
- remove mentions of "puck" from play store descriptions
- remove mentions of "puck" from fdroid descriptions
- don't show already picked perk in gold
- If last ball is out of bound, spend a life to rest it to the paddle location
- smaller rainbow icon

View file

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

File diff suppressed because one or more lines are too long

19
dist/index.html vendored

File diff suppressed because one or more lines are too long

View file

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

View file

@ -1656,4 +1656,4 @@
"name": "Zombie",
"credit": "Minecraft Zombie by CHRISS Vector"
}
]
]

View file

@ -889,5 +889,10 @@
"required": ["metamorphosis", "helium", "superhot"],
"forbidden": ["corner_shot", "passive_income", "pierce"],
"minScore": 16800
},
"Zombie": {
"required": ["corner_shot", "respawn", "addiction"],
"forbidden": ["minefield", "clairvoyant", "etherealcoins"],
"minScore": 16900
}
}

View file

@ -1 +1 @@
"29180585"
"29184940"

View file

@ -99,7 +99,11 @@ export async function play() {
export function pause(playerAskedForPause: boolean) {
if (!gameState.running) return;
if (gameState.pauseTimeout) return;
if (gameState.pauseTimeout && playerAskedForPause) {
return;
}
if (gameState.startParams.computer_controlled) {
if (gameState.startParams?.computer_controlled) {
play();
@ -114,7 +118,11 @@ export function pause(playerAskedForPause: boolean) {
}, 1000);
pauseRecording();
gameState.pauseTimeout = null;
if (gameState.pauseTimeout) {
// In case an instant pause was requested while a delayed pause was pending
clearTimeout(gameState.pauseTimeout);
gameState.pauseTimeout = null;
}
gameState.needsRender = true;
};
@ -976,8 +984,7 @@ export function restart(params: RunParams) {
if (window.location.search.match(/autoplay|stress/)) {
startComputerControlledGame(window.location.search.includes("stress"));
} else {
restart({
});
restart({});
}
export function startComputerControlledGame(stress: boolean = false) {

View file

@ -36,12 +36,9 @@ export function addToTotalPlayTime(ms: number) {
export async function gameOver(title: string, intro: string) {
if (!gameState.running) return;
// Ignore duplicated calls, can happen when ticking is split in multiple updates because the ball goes fast
if (gameState.isGameOver) return;
gameState.isGameOver = true;
pause(false);
askForPersistentStorage();
stopRecording();

View file

@ -666,6 +666,7 @@ export async function setLevel(gameState: GameState, l: number) {
if (gameState.upgradesOfferedFor >= l) {
return;
}
if (!gameState.running && l > 0) return;
pause(false);
gameState.upgradesOfferedFor = l;
stopRecording();
@ -1962,26 +1963,30 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
ball.piercePoints = gameState.perks.pierce * 3;
}
const outOfBounds=ball.y > gameState.gameZoneHeight + gameState.ballSize / 2 ||
const outOfBounds =
ball.y > gameState.gameZoneHeight + gameState.ballSize / 2 ||
ball.y < -gameState.gameZoneHeight ||
ball.x < -gameState.gameZoneHeight ||
ball.x > gameState.canvasWidth + gameState.gameZoneHeight;
if(outOfBounds && gameState.perks.extra_life && gameState.balls.filter((b) => !b.destroyed).length==1){
if (
outOfBounds &&
gameState.perks.extra_life &&
gameState.balls.filter((b) => !b.destroyed).length == 1
) {
// Rescue the ball using an extra life
gameState.balls.forEach(b=>{
// there should be just one but just in case
b.vx=getBallDefaultVx(gameState)
b.previousVX=b.vx
b.vy= -gameState.baseSpeed
b.previousVY = b.vy
})
schedulGameSound(gameState, "lifeLost", ball.x, 1);
putBallsAtPuck(gameState)
gameState.ballStickToPuck = true;
pause(false)
gameState.balls.forEach((b) => {
// there should be just one but just in case
b.vx = getBallDefaultVx(gameState);
b.previousVX = b.vx;
b.vy = -gameState.baseSpeed;
b.previousVY = b.vy;
});
schedulGameSound(gameState, "lifeLost", ball.x, 1);
putBallsAtPuck(gameState);
gameState.ballStickToPuck = true;
pause(false);
gameState.perks.extra_life -= 1;
}else if (outOfBounds) {
} else if (outOfBounds) {
ball.destroyed = true;
gameState.runStatistics.balls_lost++;
if (gameState.perks.happy_family) {

View file

@ -202,7 +202,7 @@
"upgrades.addiction.tooltip": "More coins if you break bricks without pause",
"upgrades.addiction.verbose_description": "+{{lvl}} combo / brick broken, combo resets {{delay}}s after breaking a brick. The countdown only starts after breaking the first brick of each level. It stops as soon as all bricks are destroyed.",
"upgrades.asceticism.name": "Asceticism",
"upgrades.asceticism.tooltip": "More coins if you don't catch them immediately",
"upgrades.asceticism.tooltip": "+{{combo}} combo per brick broken, -{{combo}} combo per coin caught.",
"upgrades.asceticism.verbose_description": "You'll need to store the coins somewhere while your combo climbs.",
"upgrades.ball_attract_ball.name": "Gravity",
"upgrades.ball_attract_ball.tooltip": "Balls attract balls",
@ -281,7 +281,7 @@
"upgrades.helium.verbose_description": "At level 1, gravity is reduced. At level 2, coins slowly float up. At level 3 they really fly.",
"upgrades.hot_start.name": "Hot start",
"upgrades.hot_start.tooltip": "More coins if you clear the level under 30s",
"upgrades.hot_start.verbose_description": "At the start of every level, your combo will start at +30 points, but then every second it will be decreased by one. The effect stacks with other perks.",
"upgrades.hot_start.verbose_description": "At the start of every level, your combo will start at +{{start}} points, but then every second it will be decreased by {{loss}}. The effect stacks with other perks.",
"upgrades.implosions.name": "Implosions",
"upgrades.implosions.tooltip": "Explosions suck coins in instead of blowing them out",
"upgrades.implosions.verbose_description": "The explosion force is applied the other way. Further levels act as \"bigger explosion\"",
@ -320,7 +320,7 @@
"upgrades.pierce.verbose_description": "The ball normally bounces as soon as it touches something. With this perk, it will continue its trajectory for up to 3 bricks broken. \n\nAfter that, it will bounce on the 4th brick, and you'll need to touch the paddle to reset the counter.",
"upgrades.pierce_color.name": "Color pierce",
"upgrades.pierce_color.tooltip": "The ball goes through bricks of the same color",
"upgrades.pierce_color.verbose_description": "Normally, balls do 1 damage and bricks have 1 health point (HP). S\nEach level of this perk increase the damage balls do to bricks of their color. \nWhen a ball does more damage than the brick's health points, it will continue straight instead of bouncing;\n\nWhenever a ball hits a brick of the same color, it will just go through unimpeded. \nOnce it reaches a brick of a different color, it will break it, take its color and bounce.\nIf you have sturdy bricks, the ball might still bounce off a brick of the same color.",
"upgrades.pierce_color.verbose_description": "Normally, balls do 1 damage and bricks have 1 health point (HP).\nWhenever a ball hits a brick of the same color, it will just go through unimpeded. \nOnce it reaches a brick of a different color, it will break it, take its color and bounce.\nIf you have sturdy bricks, the ball might still bounce off a brick of the same color.",
"upgrades.puck_repulse_ball.name": "Soft landing",
"upgrades.puck_repulse_ball.tooltip": "Paddle repulses balls",
"upgrades.puck_repulse_ball.verbose_description": "When a ball gets close to the paddle, it will start slowing down, and even potentially bouncing without touching the paddle.",

View file

@ -280,8 +280,8 @@
"upgrades.helium.tooltip": "Les pièce flottent au lieu de tomber autours de la raquette.",
"upgrades.helium.verbose_description": "Au niveau 1, la gravité est réduite. Au niveau 2, les pièces flottent lentement. Au niveau 3, elles volent vraiment.",
"upgrades.hot_start.name": "Démarrage à chaud",
"upgrades.hot_start.tooltip": "Combo à {{start}}, -{{loss}} combo par seconde",
"upgrades.hot_start.verbose_description": "Au début de chaque niveau, votre combo commencera à +30 points, mais à chaque seconde, il sera diminué d'un point.",
"upgrades.hot_start.tooltip": "Plus de pièces si vous détruisez toutes les briques en 30s",
"upgrades.hot_start.verbose_description": "Au début de chaque niveau, votre combo commencera à +{{start}} points, mais à chaque seconde, il sera diminué de {{loss}} point.",
"upgrades.implosions.name": "Implosions",
"upgrades.implosions.tooltip": "Les explosions aspirent les pièces au lieu de les faire exploser.",
"upgrades.implosions.verbose_description": "La force dexplosion est appliquée dans lautre sens. Les niveaux 2+ augmentent la puissance de l'implosion.",

View file

@ -1,4 +1,6 @@
import { languages } from "./i18n";
import en from "./en.json";
const englishTranslation = en as Record<string, string>;
describe("translation quality checks", () => {
it("no html, links, puck", () => {
@ -17,4 +19,41 @@ describe("translation quality checks", () => {
}
expect(badKeys).toEqual([]);
});
it("reasonable number of braces", () => {
const badKeys: String[] = [];
for (let { value: languageCode, strings } of languages) {
const translations = strings as Record<string, string>;
for (let key in translations) {
if (
translations[key].split("{").length !==
translations[key].split("}").length
) {
badKeys.push(languageCode + ":" + key + " : " + translations[key]);
}
}
}
expect(badKeys).toEqual([]);
});
it("only variable names used somewhere in english translation will work ", () => {
let knownVariableNames = new Set<string>();
for (let key in englishTranslation) {
englishTranslation[key]
.match(/\{\{[^}]+\}\}/gi)
?.forEach((name) => knownVariableNames.add(name));
}
const badKeys: String[] = [];
for (let { value: languageCode, strings } of languages) {
const translations = strings as Record<string, string>;
for (let key in translations) {
if (
translations[key]
.match(/\{\{[^}]+\}\}/gi)
?.find((name: string) => !knownVariableNames.has(name))
) {
badKeys.push(languageCode + ":" + key + " : " + translations[key]);
}
}
}
expect(badKeys).toEqual([]);
});
});

View file

@ -104,7 +104,7 @@
"play.stats.levelWallBounces": "Quicadas na parede",
"score_panel.close_to_unlock": "Próximo nível desbloqueia:",
"score_panel.get_upgrades_to_unlock": "Obtenha {{missingUpgrades}} e marque mais {{points}} pontos para desbloquear o nível \"{{level}}\"",
"score_panel.score_to_unlock": "Pontue mais {{pontos}} pontos para desbloquear o nível \"{{level}}\"",
"score_panel.score_to_unlock": "Pontue mais {{points}} pontos para desbloquear o nível \"{{level}}\"",
"score_panel.title": "{{score}} pontos no nível {{level}}/{{max}}",
"score_panel.upcoming_levels": "Próximos níveis",
"score_panel.upgrade_point_count": "Você acumulou {{count}} pontos de melhoria.",
@ -316,7 +316,7 @@
"upgrades.picky_eater.tooltip": "Mais moedas se você quebrar blocos da cor da bola",
"upgrades.picky_eater.verbose_description": "Sempre que você quebrar um tijolo a mesma cor que sua bola, sua combinação aumenta pelo número de cores na tela menos uma.\nSe é uma cor diferente, a bola leva essa nova cor, mas a combinação repõe, a menos que não houvesse tijolos deixados da cor da bola.\nUma vez que você obter uma combinação superior ao seu mínimo, os tijolos da cor errada obterão uma borda vermelha.\nSe você tem mais de uma bola, todos eles mudam de cor sempre que um deles atinge um tijolo.",
"upgrades.pierce.name": "Piercing",
"upgrades.pierce.tooltip": "Bola perfura {{conta}} tijolos após um remo",
"upgrades.pierce.tooltip": "Bola perfura {{count}} tijolos após um remo",
"upgrades.pierce.verbose_description": "A bola normalmente salta assim que toca algo. Com este garfo, continuará sua trajetória para até 3 tijolos quebrados.\n\nDepois disso, ele vai saltar no 4o tijolo, e você vai precisar tocar o remo para redefinir o contador.",
"upgrades.pierce_color.name": "Torcer de cor",
"upgrades.pierce_color.tooltip": "A bola passa por tijolos da mesma cor",