mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-22 13:06:15 -04:00
Build 29087244
This commit is contained in:
parent
5ba93500b4
commit
49f3769b54
21 changed files with 2505 additions and 2517 deletions
12
Readme.md
12
Readme.md
|
@ -11,19 +11,13 @@ Break colourful bricks, catch bouncing coins and select powerful upgrades !
|
||||||
- [Google Play](https://play.google.com/store/apps/details?id=me.lecaro.breakout)
|
- [Google Play](https://play.google.com/store/apps/details?id=me.lecaro.breakout)
|
||||||
- [GitLab](https://gitlab.com/lecarore/breakout71)
|
- [GitLab](https://gitlab.com/lecarore/breakout71)
|
||||||
|
|
||||||
# Current priorities
|
|
||||||
|
|
||||||
The goal of this project is to make a game used by many people.
|
|
||||||
The game is already pretty fun.
|
|
||||||
|
|
||||||
I'm now trying to translate it to (Lebanese) Arabic, Russian and (Chilean) Spanish.
|
|
||||||
Other translation are very welcome, contact me if you'd like to submit one.
|
|
||||||
|
|
||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
## To do
|
## To do
|
||||||
## Done
|
## Done
|
||||||
|
|
||||||
|
- apply percentage boost to combo shown on brick
|
||||||
|
- smaller puck now gives +50% coins per level
|
||||||
|
- transparency now gives +50% coins if ALL balls are fully transparent, less otherwise
|
||||||
- new perk : sticky coins (coins stick to bricks)
|
- new perk : sticky coins (coins stick to bricks)
|
||||||
- left/top/right is laval perks : at level 2+, the corresponding borders completely disappears (reachable with limitless)
|
- left/top/right is laval perks : at level 2+, the corresponding borders completely disappears (reachable with limitless)
|
||||||
- new perk : three cushion (gain point for indirect hits)
|
- new perk : three cushion (gain point for indirect hits)
|
||||||
|
|
|
@ -29,8 +29,8 @@ android {
|
||||||
applicationId = "me.lecaro.breakout"
|
applicationId = "me.lecaro.breakout"
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 29085904
|
versionCode = 29087244
|
||||||
versionName = "29085904"
|
versionName = "29087244"
|
||||||
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
819
dist/index.html
vendored
819
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 = "29085904";
|
const VERSION = "29087244";
|
||||||
|
|
||||||
// The name of the cache
|
// The name of the cache
|
||||||
const CACHE_NAME = `breakout-71-${VERSION}`;
|
const CACHE_NAME = `breakout-71-${VERSION}`;
|
||||||
|
|
|
@ -43,19 +43,17 @@ export async function openCreativeModePerksPicker() {
|
||||||
transformRawLevel,
|
transformRawLevel,
|
||||||
);
|
);
|
||||||
|
|
||||||
while (true ) {
|
while (true) {
|
||||||
|
const levelOptions = [
|
||||||
const levelOptions= [
|
|
||||||
...allLevels.map((l, li) => {
|
...allLevels.map((l, li) => {
|
||||||
const problem =
|
const problem = reasonLevelIsLocked(li, getHistory(), true)?.text || "";
|
||||||
reasonLevelIsLocked(li, getHistory(), true)?.text || "";
|
|
||||||
return {
|
return {
|
||||||
icon: icons[l.name],
|
icon: icons[l.name],
|
||||||
text: l.name,
|
text: l.name,
|
||||||
value: l,
|
value: l,
|
||||||
disabled: !!problem,
|
disabled: !!problem,
|
||||||
tooltip: problem || describeLevel(l),
|
tooltip: problem || describeLevel(l),
|
||||||
className:''
|
className: "",
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
...customLevels.map((l) => ({
|
...customLevels.map((l) => ({
|
||||||
|
@ -64,26 +62,28 @@ export async function openCreativeModePerksPicker() {
|
||||||
value: l,
|
value: l,
|
||||||
disabled: !l.bricks.filter((b) => b !== "_").length,
|
disabled: !l.bricks.filter((b) => b !== "_").length,
|
||||||
tooltip: describeLevel(l),
|
tooltip: describeLevel(l),
|
||||||
className:''
|
className: "",
|
||||||
}))
|
})),
|
||||||
]
|
];
|
||||||
|
|
||||||
const selectedLeveOption= levelOptions.find(l=>l.text===getSettingValue("creativeModeLevel", '')) || levelOptions[0]
|
const selectedLeveOption =
|
||||||
selectedLeveOption.className= 'highlight'
|
levelOptions.find(
|
||||||
|
(l) => l.text === getSettingValue("creativeModeLevel", ""),
|
||||||
|
) || levelOptions[0];
|
||||||
|
selectedLeveOption.className = "highlight";
|
||||||
|
|
||||||
|
const choice = await asyncAlert<Upgrade | Level | "reset" | "play">({
|
||||||
const choice=await asyncAlert<Upgrade | Level | "reset" | "play">({
|
|
||||||
title: t("lab.menu_entry"),
|
title: t("lab.menu_entry"),
|
||||||
className: "actionsAsGrid",
|
className: "actionsAsGrid",
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
icon: icons['icon:reset'],
|
icon: icons["icon:reset"],
|
||||||
value: "reset",
|
value: "reset",
|
||||||
text: t("lab.reset"),
|
text: t("lab.reset"),
|
||||||
disabled: !sumOfValues(creativeModePerks),
|
disabled: !sumOfValues(creativeModePerks),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: icons['icon:new_run'],
|
icon: icons["icon:new_run"],
|
||||||
value: "play",
|
value: "play",
|
||||||
text: t("lab.play"),
|
text: t("lab.play"),
|
||||||
disabled: !sumOfValues(creativeModePerks),
|
disabled: !sumOfValues(creativeModePerks),
|
||||||
|
@ -106,24 +106,28 @@ export async function openCreativeModePerksPicker() {
|
||||||
tooltip: u.help(creativeModePerks[u.id] || 1),
|
tooltip: u.help(creativeModePerks[u.id] || 1),
|
||||||
})),
|
})),
|
||||||
t("lab.select_level"),
|
t("lab.select_level"),
|
||||||
...levelOptions
|
...levelOptions,
|
||||||
],
|
],
|
||||||
})
|
});
|
||||||
if(!choice)return
|
if (!choice) return;
|
||||||
if (choice === "reset") {
|
if (choice === "reset") {
|
||||||
upgrades.forEach((u) => {
|
upgrades.forEach((u) => {
|
||||||
creativeModePerks[u.id] = 0;
|
creativeModePerks[u.id] = 0;
|
||||||
});
|
});
|
||||||
setSettingValue("creativeModePerks", creativeModePerks);
|
setSettingValue("creativeModePerks", creativeModePerks);
|
||||||
setSettingValue("creativeModeLevel", '')
|
setSettingValue("creativeModeLevel", "");
|
||||||
} else if (choice === "play" || ("bricks" in choice && choice.name==getSettingValue("creativeModeLevel", ''))) {
|
} else if (
|
||||||
|
choice === "play" ||
|
||||||
|
("bricks" in choice &&
|
||||||
|
choice.name == getSettingValue("creativeModeLevel", ""))
|
||||||
|
) {
|
||||||
if (await confirmRestart(gameState)) {
|
if (await confirmRestart(gameState)) {
|
||||||
restart({
|
restart({
|
||||||
perks: creativeModePerks,
|
perks: creativeModePerks,
|
||||||
level: selectedLeveOption.value,
|
level: selectedLeveOption.value,
|
||||||
isCreativeRun: true,
|
isCreativeRun: true,
|
||||||
});
|
});
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
} else if ("bricks" in choice) {
|
} else if ("bricks" in choice) {
|
||||||
setSettingValue("creativeModeLevel", choice.name);
|
setSettingValue("creativeModeLevel", choice.name);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
"29085904"
|
"29087244"
|
||||||
|
|
|
@ -585,8 +585,7 @@ h2.histogram-title strong {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.not-highlighed{
|
.not-highlighed {
|
||||||
opacity: 0.8; color: #8a8a8a;
|
opacity: 0.8;
|
||||||
|
color: #8a8a8a;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
describeLevel,
|
describeLevel,
|
||||||
getRowColIndex,
|
getRowColIndex,
|
||||||
highScoreText,
|
highScoreText,
|
||||||
|
hoursSpentPlaying,
|
||||||
isInWebView,
|
isInWebView,
|
||||||
levelsListHTMl,
|
levelsListHTMl,
|
||||||
max_levels,
|
max_levels,
|
||||||
|
@ -79,7 +80,6 @@ import {
|
||||||
catchRateBest,
|
catchRateBest,
|
||||||
catchRateGood,
|
catchRateGood,
|
||||||
clamp,
|
clamp,
|
||||||
hoursSpentPlaying,
|
|
||||||
levelTimeBest,
|
levelTimeBest,
|
||||||
levelTimeGood,
|
levelTimeGood,
|
||||||
missesBest,
|
missesBest,
|
||||||
|
@ -248,7 +248,8 @@ setInterval(() => {
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
export async function openUpgradesPicker(gameState: GameState) {
|
export async function openUpgradesPicker(gameState: GameState) {
|
||||||
const catchRate = (gameState.score - gameState.levelStartScore) /
|
const catchRate =
|
||||||
|
(gameState.score - gameState.levelStartScore) /
|
||||||
(gameState.levelSpawnedCoins || 1);
|
(gameState.levelSpawnedCoins || 1);
|
||||||
|
|
||||||
let repeats = 1;
|
let repeats = 1;
|
||||||
|
|
|
@ -12,7 +12,6 @@ import {
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ballTransparency,
|
|
||||||
brickCenterX,
|
brickCenterX,
|
||||||
brickCenterY,
|
brickCenterY,
|
||||||
currentLevelInfo,
|
currentLevelInfo,
|
||||||
|
@ -32,12 +31,12 @@ import {
|
||||||
telekinesisEffectRate,
|
telekinesisEffectRate,
|
||||||
yoyoEffectRate,
|
yoyoEffectRate,
|
||||||
} from "./game_utils";
|
} from "./game_utils";
|
||||||
import {t} from "./i18n/i18n";
|
import { t } from "./i18n/i18n";
|
||||||
import {icons} from "./loadGameData";
|
import { icons } from "./loadGameData";
|
||||||
|
|
||||||
import {getCurrentMaxCoins, getCurrentMaxParticles} from "./settings";
|
import { getCurrentMaxCoins, getCurrentMaxParticles } from "./settings";
|
||||||
import {background} from "./render";
|
import { background } from "./render";
|
||||||
import {gameOver} from "./gameOver";
|
import { gameOver } from "./gameOver";
|
||||||
import {
|
import {
|
||||||
brickIndex,
|
brickIndex,
|
||||||
fitSize,
|
fitSize,
|
||||||
|
@ -48,11 +47,17 @@ import {
|
||||||
pause,
|
pause,
|
||||||
startComputerControlledGame,
|
startComputerControlledGame,
|
||||||
} from "./game";
|
} from "./game";
|
||||||
import {stopRecording} from "./recording";
|
import { stopRecording } from "./recording";
|
||||||
import {isOptionOn} from "./options";
|
import { isOptionOn } from "./options";
|
||||||
import {clamp, coinsBoostedCombo, comboKeepingRate, shouldCoinsStick} from "./pure_functions";
|
import {
|
||||||
import {addToTotalScore} from "./addToTotalScore";
|
ballTransparency,
|
||||||
import {hashCode} from "./getLevelBackground";
|
clamp,
|
||||||
|
coinsBoostedCombo,
|
||||||
|
comboKeepingRate,
|
||||||
|
shouldCoinsStick,
|
||||||
|
} from "./pure_functions";
|
||||||
|
import { addToTotalScore } from "./addToTotalScore";
|
||||||
|
import { hashCode } from "./getLevelBackground";
|
||||||
|
|
||||||
export function setMousePos(gameState: GameState, x: number) {
|
export function setMousePos(gameState: GameState, x: number) {
|
||||||
if (gameState.startParams.computer_controlled) return;
|
if (gameState.startParams.computer_controlled) return;
|
||||||
|
@ -216,11 +221,7 @@ export function baseCombo(gameState: GameState) {
|
||||||
gameState.perks.minefield &&
|
gameState.perks.minefield &&
|
||||||
gameState.bricks.filter((b) => b === "black").length *
|
gameState.bricks.filter((b) => b === "black").length *
|
||||||
gameState.perks.minefield;
|
gameState.perks.minefield;
|
||||||
return (
|
return 1 + gameState.perks.base_combo * 3 + mineFieldBonus;
|
||||||
1 +
|
|
||||||
gameState.perks.base_combo * 3 +
|
|
||||||
mineFieldBonus
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetCombo(
|
export function resetCombo(
|
||||||
|
@ -432,7 +433,7 @@ export function explodeBrick(
|
||||||
|
|
||||||
setBrick(gameState, index, "");
|
setBrick(gameState, index, "");
|
||||||
|
|
||||||
let coinsToSpawn = coinsBoostedCombo(gameState)
|
let coinsToSpawn = coinsBoostedCombo(gameState);
|
||||||
|
|
||||||
gameState.levelSpawnedCoins += coinsToSpawn;
|
gameState.levelSpawnedCoins += coinsToSpawn;
|
||||||
gameState.runStatistics.coins_spawned += coinsToSpawn;
|
gameState.runStatistics.coins_spawned += coinsToSpawn;
|
||||||
|
@ -449,7 +450,7 @@ export function explodeBrick(
|
||||||
while (coinsToSpawn > 0) {
|
while (coinsToSpawn > 0) {
|
||||||
const points = Math.min(pointsPerCoin, coinsToSpawn);
|
const points = Math.min(pointsPerCoin, coinsToSpawn);
|
||||||
if (points < 0 || isNaN(points)) {
|
if (points < 0 || isNaN(points)) {
|
||||||
console.error({points});
|
console.error({ points });
|
||||||
debugger;
|
debugger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,9 +631,7 @@ export function addToScore(gameState: GameState, coin: Coin) {
|
||||||
gameState.highScore = gameState.score;
|
gameState.highScore = gameState.score;
|
||||||
try {
|
try {
|
||||||
localStorage.setItem("breakout-3-hs-short", gameState.score.toString());
|
localStorage.setItem("breakout-3-hs-short", gameState.score.toString());
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!isOptionOn("basic")) {
|
if (!isOptionOn("basic")) {
|
||||||
makeParticle(
|
makeParticle(
|
||||||
|
@ -872,7 +871,7 @@ export function attract(gameState: GameState, a: Ball, b: Ball, power: number) {
|
||||||
export function coinBrickHitCheck(gameState: GameState, coin: Coin) {
|
export function coinBrickHitCheck(gameState: GameState, coin: Coin) {
|
||||||
// Make ball/coin bonce, and return bricks that were hit
|
// Make ball/coin bonce, and return bricks that were hit
|
||||||
const radius = coin.size / 2;
|
const radius = coin.size / 2;
|
||||||
const {x, y, previousX, previousY} = coin;
|
const { x, y, previousX, previousY } = coin;
|
||||||
|
|
||||||
const vhit = hitsSomething(previousX, y, radius);
|
const vhit = hitsSomething(previousX, y, radius);
|
||||||
const hhit = hitsSomething(x, previousY, radius);
|
const hhit = hitsSomething(x, previousY, radius);
|
||||||
|
@ -884,12 +883,12 @@ export function coinBrickHitCheck(gameState: GameState, coin: Coin) {
|
||||||
|
|
||||||
if (typeof (vhit ?? hhit ?? chit) !== "undefined") {
|
if (typeof (vhit ?? hhit ?? chit) !== "undefined") {
|
||||||
if (shouldCoinsStick(gameState)) {
|
if (shouldCoinsStick(gameState)) {
|
||||||
if(coin.collidedLastFrame) {
|
if (coin.collidedLastFrame) {
|
||||||
coin.x = previousX
|
coin.x = previousX;
|
||||||
coin.y = previousY
|
coin.y = previousY;
|
||||||
}
|
}
|
||||||
coin.vx = 0
|
coin.vx = 0;
|
||||||
coin.vy = 0
|
coin.vy = 0;
|
||||||
} else if (gameState.perks.ghost_coins) {
|
} else if (gameState.perks.ghost_coins) {
|
||||||
// slow down
|
// slow down
|
||||||
coin.vy *= 1 - 0.2 / gameState.perks.ghost_coins;
|
coin.vy *= 1 - 0.2 / gameState.perks.ghost_coins;
|
||||||
|
@ -945,7 +944,10 @@ export function bordersHitCheck(
|
||||||
let vhit = 0,
|
let vhit = 0,
|
||||||
hhit = 0;
|
hhit = 0;
|
||||||
|
|
||||||
if (coin.x < gameState.offsetXRoundedDown + radius && gameState.perks.left_is_lava < 2) {
|
if (
|
||||||
|
coin.x < gameState.offsetXRoundedDown + radius &&
|
||||||
|
gameState.perks.left_is_lava < 2
|
||||||
|
) {
|
||||||
coin.x =
|
coin.x =
|
||||||
gameState.offsetXRoundedDown +
|
gameState.offsetXRoundedDown +
|
||||||
radius +
|
radius +
|
||||||
|
@ -958,7 +960,10 @@ export function bordersHitCheck(
|
||||||
coin.vy *= -1;
|
coin.vy *= -1;
|
||||||
vhit = 1;
|
vhit = 1;
|
||||||
}
|
}
|
||||||
if (coin.x > gameState.canvasWidth - gameState.offsetXRoundedDown - radius && gameState.perks.right_is_lava < 2) {
|
if (
|
||||||
|
coin.x > gameState.canvasWidth - gameState.offsetXRoundedDown - radius &&
|
||||||
|
gameState.perks.right_is_lava < 2
|
||||||
|
) {
|
||||||
coin.x =
|
coin.x =
|
||||||
gameState.canvasWidth -
|
gameState.canvasWidth -
|
||||||
gameState.offsetXRoundedDown -
|
gameState.offsetXRoundedDown -
|
||||||
|
@ -969,7 +974,6 @@ export function bordersHitCheck(
|
||||||
hhit = 1;
|
hhit = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return hhit + vhit * 2;
|
return hhit + vhit * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1014,10 +1018,8 @@ export function gameStateTick(
|
||||||
if (gameState.perks.hot_start) {
|
if (gameState.perks.hot_start) {
|
||||||
if (gameState.combo === baseCombo(gameState)) {
|
if (gameState.combo === baseCombo(gameState)) {
|
||||||
// Give 1s of time between catching a coin and tick down
|
// Give 1s of time between catching a coin and tick down
|
||||||
gameState.lastTickDown = gameState.levelTime
|
gameState.lastTickDown = gameState.levelTime;
|
||||||
} else if (
|
} else if (gameState.levelTime > gameState.lastTickDown + 1000) {
|
||||||
gameState.levelTime > gameState.lastTickDown + 1000
|
|
||||||
) {
|
|
||||||
gameState.lastTickDown = gameState.levelTime;
|
gameState.lastTickDown = gameState.levelTime;
|
||||||
decreaseCombo(
|
decreaseCombo(
|
||||||
gameState,
|
gameState,
|
||||||
|
@ -1028,7 +1030,6 @@ export function gameStateTick(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
remainingBricks <= gameState.perks.skip_last &&
|
remainingBricks <= gameState.perks.skip_last &&
|
||||||
!gameState.autoCleanUses
|
!gameState.autoCleanUses
|
||||||
|
@ -1066,7 +1067,7 @@ export function gameStateTick(
|
||||||
} else {
|
} else {
|
||||||
gameOver(
|
gameOver(
|
||||||
t("gameOver.win.title"),
|
t("gameOver.win.title"),
|
||||||
t("gameOver.win.summary", {score: gameState.score}),
|
t("gameOver.win.summary", { score: gameState.score }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (gameState.running || gameState.levelTime) {
|
} else if (gameState.running || gameState.levelTime) {
|
||||||
|
@ -1161,10 +1162,12 @@ export function gameStateTick(
|
||||||
coin.vy *= ratio;
|
coin.vy *= ratio;
|
||||||
coin.vx *= ratio;
|
coin.vx *= ratio;
|
||||||
}
|
}
|
||||||
if (coin.y > gameState.gameZoneHeight && coin.floatingTime < gameState.perks.buoy * 30) {
|
if (
|
||||||
|
coin.y > gameState.gameZoneHeight &&
|
||||||
coin.floatingTime += frames
|
coin.floatingTime < gameState.perks.buoy * 30
|
||||||
coin.vy -= 1.5
|
) {
|
||||||
|
coin.floatingTime += frames;
|
||||||
|
coin.vy -= 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coin.vx > 7 * gameState.baseSpeed) coin.vx = 7 * gameState.baseSpeed;
|
if (coin.vx > 7 * gameState.baseSpeed) coin.vx = 7 * gameState.baseSpeed;
|
||||||
|
@ -1215,7 +1218,6 @@ export function gameStateTick(
|
||||||
|
|
||||||
const hitBorder = bordersHitCheck(gameState, coin, coin.size / 2, frames);
|
const hitBorder = bordersHitCheck(gameState, coin, coin.size / 2, frames);
|
||||||
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
coin.previousY < gameState.gameZoneHeight &&
|
coin.previousY < gameState.gameZoneHeight &&
|
||||||
coin.y > gameState.gameZoneHeight &&
|
coin.y > gameState.gameZoneHeight &&
|
||||||
|
@ -1267,11 +1269,14 @@ export function gameStateTick(
|
||||||
|
|
||||||
if (
|
if (
|
||||||
gameState.combo < gameState.perks.fountain_toss * 30 &&
|
gameState.combo < gameState.perks.fountain_toss * 30 &&
|
||||||
Math.random() / coin.points < (1 / gameState.combo) * gameState.perks.fountain_toss
|
Math.random() / coin.points <
|
||||||
|
(1 / gameState.combo) * gameState.perks.fountain_toss
|
||||||
) {
|
) {
|
||||||
increaseCombo(gameState, 1,
|
increaseCombo(
|
||||||
|
gameState,
|
||||||
|
1,
|
||||||
clamp(coin.x, 20, gameState.canvasWidth - 20),
|
clamp(coin.x, 20, gameState.canvasWidth - 20),
|
||||||
clamp(coin.y, 20, gameState.gameZoneHeight - 20)
|
clamp(coin.y, 20, gameState.gameZoneHeight - 20),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1319,10 +1324,7 @@ export function gameStateTick(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// remember collision
|
// remember collision
|
||||||
coin.collidedLastFrame = !!(
|
coin.collidedLastFrame = !!(typeof hitBrick !== "undefined" || hitBorder);
|
||||||
typeof hitBrick !== "undefined" ||
|
|
||||||
hitBorder
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
gameState.balls.forEach((ball) => ballTick(gameState, ball, frames));
|
gameState.balls.forEach((ball) => ballTick(gameState, ball, frames));
|
||||||
|
@ -1330,7 +1332,6 @@ export function gameStateTick(
|
||||||
if (gameState.perks.shocks) {
|
if (gameState.perks.shocks) {
|
||||||
gameState.balls.forEach((a, ai) =>
|
gameState.balls.forEach((a, ai) =>
|
||||||
gameState.balls.forEach((b, bi) => {
|
gameState.balls.forEach((b, bi) => {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
ai < bi &&
|
ai < bi &&
|
||||||
!a.destroyed &&
|
!a.destroyed &&
|
||||||
|
@ -1349,7 +1350,7 @@ export function gameStateTick(
|
||||||
let y = (a.y + b.y) / 2;
|
let y = (a.y + b.y) / 2;
|
||||||
// space out the balls with extra speed
|
// space out the balls with extra speed
|
||||||
if (gameState.perks.shocks > 1) {
|
if (gameState.perks.shocks > 1) {
|
||||||
const limit = gameState.baseSpeed * gameState.perks.shocks / 2;
|
const limit = (gameState.baseSpeed * gameState.perks.shocks) / 2;
|
||||||
a.vx +=
|
a.vx +=
|
||||||
clamp(a.x - x, -limit, limit) +
|
clamp(a.x - x, -limit, limit) +
|
||||||
((Math.random() - 0.5) * limit) / 3;
|
((Math.random() - 0.5) * limit) / 3;
|
||||||
|
@ -1512,7 +1513,7 @@ export function gameStateTick(
|
||||||
setBrick(gameState, r.index, r.color);
|
setBrick(gameState, r.index, r.color);
|
||||||
destroy(gameState.respawns, ri);
|
destroy(gameState.respawns, ri);
|
||||||
} else {
|
} else {
|
||||||
const {index, color} = r;
|
const { index, color } = r;
|
||||||
const vertical = Math.random() > 0.5;
|
const vertical = Math.random() > 0.5;
|
||||||
const dx = Math.random() > 0.5 ? 1 : -1;
|
const dx = Math.random() > 0.5 ? 1 : -1;
|
||||||
const dy = Math.random() > 0.5 ? 1 : -1;
|
const dy = Math.random() > 0.5 ? 1 : -1;
|
||||||
|
@ -1641,8 +1642,7 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
|
||||||
frames,
|
frames,
|
||||||
);
|
);
|
||||||
if (borderHitCode) {
|
if (borderHitCode) {
|
||||||
|
ball.sidesHitsSinceBounce++;
|
||||||
ball.sidesHitsSinceBounce++
|
|
||||||
if (ball.sidesHitsSinceBounce <= gameState.perks.three_cushion * 3) {
|
if (ball.sidesHitsSinceBounce <= gameState.perks.three_cushion * 3) {
|
||||||
increaseCombo(gameState, 1, ball.x, ball.y);
|
increaseCombo(gameState, 1, ball.x, ball.y);
|
||||||
}
|
}
|
||||||
|
@ -1755,13 +1755,10 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
gameState.running &&
|
gameState.running &&
|
||||||
(
|
(ball.y > gameState.gameZoneHeight + gameState.ballSize / 2 ||
|
||||||
ball.y > gameState.gameZoneHeight + gameState.ballSize / 2 ||
|
|
||||||
ball.y < -gameState.gameZoneHeight ||
|
ball.y < -gameState.gameZoneHeight ||
|
||||||
ball.x < -gameState.gameZoneHeight ||
|
ball.x < -gameState.gameZoneHeight ||
|
||||||
ball.x > gameState.canvasWidth + gameState.gameZoneHeight
|
ball.x > gameState.canvasWidth + gameState.gameZoneHeight)
|
||||||
)
|
|
||||||
|
|
||||||
) {
|
) {
|
||||||
ball.destroyed = true;
|
ball.destroyed = true;
|
||||||
gameState.runStatistics.balls_lost++;
|
gameState.runStatistics.balls_lost++;
|
||||||
|
@ -1771,14 +1768,14 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
|
||||||
} else {
|
} else {
|
||||||
gameOver(
|
gameOver(
|
||||||
t("gameOver.lost.title"),
|
t("gameOver.lost.title"),
|
||||||
t("gameOver.lost.summary", {score: gameState.score}),
|
t("gameOver.lost.summary", { score: gameState.score }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const radius = gameState.ballSize / 2;
|
const radius = gameState.ballSize / 2;
|
||||||
// Make ball/coin bonce, and return bricks that were hit
|
// 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 vhit = hitsSomething(previousX, y, radius);
|
||||||
const hhit = hitsSomething(x, previousY, radius);
|
const hhit = hitsSomething(x, previousY, radius);
|
||||||
|
@ -1841,7 +1838,7 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
|
||||||
|
|
||||||
if (!gameState.brickHP[hitBrick]) {
|
if (!gameState.brickHP[hitBrick]) {
|
||||||
ball.brokenSinceBounce++;
|
ball.brokenSinceBounce++;
|
||||||
applyOttawaTreatyPerk(gameState, hitBrick, ball)
|
applyOttawaTreatyPerk(gameState, hitBrick, ball);
|
||||||
explodeBrick(gameState, hitBrick, ball, false);
|
explodeBrick(gameState, hitBrick, ball, false);
|
||||||
if (
|
if (
|
||||||
ball.sapperUses < gameState.perks.sapper &&
|
ball.sapperUses < gameState.perks.sapper &&
|
||||||
|
@ -1851,8 +1848,6 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
|
||||||
setBrick(gameState, hitBrick, "black");
|
setBrick(gameState, hitBrick, "black");
|
||||||
ball.sapperUses++;
|
ball.sapperUses++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
schedulGameSound(gameState, "wallBeep", x, 1);
|
schedulGameSound(gameState, "wallBeep", x, 1);
|
||||||
makeLight(
|
makeLight(
|
||||||
|
@ -1971,7 +1966,7 @@ function makeCoin(
|
||||||
p.points = points;
|
p.points = points;
|
||||||
p.weight = weight;
|
p.weight = weight;
|
||||||
p.metamorphosisPoints = gameState.perks.metamorphosis;
|
p.metamorphosisPoints = gameState.perks.metamorphosis;
|
||||||
p.floatingTime = 0
|
p.floatingTime = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2053,7 +2048,7 @@ export function append<T>(
|
||||||
makeItem(where.list[where.indexMin]);
|
makeItem(where.list[where.indexMin]);
|
||||||
where.indexMin++;
|
where.indexMin++;
|
||||||
} else {
|
} else {
|
||||||
const p = {destroyed: false};
|
const p = { destroyed: false };
|
||||||
makeItem(p);
|
makeItem(p);
|
||||||
where.list.push(p);
|
where.list.push(p);
|
||||||
}
|
}
|
||||||
|
@ -2146,32 +2141,37 @@ function goToNearestBrick(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyOttawaTreatyPerk(
|
||||||
|
gameState: GameState,
|
||||||
|
index: number,
|
||||||
|
ball: Ball,
|
||||||
|
) {
|
||||||
|
if (!gameState.perks.ottawa_treaty) return;
|
||||||
|
if (ball.sapperUses) return;
|
||||||
|
|
||||||
function applyOttawaTreatyPerk(gameState: GameState, index: number, ball: Ball) {
|
const originalColor = gameState.bricks[index];
|
||||||
if (!gameState.perks.ottawa_treaty) return
|
if (originalColor == "black") return;
|
||||||
if (ball.sapperUses) return
|
const x = index % gameState.gridSize;
|
||||||
|
const y = Math.floor(index / gameState.gridSize);
|
||||||
const originalColor = gameState.bricks[index]
|
let converted = 0;
|
||||||
if (originalColor == 'black') return
|
|
||||||
const x = index % gameState.gridSize
|
|
||||||
const y = Math.floor(index / gameState.gridSize)
|
|
||||||
let converted = 0
|
|
||||||
for (let dx = -1; dx <= 1; dx++)
|
for (let dx = -1; dx <= 1; dx++)
|
||||||
for (let dy = -1; dy <= 1; dy++)
|
for (let dy = -1; dy <= 1; dy++)
|
||||||
if (dx || dy) {
|
if (dx || dy) {
|
||||||
const nIndex = getRowColIndex(gameState, y + dy, x + dx)
|
const nIndex = getRowColIndex(gameState, y + dy, x + dx);
|
||||||
if (gameState.bricks[nIndex] && gameState.bricks[nIndex] === 'black') {
|
if (gameState.bricks[nIndex] && gameState.bricks[nIndex] === "black") {
|
||||||
|
setBrick(gameState, nIndex, originalColor);
|
||||||
setBrick(gameState, nIndex, originalColor)
|
schedulGameSound(
|
||||||
schedulGameSound(gameState, "colorChange", brickCenterX(gameState, index), 1)
|
gameState,
|
||||||
|
"colorChange",
|
||||||
|
brickCenterX(gameState, index),
|
||||||
|
1,
|
||||||
|
);
|
||||||
// Avoid infinite bricks generation hack
|
// Avoid infinite bricks generation hack
|
||||||
ball.sapperUses = Infinity
|
ball.sapperUses = Infinity;
|
||||||
converted++
|
converted++;
|
||||||
// Don't convert more than one brick per hit normally
|
// Don't convert more than one brick per hit normally
|
||||||
if (converted >= gameState.perks.ottawa_treaty) return
|
if (converted >= gameState.perks.ottawa_treaty) return;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { t } from "./i18n/i18n";
|
||||||
import { clamp } from "./pure_functions";
|
import { clamp } from "./pure_functions";
|
||||||
import { rawUpgrades } from "./upgrades";
|
import { rawUpgrades } from "./upgrades";
|
||||||
import { hashCode } from "./getLevelBackground";
|
import { hashCode } from "./getLevelBackground";
|
||||||
import { getTotalScore } from "./settings";
|
import { getSettingValue, getTotalScore } from "./settings";
|
||||||
import { isOptionOn } from "./options";
|
import { isOptionOn } from "./options";
|
||||||
|
|
||||||
export function describeLevel(level: Level) {
|
export function describeLevel(level: Level) {
|
||||||
|
@ -392,16 +392,6 @@ export function reasonLevelIsLocked(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ballTransparency(ball: Ball, gameState: GameState) {
|
|
||||||
if (!gameState.perks.transparency) return 0;
|
|
||||||
return clamp(
|
|
||||||
gameState.perks.transparency *
|
|
||||||
(1 - (ball.y / gameState.gameZoneHeight) * 1.2),
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCoinRenderColor(gameState: GameState, coin: Coin) {
|
export function getCoinRenderColor(gameState: GameState, coin: Coin) {
|
||||||
if (
|
if (
|
||||||
gameState.perks.metamorphosis ||
|
gameState.perks.metamorphosis ||
|
||||||
|
@ -423,3 +413,12 @@ export function getCornerOffset(gameState: GameState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isInWebView = !!window.location.href.includes("isInWebView=true");
|
export const isInWebView = !!window.location.href.includes("isInWebView=true");
|
||||||
|
|
||||||
|
export function hoursSpentPlaying() {
|
||||||
|
try {
|
||||||
|
const timePlayed = getSettingValue("breakout_71_total_play_time", 0);
|
||||||
|
return Math.floor(timePlayed / 1000 / 60 / 60);
|
||||||
|
} catch (e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import { icons, transformRawLevel } from "./loadGameData";
|
import { icons, transformRawLevel } from "./loadGameData";
|
||||||
import { t } from "./i18n/i18n";
|
import { t } from "./i18n/i18n";
|
||||||
import {
|
import { getSettingValue, getTotalScore, setSettingValue } from "./settings";
|
||||||
getSettingValue,
|
|
||||||
getTotalScore,
|
|
||||||
setSettingValue,
|
|
||||||
} from "./settings";
|
|
||||||
import { asyncAlert } from "./asyncAlert";
|
import { asyncAlert } from "./asyncAlert";
|
||||||
import { Palette, RawLevel } from "./types";
|
import { Palette, RawLevel } from "./types";
|
||||||
import { levelIconHTML } from "./levelIcon";
|
import { levelIconHTML } from "./levelIcon";
|
||||||
|
@ -165,7 +161,6 @@ export async function editRawLevelList(nth: number, color = "W") {
|
||||||
text: t("editor.editing.copy"),
|
text: t("editor.editing.copy"),
|
||||||
value: "copy",
|
value: "copy",
|
||||||
help: t("editor.editing.copy_help"),
|
help: t("editor.editing.copy_help"),
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: t("editor.editing.bigger"),
|
text: t("editor.editing.bigger"),
|
||||||
|
@ -250,7 +245,10 @@ export async function editRawLevelList(nth: number, color = "W") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (action === "copy") {
|
if (action === "copy") {
|
||||||
let text = "```\n[" + (level.name||'unnamed level')?.replace(/\[|\]/gi, " ") + "]";
|
let text =
|
||||||
|
"```\n[" +
|
||||||
|
(level.name || "unnamed level")?.replace(/\[|\]/gi, " ") +
|
||||||
|
"]";
|
||||||
bricks.forEach((b, bi) => {
|
bricks.forEach((b, bi) => {
|
||||||
if (!(bi % level.size)) text += "\n";
|
if (!(bi % level.size)) text += "\n";
|
||||||
text += b;
|
text += b;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import _palette from "./data/palette.json";
|
import _palette from "./data/palette.json";
|
||||||
import _rawLevelsList from "./data/levels.json";
|
import _rawLevelsList from "./data/levels.json";
|
||||||
import _appVersion from "./data/version.json";
|
import _appVersion from "./data/version.json";
|
||||||
import { rawUpgrades } from "./upgrades";
|
|
||||||
|
|
||||||
describe("json data checks", () => {
|
describe("json data checks", () => {
|
||||||
it("_rawLevelsList has icon levels", () => {
|
it("_rawLevelsList has icon levels", () => {
|
||||||
|
@ -10,13 +9,6 @@ describe("json data checks", () => {
|
||||||
).toBeGreaterThan(10);
|
).toBeGreaterThan(10);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("all upgrades have icons", () => {
|
|
||||||
const missingIcon = rawUpgrades.filter(
|
|
||||||
(u) => !_rawLevelsList.find((l) => l.name == "icon:" + u.id),
|
|
||||||
);
|
|
||||||
expect(missingIcon).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("_rawLevelsList has non-icon few levels", () => {
|
it("_rawLevelsList has non-icon few levels", () => {
|
||||||
expect(
|
expect(
|
||||||
_rawLevelsList.filter((l) => !l.name.startsWith("icon:")).length,
|
_rawLevelsList.filter((l) => !l.name.startsWith("icon:")).length,
|
||||||
|
|
|
@ -140,16 +140,15 @@ migrate("set_breakout_71_unlocked_levels" + _appVersion, () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrate('clean_ls', ()=>{
|
migrate("clean_ls", () => {
|
||||||
for (let key in localStorage) {
|
for (let key in localStorage) {
|
||||||
try {
|
try {
|
||||||
JSON.parse(localStorage.getItem(key) || "null");
|
JSON.parse(localStorage.getItem(key) || "null");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
localStorage.removeItem(key)
|
localStorage.removeItem(key);
|
||||||
console.warn('Removed invalid key '+key,e);
|
console.warn("Removed invalid key " + key, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
})
|
|
||||||
|
|
||||||
afterMigration();
|
afterMigration();
|
||||||
|
|
|
@ -2,7 +2,8 @@ import { t } from "./i18n/i18n";
|
||||||
|
|
||||||
import { OptionDef, OptionId } from "./types";
|
import { OptionDef, OptionId } from "./types";
|
||||||
import { getSettingValue, setSettingValue } from "./settings";
|
import { getSettingValue, setSettingValue } from "./settings";
|
||||||
import { hoursSpentPlaying } from "./pure_functions";
|
|
||||||
|
import { hoursSpentPlaying } from "./game_utils";
|
||||||
|
|
||||||
export const options = {
|
export const options = {
|
||||||
sound: {
|
sound: {
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import { getSettingValue } from "./settings";
|
import { Ball, GameState } from "./types";
|
||||||
import {GameState} from "./types";
|
|
||||||
import {ballTransparency} from "./game_utils";
|
|
||||||
|
|
||||||
export function clamp(value: number, min: number, max: number) {
|
export function clamp(value: number, min: number, max: number) {
|
||||||
return Math.max(min, Math.min(value, max));
|
return Math.max(min, Math.min(value, max));
|
||||||
|
@ -10,33 +8,39 @@ export function comboKeepingRate(level: number) {
|
||||||
return clamp(1 - (1 / (1 + level)) * 1.5, 0, 1);
|
return clamp(1 - (1 / (1 + level)) * 1.5, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hoursSpentPlaying() {
|
export function shouldCoinsStick(gameState: GameState) {
|
||||||
try {
|
return (
|
||||||
const timePlayed = getSettingValue("breakout_71_total_play_time", 0);
|
gameState.perks.sticky_coins &&
|
||||||
return Math.floor(timePlayed / 1000 / 60 / 60);
|
(!gameState.lastExplosion ||
|
||||||
} catch (e) {
|
gameState.lastExplosion <
|
||||||
return 0;
|
gameState.levelTime - 300 * gameState.perks.sticky_coins)
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shouldCoinsStick(gameState:GameState){
|
export function ballTransparency(ball: Ball, gameState: GameState) {
|
||||||
return gameState.perks.sticky_coins && (!gameState.lastExplosion || gameState.lastExplosion < gameState.levelTime - 300 * gameState.perks.sticky_coins)
|
if (!gameState.perks.transparency) return 0;
|
||||||
|
return clamp(
|
||||||
|
gameState.perks.transparency *
|
||||||
|
(1 - (ball.y / gameState.gameZoneHeight) * 1.2),
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function coinsBoostedCombo(gameState:GameState){
|
export function coinsBoostedCombo(gameState: GameState) {
|
||||||
let boost = 1+gameState.perks.sturdy_bricks / 2 + gameState.perks.smaller_puck/2
|
let boost =
|
||||||
if(gameState.perks.transparency){
|
1 + gameState.perks.sturdy_bricks / 2 + gameState.perks.smaller_puck / 2;
|
||||||
let min=1;
|
if (gameState.perks.transparency) {
|
||||||
gameState.balls.forEach(ball=>{
|
let min = 1;
|
||||||
const bt=ballTransparency(ball, gameState)
|
gameState.balls.forEach((ball) => {
|
||||||
if(bt<min){
|
const bt = ballTransparency(ball, gameState);
|
||||||
min=bt
|
if (bt < min) {
|
||||||
|
min = bt;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
boost+=min*gameState.perks.transparency / 2
|
boost += (min * gameState.perks.transparency) / 2;
|
||||||
}
|
}
|
||||||
return Math.ceil(Math.max(gameState.combo,gameState.lastCombo) * boost)
|
return Math.ceil(Math.max(gameState.combo, gameState.lastCombo) * boost);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function miniMarkDown(md: string) {
|
export function miniMarkDown(md: string) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { baseCombo, forEachLiveOne, liveCount } from "./gameStateMutators";
|
import { baseCombo, forEachLiveOne, liveCount } from "./gameStateMutators";
|
||||||
import {
|
import {
|
||||||
ballTransparency,
|
|
||||||
brickCenterX,
|
brickCenterX,
|
||||||
brickCenterY,
|
brickCenterY,
|
||||||
currentLevelInfo,
|
currentLevelInfo,
|
||||||
|
@ -18,8 +17,10 @@ import { t } from "./i18n/i18n";
|
||||||
import { gameState, lastMeasuredFPS, startWork } from "./game";
|
import { gameState, lastMeasuredFPS, startWork } from "./game";
|
||||||
import { isOptionOn } from "./options";
|
import { isOptionOn } from "./options";
|
||||||
import {
|
import {
|
||||||
|
ballTransparency,
|
||||||
catchRateBest,
|
catchRateBest,
|
||||||
catchRateGood, coinsBoostedCombo,
|
catchRateGood,
|
||||||
|
coinsBoostedCombo,
|
||||||
levelTimeBest,
|
levelTimeBest,
|
||||||
levelTimeGood,
|
levelTimeGood,
|
||||||
missesBest,
|
missesBest,
|
||||||
|
@ -75,12 +76,11 @@ export function render(gameState: GameState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const catchRate = gameState.levelSpawnedCoins
|
const catchRate = gameState.levelSpawnedCoins
|
||||||
?
|
? (gameState.score - gameState.levelStartScore) /
|
||||||
(gameState.score - gameState.levelStartScore) /
|
|
||||||
(gameState.levelSpawnedCoins || 1)
|
(gameState.levelSpawnedCoins || 1)
|
||||||
// (gameState.levelSpawnedCoins - gameState.levelLostCoins) /
|
: // (gameState.levelSpawnedCoins - gameState.levelLostCoins) /
|
||||||
// gameState.levelSpawnedCoins
|
// gameState.levelSpawnedCoins
|
||||||
: 1;
|
1;
|
||||||
startWork("render:scoreDisplay");
|
startWork("render:scoreDisplay");
|
||||||
scoreDisplay.innerHTML =
|
scoreDisplay.innerHTML =
|
||||||
(isOptionOn("show_fps") || gameState.startParams.computer_controlled
|
(isOptionOn("show_fps") || gameState.startParams.computer_controlled
|
||||||
|
@ -440,7 +440,7 @@ export function render(gameState: GameState) {
|
||||||
);
|
);
|
||||||
|
|
||||||
startWork("render:combotext");
|
startWork("render:combotext");
|
||||||
const spawns=coinsBoostedCombo(gameState)
|
const spawns = coinsBoostedCombo(gameState);
|
||||||
if (spawns > 1) {
|
if (spawns > 1) {
|
||||||
ctx.globalCompositeOperation = "source-over";
|
ctx.globalCompositeOperation = "source-over";
|
||||||
ctx.globalAlpha = 1;
|
ctx.globalAlpha = 1;
|
||||||
|
@ -500,7 +500,7 @@ export function render(gameState: GameState) {
|
||||||
|
|
||||||
if (gameState.offsetXRoundedDown) {
|
if (gameState.offsetXRoundedDown) {
|
||||||
// draw outside of gaming area to avoid capturing borders in recordings
|
// draw outside of gaming area to avoid capturing borders in recordings
|
||||||
if(gameState.perks.left_is_lava<2)
|
if (gameState.perks.left_is_lava < 2)
|
||||||
drawStraightLine(
|
drawStraightLine(
|
||||||
ctx,
|
ctx,
|
||||||
gameState,
|
gameState,
|
||||||
|
@ -511,7 +511,7 @@ export function render(gameState: GameState) {
|
||||||
height,
|
height,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
if(gameState.perks.right_is_lava<2)
|
if (gameState.perks.right_is_lava < 2)
|
||||||
drawStraightLine(
|
drawStraightLine(
|
||||||
ctx,
|
ctx,
|
||||||
gameState,
|
gameState,
|
||||||
|
@ -523,8 +523,7 @@ export function render(gameState: GameState) {
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
if (gameState.perks.left_is_lava < 2)
|
||||||
if(gameState.perks.left_is_lava<2)
|
|
||||||
drawStraightLine(
|
drawStraightLine(
|
||||||
ctx,
|
ctx,
|
||||||
gameState,
|
gameState,
|
||||||
|
@ -536,7 +535,7 @@ export function render(gameState: GameState) {
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
|
||||||
if(gameState.perks.right_is_lava<2)
|
if (gameState.perks.right_is_lava < 2)
|
||||||
drawStraightLine(
|
drawStraightLine(
|
||||||
ctx,
|
ctx,
|
||||||
gameState,
|
gameState,
|
||||||
|
@ -549,7 +548,7 @@ export function render(gameState: GameState) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (redTop && gameState.perks.top_is_lava<2)
|
if (redTop && gameState.perks.top_is_lava < 2)
|
||||||
drawStraightLine(
|
drawStraightLine(
|
||||||
ctx,
|
ctx,
|
||||||
gameState,
|
gameState,
|
||||||
|
|
|
@ -14,7 +14,7 @@ try {
|
||||||
warnedUserAboutLSIssue = true;
|
warnedUserAboutLSIssue = true;
|
||||||
toast(`Storage issue : ${(e as Error)?.message}`);
|
toast(`Storage issue : ${(e as Error)?.message}`);
|
||||||
}
|
}
|
||||||
console.warn('Reading '+key,e);
|
console.warn("Reading " + key, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
2
src/types.d.ts
vendored
2
src/types.d.ts
vendored
|
@ -84,7 +84,7 @@ export type Coin = {
|
||||||
destroyed?: boolean;
|
destroyed?: boolean;
|
||||||
collidedLastFrame?: boolean;
|
collidedLastFrame?: boolean;
|
||||||
metamorphosisPoints: number;
|
metamorphosisPoints: number;
|
||||||
floatingTime:number;
|
floatingTime: number;
|
||||||
};
|
};
|
||||||
export type Ball = {
|
export type Ball = {
|
||||||
x: number;
|
x: number;
|
||||||
|
|
|
@ -189,7 +189,8 @@ export const rawUpgrades = [
|
||||||
id: "smaller_puck",
|
id: "smaller_puck",
|
||||||
max: 2,
|
max: 2,
|
||||||
name: t("upgrades.smaller_puck.name"),
|
name: t("upgrades.smaller_puck.name"),
|
||||||
help: (lvl: number) => t("upgrades.smaller_puck.tooltip", {percent:50*lvl}),
|
help: (lvl: number) =>
|
||||||
|
t("upgrades.smaller_puck.tooltip", { percent: 50 * lvl }),
|
||||||
fullHelp: t("upgrades.smaller_puck.verbose_description"),
|
fullHelp: t("upgrades.smaller_puck.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -725,7 +726,6 @@ export const rawUpgrades = [
|
||||||
requires: "",
|
requires: "",
|
||||||
threshold: 175000,
|
threshold: 175000,
|
||||||
gift: false,
|
gift: false,
|
||||||
|
|
||||||
id: "limitless",
|
id: "limitless",
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.limitless.name"),
|
name: t("upgrades.limitless.name"),
|
||||||
|
@ -828,8 +828,7 @@ export const rawUpgrades = [
|
||||||
id: "buoy",
|
id: "buoy",
|
||||||
max: 3,
|
max: 3,
|
||||||
name: t("upgrades.buoy.name"),
|
name: t("upgrades.buoy.name"),
|
||||||
help: (lvl: number) =>
|
help: (lvl: number) => t("upgrades.buoy.tooltip", { duration: lvl * 0.5 }),
|
||||||
t("upgrades.buoy.tooltip", { duration: lvl * 0.5 }),
|
|
||||||
fullHelp: t("upgrades.buoy.verbose_description"),
|
fullHelp: t("upgrades.buoy.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -839,7 +838,7 @@ export const rawUpgrades = [
|
||||||
id: "ottawa_treaty",
|
id: "ottawa_treaty",
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.ottawa_treaty.name"),
|
name: t("upgrades.ottawa_treaty.name"),
|
||||||
help: () =>t("upgrades.ottawa_treaty.tooltip"),
|
help: () => t("upgrades.ottawa_treaty.tooltip"),
|
||||||
fullHelp: t("upgrades.ottawa_treaty.verbose_description"),
|
fullHelp: t("upgrades.ottawa_treaty.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -849,7 +848,8 @@ export const rawUpgrades = [
|
||||||
id: "three_cushion",
|
id: "three_cushion",
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.three_cushion.name"),
|
name: t("upgrades.three_cushion.name"),
|
||||||
help: (lvl:number) =>t("upgrades.three_cushion.tooltip",{max:lvl*3}),
|
help: (lvl: number) =>
|
||||||
|
t("upgrades.three_cushion.tooltip", { max: lvl * 3 }),
|
||||||
fullHelp: t("upgrades.three_cushion.verbose_description"),
|
fullHelp: t("upgrades.three_cushion.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -859,8 +859,7 @@ export const rawUpgrades = [
|
||||||
id: "sticky_coins",
|
id: "sticky_coins",
|
||||||
max: 1,
|
max: 1,
|
||||||
name: t("upgrades.sticky_coins.name"),
|
name: t("upgrades.sticky_coins.name"),
|
||||||
help: (lvl:number) =>t("upgrades.sticky_coins.tooltip"),
|
help: (lvl: number) => t("upgrades.sticky_coins.tooltip"),
|
||||||
fullHelp: t("upgrades.sticky_coins.verbose_description"),
|
fullHelp: t("upgrades.sticky_coins.verbose_description"),
|
||||||
},
|
},
|
||||||
|
|
||||||
] as const;
|
] as const;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue