mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-20 04:05:06 -04:00
Build 29071900
This commit is contained in:
parent
4bb5d820c5
commit
1b94bcd6be
16 changed files with 526 additions and 143 deletions
14
Readme.md
14
Readme.md
|
@ -23,14 +23,25 @@ Some upgrades currently are not really useful
|
||||||
- remove them
|
- remove them
|
||||||
- add more upgrades to complement them
|
- add more upgrades to complement them
|
||||||
- update them to be more useful
|
- update them to be more useful
|
||||||
|
-
|
||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
## To do
|
## To do
|
||||||
|
|
||||||
|
- rework unbounded to just add padding around bricks
|
||||||
|
- bricks attract balls
|
||||||
|
|
||||||
## Done
|
## Done
|
||||||
|
|
||||||
|
- new perk : hypnosis
|
||||||
|
- new perk : rainbow
|
||||||
|
- new perk : bricks attract coins
|
||||||
|
- super hot level rework
|
||||||
|
- zen level added bombs
|
||||||
|
|
||||||
|
## 29071527
|
||||||
|
|
||||||
- super hot : time moves only when paddle moves. Later levels slow down even more the time when you're not moving.
|
- super hot : time moves only when paddle moves. Later levels slow down even more the time when you're not moving.
|
||||||
- fixed memory leak in language detection code
|
|
||||||
- transparency : ball becomes transparent towards top of screen, +50% coins.
|
- transparency : ball becomes transparent towards top of screen, +50% coins.
|
||||||
- space coins : coins bounce without loosing momentum
|
- space coins : coins bounce without loosing momentum
|
||||||
- trickledown : coins spawn at the top of the screen
|
- trickledown : coins spawn at the top of the screen
|
||||||
|
@ -38,6 +49,7 @@ Some upgrades currently are not really useful
|
||||||
- allow removing all starting perks, to get full random
|
- allow removing all starting perks, to get full random
|
||||||
- rename "puck" into paddle
|
- rename "puck" into paddle
|
||||||
- use french as base language to keep consistent formal/informal tone
|
- use french as base language to keep consistent formal/informal tone
|
||||||
|
- fixed memory leak in language detection code
|
||||||
|
|
||||||
## 29069860
|
## 29069860
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ android {
|
||||||
applicationId = "me.lecaro.breakout"
|
applicationId = "me.lecaro.breakout"
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 29071541
|
versionCode = 29071900
|
||||||
versionName = "29071541"
|
versionName = "29071900"
|
||||||
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
161
dist/index.html
vendored
161
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 = "29071541";
|
const VERSION = "29071900";
|
||||||
|
|
||||||
// The name of the cache
|
// The name of the cache
|
||||||
const CACHE_NAME = `breakout-71-${VERSION}`;
|
const CACHE_NAME = `breakout-71-${VERSION}`;
|
||||||
|
|
|
@ -910,7 +910,7 @@
|
||||||
{
|
{
|
||||||
"name": "icon:zen",
|
"name": "icon:zen",
|
||||||
"size": 9,
|
"size": 9,
|
||||||
"bricks": "___vv______vvvv______vv______bbbb____bbbbbb____bbbb____tttttt__tttttttt__tttttt__",
|
"bricks": "___tt______tttt_____BttB_____bbbb____bbbbbb___BbbbbB___tttttt__tttttttt__tttttt__",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": ""
|
"color": ""
|
||||||
},
|
},
|
||||||
|
@ -1310,7 +1310,7 @@
|
||||||
{
|
{
|
||||||
"name": "icon:minefield",
|
"name": "icon:minefield",
|
||||||
"size": 7,
|
"size": 7,
|
||||||
"bricks": "W__W__W_W___W___W_W__W_____W_W___W____l_____lll__",
|
"bricks": "W__B__WWWBBBWWB__W__BBBWWWBBW__B__WWWBBBWW_______",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": ""
|
"color": ""
|
||||||
},
|
},
|
||||||
|
@ -1379,8 +1379,29 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "icon:superhot",
|
"name": "icon:superhot",
|
||||||
"size": 19,
|
"size": 11,
|
||||||
"bricks": "_________________________________________________________WWWBWBWBWWWBWWWBWWWWBBBWBWBWBWBWBBBWBWWWWBWBWBWWWBWWBBWWWBBWBWBWBWBBBWBBBWWBWWWBWWWBWBBBWWWBWBW___________________WWBBWWBWWWWWBWWWWWWWWBBWWBWWWWWBWWWWWWWWBBWWBWWBWWBBBWWBBWWWWWWBWWBWWBBBWWBBWWWWWWBWWBWWBBBWWBBWWBBWWBWWWWWBBBWWBBWWBBWWBWWWWWBBBWWBB_________________________________________________________",
|
"bricks": "____________________________________________W_W_WWW_WWWWWW_W_W__W_W_W_WWW__W_____________________________________________",
|
||||||
|
"svg": null,
|
||||||
|
"color": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon:bricks_attract_coins",
|
||||||
|
"size": 7,
|
||||||
|
"bricks": "_y__y___tttttyyttttt__ttttt_yttttty_ttttt___y__y_",
|
||||||
|
"svg": null,
|
||||||
|
"color": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon:rainbow",
|
||||||
|
"size": 6,
|
||||||
|
"bricks": "__rOyC_rOyCa_rOyCarOyCatrOyCatrOyCat",
|
||||||
|
"svg": null,
|
||||||
|
"color": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon:hypnosis",
|
||||||
|
"size": 8,
|
||||||
|
"bricks": "WrrrrrrrWrWWWWWrWrWrrrWrWrWrWrWrWrWWWrWrWrrrrrWrWWWWWWWrrrrrrrrr",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": ""
|
"color": ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
"29071541"
|
"29071900"
|
||||||
|
|
|
@ -957,7 +957,7 @@ document.addEventListener("keyup", async (e) => {
|
||||||
} else if (e.key.toLowerCase() === "m" && !alertsOpen) {
|
} else if (e.key.toLowerCase() === "m" && !alertsOpen) {
|
||||||
openMainMenu().then();
|
openMainMenu().then();
|
||||||
} else if (e.key.toLowerCase() === "s" && !alertsOpen) {
|
} else if (e.key.toLowerCase() === "s" && !alertsOpen) {
|
||||||
openScorePanel().then();
|
openScorePanel(gameState).then();
|
||||||
} else if (
|
} else if (
|
||||||
e.key.toLowerCase() === "r" &&
|
e.key.toLowerCase() === "r" &&
|
||||||
!alertsOpen &&
|
!alertsOpen &&
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
currentLevelInfo,
|
currentLevelInfo,
|
||||||
distance2,
|
distance2,
|
||||||
distanceBetween,
|
distanceBetween,
|
||||||
|
getClosestBall,
|
||||||
getMajorityValue,
|
getMajorityValue,
|
||||||
getPossibleUpgrades,
|
getPossibleUpgrades,
|
||||||
getRowColIndex,
|
getRowColIndex,
|
||||||
|
@ -412,6 +413,7 @@ export function explodeBrick(
|
||||||
gameState.levelSpawnedCoins += coinsToSpawn;
|
gameState.levelSpawnedCoins += coinsToSpawn;
|
||||||
gameState.runStatistics.coins_spawned += coinsToSpawn;
|
gameState.runStatistics.coins_spawned += coinsToSpawn;
|
||||||
gameState.runStatistics.bricks_broken++;
|
gameState.runStatistics.bricks_broken++;
|
||||||
|
|
||||||
const maxCoins = getCurrentMaxCoins() * (isOptionOn("basic") ? 0.5 : 1);
|
const maxCoins = getCurrentMaxCoins() * (isOptionOn("basic") ? 0.5 : 1);
|
||||||
const spawnableCoins =
|
const spawnableCoins =
|
||||||
liveCount(gameState.coins) > getCurrentMaxCoins()
|
liveCount(gameState.coins) > getCurrentMaxCoins()
|
||||||
|
@ -435,6 +437,7 @@ export function explodeBrick(
|
||||||
cy =
|
cy =
|
||||||
y +
|
y +
|
||||||
(Math.random() - 0.5) * (gameState.brickWidth - gameState.coinSize);
|
(Math.random() - 0.5) * (gameState.brickWidth - gameState.coinSize);
|
||||||
|
|
||||||
makeCoin(
|
makeCoin(
|
||||||
gameState,
|
gameState,
|
||||||
cx,
|
cx,
|
||||||
|
@ -442,7 +445,6 @@ export function explodeBrick(
|
||||||
ball.previousVX * (0.5 + Math.random()),
|
ball.previousVX * (0.5 + Math.random()),
|
||||||
ball.previousVY * (0.5 + Math.random()),
|
ball.previousVY * (0.5 + Math.random()),
|
||||||
color,
|
color,
|
||||||
|
|
||||||
points,
|
points,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1050,56 +1052,80 @@ export function gameStateTick(
|
||||||
coin.sa -= attractionX / 10;
|
coin.sa -= attractionX / 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameState.perks.ball_attracts_coins) {
|
if (gameState.perks.ball_attracts_coins && gameState.balls.length) {
|
||||||
// Find closest ball
|
// Find closest ball
|
||||||
let closestBall = gameState.balls[0];
|
let closestBall = getClosestBall(gameState, coin.x, coin.y);
|
||||||
let dist = distance2(closestBall, coin);
|
if (closestBall) {
|
||||||
gameState.balls.forEach((ball) => {
|
let dist = distance2(closestBall, coin);
|
||||||
if (ball == closestBall) return;
|
|
||||||
const d2 = distance2(ball, coin);
|
|
||||||
if (d2 < dist) {
|
|
||||||
closestBall = ball;
|
|
||||||
dist = d2;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const minDist = gameState.brickWidth * gameState.brickWidth;
|
|
||||||
if (
|
|
||||||
dist > minDist &&
|
|
||||||
dist < minDist * 4 * 4 * gameState.perks.ball_attracts_coins
|
|
||||||
) {
|
|
||||||
// Slow down coins in effect radius
|
|
||||||
const ratio = 1 - 0.02 * (0.5 + gameState.perks.ball_attracts_coins);
|
|
||||||
coin.vx *= ratio;
|
|
||||||
coin.vy *= ratio;
|
|
||||||
coin.vy *= ratio;
|
|
||||||
// Carry them
|
|
||||||
const dx =
|
|
||||||
((closestBall.x - coin.x) / dist) *
|
|
||||||
50 *
|
|
||||||
gameState.perks.ball_attracts_coins;
|
|
||||||
const dy =
|
|
||||||
((closestBall.y - coin.y) / dist) *
|
|
||||||
50 *
|
|
||||||
gameState.perks.ball_attracts_coins;
|
|
||||||
coin.vx += dx;
|
|
||||||
coin.vy += dy;
|
|
||||||
|
|
||||||
|
const minDist = gameState.brickWidth * gameState.brickWidth;
|
||||||
if (
|
if (
|
||||||
!isOptionOn("basic") &&
|
dist > minDist &&
|
||||||
Math.random() * gameState.perks.ball_attracts_coins * frames > 0.9
|
dist < minDist * 4 * 4 * gameState.perks.ball_attracts_coins
|
||||||
) {
|
) {
|
||||||
makeParticle(
|
// Slow down coins in effect radius
|
||||||
gameState,
|
const ratio =
|
||||||
coin.x + dx * 5,
|
1 - 0.02 * (0.5 + gameState.perks.ball_attracts_coins);
|
||||||
coin.y + dy * 5,
|
coin.vx *= ratio;
|
||||||
dx * 2,
|
coin.vy *= ratio;
|
||||||
dy * 2,
|
coin.vy *= ratio;
|
||||||
rainbowColor(),
|
// Carry them
|
||||||
true,
|
const dx =
|
||||||
gameState.coinSize / 2,
|
((closestBall.x - coin.x) / dist) *
|
||||||
100,
|
50 *
|
||||||
);
|
gameState.perks.ball_attracts_coins;
|
||||||
|
const dy =
|
||||||
|
((closestBall.y - coin.y) / dist) *
|
||||||
|
50 *
|
||||||
|
gameState.perks.ball_attracts_coins;
|
||||||
|
coin.vx += dx;
|
||||||
|
coin.vy += dy;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!isOptionOn("basic") &&
|
||||||
|
Math.random() * gameState.perks.ball_attracts_coins * frames > 0.9
|
||||||
|
) {
|
||||||
|
makeParticle(
|
||||||
|
gameState,
|
||||||
|
coin.x + dx * 5,
|
||||||
|
coin.y + dy * 5,
|
||||||
|
dx * 2,
|
||||||
|
dy * 2,
|
||||||
|
rainbowColor(),
|
||||||
|
true,
|
||||||
|
gameState.coinSize / 2,
|
||||||
|
100,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gameState.perks.bricks_attract_coins) {
|
||||||
|
const row = Math.floor(coin.y / gameState.brickWidth);
|
||||||
|
const col = Math.floor(
|
||||||
|
(coin.x - gameState.offsetX) / gameState.brickWidth,
|
||||||
|
);
|
||||||
|
|
||||||
|
const size = 2;
|
||||||
|
for (let dcol = -size; dcol < size; dcol++) {
|
||||||
|
for (let drow = -size; drow < size; drow++) {
|
||||||
|
const index = getRowColIndex(gameState, row + drow, col + dcol);
|
||||||
|
if (gameState.bricks[index]) {
|
||||||
|
const dx =
|
||||||
|
brickCenterX(gameState, index) +
|
||||||
|
(clamp(dcol, -1, 1) * gameState.brickWidth) / 2 -
|
||||||
|
coin.x;
|
||||||
|
const dy =
|
||||||
|
brickCenterY(gameState, index) +
|
||||||
|
(clamp(drow, -1, 1) * gameState.brickWidth) / 2 -
|
||||||
|
coin.y;
|
||||||
|
const d = dx * dx + dy * dy;
|
||||||
|
coin.vx +=
|
||||||
|
(dx / d) * 80 * gameState.perks.bricks_attract_coins * frames;
|
||||||
|
coin.vy +=
|
||||||
|
(dy / d) * 100 * gameState.perks.bricks_attract_coins * frames;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1108,7 +1134,6 @@ export function gameStateTick(
|
||||||
1 -
|
1 -
|
||||||
((gameState.perks.viscosity * 0.03 + 0.002) * frames) /
|
((gameState.perks.viscosity * 0.03 + 0.002) * frames) /
|
||||||
(1 + gameState.perks.etherealcoins);
|
(1 + gameState.perks.etherealcoins);
|
||||||
|
|
||||||
if (!gameState.perks.etherealcoins) {
|
if (!gameState.perks.etherealcoins) {
|
||||||
coin.vy *= ratio;
|
coin.vy *= ratio;
|
||||||
coin.vx *= ratio;
|
coin.vx *= ratio;
|
||||||
|
@ -1122,30 +1147,43 @@ export function gameStateTick(
|
||||||
coin.a += coin.sa;
|
coin.a += coin.sa;
|
||||||
|
|
||||||
// Gravity
|
// Gravity
|
||||||
if (!gameState.perks.etherealcoins) {
|
const flip =
|
||||||
const flip =
|
gameState.perks.helium > 0 &&
|
||||||
gameState.perks.helium > 0 &&
|
Math.abs(coin.x - gameState.puckPosition) * 2 >
|
||||||
Math.abs(coin.x - gameState.puckPosition) * 2 >
|
gameState.puckWidth + coin.size;
|
||||||
gameState.puckWidth + coin.size;
|
let dvy =
|
||||||
coin.vy +=
|
frames * coin.weight * 0.8 * (flip ? -gameState.perks.helium : 1);
|
||||||
frames * coin.weight * 0.8 * (flip ? -gameState.perks.helium : 1);
|
|
||||||
if (flip && !isOptionOn("basic") && Math.random() < 0.1 * frames) {
|
if (gameState.perks.etherealcoins) {
|
||||||
makeParticle(
|
if (gameState.perks.helium) {
|
||||||
gameState,
|
dvy *= 0.2 / gameState.perks.etherealcoins;
|
||||||
coin.x,
|
} else {
|
||||||
coin.y,
|
dvy *= 0;
|
||||||
0,
|
|
||||||
gameState.baseSpeed,
|
|
||||||
gameState.perks.metamorphosis || isOptionOn("colorful_coins")
|
|
||||||
? coin.color
|
|
||||||
: "#ffd300",
|
|
||||||
true,
|
|
||||||
5,
|
|
||||||
250,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
coin.vy += dvy;
|
||||||
|
|
||||||
|
if (
|
||||||
|
gameState.perks.helium &&
|
||||||
|
!isOptionOn("basic") &&
|
||||||
|
Math.random() < 0.1 * frames
|
||||||
|
) {
|
||||||
|
makeParticle(
|
||||||
|
gameState,
|
||||||
|
coin.x,
|
||||||
|
coin.y,
|
||||||
|
0,
|
||||||
|
dvy * 10,
|
||||||
|
gameState.perks.metamorphosis || isOptionOn("colorful_coins")
|
||||||
|
? coin.color
|
||||||
|
: "#ffd300",
|
||||||
|
true,
|
||||||
|
5,
|
||||||
|
250,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const speed = (Math.abs(coin.vx) + Math.abs(coin.vy)) * 10;
|
const speed = (Math.abs(coin.vx) + Math.abs(coin.vy)) * 10;
|
||||||
const hitBorder = bordersHitCheck(gameState, coin, coin.size / 2, frames);
|
const hitBorder = bordersHitCheck(gameState, coin, coin.size / 2, frames);
|
||||||
|
|
||||||
|
@ -1195,6 +1233,17 @@ export function gameStateTick(
|
||||||
gameState.bricks[hitBrick] = coin.color;
|
gameState.bricks[hitBrick] = coin.color;
|
||||||
coin.metamorphosisPoints--;
|
coin.metamorphosisPoints--;
|
||||||
schedulGameSound(gameState, "colorChange", coin.x, 0.3);
|
schedulGameSound(gameState, "colorChange", coin.x, 0.3);
|
||||||
|
|
||||||
|
if (gameState.perks.hypnosis) {
|
||||||
|
const closestBall = getClosestBall(gameState, coin.x, coin.y);
|
||||||
|
if (closestBall) {
|
||||||
|
coin.x = closestBall.x;
|
||||||
|
coin.y = closestBall.y;
|
||||||
|
coin.vx = (Math.random() - 0.5) * gameState.baseSpeed;
|
||||||
|
coin.vy = (Math.random() - 0.5) * gameState.baseSpeed;
|
||||||
|
coin.metamorphosisPoints = gameState.perks.metamorphosis;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1202,12 +1251,11 @@ export function gameStateTick(
|
||||||
(!gameState.perks.ghost_coins && typeof hitBrick !== "undefined") ||
|
(!gameState.perks.ghost_coins && typeof hitBrick !== "undefined") ||
|
||||||
hitBorder
|
hitBorder
|
||||||
) {
|
) {
|
||||||
if (!gameState.perks.etherealcoins) {
|
const ratio = 1 - 0.2 / (1 + gameState.perks.etherealcoins);
|
||||||
coin.vx *= 0.8;
|
coin.vx *= ratio;
|
||||||
coin.vy *= 0.8;
|
coin.vy *= ratio;
|
||||||
if (Math.abs(coin.vy) < 3) {
|
if (Math.abs(coin.vy) < 1) {
|
||||||
coin.vy = 0;
|
coin.vy = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
coin.sa *= 0.9;
|
coin.sa *= 0.9;
|
||||||
if (speed > 20 && !coin.collidedLastFrame) {
|
if (speed > 20 && !coin.collidedLastFrame) {
|
||||||
|
@ -1732,12 +1780,16 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isOptionOn("basic")) {
|
if (
|
||||||
|
!isOptionOn("basic") &&
|
||||||
|
ballTransparency(ball, gameState) < Math.random()
|
||||||
|
) {
|
||||||
const remainingPierce = ball.piercePoints;
|
const remainingPierce = ball.piercePoints;
|
||||||
const remainingSapper = ball.sapperUses < gameState.perks.sapper;
|
const remainingSapper = ball.sapperUses < gameState.perks.sapper;
|
||||||
const willMiss =
|
const willMiss =
|
||||||
isOptionOn("red_miss") && ball.vy > 0 && !ball.hitSinceBounce;
|
isOptionOn("red_miss") && ball.vy > 0 && !ball.hitSinceBounce;
|
||||||
const extraCombo = gameState.combo - 1;
|
const extraCombo = gameState.combo - 1;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
willMiss ||
|
willMiss ||
|
||||||
(extraCombo && Math.random() > 0.1 / (1 + extraCombo)) ||
|
(extraCombo && Math.random() > 0.1 / (1 + extraCombo)) ||
|
||||||
|
@ -1809,9 +1861,12 @@ function makeCoin(
|
||||||
let weight = 0.8 + Math.random() * 0.2 + Math.min(2, points * 0.01);
|
let weight = 0.8 + Math.random() * 0.2 + Math.min(2, points * 0.01);
|
||||||
weight *= 5 / (5 + gameState.perks.etherealcoins);
|
weight *= 5 / (5 + gameState.perks.etherealcoins);
|
||||||
|
|
||||||
if (gameState.perks.trickledown) {
|
if (gameState.perks.trickledown) y = -20;
|
||||||
y = -20;
|
if (
|
||||||
}
|
gameState.perks.rainbow &&
|
||||||
|
Math.random() > 1 / (1 + gameState.perks.rainbow)
|
||||||
|
)
|
||||||
|
color = rainbowColor();
|
||||||
|
|
||||||
append(gameState.coins, (p: Partial<Coin>) => {
|
append(gameState.coins, (p: Partial<Coin>) => {
|
||||||
p.x = x;
|
p.x = x;
|
||||||
|
|
|
@ -81,6 +81,22 @@ export function getRowColIndex(gameState: GameState, row: number, col: number) {
|
||||||
return row * gameState.gridSize + col;
|
return row * gameState.gridSize + col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getClosestBall(
|
||||||
|
gameState: GameState,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
): Ball | null {
|
||||||
|
let closestBall: Ball | null = null;
|
||||||
|
let dist = 0;
|
||||||
|
gameState.balls.forEach((ball) => {
|
||||||
|
const d2 = (ball.x - x) * (ball.x - x) + (ball.y - y) * (ball.y - y);
|
||||||
|
if (d2 < dist || !closestBall) {
|
||||||
|
closestBall = ball;
|
||||||
|
dist = d2;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return closestBall;
|
||||||
|
}
|
||||||
export function getPossibleUpgrades(gameState: GameState) {
|
export function getPossibleUpgrades(gameState: GameState) {
|
||||||
return upgrades
|
return upgrades
|
||||||
.filter((u) => getTotalScore() >= u.threshold)
|
.filter((u) => getTotalScore() >= u.threshold)
|
||||||
|
@ -375,9 +391,10 @@ export function reasonLevelIsLocked(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ballTransparency(ball: Ball, gameState: GameState) {
|
export function ballTransparency(ball: Ball, gameState: GameState) {
|
||||||
|
if (!gameState.perks.transparency) return 0;
|
||||||
return clamp(
|
return clamp(
|
||||||
gameState.perks.transparency * (1 - ball.y / gameState.gameZoneHeight) -
|
gameState.perks.transparency *
|
||||||
0.2,
|
(1 - (ball.y / gameState.gameZoneHeight) * 1.2),
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
|
|
@ -2697,6 +2697,56 @@
|
||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>bricks_attract_coins</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>name</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>tooltip</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>verbose_description</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>clairvoyant</name>
|
<name>clairvoyant</name>
|
||||||
<children>
|
<children>
|
||||||
|
@ -3377,6 +3427,56 @@
|
||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>hypnosis</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>name</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>tooltip</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>verbose_description</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>implosions</name>
|
<name>implosions</name>
|
||||||
<children>
|
<children>
|
||||||
|
@ -4092,6 +4192,56 @@
|
||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>rainbow</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>name</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>tooltip</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>verbose_description</name>
|
||||||
|
<description/>
|
||||||
|
<comment/>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-FR</language>
|
||||||
|
<approved>true</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>reach</name>
|
<name>reach</name>
|
||||||
<children>
|
<children>
|
||||||
|
@ -5538,7 +5688,7 @@
|
||||||
<custom_languages/>
|
<custom_languages/>
|
||||||
<id_extractor_ignores/>
|
<id_extractor_ignores/>
|
||||||
</editor_configuration>
|
</editor_configuration>
|
||||||
<primary_language>fr-FR</primary_language>
|
<primary_language>en-US</primary_language>
|
||||||
<configuration>
|
<configuration>
|
||||||
<indent>space2</indent>
|
<indent>space2</indent>
|
||||||
<format>json</format>
|
<format>json</format>
|
||||||
|
|
|
@ -170,6 +170,9 @@
|
||||||
"upgrades.bigger_puck.name": "Bigger paddle",
|
"upgrades.bigger_puck.name": "Bigger paddle",
|
||||||
"upgrades.bigger_puck.tooltip": "Easily catch more coins.",
|
"upgrades.bigger_puck.tooltip": "Easily catch more coins.",
|
||||||
"upgrades.bigger_puck.verbose_description": "A bigger paddle makes it easier to never miss the ball and to catch more coins, and also to precisely angle the bounces (the ball's angle only depends on where it hits the paddle). ",
|
"upgrades.bigger_puck.verbose_description": "A bigger paddle makes it easier to never miss the ball and to catch more coins, and also to precisely angle the bounces (the ball's angle only depends on where it hits the paddle). ",
|
||||||
|
"upgrades.bricks_attract_coins.name": "Bricks attract coins",
|
||||||
|
"upgrades.bricks_attract_coins.tooltip": "Helps them stay up there",
|
||||||
|
"upgrades.bricks_attract_coins.verbose_description": "",
|
||||||
"upgrades.clairvoyant.name": "Clairvoyant",
|
"upgrades.clairvoyant.name": "Clairvoyant",
|
||||||
"upgrades.clairvoyant.tooltip": "See upcoming levels, bricks HP and ball direction",
|
"upgrades.clairvoyant.tooltip": "See upcoming levels, bricks HP and ball direction",
|
||||||
"upgrades.clairvoyant.verbose_description": "Helps you pick the right upgrades and understand what's going on with sturdy bricks. Level 2 and 3 bring additional knowledge of dubious utility (reachable in loop mode)",
|
"upgrades.clairvoyant.verbose_description": "Helps you pick the right upgrades and understand what's going on with sturdy bricks. Level 2 and 3 bring additional knowledge of dubious utility (reachable in loop mode)",
|
||||||
|
@ -211,6 +214,9 @@
|
||||||
"upgrades.hot_start.name": "Hot start",
|
"upgrades.hot_start.name": "Hot start",
|
||||||
"upgrades.hot_start.tooltip": "Start at combo {{start}}, -{{loss}} combo per second",
|
"upgrades.hot_start.tooltip": "Start at combo {{start}}, -{{loss}} combo per second",
|
||||||
"upgrades.hot_start.verbose_description": "At the start of every level, your combo will start at +30 points, but then every second it will be decreased by one. The effect stacks with other perks. ",
|
"upgrades.hot_start.verbose_description": "At the start of every level, your combo will start at +30 points, but then every second it will be decreased by one. The effect stacks with other perks. ",
|
||||||
|
"upgrades.hypnosis.name": "Hypnosis",
|
||||||
|
"upgrades.hypnosis.tooltip": "Whenever a brick changes color, teleport that coin to the nearest ball and recharge its ability to stain a brick. ",
|
||||||
|
"upgrades.hypnosis.verbose_description": "",
|
||||||
"upgrades.implosions.name": "Implosions",
|
"upgrades.implosions.name": "Implosions",
|
||||||
"upgrades.implosions.tooltip": "Explosions suck coins in instead of blowing them out",
|
"upgrades.implosions.tooltip": "Explosions suck coins in instead of blowing them out",
|
||||||
"upgrades.implosions.verbose_description": "The explosion force is applied the other way. Further levels act as \"bigger explosion\"",
|
"upgrades.implosions.verbose_description": "The explosion force is applied the other way. Further levels act as \"bigger explosion\"",
|
||||||
|
@ -225,7 +231,7 @@
|
||||||
"upgrades.limitless.verbose_description": "Choosing this perk also raises his own limit by one, letting you pick it again.",
|
"upgrades.limitless.verbose_description": "Choosing this perk also raises his own limit by one, letting you pick it again.",
|
||||||
"upgrades.metamorphosis.name": "Metamorphosis",
|
"upgrades.metamorphosis.name": "Metamorphosis",
|
||||||
"upgrades.metamorphosis.tooltip": "Each coin can stain {{lvl}} brick(s) with its color",
|
"upgrades.metamorphosis.tooltip": "Each coin can stain {{lvl}} brick(s) with its color",
|
||||||
"upgrades.metamorphosis.verbose_description": "With this perk, coins will be of the color of the brick they come from, and will color the first brick they touch in the same color. \n\nCoins spawn with the speed of the ball that broke them, which means you can aim a bit in the direction of the bricks you want to \"paint\".",
|
"upgrades.metamorphosis.verbose_description": "With this perk, coins will be of the color of the brick they come from, and will color the first brick they touch in the same color. Coins spawn with the speed of the ball that broke them, which means you can aim a bit in the direction of the bricks you want to \"paint\". At level 1, each coin can color 1 bricks before it is \"spent\" and appears hollow. ",
|
||||||
"upgrades.minefield.name": "Minefield",
|
"upgrades.minefield.name": "Minefield",
|
||||||
"upgrades.minefield.tooltip": "+{{lvl}} combo per bomb brick on screen",
|
"upgrades.minefield.tooltip": "+{{lvl}} combo per bomb brick on screen",
|
||||||
"upgrades.minefield.verbose_description": "Adds +lvl to the combo when a brick is place, -lvl when it is destroyed, and raises the base combo by the number of bricks times lvl",
|
"upgrades.minefield.verbose_description": "Adds +lvl to the combo when a brick is place, -lvl when it is destroyed, and raises the base combo by the number of bricks times lvl",
|
||||||
|
@ -254,6 +260,9 @@
|
||||||
"upgrades.puck_repulse_ball.name": "Soft landing",
|
"upgrades.puck_repulse_ball.name": "Soft landing",
|
||||||
"upgrades.puck_repulse_ball.tooltip": "Paddle repulses balls",
|
"upgrades.puck_repulse_ball.tooltip": "Paddle repulses balls",
|
||||||
"upgrades.puck_repulse_ball.verbose_description": "When a ball gets close to the paddle, it will start slowing down, and even potentially bouncing without touching the paddle.",
|
"upgrades.puck_repulse_ball.verbose_description": "When a ball gets close to the paddle, it will start slowing down, and even potentially bouncing without touching the paddle.",
|
||||||
|
"upgrades.rainbow.name": "Rainbow",
|
||||||
|
"upgrades.rainbow.tooltip": "Coins spawn with rainbow color.",
|
||||||
|
"upgrades.rainbow.verbose_description": "Each level increases the proportion of colored coins. The color depends on level time. ",
|
||||||
"upgrades.reach.name": "Top down",
|
"upgrades.reach.name": "Top down",
|
||||||
"upgrades.reach.tooltip": " Touching the N bricks of the lowest row resets the combo. Otherwise, +N combo",
|
"upgrades.reach.tooltip": " Touching the N bricks of the lowest row resets the combo. Otherwise, +N combo",
|
||||||
"upgrades.reach.verbose_description": "If there is only one row of bricks, or if the lowest row of bricks cover the whole width of the game, then this perk does nothing. Otherwise, breaking this lowest row resets the combo, while breaking anything else increases the combo by the number of bricks present on that lowest row. \n\nThe lowest row will be highlighted in red. ",
|
"upgrades.reach.verbose_description": "If there is only one row of bricks, or if the lowest row of bricks cover the whole width of the game, then this perk does nothing. Otherwise, breaking this lowest row resets the combo, while breaking anything else increases the combo by the number of bricks present on that lowest row. \n\nThe lowest row will be highlighted in red. ",
|
||||||
|
|
|
@ -170,6 +170,9 @@
|
||||||
"upgrades.bigger_puck.name": "Raquette plus grande",
|
"upgrades.bigger_puck.name": "Raquette plus grande",
|
||||||
"upgrades.bigger_puck.tooltip": "Attrapez facilement plus de pièces.",
|
"upgrades.bigger_puck.tooltip": "Attrapez facilement plus de pièces.",
|
||||||
"upgrades.bigger_puck.verbose_description": "Une grande raquette permet de ne jamais rater la balle et d'attraper plus de pièces, ainsi que d'orienter précisément les rebonds. Cependant, une grande raquette est plus difficile à utiliser sur les côtés du niveau.",
|
"upgrades.bigger_puck.verbose_description": "Une grande raquette permet de ne jamais rater la balle et d'attraper plus de pièces, ainsi que d'orienter précisément les rebonds. Cependant, une grande raquette est plus difficile à utiliser sur les côtés du niveau.",
|
||||||
|
"upgrades.bricks_attract_coins.name": "Briques attirent les pièces",
|
||||||
|
"upgrades.bricks_attract_coins.tooltip": "Aide à garder les pièces en suspension",
|
||||||
|
"upgrades.bricks_attract_coins.verbose_description": "",
|
||||||
"upgrades.clairvoyant.name": "Clairvoyant",
|
"upgrades.clairvoyant.name": "Clairvoyant",
|
||||||
"upgrades.clairvoyant.tooltip": "Révèle les niveaux, PV des briques et direction des balles",
|
"upgrades.clairvoyant.tooltip": "Révèle les niveaux, PV des briques et direction des balles",
|
||||||
"upgrades.clairvoyant.verbose_description": "Vous aide à choisir les bonnes améliorations et à comprendre ce qu'il se passe avec \"briques solides\". Les niveaux 2 et 3 (en mode loop) amènent des informations complémentaires d'une utilité douteuse. ",
|
"upgrades.clairvoyant.verbose_description": "Vous aide à choisir les bonnes améliorations et à comprendre ce qu'il se passe avec \"briques solides\". Les niveaux 2 et 3 (en mode loop) amènent des informations complémentaires d'une utilité douteuse. ",
|
||||||
|
@ -211,6 +214,9 @@
|
||||||
"upgrades.hot_start.name": "Démarrage à chaud",
|
"upgrades.hot_start.name": "Démarrage à chaud",
|
||||||
"upgrades.hot_start.tooltip": "Combo à {{start}}, -{{loss}} combo par seconde",
|
"upgrades.hot_start.tooltip": "Combo à {{start}}, -{{loss}} combo par seconde",
|
||||||
"upgrades.hot_start.verbose_description": "Au début de chaque niveau, votre combo commencera à +30 points, mais à chaque seconde, il sera diminué d'un point. ",
|
"upgrades.hot_start.verbose_description": "Au début de chaque niveau, votre combo commencera à +30 points, mais à chaque seconde, il sera diminué d'un point. ",
|
||||||
|
"upgrades.hypnosis.name": "Hypnose",
|
||||||
|
"upgrades.hypnosis.tooltip": "Chaque fois qu'une brique change de couleur, téléportez cette pièce vers la boule la plus proche et rechargez sa capacité à tacher une brique.",
|
||||||
|
"upgrades.hypnosis.verbose_description": "",
|
||||||
"upgrades.implosions.name": "Implosions",
|
"upgrades.implosions.name": "Implosions",
|
||||||
"upgrades.implosions.tooltip": "Les explosions aspirent les pièces au lieu de les faire exploser.",
|
"upgrades.implosions.tooltip": "Les explosions aspirent les pièces au lieu de les faire exploser.",
|
||||||
"upgrades.implosions.verbose_description": "La force d’explosion est appliquée dans l’autre sens. Les niveaux 2+ augmentent la puissance de l'implosion. ",
|
"upgrades.implosions.verbose_description": "La force d’explosion est appliquée dans l’autre sens. Les niveaux 2+ augmentent la puissance de l'implosion. ",
|
||||||
|
@ -225,7 +231,7 @@
|
||||||
"upgrades.limitless.verbose_description": "Choisir cet avantage augmente également sa propre limite d'un point, vous permettant de le choisir à nouveau.",
|
"upgrades.limitless.verbose_description": "Choisir cet avantage augmente également sa propre limite d'un point, vous permettant de le choisir à nouveau.",
|
||||||
"upgrades.metamorphosis.name": "Métamorphose",
|
"upgrades.metamorphosis.name": "Métamorphose",
|
||||||
"upgrades.metamorphosis.tooltip": "Chaque pièce peut tacher {{lvl}} brique(s) avec sa couleur",
|
"upgrades.metamorphosis.tooltip": "Chaque pièce peut tacher {{lvl}} brique(s) avec sa couleur",
|
||||||
"upgrades.metamorphosis.verbose_description": "Avec cette amélioration, les pièces seront de la couleur de la brique d'où elles proviennent et coloreront la première brique qu'elles toucheront. \n\nLes pièces apparaissent à la vitesse de la balle qui les a cassées, ce qui signifie que vous pouvez viser un peu dans la direction des briques que vous voulez \"peindre\".",
|
"upgrades.metamorphosis.verbose_description": "Avec cette amélioration, les pièces seront de la couleur de la brique d'où elles proviennent et coloreront la première brique qu'elles toucheront. Les pièces apparaissent à la vitesse de la balle qui les a cassées, ce qui signifie que vous pouvez viser un peu dans la direction des briques que vous voulez \"peindre\". Au à chaque niveau, chaque pièce peut colorier une brique de plus avant d'être \"épuisée\" et d'apparaître vide.",
|
||||||
"upgrades.minefield.name": "Terrain miné",
|
"upgrades.minefield.name": "Terrain miné",
|
||||||
"upgrades.minefield.tooltip": "+{{lvl}} combo par brique explosive à l'écran",
|
"upgrades.minefield.tooltip": "+{{lvl}} combo par brique explosive à l'écran",
|
||||||
"upgrades.minefield.verbose_description": "Ajoute +lvl au combo lorsqu'une brique est placée, -lvl lorsqu'elle est détruite et augmente le combo de base du nombre de briques multiplié par le niveau",
|
"upgrades.minefield.verbose_description": "Ajoute +lvl au combo lorsqu'une brique est placée, -lvl lorsqu'elle est détruite et augmente le combo de base du nombre de briques multiplié par le niveau",
|
||||||
|
@ -254,6 +260,9 @@
|
||||||
"upgrades.puck_repulse_ball.name": "Atterrissage en douceur",
|
"upgrades.puck_repulse_ball.name": "Atterrissage en douceur",
|
||||||
"upgrades.puck_repulse_ball.tooltip": "La raquette repousse les balles",
|
"upgrades.puck_repulse_ball.tooltip": "La raquette repousse les balles",
|
||||||
"upgrades.puck_repulse_ball.verbose_description": "Lorsqu'une balle s'approche de la raquette, elle commence à ralentir, voire à rebondir sans toucher le palet.",
|
"upgrades.puck_repulse_ball.verbose_description": "Lorsqu'une balle s'approche de la raquette, elle commence à ralentir, voire à rebondir sans toucher le palet.",
|
||||||
|
"upgrades.rainbow.name": "Arc en ciel",
|
||||||
|
"upgrades.rainbow.tooltip": "Les pièces apparaissent avec la couleur de l'arc en ciel.",
|
||||||
|
"upgrades.rainbow.verbose_description": "Chaque niveau augment la proportion de pièces colorée. La couleur dépends du temps de jeu. ",
|
||||||
"upgrades.reach.name": "Attaque aérienne",
|
"upgrades.reach.name": "Attaque aérienne",
|
||||||
"upgrades.reach.tooltip": "Casser une des N briques de la ligne la plus basse détruit le combo. Sinon, +N combo.",
|
"upgrades.reach.tooltip": "Casser une des N briques de la ligne la plus basse détruit le combo. Sinon, +N combo.",
|
||||||
"upgrades.reach.verbose_description": "S'il n'y a qu'une seule rangée de briques, ou si la rangée la plus basse couvre toute la largeur du jeu, cet avantage est sans effet. Sinon, briser cette rangée la plus basse réinitialise le combo ; briser toute autre rangée augmente le combo du nombre de briques présentes sur cette rangée.\n\nLa rangée de briques du bas sera entourée en rouge pour vous rappeler de ne pas la toucher. ",
|
"upgrades.reach.verbose_description": "S'il n'y a qu'une seule rangée de briques, ou si la rangée la plus basse couvre toute la largeur du jeu, cet avantage est sans effet. Sinon, briser cette rangée la plus basse réinitialise le combo ; briser toute autre rangée augmente le combo du nombre de briques présentes sur cette rangée.\n\nLa rangée de briques du bas sera entourée en rouge pour vous rappeler de ne pas la toucher. ",
|
||||||
|
|
|
@ -136,7 +136,9 @@ export function newGameState(params: RunParams): GameState {
|
||||||
autoCleanUses: 0,
|
autoCleanUses: 0,
|
||||||
...defaultSounds(),
|
...defaultSounds(),
|
||||||
rerolls: 0,
|
rerolls: 0,
|
||||||
creative: sumOfValues(params.perks) > 1 || params.level,
|
creative:
|
||||||
|
sumOfValues(params.perks) > 1 ||
|
||||||
|
(params.level && params.level !== "icon:" + randomGift),
|
||||||
};
|
};
|
||||||
resetBalls(gameState);
|
resetBalls(gameState);
|
||||||
|
|
||||||
|
|
|
@ -123,8 +123,9 @@ export function render(gameState: GameState) {
|
||||||
coin.y / haloScale,
|
coin.y / haloScale,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
haloCanvasCtx.globalAlpha = 0.3;
|
|
||||||
gameState.balls.forEach((ball) => {
|
gameState.balls.forEach((ball) => {
|
||||||
|
haloCanvasCtx.globalAlpha = 0.3 * (1 - ballTransparency(ball, gameState));
|
||||||
drawFuzzyBall(
|
drawFuzzyBall(
|
||||||
haloCanvasCtx,
|
haloCanvasCtx,
|
||||||
gameState.ballsColor,
|
gameState.ballsColor,
|
||||||
|
@ -251,12 +252,12 @@ export function render(gameState: GameState) {
|
||||||
ctx.globalAlpha = 1;
|
ctx.globalAlpha = 1;
|
||||||
forEachLiveOne(gameState.coins, (coin) => {
|
forEachLiveOne(gameState.coins, (coin) => {
|
||||||
const color = getCoinRenderColor(gameState, coin);
|
const color = getCoinRenderColor(gameState, coin);
|
||||||
|
const hollow = gameState.perks.metamorphosis && !coin.metamorphosisPoints;
|
||||||
|
|
||||||
// ctx.globalCompositeOperation = "source-over";
|
|
||||||
ctx.globalCompositeOperation = "source-over";
|
ctx.globalCompositeOperation = "source-over";
|
||||||
drawCoin(
|
drawCoin(
|
||||||
ctx,
|
ctx,
|
||||||
color,
|
hollow ? "transparent" : color,
|
||||||
coin.size,
|
coin.size,
|
||||||
coin.x,
|
coin.x,
|
||||||
coin.y,
|
coin.y,
|
||||||
|
@ -264,6 +265,7 @@ export function render(gameState: GameState) {
|
||||||
(hasCombo && gameState.perks.asceticism && "#FF0000") ||
|
(hasCombo && gameState.perks.asceticism && "#FF0000") ||
|
||||||
// Gold coins
|
// Gold coins
|
||||||
// (color === "#ffd300" && "#ffd300") ||
|
// (color === "#ffd300" && "#ffd300") ||
|
||||||
|
(hollow && color) ||
|
||||||
gameState.level.color,
|
gameState.level.color,
|
||||||
coin.a,
|
coin.a,
|
||||||
);
|
);
|
||||||
|
@ -869,6 +871,9 @@ export function drawCoin(
|
||||||
canctx.lineWidth = 2;
|
canctx.lineWidth = 2;
|
||||||
canctx.setLineDash(redBorderDash);
|
canctx.setLineDash(redBorderDash);
|
||||||
}
|
}
|
||||||
|
if (color === "transparent") {
|
||||||
|
canctx.lineWidth = 2;
|
||||||
|
}
|
||||||
canctx.stroke();
|
canctx.stroke();
|
||||||
|
|
||||||
if (color === "#ffd300") {
|
if (color === "#ffd300") {
|
||||||
|
|
|
@ -710,4 +710,34 @@ export const rawUpgrades = [
|
||||||
help: (lvl: number) => t("upgrades.superhot.tooltip", { lvl }),
|
help: (lvl: number) => t("upgrades.superhot.tooltip", { lvl }),
|
||||||
fullHelp: t("upgrades.superhot.verbose_description"),
|
fullHelp: t("upgrades.superhot.verbose_description"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
requires: "",
|
||||||
|
threshold: 200000,
|
||||||
|
giftable: false,
|
||||||
|
id: "bricks_attract_coins",
|
||||||
|
max: 3,
|
||||||
|
name: t("upgrades.bricks_attract_coins.name"),
|
||||||
|
help: (lvl: number) => t("upgrades.bricks_attract_coins.tooltip", { lvl }),
|
||||||
|
fullHelp: t("upgrades.bricks_attract_coins.verbose_description"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
requires: "",
|
||||||
|
threshold: 205000,
|
||||||
|
giftable: false,
|
||||||
|
id: "rainbow",
|
||||||
|
max: 7,
|
||||||
|
name: t("upgrades.rainbow.name"),
|
||||||
|
help: (lvl: number) => t("upgrades.rainbow.tooltip", { lvl }),
|
||||||
|
fullHelp: t("upgrades.rainbow.verbose_description"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
requires: "metamorphosis",
|
||||||
|
threshold: 210000,
|
||||||
|
giftable: false,
|
||||||
|
id: "hypnosis",
|
||||||
|
max: 1,
|
||||||
|
name: t("upgrades.hypnosis.name"),
|
||||||
|
help: (lvl: number) => t("upgrades.hypnosis.tooltip", { lvl }),
|
||||||
|
fullHelp: t("upgrades.hypnosis.verbose_description"),
|
||||||
|
},
|
||||||
] as const;
|
] as const;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue