mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-20 12:15:06 -04:00
Build 29058943
This commit is contained in:
parent
9958717260
commit
b7b4879e6d
15 changed files with 123 additions and 72 deletions
|
@ -16,12 +16,12 @@ Break colourful bricks, catch bouncing coins and select powerful upgrades !
|
||||||
# changelog
|
# changelog
|
||||||
|
|
||||||
## next goals
|
## next goals
|
||||||
- [jaceys] A visual indication of whether a ball has hit a brick this serve
|
|
||||||
- choose starting perks
|
- choose starting perks
|
||||||
- wind : move coins based on puck movement not position
|
- wind : move coins based on puck movement not position
|
||||||
|
|
||||||
## next release
|
## next release
|
||||||
|
|
||||||
|
- [jaceys] A visual indication of whether a ball has hit a brick this serve (as an option)
|
||||||
- Top down /reach: now only the lowest level of N bricks resets combo, and all other bricks do +N combo
|
- Top down /reach: now only the lowest level of N bricks resets combo, and all other bricks do +N combo
|
||||||
- picky eater: don't reset if no brick of ball color
|
- picky eater: don't reset if no brick of ball color
|
||||||
- main menu : show high score
|
- main menu : show high score
|
||||||
|
|
|
@ -11,8 +11,8 @@ android {
|
||||||
applicationId = "me.lecaro.breakout"
|
applicationId = "me.lecaro.breakout"
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 29058753
|
versionCode = 29058943
|
||||||
versionName = "29058753"
|
versionName = "29058943"
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
useSupportLibrary = true
|
useSupportLibrary = true
|
||||||
|
|
File diff suppressed because one or more lines are too long
23
dist/index.html
vendored
23
dist/index.html
vendored
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
||||||
// The version of the cache.
|
// The version of the cache.
|
||||||
const VERSION = "29058753";
|
const VERSION = "29058943";
|
||||||
|
|
||||||
// The name of the cache
|
// The name of the cache
|
||||||
const CACHE_NAME = `breakout-71-${VERSION}`;
|
const CACHE_NAME = `breakout-71-${VERSION}`;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { t } from "./i18n/i18n";
|
||||||
import { getSettingValue, getTotalScore, setSettingValue } from "./settings";
|
import { getSettingValue, getTotalScore, setSettingValue } from "./settings";
|
||||||
import { confirmRestart, creativeModeThreshold, restart } from "./game";
|
import { confirmRestart, creativeModeThreshold, restart } from "./game";
|
||||||
import { requiredAsyncAlert } from "./asyncAlert";
|
import { requiredAsyncAlert } from "./asyncAlert";
|
||||||
import {describeLevel, highScoreForMode, sumOfValues} from "./game_utils";
|
import { describeLevel, highScoreForMode, sumOfValues } from "./game_utils";
|
||||||
|
|
||||||
export function creativeMode(gameState: GameState) {
|
export function creativeMode(gameState: GameState) {
|
||||||
return {
|
return {
|
||||||
|
@ -34,7 +34,7 @@ export async function openCreativeModePerksPicker(
|
||||||
"creativeModePerks_" + currentLevel,
|
"creativeModePerks_" + currentLevel,
|
||||||
{},
|
{},
|
||||||
),
|
),
|
||||||
choice: Upgrade | Level | 'reset'| void;
|
choice: Upgrade | Level | "reset" | void;
|
||||||
|
|
||||||
upgrades.forEach((u) => {
|
upgrades.forEach((u) => {
|
||||||
creativeModePerks[u.id] = Math.min(
|
creativeModePerks[u.id] = Math.min(
|
||||||
|
@ -51,15 +51,15 @@ export async function openCreativeModePerksPicker(
|
||||||
];
|
];
|
||||||
|
|
||||||
while (
|
while (
|
||||||
(choice = await requiredAsyncAlert<Upgrade | Level|'reset'>({
|
(choice = await requiredAsyncAlert<Upgrade | Level | "reset">({
|
||||||
title: t("lab.title", { lvl: currentLevel + 1 }),
|
title: t("lab.title", { lvl: currentLevel + 1 }),
|
||||||
actionsAsGrid: true,
|
actionsAsGrid: true,
|
||||||
content: [
|
content: [
|
||||||
t("lab.instructions"),
|
t("lab.instructions"),
|
||||||
{
|
{
|
||||||
value:'reset',
|
value: "reset",
|
||||||
text:t('lab.reset'),
|
text: t("lab.reset"),
|
||||||
disabled: !sumOfValues(creativeModePerks)
|
disabled: !sumOfValues(creativeModePerks),
|
||||||
},
|
},
|
||||||
...upgrades
|
...upgrades
|
||||||
.filter((u) => !noCreative.includes(u.id))
|
.filter((u) => !noCreative.includes(u.id))
|
||||||
|
@ -87,11 +87,11 @@ export async function openCreativeModePerksPicker(
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
) {
|
) {
|
||||||
if(choice==='reset'){
|
if (choice === "reset") {
|
||||||
upgrades.forEach((u) => {
|
upgrades.forEach((u) => {
|
||||||
creativeModePerks[u.id]=0
|
creativeModePerks[u.id] = 0;
|
||||||
});
|
});
|
||||||
}else if ("bricks" in choice) {
|
} else if ("bricks" in choice) {
|
||||||
setSettingValue("creativeModePerks_" + currentLevel, creativeModePerks);
|
setSettingValue("creativeModePerks_" + currentLevel, creativeModePerks);
|
||||||
upgrades.forEach((u) => {
|
upgrades.forEach((u) => {
|
||||||
gameState.perks[u.id] = creativeModePerks[u.id];
|
gameState.perks[u.id] = creativeModePerks[u.id];
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
"29058753"
|
"29058943"
|
||||||
|
|
|
@ -21,11 +21,13 @@ import {
|
||||||
distanceBetween,
|
distanceBetween,
|
||||||
getMajorityValue,
|
getMajorityValue,
|
||||||
getPossibleUpgrades,
|
getPossibleUpgrades,
|
||||||
getRowColIndex, isPickyEatingPossible,
|
getRowColIndex,
|
||||||
|
isPickyEatingPossible,
|
||||||
isTelekinesisActive,
|
isTelekinesisActive,
|
||||||
isYoyoActive,
|
isYoyoActive,
|
||||||
makeEmptyPerksMap,
|
makeEmptyPerksMap,
|
||||||
max_levels, reachRedRowIndex,
|
max_levels,
|
||||||
|
reachRedRowIndex,
|
||||||
shouldPierceByColor,
|
shouldPierceByColor,
|
||||||
} from "./game_utils";
|
} from "./game_utils";
|
||||||
import { t } from "./i18n/i18n";
|
import { t } from "./i18n/i18n";
|
||||||
|
@ -344,8 +346,9 @@ export function explodeBrick(
|
||||||
const color = gameState.bricks[index];
|
const color = gameState.bricks[index];
|
||||||
if (!color) return;
|
if (!color) return;
|
||||||
|
|
||||||
const wasPickyEaterPossible = gameState.perks.picky_eater&& isPickyEatingPossible(gameState)
|
const wasPickyEaterPossible =
|
||||||
const redRowReach=reachRedRowIndex(gameState)
|
gameState.perks.picky_eater && isPickyEatingPossible(gameState);
|
||||||
|
const redRowReach = reachRedRowIndex(gameState);
|
||||||
|
|
||||||
gameState.lastBrickBroken = gameState.levelTime;
|
gameState.lastBrickBroken = gameState.levelTime;
|
||||||
|
|
||||||
|
@ -437,18 +440,17 @@ export function explodeBrick(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(redRowReach!==-1){
|
if (redRowReach !== -1) {
|
||||||
if(Math.floor(index/gameState.level.size)===redRowReach ) {
|
if (Math.floor(index / gameState.level.size) === redRowReach) {
|
||||||
resetCombo(gameState, x, y);
|
resetCombo(gameState, x, y);
|
||||||
}else{
|
} else {
|
||||||
|
for (let x = 0; x < gameState.level.size; x++) {
|
||||||
for(let x=0;x<gameState.level.size;x++){
|
if (gameState.bricks[redRowReach * gameState.level.size + x])
|
||||||
if(gameState.bricks[redRowReach * gameState.level.size+ x])gameState.combo++
|
gameState.combo++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
gameState.lastPuckMove &&
|
gameState.lastPuckMove &&
|
||||||
gameState.perks.passive_income &&
|
gameState.perks.passive_income &&
|
||||||
|
@ -473,7 +475,7 @@ export function explodeBrick(
|
||||||
color !== gameState.ballsColor &&
|
color !== gameState.ballsColor &&
|
||||||
color
|
color
|
||||||
) {
|
) {
|
||||||
if ( wasPickyEaterPossible) {
|
if (wasPickyEaterPossible) {
|
||||||
resetCombo(gameState, ball.x, ball.y);
|
resetCombo(gameState, ball.x, ball.y);
|
||||||
}
|
}
|
||||||
schedulGameSound(gameState, "colorChange", ball.x, 0.8);
|
schedulGameSound(gameState, "colorChange", ball.x, 0.8);
|
||||||
|
@ -1675,17 +1677,19 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
||||||
if (!isOptionOn("basic")) {
|
if (!isOptionOn("basic")) {
|
||||||
const remainingPierce = ball.piercePoints;
|
const remainingPierce = ball.piercePoints;
|
||||||
const remainingSapper = ball.sapperUses < gameState.perks.sapper;
|
const remainingSapper = ball.sapperUses < gameState.perks.sapper;
|
||||||
|
const willMiss =
|
||||||
|
isOptionOn("red_miss") && ball.vy > 0 && !ball.hitSinceBounce;
|
||||||
const extraCombo = gameState.combo - 1;
|
const extraCombo = gameState.combo - 1;
|
||||||
if (
|
if (
|
||||||
|
willMiss ||
|
||||||
(extraCombo && Math.random() > 0.1 / (1 + extraCombo)) ||
|
(extraCombo && Math.random() > 0.1 / (1 + extraCombo)) ||
|
||||||
(remainingSapper && Math.random() > 0.1 / (1 + remainingSapper)) ||
|
(remainingSapper && Math.random() > 0.1 / (1 + remainingSapper)) ||
|
||||||
(extraCombo && Math.random() > 0.1 / (1 + extraCombo))
|
(extraCombo && Math.random() > 0.1 / (1 + extraCombo))
|
||||||
) {
|
) {
|
||||||
const color = remainingSapper
|
const color =
|
||||||
? Math.random() > 0.5
|
(remainingSapper && (Math.random() > 0.5 ? "orange" : "red")) ||
|
||||||
? "orange"
|
(willMiss && "red") ||
|
||||||
: "red"
|
gameState.ballsColor;
|
||||||
: gameState.ballsColor;
|
|
||||||
|
|
||||||
makeParticle(
|
makeParticle(
|
||||||
gameState,
|
gameState,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Ball, GameState, Level, PerkId, PerksMap } from "./types";
|
import { Ball, GameState, Level, PerkId, PerksMap } from "./types";
|
||||||
import { icons, upgrades } from "./loadGameData";
|
import { icons, upgrades } from "./loadGameData";
|
||||||
import { t } from "./i18n/i18n";
|
import { t } from "./i18n/i18n";
|
||||||
import {brickAt} from "./level_editor/levels_editor_util";
|
import { brickAt } from "./level_editor/levels_editor_util";
|
||||||
|
|
||||||
export function describeLevel(level: Level) {
|
export function describeLevel(level: Level) {
|
||||||
let bricks = 0,
|
let bricks = 0,
|
||||||
|
@ -132,29 +132,31 @@ export function currentLevelInfo(gameState: GameState) {
|
||||||
return gameState.level;
|
return gameState.level;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isPickyEatingPossible(gameState: GameState){
|
export function isPickyEatingPossible(gameState: GameState) {
|
||||||
return gameState.bricks.indexOf(gameState.ballsColor)!==-1
|
return gameState.bricks.indexOf(gameState.ballsColor) !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function reachRedRowIndex(gameState: GameState){
|
export function reachRedRowIndex(gameState: GameState) {
|
||||||
if(!gameState.perks.reach) return -1
|
if (!gameState.perks.reach) return -1;
|
||||||
const {size}=gameState.level
|
const { size } = gameState.level;
|
||||||
let minY=-1, maxY=-1, maxYCount=-1;
|
let minY = -1,
|
||||||
for(let y=0;y<size;y++)
|
maxY = -1,
|
||||||
for(let x=0;x<size;x++)
|
maxYCount = -1;
|
||||||
if(gameState.bricks[x+y*size]){
|
for (let y = 0; y < size; y++)
|
||||||
if(minY==-1) minY=y
|
for (let x = 0; x < size; x++)
|
||||||
if(maxY<y) {
|
if (gameState.bricks[x + y * size]) {
|
||||||
maxY = y
|
if (minY == -1) minY = y;
|
||||||
maxYCount = 0
|
if (maxY < y) {
|
||||||
|
maxY = y;
|
||||||
|
maxYCount = 0;
|
||||||
|
}
|
||||||
|
if (maxY == y) maxYCount++;
|
||||||
}
|
}
|
||||||
if(maxY==y) maxYCount++
|
|
||||||
}
|
|
||||||
|
|
||||||
if(maxY<1) return -1
|
if (maxY < 1) return -1;
|
||||||
if(maxY==minY) return -1
|
if (maxY == minY) return -1;
|
||||||
if(maxYCount===size) return -1
|
if (maxYCount === size) return -1;
|
||||||
return maxY
|
return maxY;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isTelekinesisActive(gameState: GameState, ball: Ball) {
|
export function isTelekinesisActive(gameState: GameState, ball: Ball) {
|
||||||
|
|
|
@ -1447,6 +1447,36 @@
|
||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>red_miss</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>
|
||||||
|
<name>red_miss_help</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>reset</name>
|
<name>reset</name>
|
||||||
<description/>
|
<description/>
|
||||||
|
|
|
@ -91,6 +91,8 @@
|
||||||
"main_menu.record": "Record gameplay videos",
|
"main_menu.record": "Record gameplay videos",
|
||||||
"main_menu.record_download": "Download video ({{size}} MB)",
|
"main_menu.record_download": "Download video ({{size}} MB)",
|
||||||
"main_menu.record_help": "Get a video of each level.",
|
"main_menu.record_help": "Get a video of each level.",
|
||||||
|
"main_menu.red_miss": "Miss warning",
|
||||||
|
"main_menu.red_miss_help": "Show red particles around balls going down without a hit.",
|
||||||
"main_menu.reset": "Reset Game",
|
"main_menu.reset": "Reset Game",
|
||||||
"main_menu.reset_cancel": "No",
|
"main_menu.reset_cancel": "No",
|
||||||
"main_menu.reset_confirm": "Yes",
|
"main_menu.reset_confirm": "Yes",
|
||||||
|
|
|
@ -91,6 +91,8 @@
|
||||||
"main_menu.record": "Enregistrer des vidéos de jeu",
|
"main_menu.record": "Enregistrer des vidéos de jeu",
|
||||||
"main_menu.record_download": "Télécharger la vidéo ({{size}} MB)",
|
"main_menu.record_download": "Télécharger la vidéo ({{size}} MB)",
|
||||||
"main_menu.record_help": "Obtenez une vidéo de chaque niveau.",
|
"main_menu.record_help": "Obtenez une vidéo de chaque niveau.",
|
||||||
|
"main_menu.red_miss": "Balles ratées",
|
||||||
|
"main_menu.red_miss_help": "Afficher des particules rouges autours des balles qui redescendent sans avoir touché une brique.",
|
||||||
"main_menu.reset": "Réinitialiser le jeu",
|
"main_menu.reset": "Réinitialiser le jeu",
|
||||||
"main_menu.reset_cancel": "Non",
|
"main_menu.reset_cancel": "Non",
|
||||||
"main_menu.reset_confirm": "Oui",
|
"main_menu.reset_confirm": "Oui",
|
||||||
|
|
|
@ -61,6 +61,11 @@ export const options = {
|
||||||
name: t("main_menu.donation_reminder"),
|
name: t("main_menu.donation_reminder"),
|
||||||
help: t("main_menu.donation_reminder_help"),
|
help: t("main_menu.donation_reminder_help"),
|
||||||
},
|
},
|
||||||
|
red_miss: {
|
||||||
|
default: false,
|
||||||
|
name: t("main_menu.red_miss"),
|
||||||
|
help: t("main_menu.red_miss_help"),
|
||||||
|
},
|
||||||
} as const satisfies { [k: string]: OptionDef };
|
} as const satisfies { [k: string]: OptionDef };
|
||||||
|
|
||||||
export function isOptionOn(key: OptionId) {
|
export function isOptionOn(key: OptionId) {
|
||||||
|
|
|
@ -4,10 +4,12 @@ import {
|
||||||
brickCenterY,
|
brickCenterY,
|
||||||
// countBricksAbove,
|
// countBricksAbove,
|
||||||
// countBricksBelow,
|
// countBricksBelow,
|
||||||
currentLevelInfo, isPickyEatingPossible,
|
currentLevelInfo,
|
||||||
|
isPickyEatingPossible,
|
||||||
isTelekinesisActive,
|
isTelekinesisActive,
|
||||||
isYoyoActive,
|
isYoyoActive,
|
||||||
max_levels, reachRedRowIndex,
|
max_levels,
|
||||||
|
reachRedRowIndex,
|
||||||
} from "./game_utils";
|
} from "./game_utils";
|
||||||
import { colorString, GameState } from "./types";
|
import { colorString, GameState } from "./types";
|
||||||
import { t } from "./i18n/i18n";
|
import { t } from "./i18n/i18n";
|
||||||
|
@ -547,9 +549,8 @@ export function renderAllBricks() {
|
||||||
const hasCombo = gameState.combo > baseCombo(gameState);
|
const hasCombo = gameState.combo > baseCombo(gameState);
|
||||||
|
|
||||||
const redBorderOnBricksWithWrongColor =
|
const redBorderOnBricksWithWrongColor =
|
||||||
hasCombo && gameState.perks.picky_eater && isPickyEatingPossible(gameState);
|
hasCombo && gameState.perks.picky_eater && isPickyEatingPossible(gameState);
|
||||||
|
|
||||||
console.log('redBorderOnBricksWithWrongColor '+redBorderOnBricksWithWrongColor)
|
|
||||||
const redColorOnAllBricks = !!(
|
const redColorOnAllBricks = !!(
|
||||||
gameState.lastPuckMove &&
|
gameState.lastPuckMove &&
|
||||||
gameState.perks.passive_income &&
|
gameState.perks.passive_income &&
|
||||||
|
@ -558,14 +559,14 @@ export function renderAllBricks() {
|
||||||
gameState.levelTime - 250 * gameState.perks.passive_income
|
gameState.levelTime - 250 * gameState.perks.passive_income
|
||||||
);
|
);
|
||||||
|
|
||||||
const redRowReach= reachRedRowIndex(gameState)
|
const redRowReach = reachRedRowIndex(gameState);
|
||||||
|
|
||||||
let offset = getDashOffset(gameState);
|
let offset = getDashOffset(gameState);
|
||||||
if (
|
if (
|
||||||
!(
|
!(
|
||||||
redBorderOnBricksWithWrongColor ||
|
redBorderOnBricksWithWrongColor ||
|
||||||
redColorOnAllBricks ||
|
redColorOnAllBricks ||
|
||||||
redRowReach!==-1 ||
|
redRowReach !== -1 ||
|
||||||
gameState.perks.zen
|
gameState.perks.zen
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
@ -575,14 +576,13 @@ export function renderAllBricks() {
|
||||||
const clairVoyance =
|
const clairVoyance =
|
||||||
gameState.perks.clairvoyant && gameState.brickHP.reduce((a, b) => a + b, 0);
|
gameState.perks.clairvoyant && gameState.brickHP.reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
|
|
||||||
const newKey =
|
const newKey =
|
||||||
gameState.gameZoneWidth +
|
gameState.gameZoneWidth +
|
||||||
"_" +
|
"_" +
|
||||||
gameState.bricks.join("_") +
|
gameState.bricks.join("_") +
|
||||||
bombSVG.complete +
|
bombSVG.complete +
|
||||||
"_" +
|
"_" +
|
||||||
redRowReach+
|
redRowReach +
|
||||||
"_" +
|
"_" +
|
||||||
redBorderOnBricksWithWrongColor +
|
redBorderOnBricksWithWrongColor +
|
||||||
"_" +
|
"_" +
|
||||||
|
@ -614,7 +614,8 @@ export function renderAllBricks() {
|
||||||
|
|
||||||
if (!color) return;
|
if (!color) return;
|
||||||
|
|
||||||
let redBecauseOfReach = redRowReach===Math.floor(index/gameState.level.size) ;
|
let redBecauseOfReach =
|
||||||
|
redRowReach === Math.floor(index / gameState.level.size);
|
||||||
|
|
||||||
let redBorder =
|
let redBorder =
|
||||||
(gameState.ballsColor !== color &&
|
(gameState.ballsColor !== color &&
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue