mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-20 12:15:06 -04:00
Fixed an issue with resizing and pacman level, changed ball attracts coins
This commit is contained in:
parent
83b9c0dec5
commit
183a11f989
10 changed files with 1837 additions and 1761 deletions
|
@ -28,11 +28,11 @@ Some upgrades currently are not really useful
|
||||||
|
|
||||||
## To do
|
## To do
|
||||||
|
|
||||||
- change fortunate ball to work more like coin magnet, carrying the balls around to catch them at next puck bounce
|
|
||||||
- add a test to forbid more than 5% grey bricks on black background, remove grey bricks border
|
|
||||||
|
|
||||||
## Done
|
## Done
|
||||||
|
|
||||||
|
- change fortunate ball to work more like coin magnet, carrying the balls around to catch them at next puck bounce
|
||||||
|
- add a test to forbid more than 5% grey bricks on black background, remove grey bricks border
|
||||||
- simplified texts to make translation easier
|
- simplified texts to make translation easier
|
||||||
- fixed some issues around saved level unlocks
|
- fixed some issues around saved level unlocks
|
||||||
- change donation text to not suggest an amount
|
- change donation text to not suggest an amount
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// npx nodemon checks.js
|
// npx nodemon checks.js
|
||||||
const fs= require('fs')
|
const fs= require('fs')
|
||||||
const english = JSON.parse(fs.readFileSync('./src/i18n/en.json'))
|
const english = JSON.parse(fs.readFileSync('./src/i18n/en.json'))
|
||||||
console.log(Object.entries(english).sort((a,b)=>a[1].length-b[1].length).slice(-10,-1).map(([k,v])=>k+'\n'+k.split('').map(c=>'=').join('')+'\n\n'+v).join('\n\n'))
|
console.debug(Object.entries(english).sort((a,b)=>a[1].length-b[1].length).slice(-10,-1).map(([k,v])=>k+'\n'+k.split('').map(c=>'=').join('')+'\n\n'+v).join('\n\n'))
|
56
dist/index.html
vendored
56
dist/index.html
vendored
File diff suppressed because one or more lines are too long
|
@ -10,13 +10,11 @@ app.use(bodyParser.text({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
app.get('/src/data/levels.json', (req, res) => {
|
app.get('/src/data/levels.json', (req, res) => {
|
||||||
console.log('src/data/levels.json')
|
|
||||||
res.json(JSON.parse(fs.readFileSync('src/data/levels.json')))
|
res.json(JSON.parse(fs.readFileSync('src/data/levels.json')))
|
||||||
})
|
})
|
||||||
|
|
||||||
app.post('/src/data/levels.json', (req, res) => {
|
app.post('/src/data/levels.json', (req, res) => {
|
||||||
if(req.body?.trim()) {
|
if(req.body?.trim()) {
|
||||||
console.log('Levels updated')
|
|
||||||
fs.writeFileSync('src/data/levels.json', req.body)
|
fs.writeFileSync('src/data/levels.json', req.body)
|
||||||
}
|
}
|
||||||
res.end('OK')
|
res.end('OK')
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
"size": 6,
|
"size": 6,
|
||||||
"bricks": "_______gggg__rrrr__yyyy",
|
"bricks": "_______gggg__rrrr__yyyy",
|
||||||
"svg": 8,
|
"svg": 8,
|
||||||
"color": ""
|
"color": "#5da3ea"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "France",
|
"name": "France",
|
||||||
|
@ -413,12 +413,13 @@
|
||||||
"name": "Wiki",
|
"name": "Wiki",
|
||||||
"size": 10,
|
"size": 10,
|
||||||
"bricks": "_______________________GGGG_____GGkkGG___GkggggkG__GgWWWWgG__GkggggkG___GGkkGG_____GGGG_______________________",
|
"bricks": "_______________________GGGG_____GGkkGG___GkggggkG__GgWWWWgG__GkggggkG___GGkkGG_____GGGG_______________________",
|
||||||
"svg": null
|
"svg": null,
|
||||||
|
"color": "#1c71d8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Baby Dog",
|
"name": "Baby Dog",
|
||||||
"size": 8,
|
"size": 8,
|
||||||
"bricks": "_______W__eeeeWWWWeeWeWWWegWegeeeeWWWWee_eWggWe__eWWWWe____WW",
|
"bricks": "_______W__eeeeWWWWeeWeWWWeBWeBeeeeWWWWee_eWBBWe__eWWWWe____WW___",
|
||||||
"svg": null
|
"svg": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -570,7 +571,7 @@
|
||||||
{
|
{
|
||||||
"name": "icon:soft_reset",
|
"name": "icon:soft_reset",
|
||||||
"size": 8,
|
"size": 8,
|
||||||
"bricks": "___rg_____rrgg___rryggg_rryWggggrryWgggg_ryyggg___rrgg_____rg___",
|
"bricks": "____yy______yyy_____yyyy____yyyyyyyyyyyyyyyyyyyy_yyyyyy___yyyy__",
|
||||||
"svg": null
|
"svg": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -782,7 +783,7 @@
|
||||||
"size": 8,
|
"size": 8,
|
||||||
"bricks": "_________tttttt__tttttt__gggggg__gggggg__WWWWWW__WWWWWW",
|
"bricks": "_________tttttt__tttttt__gggggg__gggggg__WWWWWW__WWWWWW",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": "#986a44"
|
"color": "#26a269"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Finland",
|
"name": "Finland",
|
||||||
|
@ -1039,7 +1040,7 @@
|
||||||
"size": 24,
|
"size": 24,
|
||||||
"bricks": "____________________________________________________ggggg______ggggg_______gg___g______g___gg_____gg________________gg___gg__________________gg_gggggggggg____gggggggggggggtttttggggggggbbbbbgggggtWWWttttggggbbbbWWWbgg_gtWttttttggggbbbbWbbbg__gtttttttgg__ggbbbbbbbg__gtttttttg____gbbbbbbbg__ggtttttgg____ggbbbbbgg___ggtttgg______ggbbbgg_____ggggg________ggggg___________________________________________________________________________________________________________________________________________________________________________________________________________________________",
|
"bricks": "____________________________________________________ggggg______ggggg_______gg___g______g___gg_____gg________________gg___gg__________________gg_gggggggggg____gggggggggggggtttttggggggggbbbbbgggggtWWWttttggggbbbbWWWbgg_gtWttttttggggbbbbWbbbg__gtttttttgg__ggbbbbbbbg__gtttttttg____gbbbbbbbg__ggtttttgg____ggbbbbbgg___ggtttgg______ggbbbgg_____ggggg________ggggg___________________________________________________________________________________________________________________________________________________________________________________________________________________________",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": "#1a5fb4",
|
"color": "#26a269",
|
||||||
"credit": "https://prohama.com/sunglasses-pattern-1/"
|
"credit": "https://prohama.com/sunglasses-pattern-1/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1109,7 +1110,7 @@
|
||||||
{
|
{
|
||||||
"name": "icon:fountain_toss",
|
"name": "icon:fountain_toss",
|
||||||
"size": 12,
|
"size": 12,
|
||||||
"bricks": "________________tttt______tttggttt____tggggggt____t__gg__t____tllggllt___ltbyggbbtl_lbtttggtytblgyttybbtttyggggttbbtyggg_gggggggggg____gggggg___",
|
"bricks": "__________________________________________________WWWWWWWW___WttttttttW_WtytttytyttWWtttyttttttWlWtyttttytWl_lWWWWWWWWl___llllllll______________",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": ""
|
"color": ""
|
||||||
},
|
},
|
||||||
|
@ -1122,8 +1123,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Gear",
|
"name": "Gear",
|
||||||
"size": 14,
|
"size": 13,
|
||||||
"bricks": "_________________________________l_l_l_______l_lllll_l______lllllll_____lllll_lllll____lll___lll____lll_____lll____lll___lll____lllll_lllll_____lllllll______l_lllll_l_______l_l_l__________________",
|
"bricks": "_________________l_l_l______l_lllll_l_____lllllll____lllll_lllll___lll___lll___lll_____lll___lll___lll___lllll_lllll____lllllll_____l_lllll_l______l_l_l_________________",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": ""
|
"color": ""
|
||||||
},
|
},
|
||||||
|
@ -1279,7 +1280,7 @@
|
||||||
"size": 11,
|
"size": 11,
|
||||||
"bricks": "___gggg_____gggrrgg_____ggrrg_______gggg_____gggyygg_____ggyyg_______gggg_____gggCCgg_____ggCCg_______gggg________gg_____",
|
"bricks": "___gggg_____gggrrgg_____ggrrg_______gggg_____gggyygg_____ggyyg_______gggg_____gggCCgg_____ggCCg_______gggg________gg_____",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": "",
|
"color": "#240a8b",
|
||||||
"credit": "Left a wonderful review on the play store."
|
"credit": "Left a wonderful review on the play store."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1287,7 +1288,7 @@
|
||||||
"size": 13,
|
"size": 13,
|
||||||
"bricks": "_______________________________________OOOORgRgRgOOOOWOORgRgRgOOOOOWORgRgRgOWOOWOORgRgRgOOWOOWORgRgRgOWOOWOORgRgRgOOOOOOORgRgRgOOO_______________________________________",
|
"bricks": "_______________________________________OOOORgRgRgOOOOWOORgRgRgOOOOOWORgRgRgOWOOWOORgRgRgOOWOOWORgRgRgOWOOWOORgRgRgOOOOOOORgRgRgOOO_______________________________________",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": "",
|
"color": "#62a0ea",
|
||||||
"credit": "Colin helped a lot with the game design https://colin-crapahute.bearblog.dev/"
|
"credit": "Colin helped a lot with the game design https://colin-crapahute.bearblog.dev/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1295,7 +1296,7 @@
|
||||||
"size": 15,
|
"size": 15,
|
||||||
"bricks": "_________________________________ggggggggg_____g_________g___g___________g_g_____________gg_____________gg_____yyy_____ggg__yyyyyyy__ggggtyyyyyyyyytggggtttttttttttgggg_ttttttttt_gg_____ttttt___________________________________",
|
"bricks": "_________________________________ggggggggg_____g_________g___g___________g_g_____________gg_____________gg_____yyy_____ggg__yyyyyyy__ggggtyyyyyyyyytggggtttttttttttgggg_ttttttttt_gg_____ttttt___________________________________",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": "",
|
"color": "#240a8b",
|
||||||
"credit": "Early adopter of the game"
|
"credit": "Early adopter of the game"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1309,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____g_____ggg__",
|
"bricks": "W__W__W_W___W___W_W__W_____W_W___W____l_____lll__",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": ""
|
"color": ""
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"B": "black",
|
"B": "black",
|
||||||
"W": "#FFFFFF",
|
"W": "#FFFFFF",
|
||||||
"g": "#231f20",
|
"g": "#231f20",
|
||||||
"y": "#ffd300",
|
"y": "#FFD300",
|
||||||
"b": "#6262EA",
|
"b": "#6262EA",
|
||||||
"t": "#5DA3EA",
|
"t": "#5DA3EA",
|
||||||
"s": "#E67070",
|
"s": "#E67070",
|
||||||
|
|
|
@ -156,6 +156,7 @@ export const fitSize = () => {
|
||||||
Math.min(gameState.canvasWidth, gameState.gameZoneHeight * 0.73),
|
Math.min(gameState.canvasWidth, gameState.gameZoneHeight * 0.73),
|
||||||
);
|
);
|
||||||
gameState.brickWidth = Math.floor(baseWidth / gameState.gridSize / 2) * 2;
|
gameState.brickWidth = Math.floor(baseWidth / gameState.gridSize / 2) * 2;
|
||||||
|
|
||||||
gameState.gameZoneWidth = gameState.brickWidth * gameState.gridSize;
|
gameState.gameZoneWidth = gameState.brickWidth * gameState.gridSize;
|
||||||
gameState.offsetX = Math.floor(
|
gameState.offsetX = Math.floor(
|
||||||
(gameState.canvasWidth - gameState.gameZoneWidth) / 2,
|
(gameState.canvasWidth - gameState.gameZoneWidth) / 2,
|
||||||
|
@ -974,8 +975,10 @@ document.addEventListener("keyup", async (e) => {
|
||||||
export const gameState = newGameState({});
|
export const gameState = newGameState({});
|
||||||
|
|
||||||
export function restart(params: RunParams) {
|
export function restart(params: RunParams) {
|
||||||
fitSize();
|
// fitSize();
|
||||||
Object.assign(gameState, newGameState(params));
|
Object.assign(gameState, newGameState(params));
|
||||||
|
// Recompute brick size according to level
|
||||||
|
fitSize();
|
||||||
pauseRecording();
|
pauseRecording();
|
||||||
setLevel(gameState, 0);
|
setLevel(gameState, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,25 +28,17 @@ 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, fitSize, gameState, hasBrick, hitsSomething, openUpgradesPicker, pause,} from "./game";
|
||||||
brickIndex,
|
import {stopRecording} from "./recording";
|
||||||
fitSize,
|
import {isOptionOn} from "./options";
|
||||||
gameState,
|
import {clamp, comboKeepingRate} from "./pure_functions";
|
||||||
hasBrick,
|
import {addToTotalScore} from "./addToTotalScore";
|
||||||
hitsSomething,
|
|
||||||
openUpgradesPicker,
|
|
||||||
pause,
|
|
||||||
} from "./game";
|
|
||||||
import { stopRecording } from "./recording";
|
|
||||||
import { isOptionOn } from "./options";
|
|
||||||
import { clamp, comboKeepingRate } from "./pure_functions";
|
|
||||||
import { addToTotalScore } from "./addToTotalScore";
|
|
||||||
|
|
||||||
export function setMousePos(gameState: GameState, x: number) {
|
export function setMousePos(gameState: GameState, x: number) {
|
||||||
gameState.puckPosition = x;
|
gameState.puckPosition = x;
|
||||||
|
@ -414,7 +406,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -834,7 +826,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);
|
||||||
|
@ -1017,7 +1009,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) {
|
||||||
|
@ -1042,13 +1034,45 @@ export function gameStateTick(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameState.perks.ball_attracts_coins) {
|
if (gameState.perks.ball_attracts_coins) {
|
||||||
|
// Find closest ball
|
||||||
|
let closestBall = gameState.balls[0]
|
||||||
|
let dist = distance2(closestBall, coin)
|
||||||
gameState.balls.forEach((ball) => {
|
gameState.balls.forEach((ball) => {
|
||||||
|
if (ball == closestBall) return
|
||||||
const d2 = distance2(ball, coin);
|
const d2 = distance2(ball, coin);
|
||||||
coin.vx +=
|
if (d2 < dist) {
|
||||||
((ball.x - coin.x) / d2) * 50 * gameState.perks.ball_attracts_coins;
|
closestBall = ball
|
||||||
coin.vy +=
|
dist = d2
|
||||||
((ball.y - coin.y) / d2) * 50 * gameState.perks.ball_attracts_coins;
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
if (!isOptionOn('basic') && Math.random()*gameState.perks.ball_attracts_coins > 0.9 ) {
|
||||||
|
makeParticle(
|
||||||
|
gameState,
|
||||||
|
coin.x+dx*5,
|
||||||
|
coin.y+dy*5,
|
||||||
|
dx*2,
|
||||||
|
dy*2,
|
||||||
|
rainbowColor(),
|
||||||
|
true,
|
||||||
|
gameState.coinSize / 2,
|
||||||
|
100,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ratio =
|
const ratio =
|
||||||
|
@ -1346,7 +1370,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;
|
||||||
|
@ -1587,13 +1611,13 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
|
||||||
if (!gameState.balls.find((b) => !b.destroyed)) {
|
if (!gameState.balls.find((b) => !b.destroyed)) {
|
||||||
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);
|
||||||
|
@ -1851,7 +1875,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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
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", () => {
|
||||||
|
@ -8,6 +9,14 @@ describe("json data checks", () => {
|
||||||
_rawLevelsList.filter((l) => l.name.startsWith("icon:")).length,
|
_rawLevelsList.filter((l) => l.name.startsWith("icon:")).length,
|
||||||
).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,
|
||||||
|
@ -29,6 +38,18 @@ describe("json data checks", () => {
|
||||||
it("Has a few colors", () => {
|
it("Has a few colors", () => {
|
||||||
expect(Object.keys(_palette).length).toBeGreaterThan(10);
|
expect(Object.keys(_palette).length).toBeGreaterThan(10);
|
||||||
});
|
});
|
||||||
|
it("Avoids dark bricks on dark bg", () => {
|
||||||
|
const levelsWithDarkBricksAndBG = _rawLevelsList
|
||||||
|
.filter(l=>!l.color && !l.name.match(/^icon:/))
|
||||||
|
.map(l=>({
|
||||||
|
name:l.name,
|
||||||
|
bricks:l.bricks.split('').filter(c=>c!=='_').length,
|
||||||
|
darkBricks:l.bricks.split('').filter(c=>c==='g').length,
|
||||||
|
}))
|
||||||
|
.filter(l=>l.darkBricks>0.05*l.bricks)
|
||||||
|
|
||||||
|
expect(levelsWithDarkBricksAndBG).toEqual([]);
|
||||||
|
});
|
||||||
it("Has an _appVersion", () => {
|
it("Has an _appVersion", () => {
|
||||||
expect(parseInt(_appVersion)).toBeGreaterThan(2000);
|
expect(parseInt(_appVersion)).toBeGreaterThan(2000);
|
||||||
});
|
});
|
||||||
|
|
|
@ -257,11 +257,10 @@ export function render(gameState: GameState) {
|
||||||
coin.size,
|
coin.size,
|
||||||
coin.x,
|
coin.x,
|
||||||
coin.y,
|
coin.y,
|
||||||
|
// Red border around coins with asceticism
|
||||||
(hasCombo && gameState.perks.asceticism && "#FF0000") ||
|
(hasCombo && gameState.perks.asceticism && "#FF0000") ||
|
||||||
(color === "#ffd300" && "#ffd300") ||
|
// Gold coins
|
||||||
(color == "#231f20" &&
|
// (color === "#ffd300" && "#ffd300") ||
|
||||||
gameState.level.color == "#000000" &&
|
|
||||||
"#FFFFFF") ||
|
|
||||||
gameState.level.color,
|
gameState.level.color,
|
||||||
coin.a,
|
coin.a,
|
||||||
);
|
);
|
||||||
|
@ -408,7 +407,7 @@ export function render(gameState: GameState) {
|
||||||
gameState.coinSize,
|
gameState.coinSize,
|
||||||
left + gameState.coinSize / 2,
|
left + gameState.coinSize / 2,
|
||||||
gameState.gameZoneHeight - gameState.puckHeight / 2,
|
gameState.gameZoneHeight - gameState.puckHeight / 2,
|
||||||
gameState.puckColor,
|
"#ffd300",
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
drawText(
|
drawText(
|
||||||
|
@ -895,9 +894,15 @@ export function drawFuzzyBall(
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
const key = "fuzzy-circle" + color + "_" + width;
|
const key = "fuzzy-circle" + color + "_" + width;
|
||||||
if (!color) debugger;
|
if (!color?.startsWith('#')) debugger;
|
||||||
|
|
||||||
const size = Math.round(width * 3);
|
const size = Math.round(width * 3);
|
||||||
|
if (!size || isNaN(size)) {
|
||||||
|
debugger;
|
||||||
|
return
|
||||||
|
}
|
||||||
if (!cachedGraphics[key]) {
|
if (!cachedGraphics[key]) {
|
||||||
const can = document.createElement("canvas");
|
const can = document.createElement("canvas");
|
||||||
can.width = size;
|
can.width = size;
|
||||||
|
@ -919,6 +924,7 @@ export function drawFuzzyBall(
|
||||||
canctx.fillStyle = gradient;
|
canctx.fillStyle = gradient;
|
||||||
canctx.fillRect(0, 0, size, size);
|
canctx.fillRect(0, 0, size, size);
|
||||||
cachedGraphics[key] = can;
|
cachedGraphics[key] = can;
|
||||||
|
|
||||||
}
|
}
|
||||||
ctx.drawImage(
|
ctx.drawImage(
|
||||||
cachedGraphics[key],
|
cachedGraphics[key],
|
||||||
|
@ -944,12 +950,6 @@ export function drawBrick(
|
||||||
const width = brx - tlx,
|
const width = brx - tlx,
|
||||||
height = bry - tly;
|
height = bry - tly;
|
||||||
|
|
||||||
const whiteBorder =
|
|
||||||
offset == -1 &&
|
|
||||||
color == "#231f20" &&
|
|
||||||
gameState.level.color == "#000000" &&
|
|
||||||
"#FFFFFF";
|
|
||||||
|
|
||||||
const key =
|
const key =
|
||||||
"brick" +
|
"brick" +
|
||||||
color +
|
color +
|
||||||
|
@ -962,8 +962,7 @@ export function drawBrick(
|
||||||
offset +
|
offset +
|
||||||
"_" +
|
"_" +
|
||||||
borderOnly +
|
borderOnly +
|
||||||
"_" +
|
"_" ;
|
||||||
whiteBorder;
|
|
||||||
|
|
||||||
if (!cachedGraphics[key]) {
|
if (!cachedGraphics[key]) {
|
||||||
const can = document.createElement("canvas");
|
const can = document.createElement("canvas");
|
||||||
|
@ -977,9 +976,9 @@ export function drawBrick(
|
||||||
|
|
||||||
canctx.setLineDash(offset !== -1 ? redBorderDash : emptyArray);
|
canctx.setLineDash(offset !== -1 ? redBorderDash : emptyArray);
|
||||||
canctx.lineDashOffset = offset;
|
canctx.lineDashOffset = offset;
|
||||||
canctx.strokeStyle = (offset !== -1 && "#FF000033") || whiteBorder || color;
|
canctx.strokeStyle = (offset !== -1 && "#FF000033") || color;
|
||||||
canctx.lineJoin = "round";
|
canctx.lineJoin = "round";
|
||||||
canctx.lineWidth = whiteBorder ? 1 : bord;
|
canctx.lineWidth = bord;
|
||||||
roundRect(
|
roundRect(
|
||||||
canctx,
|
canctx,
|
||||||
bord / 2,
|
bord / 2,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue