mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-20 12:15:06 -04:00
Sacrifice : clear screen instead of doubling coins
This commit is contained in:
parent
39b6738805
commit
a134821a94
5 changed files with 1573 additions and 1641 deletions
|
@ -22,16 +22,13 @@ If the app stutters, turn on "fast mode" in the settings to render a simplified
|
|||
There's also an easy mode for kids (slower ball).
|
||||
|
||||
# Todo
|
||||
- strict sample size red borders ?
|
||||
- zen : red border on bombs
|
||||
- add marching ants effect + disable animation toggle
|
||||
- explosion doesn't break nearby bricks on level 2, with compound interest, hot start, concave puck
|
||||
|
||||
- popups not scrollable sometimes
|
||||
- sacrifice : clear all level
|
||||
- fdroid build
|
||||
|
||||
# UX
|
||||
|
||||
- strict sample size red borders ?
|
||||
- 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.
|
||||
- on mobile, add an element that feels like it can be "grabbed" and make it shine while writing "Push here to play"
|
||||
|
|
34
dist/index.html
vendored
34
dist/index.html
vendored
File diff suppressed because one or more lines are too long
|
@ -28,28 +28,15 @@ import {
|
|||
max_levels,
|
||||
shouldPierceByColor,
|
||||
} from "./game_utils";
|
||||
import { t } from "./i18n/i18n";
|
||||
import { icons } from "./loadGameData";
|
||||
import {t} from "./i18n/i18n";
|
||||
import {icons} from "./loadGameData";
|
||||
|
||||
import {
|
||||
addToTotalScore,
|
||||
getCurrentMaxCoins,
|
||||
getCurrentMaxParticles,
|
||||
} from "./settings";
|
||||
import { background } from "./render";
|
||||
import { gameOver } from "./gameOver";
|
||||
import {
|
||||
brickIndex,
|
||||
fitSize,
|
||||
gameState,
|
||||
hasBrick,
|
||||
hitsSomething,
|
||||
openUpgradesPicker,
|
||||
pause,
|
||||
} from "./game";
|
||||
import { stopRecording } from "./recording";
|
||||
import { isOptionOn } from "./options";
|
||||
import { use } from "react";
|
||||
import {addToTotalScore, getCurrentMaxCoins, getCurrentMaxParticles,} from "./settings";
|
||||
import {background} from "./render";
|
||||
import {gameOver} from "./gameOver";
|
||||
import {brickIndex, fitSize, gameState, hasBrick, hitsSomething, openUpgradesPicker, pause,} from "./game";
|
||||
import {stopRecording} from "./recording";
|
||||
import {isOptionOn} from "./options";
|
||||
|
||||
export function setMousePos(gameState: GameState, x: number) {
|
||||
// Sets the puck position, and updates the ball position if they are supposed to follow it
|
||||
|
@ -248,6 +235,7 @@ export function spawnExplosion(
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function spawnImplosion(
|
||||
gameState: GameState,
|
||||
count: number,
|
||||
|
@ -377,7 +365,7 @@ export function explodeBrick(
|
|||
while (coinsToSpawn > 0) {
|
||||
const points = Math.min(pointsPerCoin, coinsToSpawn);
|
||||
if (points < 0 || isNaN(points)) {
|
||||
console.error({ points });
|
||||
console.error({points});
|
||||
debugger;
|
||||
}
|
||||
|
||||
|
@ -742,7 +730,7 @@ export function attract(gameState: GameState, a: Ball, b: Ball, power: number) {
|
|||
export function coinBrickHitCheck(gameState: GameState, coin: Coin) {
|
||||
// Make ball/coin bonce, and return bricks that were hit
|
||||
const radius = coin.size / 2;
|
||||
const { x, y, previousX, previousY } = coin;
|
||||
const {x, y, previousX, previousY} = coin;
|
||||
|
||||
const vhit = hitsSomething(previousX, y, radius);
|
||||
const hhit = hitsSomething(x, previousY, radius);
|
||||
|
@ -908,7 +896,7 @@ export function gameStateTick(
|
|||
} else {
|
||||
gameOver(
|
||||
t("gameOver.win.title"),
|
||||
t("gameOver.win.summary", { score: gameState.score }),
|
||||
t("gameOver.win.summary", {score: gameState.score}),
|
||||
);
|
||||
}
|
||||
} else if (gameState.running || gameState.levelTime) {
|
||||
|
@ -1302,7 +1290,7 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
|||
i < ball.hitItem?.length - 1 && i < gameState.perks.respawn;
|
||||
i++
|
||||
) {
|
||||
const { index, color } = ball.hitItem[i];
|
||||
const {index, color} = ball.hitItem[i];
|
||||
if (gameState.bricks[index] || color === "black") continue;
|
||||
const vertical = Math.random() > 0.5;
|
||||
const dx = Math.random() > 0.5 ? 1 : -1;
|
||||
|
@ -1392,37 +1380,12 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
|||
if (gameState.perks.extra_life < 0) {
|
||||
gameState.perks.extra_life = 0;
|
||||
} else if (gameState.perks.sacrifice) {
|
||||
if (liveCount(gameState.coins) < getCurrentMaxCoins() / 2) {
|
||||
// true duplication
|
||||
let remaining = liveCount(gameState.coins);
|
||||
|
||||
forEachLiveOne(gameState.coins, (source, index) => {
|
||||
if (!remaining) return;
|
||||
append(gameState.coins, (copy) => {
|
||||
copy.points = source.points;
|
||||
copy.color = source.color;
|
||||
copy.x = source.x;
|
||||
copy.y = source.y;
|
||||
copy.size = source.size;
|
||||
copy.previousX = source.previousX;
|
||||
copy.previousY = source.previousY;
|
||||
copy.vx = -source.vx;
|
||||
copy.vy = -source.vy;
|
||||
// copy.sx = source.sx;
|
||||
// copy.sy = source.sy;
|
||||
copy.a = source.a;
|
||||
copy.sa = -source.sa;
|
||||
copy.weight = source.weight;
|
||||
copy.coloredABrick = source.coloredABrick;
|
||||
});
|
||||
remaining--;
|
||||
});
|
||||
} else {
|
||||
forEachLiveOne(gameState.coins, (source, index) => {
|
||||
source.points *= 2;
|
||||
});
|
||||
// spawn a few coins for effect, but mostly increment poitns counter
|
||||
}
|
||||
gameState.bricks.forEach((color, index) => color && explodeBrick(
|
||||
gameState,
|
||||
index,
|
||||
ball,
|
||||
true,
|
||||
))
|
||||
}
|
||||
|
||||
schedulGameSound(gameState, "lifeLost", ball.x, 1);
|
||||
|
@ -1458,7 +1421,7 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
|||
ball.hitItem
|
||||
.slice(0, -1)
|
||||
.slice(0, gameState.perks.respawn)
|
||||
.forEach(({ index, color }) => {
|
||||
.forEach(({index, color}) => {
|
||||
if (!gameState.bricks[index] && color !== "black") {
|
||||
// respawns with full hp
|
||||
setBrick(gameState, index, color);
|
||||
|
@ -1508,13 +1471,13 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
|||
if (!gameState.balls.find((b) => !b.destroyed)) {
|
||||
gameOver(
|
||||
t("gameOver.lost.title"),
|
||||
t("gameOver.lost.summary", { score: gameState.score }),
|
||||
t("gameOver.lost.summary", {score: gameState.score}),
|
||||
);
|
||||
}
|
||||
}
|
||||
const radius = gameState.ballSize / 2;
|
||||
// Make ball/coin bonce, and return bricks that were hit
|
||||
const { x, y, previousX, previousY } = ball;
|
||||
const {x, y, previousX, previousY} = ball;
|
||||
|
||||
const vhit = hitsSomething(previousX, y, radius);
|
||||
const hhit = hitsSomething(x, previousY, radius);
|
||||
|
@ -1716,7 +1679,7 @@ export function append<T>(
|
|||
makeItem(where.list[where.indexMin]);
|
||||
where.indexMin++;
|
||||
} else {
|
||||
const p = { destroyed: false };
|
||||
const p = {destroyed: false};
|
||||
makeItem(p);
|
||||
where.list.push(p);
|
||||
}
|
||||
|
|
|
@ -213,8 +213,8 @@
|
|||
"upgrades.right_is_lava.fullHelp": "Whenever you break a brick, your combo will increase by one, so you'll get one more coin from all the next bricks you break.\n\nHowever, your combo will reset as soon as your ball hits the right side . \n\nAs soon as your combo rises, the right side becomes red to remind you that you should avoid hitting them\n\nThe effect stacks with other combo perks, combo rises faster with more upgrades but will also reset if any\nof the reset conditions are met.",
|
||||
"upgrades.right_is_lava.help": "+1 combo per brick broken, resets on right side hit",
|
||||
"upgrades.right_is_lava.name": "Avoid right side",
|
||||
"upgrades.sacrifice.fullHelp": "This is made visual when possible, otherwise it's just going to update their score value",
|
||||
"upgrades.sacrifice.help": "Loosing a life doubles the value of each coin on screen",
|
||||
"upgrades.sacrifice.fullHelp": "This might get the combo pretty high",
|
||||
"upgrades.sacrifice.help": "Loosing a life clears all bricks",
|
||||
"upgrades.sacrifice.name": "Sacrifice",
|
||||
"upgrades.sapper.fullHelp": "Instead of just disappearing, the first brick you break will be replaced by a bomb brick. \n\nBouncing the ball on the puck re-arms the effect. \n\nLeveling-up this perk will allow you to place more bombs.\n\nRemember that bombs impact the velocity of nearby coins, so too many explosions could make it hard to catch the fruits of your hard work.",
|
||||
"upgrades.sapper.help": "The first brick broken becomes a bomb.",
|
||||
|
|
|
@ -213,8 +213,8 @@
|
|||
"upgrades.right_is_lava.fullHelp": "Chaque fois que vous cassez une brique, votre combo augmente d'une unité, ce qui vous permet d'obtenir une pièce de plus à chaque fois que vous cassez les briques suivantes.\n\nCependant, votre combinaison se réinitialise dès que votre balle touche le côté droit de la zone de jeu.\n\nDès que votre combo augmente, le côté droit devient rouge pour vous rappeler que vous devez éviter de le frapper.\n\nL'effet se cumule avec d'autres avantages de combo, le combo augmente plus rapidement avec plus d'améliorations, mais il se réinitialise également si l'une des conditions de réinitialisation est remplie.",
|
||||
"upgrades.right_is_lava.help": "Plus de pièces si vous ne touchez pas le côté droit.",
|
||||
"upgrades.right_is_lava.name": "Éviter le côté droit",
|
||||
"upgrades.sacrifice.fullHelp": "Ceci n'est pas toujours représentable visuellement",
|
||||
"upgrades.sacrifice.help": "Perdre une vie double la valeur de toutes les pièces à l'écran",
|
||||
"upgrades.sacrifice.fullHelp": "Le combo pourrait monter assez haut ",
|
||||
"upgrades.sacrifice.help": "Perdre une vie détruit toutes les briques",
|
||||
"upgrades.sacrifice.name": "Sacrifice",
|
||||
"upgrades.sapper.fullHelp": "Au lieu de disparaître, la première brique cassée est remplacée par une bombe. Faire rebondir la balle sur le palet réarme l'effet. En montant en niveau, vous pourrez placer plus de bombes. N'oubliez pas que les bombes ont un impact sur la vitesse des pièces à proximité. Trop d'explosions peuvent rendre difficile la récupération des fruits de votre dur labeur.",
|
||||
"upgrades.sapper.help": "La première brique cassée devient une bombe.",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue