This commit is contained in:
Renan LE CARO 2025-04-16 15:30:20 +02:00
parent 277aa5682b
commit 21fa5f105e
8 changed files with 71 additions and 50 deletions

View file

@ -26,9 +26,16 @@ languages, I may add features again.
## To do ## To do
- redo video presentation - redo video presentation
- Back to Creative Menu at the end of a Creative level
- make Corner Shot scale like Need Some Space
## Done ## Done
- don't show unlock toast at first startup for levels that are unlocked by default
- Droplet particle color should be gold for gold coins
## 29079818
- Imported levels : Mario, Minesweeper and Target - Imported levels : Mario, Minesweeper and Target
- Fixed an issue with localstorage saving of custom levels - Fixed an issue with localstorage saving of custom levels

24
dist/index.html vendored

File diff suppressed because one or more lines are too long

View file

@ -1317,12 +1317,13 @@
"name": "Mario!", "name": "Mario!",
"credit": "Suggested by Nicolas03. A Mario level ! Sprite taken from https://art.pixilart.com/sr2d5c0683c82aws3.png . The sprite belongs to Nintendo" "credit": "Suggested by Nicolas03. A Mario level ! Sprite taken from https://art.pixilart.com/sr2d5c0683c82aws3.png . The sprite belongs to Nintendo"
}, },
{ {
"color": "", "color": "",
"size": 16, "size": 16,
"bricks": "___llltCCttBC______lllCBBttCB______ltttBttltt______ltBrBClttt______lttCCCttBt______llttCBtttt______ltCBCttlll______ltBCCtCtCt______lttCCBCBrB______llltBCCtrB______ttttttlltt______CBrttlllll______CBrBCttttl______ttCCBttBtl______tttCCCtCCt______tBttBtltBt___", "bricks": "___llltCCttBC______lllCBBttCB______lttbBbtltt______ltBrBClttt______lttCCCttBt______llttCBtttt______ltCBCttlll______ltBCCtCtCt______lttCCBCBrB______llltBCCtrB______ttttttlltt______CBrttlllll______CBrBCttttl______ttCCBttBtl______tttCCCtCCt______tBttBtltBt___",
"name": "Minesweeper", "name": "Minesweeper",
"credit": "Suggested by Noodlemire.For once, you'll want to trigger as many mines as possible." "credit": "Suggested by Noodlemire. For once, you'll want to trigger as many mines as possible."
}, },
{ {
"color": "", "color": "",
@ -1330,5 +1331,19 @@
"bricks": "__________________________________________________________________________________________________________________________WWW_______________WrrrW_____________WrWWWrW____________WrWBWrW____________WrWWWrW_____________WrrrW_______________WWW__________________________________________________________________________________________________________________________", "bricks": "__________________________________________________________________________________________________________________________WWW_______________WrrrW_____________WrWWWrW____________WrWBWrW____________WrWWWrW_____________WrrrW_______________WWW__________________________________________________________________________________________________________________________",
"name": "Target", "name": "Target",
"credit": "Suggested by Noodlemire. Unusually small level, with lots of room to miss your shots. Acts as decent aim practice." "credit": "Suggested by Noodlemire. Unusually small level, with lots of room to miss your shots. Acts as decent aim practice."
},
{
"color": "",
"size": 10,
"bricks": "__________rrrrr_____WWrWWrrrrrWWrWWWWrWWWWrWWWWrWWrWrWWWWrWWWrWWWrWrWW_____WrWWW____________________",
"name": "The Boys",
"credit": "Suggested by Bearded-Axe. My boys initals"
},
{
"color": "#115988",
"size": 21,
"bricks": "__________________________________________________yy_______________yy__yy__yy___________yy__yy__yy____________yy__yy_yy_________y__yy__yy_yy________yyy_yyy_yy_yy_________yy__yy_yyyyy__________yy_yyyyyyyy___yyy____yyyyygggyyy__yyy______yyygBBBgyy_yyy________ygBBBBBgyyyy_________ygBBBBBgyyy__________yygBBBgyyyy___________yygBgyyyy____________yyyByyyy_____________yyyyByy_______________yyByy_________________r_________________________________",
"name": "A Very Dangerous High-Five",
"credit": "Suggested by Noodlemire. A unique shape, fun to bounce the ball between fingers. The palm was initially boring on its own, so I gave it a big bomb. It adds a distinct feeling between the top and bottom halves."
} }
] ]

View file

@ -18,7 +18,7 @@ import {
currentLevelInfo, currentLevelInfo,
distance2, distance2,
distanceBetween, distanceBetween,
getClosestBall, getClosestBall, getCoinRenderColor,
getMajorityValue, getMajorityValue,
getPossibleUpgrades, getPossibleUpgrades,
getRowColIndex, getRowColIndex,
@ -660,9 +660,7 @@ export function addToScore(gameState: GameState, coin: Coin) {
coin.previousY, coin.previousY,
(gameState.canvasWidth - coin.x) / 100, (gameState.canvasWidth - coin.x) / 100,
-coin.y / 100, -coin.y / 100,
gameState.perks.metamorphosis || isOptionOn("colorful_coins") getCoinRenderColor(gameState, coin),
? coin.color
: "#ffd300",
true, true,
gameState.coinSize / 2, gameState.coinSize / 2,
@ -1237,7 +1235,7 @@ export function gameStateTick(
gameState.gameZoneHeight, gameState.gameZoneHeight,
-coin.vx / 5, -coin.vx / 5,
-coin.vy / 5, -coin.vy / 5,
coin.color, getCoinRenderColor(gameState, coin),
false, false,
); );
} }

View file

@ -1,18 +1,11 @@
import { import {Ball, Coin, GameState, Level, PerkId, PerksMap, RunHistoryItem, UpgradeLike,} from "./types";
Ball, import {icons, upgrades} from "./loadGameData";
GameState, import {t} from "./i18n/i18n";
Level, import {clamp} from "./pure_functions";
PerkId, import {rawUpgrades} from "./upgrades";
PerksMap, import {hashCode} from "./getLevelBackground";
RunHistoryItem, import {getTotalScore} from "./settings";
UpgradeLike, import {isOptionOn} from "./options";
} from "./types";
import { icons, upgrades } from "./loadGameData";
import { t } from "./i18n/i18n";
import { clamp } from "./pure_functions";
import { rawUpgrades } from "./upgrades";
import { hashCode } from "./getLevelBackground";
import { getTotalScore } from "./settings";
export function describeLevel(level: Level) { export function describeLevel(level: Level) {
let bricks = 0, let bricks = 0,
@ -400,3 +393,14 @@ export function ballTransparency(ball: Ball, gameState: GameState) {
1, 1,
); );
} }
export function getCoinRenderColor(gameState: GameState, coin: Coin) {
if (
gameState.perks.metamorphosis ||
isOptionOn("colorful_coins") ||
gameState.perks.hypnosis ||
gameState.perks.rainbow
)
return coin.color;
return "#ffd300";
}

View file

@ -28,7 +28,7 @@ describe("json data checks", () => {
.filter((l) => { .filter((l) => {
const uniqueBricks = l.bricks const uniqueBricks = l.bricks
.split("") .split("")
.filter((b) => b !== "_" && b !== "black") .filter((b) => b !== "_" && b !== "B")
.filter((a, b, c) => c.indexOf(a) === b); .filter((a, b, c) => c.indexOf(a) === b);
return uniqueBricks.length > 5 && !l.name.startsWith("icon:"); return uniqueBricks.length > 5 && !l.name.startsWith("icon:");
}) })

View file

@ -32,6 +32,9 @@ export function monitorLevelsUnlocks(gameState: GameState) {
// Already unlocked // Already unlocked
if (unlocked.has(name)) return; if (unlocked.has(name)) return;
// Score not reached yet // Score not reached yet
if (gameState.score < minScore) return;
if (! minScore) return;
if (gameState.score < minScore) return; if (gameState.score < minScore) return;
// We are missing a required perk // We are missing a required perk
if (required.find((id) => !gameState.perks[id])) return; if (required.find((id) => !gameState.perks[id])) return;

View file

@ -1,9 +1,10 @@
import { baseCombo, forEachLiveOne, liveCount } from "./gameStateMutators"; import {baseCombo, forEachLiveOne, liveCount} from "./gameStateMutators";
import { import {
ballTransparency, ballTransparency,
brickCenterX, brickCenterX,
brickCenterY, brickCenterY,
currentLevelInfo, currentLevelInfo,
getCoinRenderColor,
isMovingWhilePassiveIncome, isMovingWhilePassiveIncome,
isPickyEatingPossible, isPickyEatingPossible,
max_levels, max_levels,
@ -11,10 +12,10 @@ import {
telekinesisEffectRate, telekinesisEffectRate,
yoyoEffectRate, yoyoEffectRate,
} from "./game_utils"; } from "./game_utils";
import { Coin, colorString, GameState } from "./types"; import {colorString, GameState} from "./types";
import { t } from "./i18n/i18n"; 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 {
catchRateBest, catchRateBest,
catchRateGood, catchRateGood,
@ -25,7 +26,7 @@ import {
wallBouncedBest, wallBouncedBest,
wallBouncedGood, wallBouncedGood,
} from "./pure_functions"; } from "./pure_functions";
import { getCurrentMaxCoins } from "./settings"; import {getCurrentMaxCoins} from "./settings";
export const gameCanvas = document.getElementById("game") as HTMLCanvasElement; export const gameCanvas = document.getElementById("game") as HTMLCanvasElement;
export const ctx = gameCanvas.getContext("2d", { export const ctx = gameCanvas.getContext("2d", {
@ -1151,17 +1152,6 @@ export function getDashOffset(gameState: GameState) {
return Math.floor(((gameState.levelTime % 500) / 500) * 10) % 10; return Math.floor(((gameState.levelTime % 500) / 500) * 10) % 10;
} }
function getCoinRenderColor(gameState: GameState, coin: Coin) {
if (
gameState.perks.metamorphosis ||
isOptionOn("colorful_coins") ||
gameState.perks.hypnosis ||
gameState.perks.rainbow
)
return coin.color;
return "#ffd300";
}
let wakeLock = null, let wakeLock = null,
wakeLockPending = false; wakeLockPending = false;
function askForWakeLock(gameState: GameState) { function askForWakeLock(gameState: GameState) {