Sturdy bricks now have a proper hit counter

This commit is contained in:
Renan LE CARO 2025-03-23 17:52:25 +01:00
parent 6899b5cf36
commit 3745b527f5
6 changed files with 64 additions and 32 deletions

View file

@ -258,7 +258,9 @@ export function explosionAt(
const size = 1 + gameState.perks.bigger_explosions;
schedulGameSound(gameState, "explode", ball.x, 1);
if (index !== -1) {
if (gameState.bricks[index] == "black") delete gameState.bricks[index];
if (gameState.bricks[index] == "black") {
setBrick(gameState, index, "")
}
const col = index % gameState.gridSize;
const row = Math.floor(index / gameState.gridSize);
@ -268,11 +270,8 @@ export function explosionAt(
const i = getRowColIndex(gameState, row + dy, col + dx);
if (gameState.bricks[i] && i !== -1) {
// Study bricks resist explosions too
if (
gameState.bricks[i] !== "black" &&
gameState.perks.sturdy_bricks > Math.random() * 5
)
continue;
gameState.brickHP[i]--
if (gameState.brickHP<=0)
explodeBrick(gameState, i, ball, true);
}
}
@ -308,7 +307,7 @@ export function explodeBrick(
gameState: GameState,
index: number,
ball: Ball,
isExplosion: boolean,
isExplosion: boolean
) {
const color = gameState.bricks[index];
if (!color) return;
@ -324,7 +323,7 @@ export function explodeBrick(
const x = brickCenterX(gameState, index),
y = brickCenterY(gameState, index);
gameState.bricks[index] = "";
setBrick( gameState,index,"");
let coinsToSpawn = gameState.combo;
if (gameState.perks.sturdy_bricks) {
@ -556,7 +555,11 @@ export async function setLevel(gameState: GameState, l: number) {
empty(gameState.particles);
empty(gameState.lights);
empty(gameState.texts);
gameState.bricks = [...lvl.bricks];
gameState.bricks = []
for(let i=0;i<lvl.size*lvl.size;i++){
setBrick(gameState, i,lvl.bricks[i])
}
// Balls color will depend on most common brick color sometimes
resetBalls(gameState);
gameState.needsRender = true;
@ -565,6 +568,12 @@ export async function setLevel(gameState: GameState, l: number) {
background.src = "data:image/svg+xml;UTF8," + lvl.svg;
}
function setBrick(gameState:GameState, index:number, color:string){
gameState.bricks[index] = color||'';
gameState.brickHP[index] = (color === 'black' && 1) ||(color && 1+gameState.perks.sturdy_bricks)||0
}
export function rainbowColor(): colorString {
return `hsl(${(Math.round(gameState.levelTime / 4) * 2) % 360},100%,70%)`;
}
@ -947,6 +956,7 @@ export function gameStateTick(
gameState.bricks[hitBrick] !== "black" &&
!coin.coloredABrick
) {
// Not using setbrick because we don't want to reset HP
gameState.bricks[hitBrick] = coin.color;
coin.coloredABrick = true;
@ -1390,8 +1400,11 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
.slice(0, -1)
.slice(0, gameState.perks.respawn)
.forEach(({ index, color }) => {
if (!gameState.bricks[index] && color !== "black")
gameState.bricks[index] = color;
if (!gameState.bricks[index] && color !== "black") {
// respawns with full hp
setBrick(gameState, index, color);
}
// gameState.bricks[index] = color;
});
}
ball.hitItem = [];
@ -1455,10 +1468,9 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
const hitBrick = vhit ?? hhit ?? chit;
if (typeof hitBrick !== "undefined") {
let sturdyBounce =
gameState.bricks[hitBrick] !== "black" &&
gameState.perks.sturdy_bricks &&
gameState.perks.sturdy_bricks > Math.random() * 5;
// TODO higher damage balls
gameState.brickHP[hitBrick]--
let sturdyBounce = gameState.brickHP[hitBrick]
ball.hitSinceBounce++;
let pierce = false;
@ -1494,7 +1506,7 @@ export function ballTick(gameState: GameState, ball: Ball, delta: number) {
initialBrickColor !== "black" && // don't replace a brick that bounced with sturdy_bricks
!gameState.bricks[hitBrick]
) {
gameState.bricks[hitBrick] = "black";
setBrick(gameState, hitBrick, "black")
ball.sapperUses++;
}
}

View file

@ -57,6 +57,7 @@ export function newGameState(params: RunParams): GameState {
balls: [],
ballsColor: "white",
bricks: [],
brickHP: [],
lights: { indexMin: 0, total: 0, list: [] },
particles: { indexMin: 0, total: 0, list: [] },
texts: { indexMin: 0, total: 0, list: [] },

View file

@ -398,7 +398,8 @@ export function renderAllBricks() {
"_" +
gameState.ballsColor +
"_" +
gameState.perks.pierce_color;
gameState.perks.pierce_color +
"_"+ gameState.brickHP.reduce((a,b)=>a+b,0);
if (newKey !== cachedBricksRenderKey) {
cachedBricksRenderKey = newKey;
@ -427,7 +428,12 @@ export function renderAllBricks() {
redBorderOnBricksWithWrongColor) ||
redBecauseOfReach;
canctx.globalCompositeOperation = "source-over";
drawBrick(canctx, color, (redBorder && "red") || color, x, y);
if(gameState.brickHP[index]>1){
canctx.globalCompositeOperation="destination-out"
drawText(canctx, gameState.brickHP[index].toString(), "white", gameState.puckHeight, x,y )
}
if (color === "black") {
canctx.globalCompositeOperation = "source-over";

2
src/types.d.ts vendored
View file

@ -226,6 +226,8 @@ export type GameState = {
ballsColor: colorString;
// Array of bricks to display. 'black' means bomb. '' means no brick.
bricks: colorString[];
// Number of times a brick has been hit already
brickHP: number[];
particles: ReusableArray<ParticleFlash>;
texts: ReusableArray<TextFlash>;