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
|
@ -10,20 +10,14 @@ Break colourful bricks, catch bouncing coins and select powerful upgrades !
|
||||||
- [F-Droid](https://f-droid.org/en/packages/me.lecaro.breakout/)
|
- [F-Droid](https://f-droid.org/en/packages/me.lecaro.breakout/)
|
||||||
- [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}`;
|
||||||
|
|
|
@ -36,54 +36,54 @@ export function creativeMode(gameState: GameState) {
|
||||||
|
|
||||||
export async function openCreativeModePerksPicker() {
|
export async function openCreativeModePerksPicker() {
|
||||||
let creativeModePerks: Partial<{ [id in PerkId]: number }> = getSettingValue(
|
let creativeModePerks: Partial<{ [id in PerkId]: number }> = getSettingValue(
|
||||||
"creativeModePerks",
|
"creativeModePerks",
|
||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
const customLevels = (getSettingValue("custom_levels", []) as RawLevel[]).map(
|
const customLevels = (getSettingValue("custom_levels", []) as RawLevel[]).map(
|
||||||
transformRawLevel,
|
transformRawLevel,
|
||||||
);
|
);
|
||||||
|
|
||||||
while (true ) {
|
while (true) {
|
||||||
|
const levelOptions = [
|
||||||
|
...allLevels.map((l, li) => {
|
||||||
|
const problem = reasonLevelIsLocked(li, getHistory(), true)?.text || "";
|
||||||
|
return {
|
||||||
|
icon: icons[l.name],
|
||||||
|
text: l.name,
|
||||||
|
value: l,
|
||||||
|
disabled: !!problem,
|
||||||
|
tooltip: problem || describeLevel(l),
|
||||||
|
className: "",
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
...customLevels.map((l) => ({
|
||||||
|
icon: levelIconHTML(l.bricks, l.size, l.color),
|
||||||
|
text: l.name,
|
||||||
|
value: l,
|
||||||
|
disabled: !l.bricks.filter((b) => b !== "_").length,
|
||||||
|
tooltip: describeLevel(l),
|
||||||
|
className: "",
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
|
||||||
const levelOptions= [
|
const selectedLeveOption =
|
||||||
...allLevels.map((l, li) => {
|
levelOptions.find(
|
||||||
const problem =
|
(l) => l.text === getSettingValue("creativeModeLevel", ""),
|
||||||
reasonLevelIsLocked(li, getHistory(), true)?.text || "";
|
) || levelOptions[0];
|
||||||
return {
|
selectedLeveOption.className = "highlight";
|
||||||
icon: icons[l.name],
|
|
||||||
text: l.name,
|
|
||||||
value: l,
|
|
||||||
disabled: !!problem,
|
|
||||||
tooltip: problem || describeLevel(l),
|
|
||||||
className:''
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
...customLevels.map((l) => ({
|
|
||||||
icon: levelIconHTML(l.bricks, l.size, l.color),
|
|
||||||
text: l.name,
|
|
||||||
value: l,
|
|
||||||
disabled: !l.bricks.filter((b) => b !== "_").length,
|
|
||||||
tooltip: describeLevel(l),
|
|
||||||
className:''
|
|
||||||
}))
|
|
||||||
]
|
|
||||||
|
|
||||||
const selectedLeveOption= levelOptions.find(l=>l.text===getSettingValue("creativeModeLevel", '')) || levelOptions[0]
|
const choice = await asyncAlert<Upgrade | Level | "reset" | "play">({
|
||||||
selectedLeveOption.className= 'highlight'
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -1373,4 +1373,4 @@
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": ""
|
"color": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -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;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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) {
|
||||||
|
|
111
src/render.ts
111
src/render.ts
|
@ -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,12 +440,12 @@ 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;
|
||||||
|
|
||||||
const comboText = spawns.toString();
|
const comboText = spawns.toString();
|
||||||
const comboTextWidth = (comboText.length * gameState.puckHeight) / 1.8;
|
const comboTextWidth = (comboText.length * gameState.puckHeight) / 1.8;
|
||||||
const totalWidth = comboTextWidth + gameState.coinSize * 2;
|
const totalWidth = comboTextWidth + gameState.coinSize * 2;
|
||||||
const left = gameState.puckPosition - totalWidth / 2;
|
const left = gameState.puckPosition - totalWidth / 2;
|
||||||
|
@ -500,56 +500,55 @@ 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,
|
||||||
(redLeftSide && "#FF0000") || "#FFFFFF",
|
(redLeftSide && "#FF0000") || "#FFFFFF",
|
||||||
gameState.offsetXRoundedDown - 1,
|
gameState.offsetXRoundedDown - 1,
|
||||||
0,
|
0,
|
||||||
gameState.offsetXRoundedDown - 1,
|
gameState.offsetXRoundedDown - 1,
|
||||||
height,
|
height,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
if(gameState.perks.right_is_lava<2)
|
if (gameState.perks.right_is_lava < 2)
|
||||||
drawStraightLine(
|
drawStraightLine(
|
||||||
ctx,
|
ctx,
|
||||||
gameState,
|
gameState,
|
||||||
(redRightSide && "#FF0000") || "#FFFFFF",
|
(redRightSide && "#FF0000") || "#FFFFFF",
|
||||||
width - gameState.offsetXRoundedDown + 1,
|
width - gameState.offsetXRoundedDown + 1,
|
||||||
0,
|
0,
|
||||||
width - gameState.offsetXRoundedDown + 1,
|
width - gameState.offsetXRoundedDown + 1,
|
||||||
height,
|
height,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
if (gameState.perks.left_is_lava < 2)
|
||||||
|
drawStraightLine(
|
||||||
|
ctx,
|
||||||
|
gameState,
|
||||||
|
(redLeftSide && "#FF0000") || "",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
height,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
if(gameState.perks.left_is_lava<2)
|
if (gameState.perks.right_is_lava < 2)
|
||||||
drawStraightLine(
|
drawStraightLine(
|
||||||
ctx,
|
ctx,
|
||||||
gameState,
|
gameState,
|
||||||
(redLeftSide && "#FF0000") || "",
|
(redRightSide && "#FF0000") || "",
|
||||||
0,
|
width - 1,
|
||||||
0,
|
0,
|
||||||
0,
|
width - 1,
|
||||||
height,
|
height,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
|
||||||
if(gameState.perks.right_is_lava<2)
|
|
||||||
drawStraightLine(
|
|
||||||
ctx,
|
|
||||||
gameState,
|
|
||||||
(redRightSide && "#FF0000") || "",
|
|
||||||
width - 1,
|
|
||||||
0,
|
|
||||||
width - 1,
|
|
||||||
height,
|
|
||||||
1,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -718,14 +719,13 @@ export const rawUpgrades = [
|
||||||
id: "fountain_toss",
|
id: "fountain_toss",
|
||||||
max: 7,
|
max: 7,
|
||||||
name: t("upgrades.fountain_toss.name"),
|
name: t("upgrades.fountain_toss.name"),
|
||||||
help: () => t("upgrades.fountain_toss.tooltip"),
|
help: () => t("upgrades.fountain_toss.tooltip"),
|
||||||
fullHelp: t("upgrades.fountain_toss.verbose_description"),
|
fullHelp: t("upgrades.fountain_toss.verbose_description"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
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,18 +848,18 @@ 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"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
requires: "",
|
requires: "",
|
||||||
threshold: 235000,
|
threshold: 235000,
|
||||||
gift: false,
|
gift: false,
|
||||||
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