mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-20 04:05:06 -04:00
Build 29044264
This commit is contained in:
parent
5725d90470
commit
cb4b1ea49e
16 changed files with 330 additions and 213 deletions
|
@ -189,10 +189,7 @@ 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 ?
|
||||
- nerf coin magnet :
|
||||
- no effect when too close
|
||||
- coins overshoot
|
||||
- coins bounce and spread more ?
|
||||
|
||||
- add red anti-coins that apply downgrades
|
||||
- destroy your combo
|
||||
- hurt your score
|
||||
|
|
|
@ -11,8 +11,8 @@ android {
|
|||
applicationId = "me.lecaro.breakout"
|
||||
minSdk = 21
|
||||
targetSdk = 34
|
||||
versionCode = 29041811
|
||||
versionName = "29041811"
|
||||
versionCode = 29044264
|
||||
versionName = "29044264"
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables {
|
||||
useSupportLibrary = true
|
||||
|
|
File diff suppressed because one or more lines are too long
268
dist/index.html
vendored
268
dist/index.html
vendored
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
|||
// The version of the cache.
|
||||
const VERSION = "29041811";
|
||||
const VERSION = "29044264";
|
||||
|
||||
// The name of the cache
|
||||
const CACHE_NAME = `breakout-71-${VERSION}`;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[ "<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><path d='M3.25 10h13.5M10 3.25v13.5' stroke-width='1' stroke='white' fill='none'/></svg>",
|
||||
[
|
||||
"<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><path d='M3.25 10h13.5M10 3.25v13.5' stroke-width='1' stroke='white' fill='none'/></svg>",
|
||||
"<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40'><path d='M11 6a5 5 0 01-5 5 5 5 0 01-5-5 5 5 0 015-5 5 5 0 015 5' stroke='none' fill='white'/></svg>",
|
||||
"<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><path d='M10-10L20 0v10L10 0zM20 0L10-10V0l10 10zm0 10L10 0v10l10 10zm0 10L10 10v10l10 10zM0 20l10-10v10L0 30zm0-10L10 0v10L0 20zM0 0l10-10V0L0 10z' stroke-width='1' stroke='white' fill='none'/></svg>",
|
||||
"<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40'><path d='M15.986 4.186 4.1 16.072v.58L16.566 4.186Zm7.62 0 12.38 12.38v-.58l-11.8-11.8Zm12.38 19.248L23.52 35.9h.58l11.886-11.886ZM4.1 23.52v.58l11.8 11.8h.58z' stroke-width='1' stroke='white' fill='none'/></svg>",
|
||||
|
|
|
@ -947,5 +947,12 @@
|
|||
"bricks": "_________yyyyyy__yyyyyy__yyyyyy__rrrrrr_______W____________WWW__",
|
||||
"svg": null,
|
||||
"color": ""
|
||||
},
|
||||
{
|
||||
"name": "icon:passive_income",
|
||||
"size": 8,
|
||||
"bricks": "__________tttt____tttt_______________W___________________rWWWr__",
|
||||
"svg": null,
|
||||
"color": ""
|
||||
}
|
||||
]
|
|
@ -1 +1 @@
|
|||
"29041811"
|
||||
"29044264"
|
||||
|
|
|
@ -45,6 +45,8 @@ export function addToTotalPlayTime(ms: number) {
|
|||
|
||||
export function gameOver(title: string, intro: string) {
|
||||
if (!gameState.running) return;
|
||||
if (gameState.isGameOver) return;
|
||||
gameState.isGameOver = true;
|
||||
pause(true);
|
||||
stopRecording();
|
||||
addToTotalPlayTime(gameState.runStatistics.runTime);
|
||||
|
|
|
@ -26,7 +26,6 @@ import {
|
|||
isTelekinesisActive,
|
||||
isYoyoActive,
|
||||
max_levels,
|
||||
sample,
|
||||
shouldPierceByColor,
|
||||
} from "./game_utils";
|
||||
import { t } from "./i18n/i18n";
|
||||
|
@ -49,6 +48,14 @@ 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
|
||||
if (
|
||||
gameState.running &&
|
||||
gameState.levelTime > 500 &&
|
||||
gameState.perks.passive_income &&
|
||||
Math.abs(x - gameState.puckPosition) > 3
|
||||
) {
|
||||
resetCombo(gameState, x, gameState.gameZoneHeight - gameState.puckHeight);
|
||||
}
|
||||
gameState.puckPosition = x;
|
||||
gameState.needsRender = true;
|
||||
}
|
||||
|
@ -88,6 +95,7 @@ export function resetBalls(gameState: GameState) {
|
|||
sy: 0,
|
||||
piercedSinceBounce: 0,
|
||||
hitSinceBounce: 0,
|
||||
brokenSinceBounce: 0,
|
||||
hitItem: [],
|
||||
sapperUses: 0,
|
||||
});
|
||||
|
@ -116,6 +124,7 @@ export function putBallsAtPuck(gameState: GameState) {
|
|||
ball.sy = 0;
|
||||
ball.hitItem = [];
|
||||
ball.hitSinceBounce = 0;
|
||||
ball.brokenSinceBounce = 0;
|
||||
ball.piercedSinceBounce = 0;
|
||||
});
|
||||
}
|
||||
|
@ -367,6 +376,8 @@ export function explodeBrick(
|
|||
gameState.perks.picky_eater +
|
||||
gameState.perks.asceticism +
|
||||
gameState.perks.zen +
|
||||
gameState.perks.passive_income +
|
||||
gameState.perks.nbricks +
|
||||
gameState.perks.unbounded;
|
||||
|
||||
if (gameState.perks.reach) {
|
||||
|
@ -499,6 +510,7 @@ export function addToScore(gameState: GameState, coin: Coin) {
|
|||
export async function setLevel(gameState: GameState, l: number) {
|
||||
// Here to alleviate double upgrades issues
|
||||
if (gameState.upgradesOfferedFor >= l) {
|
||||
debugger;
|
||||
return console.warn("Extra upgrade request ignored ");
|
||||
}
|
||||
gameState.upgradesOfferedFor = l;
|
||||
|
@ -531,8 +543,6 @@ export async function setLevel(gameState: GameState, l: number) {
|
|||
}
|
||||
gameState.combo += gameState.perks.hot_start * 15;
|
||||
|
||||
resetBalls(gameState);
|
||||
|
||||
const lvl = currentLevelInfo(gameState);
|
||||
if (lvl.size !== gameState.gridSize) {
|
||||
gameState.gridSize = lvl.size;
|
||||
|
@ -543,6 +553,8 @@ export async function setLevel(gameState: GameState, l: number) {
|
|||
empty(gameState.lights);
|
||||
empty(gameState.texts);
|
||||
gameState.bricks = [...lvl.bricks];
|
||||
// Balls color will depend on most common brick color sometimes
|
||||
resetBalls(gameState);
|
||||
gameState.needsRender = true;
|
||||
// This caused problems with accented characters like the ô of côte d'ivoire for odd reasons
|
||||
// background.src = 'data:image/svg+xml;base64,' + btoa(lvl.svg)
|
||||
|
@ -799,7 +811,15 @@ export function gameStateTick(
|
|||
});
|
||||
gameState.autoCleanUses++;
|
||||
}
|
||||
if (gameState.running && !remainingBricks && gameState.noBricksSince == 0) {
|
||||
const hasPendingBricks =
|
||||
gameState.perks.respawn &&
|
||||
gameState.balls.find((b) => b.hitItem.length > 1);
|
||||
if (
|
||||
gameState.running &&
|
||||
!remainingBricks &&
|
||||
gameState.noBricksSince == 0 &&
|
||||
!hasPendingBricks
|
||||
) {
|
||||
gameState.noBricksSince ||= gameState.levelTime;
|
||||
}
|
||||
if (
|
||||
|
@ -1350,15 +1370,12 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
|||
if (gameState.perks.trampoline) {
|
||||
gameState.combo += gameState.perks.trampoline;
|
||||
}
|
||||
if (gameState.perks.nbricks) {
|
||||
if (ball.hitSinceBounce) {
|
||||
if (gameState.perks.nbricks === ball.hitSinceBounce) {
|
||||
gameState.combo += gameState.perks.nbricks;
|
||||
} else {
|
||||
if (
|
||||
gameState.perks.nbricks &&
|
||||
gameState.perks.nbricks !== ball.brokenSinceBounce
|
||||
) {
|
||||
resetCombo(gameState, ball.x, ball.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gameState.perks.respawn) {
|
||||
ball.hitItem
|
||||
|
@ -1394,6 +1411,7 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
|||
}
|
||||
gameState.runStatistics.puck_bounces++;
|
||||
ball.hitSinceBounce = 0;
|
||||
ball.brokenSinceBounce = 0;
|
||||
ball.sapperUses = 0;
|
||||
ball.piercedSinceBounce = 0;
|
||||
}
|
||||
|
@ -1427,15 +1445,17 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
|||
undefined;
|
||||
|
||||
const hitBrick = vhit ?? hhit ?? chit;
|
||||
|
||||
if (typeof hitBrick !== "undefined") {
|
||||
let sturdyBounce =
|
||||
hitBrick &&
|
||||
gameState.bricks[hitBrick] !== "black" &&
|
||||
gameState.perks.sturdy_bricks &&
|
||||
gameState.perks.sturdy_bricks > Math.random() * 5;
|
||||
|
||||
ball.hitSinceBounce++;
|
||||
let pierce = false;
|
||||
if (sturdyBounce || typeof hitBrick === "undefined") {
|
||||
// cannot pierce
|
||||
if (sturdyBounce) {
|
||||
schedulGameSound(gameState, "wallBeep", x, 1);
|
||||
} else if (shouldPierceByColor(gameState, vhit, hhit, chit)) {
|
||||
pierce = true;
|
||||
} else if (ball.piercedSinceBounce < gameState.perks.pierce * 3) {
|
||||
|
@ -1456,16 +1476,11 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
|||
}
|
||||
}
|
||||
|
||||
if (sturdyBounce) {
|
||||
schedulGameSound(gameState, "wallBeep", x, 1);
|
||||
return;
|
||||
}
|
||||
if (typeof hitBrick !== "undefined") {
|
||||
if (!sturdyBounce) {
|
||||
const initialBrickColor = gameState.bricks[hitBrick];
|
||||
ball.brokenSinceBounce++;
|
||||
|
||||
ball.hitSinceBounce++;
|
||||
explodeBrick(gameState, hitBrick, ball, false);
|
||||
|
||||
if (
|
||||
ball.sapperUses < gameState.perks.sapper &&
|
||||
initialBrickColor !== "black" && // don't replace a brick that bounced with sturdy_bricks
|
||||
|
@ -1475,6 +1490,7 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
|||
ball.sapperUses++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isOptionOn("basic")) {
|
||||
const remainingPierce =
|
||||
|
|
|
@ -2742,6 +2742,56 @@
|
|||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
<name>passive_income</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>fullHelp</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>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>
|
||||
<name>name</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>
|
||||
</children>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
<name>picky_eater</name>
|
||||
<children>
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
"unlocks.level_description": "A {{size}}x{{size}} level with {{bricks}} bricks",
|
||||
"unlocks.title": "You unlocked {{percentUnlock}}% of the game.",
|
||||
"unlocks.unlocks_at": "Unlocks at total score {{threshold}}.",
|
||||
"upgrades.asceticism.fullHelp": "This affects the coins and will let the float up until you are ready to pick them up.",
|
||||
"upgrades.asceticism.fullHelp": "You'll need to store the coins somewhere while your combo climbs. ",
|
||||
"upgrades.asceticism.help": "+1 combo / brick, com resets on coin catch",
|
||||
"upgrades.asceticism.name": "Asceticism",
|
||||
"upgrades.ball_attract_ball.fullHelp": "Balls that are more than half a screen width away will start attracting each other. \n\nThe attraction force is stronger when they are furthest away from each other.\n\nRainbow particles will fly to symbolize the attraction force. This perk is only offered if you have more than one ball already.",
|
||||
|
@ -169,6 +169,9 @@
|
|||
"upgrades.one_more_choice.fullHelp": "Every upgrade menu will have one more option. Doesn't increase the number of upgrades you can pick.",
|
||||
"upgrades.one_more_choice.help": "Further level ups will offer one more option in the list",
|
||||
"upgrades.one_more_choice.name": "+1 choice until run end",
|
||||
"upgrades.passive_income.fullHelp": "Some perks can help the balls do what you want without needing to do anything.",
|
||||
"upgrades.passive_income.help": "+1 combo / brick, combo resets when puck moves",
|
||||
"upgrades.passive_income.name": "Passive income",
|
||||
"upgrades.picky_eater.fullHelp": "Whenever you break a brick the same color as your ball, your combo increases by one. \nIf it's a different color, the ball takes that new color, but the combo resets.\nThe bricks with the right color will get a white border. \nOnce you get a combo higher than your minimum, the bricks of the wrong color will get a red halo. \nIf you have more than one ball, they all change color whenever one of them hits a brick.",
|
||||
"upgrades.picky_eater.help": "+1 combo per brick broken, resets on ball color change",
|
||||
"upgrades.picky_eater.name": "Picky eater",
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
"unlocks.level_description": "Un niveau {{size}}x{{size}} avec {{bricks}} briques",
|
||||
"unlocks.title": "Vous avez débloqué {{percentUnlock}}% du jeu.",
|
||||
"unlocks.unlocks_at": "Déverrouillé au score total {{threshold}}.",
|
||||
"upgrades.asceticism.fullHelp": "Les pièces attendront d'être sous le palet pour tomber. ",
|
||||
"upgrades.asceticism.fullHelp": "Il faudra trouver un moyen de stocker les pièces pendant que le combo grandis. ",
|
||||
"upgrades.asceticism.help": "+1 combo par brique cassée, RAZ quand une pièce est attrapée",
|
||||
"upgrades.asceticism.name": "Ascétisme",
|
||||
"upgrades.ball_attract_ball.fullHelp": "Les balles qui sont éloignées de plus d'une demi-largeur d'écran commencent à s'attirer. La force d'attraction est plus forte lorsque les balles sont plus éloignées l'une de l'autre. Des particules arc-en-ciel voleront pour symboliser la force d'attraction. Cet avantage n'est offert que si vous avez déjà plus d'une balle en jeu.",
|
||||
|
@ -169,6 +169,9 @@
|
|||
"upgrades.one_more_choice.fullHelp": "Chaque menu d'amélioration comportera une option supplémentaire. Cela n'augmente pas le nombre d'améliorations que vous pouvez choisir, mais vous aide à créer le profile idéal. ",
|
||||
"upgrades.one_more_choice.help": "Les niveaux suivants offriront une option supplémentaire dans la liste d'améliorations.",
|
||||
"upgrades.one_more_choice.name": "+1 choix jusqu'à la fin de la course",
|
||||
"upgrades.passive_income.fullHelp": "Certaines amélioration font bouger les balles sans avoir besoin de mettre le palet en mouvement.",
|
||||
"upgrades.passive_income.help": "+1 combo par brique cassée, RAZ quand le palet bouge",
|
||||
"upgrades.passive_income.name": "Revenu passif",
|
||||
"upgrades.picky_eater.fullHelp": "Chaque fois que vous cassez une brique de la même couleur que votre balle, votre combo augmente d'une unité.\n\nS'il s'agit d'une couleur différente, la balle adopte cette nouvelle couleur, mais la combinaison est réinitialisée.\n\nLes briques de la mauvaise couleur sont entourées en rouge.\n\nSi vous avez plus d'une balle, elles changent toutes de couleur lorsque l'une d'entre elles touche une brique.",
|
||||
"upgrades.picky_eater.help": "Plus de pièces si vous cassez les briques couleur par couleur.",
|
||||
"upgrades.picky_eater.name": "Mangeur par couleur",
|
||||
|
|
|
@ -38,6 +38,7 @@ export function newGameState(params: RunParams): GameState {
|
|||
combo: 1,
|
||||
gridSize: 12,
|
||||
running: false,
|
||||
isGameOver: false,
|
||||
ballStickToPuck: true,
|
||||
puckPosition: 400,
|
||||
pauseTimeout: null,
|
||||
|
|
6
src/types.d.ts
vendored
6
src/types.d.ts
vendored
|
@ -94,8 +94,13 @@ export type Ball = {
|
|||
previousVY: number;
|
||||
sx: number;
|
||||
sy: number;
|
||||
// Uses of the pierce perk only
|
||||
piercedSinceBounce: number;
|
||||
// Any bounce counts, even if brick resisted the hit
|
||||
hitSinceBounce: number;
|
||||
// Brick was really broken ,but could have been respawned as a bomb
|
||||
brokenSinceBounce: number;
|
||||
// Bricks that have been destroyed (and not replaced by something else)
|
||||
hitItem: { index: number; color: string }[];
|
||||
sapperUses: number;
|
||||
destroyed?: boolean;
|
||||
|
@ -197,6 +202,7 @@ export type GameState = {
|
|||
combo: number;
|
||||
// Whether the game is running or paused
|
||||
running: boolean;
|
||||
isGameOver: boolean;
|
||||
ballStickToPuck: boolean;
|
||||
// Whether the game should be re-rendered once even if not running
|
||||
needsRender: boolean;
|
||||
|
|
|
@ -564,4 +564,15 @@ export const rawUpgrades = [
|
|||
help: (lvl: number) => t("upgrades.reach.help", { lvl }),
|
||||
fullHelp: t("upgrades.reach.fullHelp"),
|
||||
},
|
||||
{
|
||||
requires: "",
|
||||
rejects: "",
|
||||
threshold: 140000,
|
||||
giftable: false,
|
||||
id: "passive_income",
|
||||
max: 1,
|
||||
name: t("upgrades.passive_income.name"),
|
||||
help: (lvl: number) => t("upgrades.passive_income.help"),
|
||||
fullHelp: t("upgrades.passive_income.fullHelp"),
|
||||
},
|
||||
] as const;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue