Build 29073274

This commit is contained in:
Renan LE CARO 2025-04-11 20:34:51 +02:00
parent a8e9fc6cb6
commit 613b7cce58
13 changed files with 2680 additions and 2648 deletions

View file

@ -29,8 +29,8 @@ android {
applicationId = "me.lecaro.breakout" applicationId = "me.lecaro.breakout"
minSdk = 21 minSdk = 21
targetSdk = 34 targetSdk = 34
versionCode = 29072514 versionCode = 29073274
versionName = "29072514" versionName = "29073274"
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

7
dist/index.html vendored

File diff suppressed because one or more lines are too long

View file

@ -1,5 +1,5 @@
// The version of the cache. // The version of the cache.
const VERSION = "29072514"; const VERSION = "29073274";
// The name of the cache // The name of the cache
const CACHE_NAME = `breakout-71-${VERSION}`; const CACHE_NAME = `breakout-71-${VERSION}`;

View file

@ -1 +1 @@
"29072514" "29073274"

View file

@ -135,14 +135,14 @@ export function pause(playerAskedForPause: boolean) {
} }
export const fitSize = (gameState: GameState) => { export const fitSize = (gameState: GameState) => {
if(!gameState) throw new Error("Missign game state") if (!gameState) throw new Error("Missign game state");
const past_off = gameState.offsetXRoundedDown, const past_off = gameState.offsetXRoundedDown,
past_width = gameState.gameZoneWidthRoundedUp, past_width = gameState.gameZoneWidthRoundedUp,
past_heigh = gameState.gameZoneHeight; past_heigh = gameState.gameZoneHeight;
const width= window.innerWidth, height=window.innerHeight const width = window.innerWidth,
height = window.innerHeight;
console.log('fitSize',width, height)
gameState.canvasWidth = width; gameState.canvasWidth = width;
gameState.canvasHeight = height; gameState.canvasHeight = height;
gameCanvas.width = width; gameCanvas.width = width;
@ -153,21 +153,36 @@ export const fitSize = (gameState:GameState) => {
haloCanvas.height = height / haloScale; haloCanvas.height = height / haloScale;
gameState.gameZoneHeight = isOptionOn("mobile-mode") gameState.gameZoneHeight = isOptionOn("mobile-mode")
? Math.floor(height * .80) : height; ? Math.floor(height * 0.8)
: height;
const baseWidth = Math.round( const baseWidth = Math.round(
Math.min(gameState.canvasWidth , gameState.gameZoneHeight * (0.73 )* (gameState.gridSize+gameState.perks.unbounded*2 ) / gameState.gridSize), Math.min(
gameState.canvasWidth,
(gameState.gameZoneHeight *
0.73 *
(gameState.gridSize + gameState.perks.unbounded * 2)) /
gameState.gridSize,
),
); );
gameState.brickWidth = Math.floor(baseWidth / (gameState.gridSize+gameState.perks.unbounded*2) / 2) * 2; gameState.brickWidth =
Math.floor(
baseWidth / (gameState.gridSize + gameState.perks.unbounded * 2) / 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,
); );
// Space between left side and border // Space between left side and border
gameState.offsetXRoundedDown = gameState.offsetX - gameState.perks.unbounded*gameState.brickWidth; gameState.offsetXRoundedDown =
if (gameState.offsetX < gameState.ballSize+gameState.perks.unbounded*2*gameState.brickWidth) gameState.offsetXRoundedDown = 0; gameState.offsetX - gameState.perks.unbounded * gameState.brickWidth;
if (
gameState.offsetX <
gameState.ballSize + gameState.perks.unbounded * 2 * gameState.brickWidth
)
gameState.offsetXRoundedDown = 0;
gameState.gameZoneWidthRoundedUp = width - 2 * gameState.offsetXRoundedDown; gameState.gameZoneWidthRoundedUp = width - 2 * gameState.offsetXRoundedDown;
backgroundCanvas.title = "resized"; backgroundCanvas.title = "resized";
// Ensure puck stays within bounds // Ensure puck stays within bounds
@ -717,10 +732,7 @@ async function openSettingsMenu() {
} catch (e: any) { } catch (e: any) {
await asyncAlert({ await asyncAlert({
title: t("settings.save_file_error"), title: t("settings.save_file_error"),
content: [ content: [e.message, { text: t("settings.save_file_loaded_ok") }],
e.message,
{ text: t("settings.save_file_loaded_ok") },
],
}); });
} }
input.value = ""; input.value = "";
@ -986,17 +998,20 @@ export function restart(params: RunParams) {
setLevel(gameState, 0); setLevel(gameState, 0);
} }
restart(window.location.search.includes('stress')?{ restart(
window.location.search.includes("stress")
? {
perks: { perks: {
bricks_attract_ball: 2, bricks_attract_ball: 2,
superhot: 1, superhot: 1,
bricks_attract_coins: 3, bricks_attract_coins: 3,
hot_start: 3, hot_start: 3,
pierce: 3, pierce: 3,
rainbow:3 rainbow: 3,
},
} }
}:{}); : {},
);
tick(); tick();
setupTooltips(); setupTooltips();

View file

@ -36,7 +36,15 @@ 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 {brickIndex, fitSize, gameState, hasBrick, hitsSomething, openUpgradesPicker, pause,} from "./game"; import {
brickIndex,
fitSize,
gameState,
hasBrick,
hitsSomething,
openUpgradesPicker,
pause,
} from "./game";
import { stopRecording } from "./recording"; import { stopRecording } from "./recording";
import { isOptionOn } from "./options"; import { isOptionOn } from "./options";
import { clamp, comboKeepingRate } from "./pure_functions"; import { clamp, comboKeepingRate } from "./pure_functions";
@ -128,13 +136,13 @@ export function normalizeGameState(gameState: GameState) {
), ),
); );
const corner =
(gameState.levelTime
? gameState.perks.corner_shot * gameState.puckWidth
: 0) -
gameState.perks.unbounded * gameState.brickWidth;
const corner = (gameState.levelTime ? gameState.perks.corner_shot * gameState.puckWidth : 0) - gameState.perks.unbounded * gameState.brickWidth; let minX = gameState.offsetXRoundedDown + gameState.puckWidth / 2 - corner;
let minX =
gameState.offsetXRoundedDown +
gameState.puckWidth / 2 -
corner;
let maxX = let maxX =
gameState.offsetXRoundedDown + gameState.offsetXRoundedDown +
@ -904,9 +912,7 @@ export function bordersHitCheck(
let vhit = 0, let vhit = 0,
hhit = 0; hhit = 0;
if ( if (coin.x < gameState.offsetXRoundedDown + radius) {
coin.x < gameState.offsetXRoundedDown + radius
) {
coin.x = coin.x =
gameState.offsetXRoundedDown + gameState.offsetXRoundedDown +
radius + radius +
@ -919,9 +925,7 @@ export function bordersHitCheck(
coin.vy *= -1; coin.vy *= -1;
vhit = 1; vhit = 1;
} }
if ( if (coin.x > gameState.canvasWidth - gameState.offsetXRoundedDown - radius) {
coin.x > gameState.canvasWidth - gameState.offsetXRoundedDown - radius
) {
coin.x = coin.x =
gameState.canvasWidth - gameState.canvasWidth -
gameState.offsetXRoundedDown - gameState.offsetXRoundedDown -
@ -1093,7 +1097,13 @@ export function gameStateTick(
} }
if (gameState.perks.bricks_attract_coins) { if (gameState.perks.bricks_attract_coins) {
goToNearestBrick(gameState, coin, gameState.perks.bricks_attract_coins * frames, 2,false) goToNearestBrick(
gameState,
coin,
gameState.perks.bricks_attract_coins * frames,
2,
false,
);
} }
const ratio = const ratio =
@ -1473,8 +1483,13 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
} }
if (ball.hitSinceBounce < gameState.perks.bricks_attract_ball * 3) { if (ball.hitSinceBounce < gameState.perks.bricks_attract_ball * 3) {
goToNearestBrick(gameState, ball, gameState.perks.bricks_attract_ball * frames * 0.2, goToNearestBrick(
2 + gameState.perks.bricks_attract_ball,Math.random()<0.5*frames) gameState,
ball,
gameState.perks.bricks_attract_ball * frames * 0.2,
2 + gameState.perks.bricks_attract_ball,
Math.random() < 0.5 * frames,
);
} }
if ( if (
@ -1637,7 +1652,8 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
} }
if ( if (
gameState.running && (ball.y > gameState.gameZoneHeight + gameState.ballSize / 2) gameState.running &&
ball.y > gameState.gameZoneHeight + gameState.ballSize / 2
) { ) {
ball.destroyed = true; ball.destroyed = true;
gameState.runStatistics.balls_lost++; gameState.runStatistics.balls_lost++;
@ -1961,43 +1977,53 @@ export function forEachLiveOne<T>(
}); });
} }
function goToNearestBrick(gameState: GameState, coin: Ball | Coin, strength, size = 2, particle=false) { function goToNearestBrick(
gameState: GameState,
coin: Ball | Coin,
strength,
size = 2,
particle = false,
) {
const row = Math.floor(coin.y / gameState.brickWidth); const row = Math.floor(coin.y / gameState.brickWidth);
const col = Math.floor( const col = Math.floor((coin.x - gameState.offsetX) / gameState.brickWidth);
(coin.x - gameState.offsetX) / gameState.brickWidth, let vx = 0,
); vy = 0;
let vx = 0, vy = 0
for (let dcol = -size; dcol < size; dcol++) { for (let dcol = -size; dcol < size; dcol++) {
for (let drow = -size; drow < size; drow++) { for (let drow = -size; drow < size; drow++) {
const index = getRowColIndex(gameState, row + drow, col + dcol); const index = getRowColIndex(gameState, row + drow, col + dcol);
if (gameState.bricks[index]) { if (gameState.bricks[index]) {
const dx = const dx =
brickCenterX(gameState, index) + brickCenterX(gameState, index) +
clamp(-dcol, -1, 1) * gameState.brickWidth / 2 - (clamp(-dcol, -1, 1) * gameState.brickWidth) / 2 -
coin.x; coin.x;
const dy = const dy =
brickCenterY(gameState, index) + brickCenterY(gameState, index) +
clamp(-drow, -1, 1) * gameState.brickWidth / 2 - (clamp(-drow, -1, 1) * gameState.brickWidth) / 2 -
coin.y; coin.y;
const d2 = dx * dx + dy * dy; const d2 = dx * dx + dy * dy;
vx += (dx / d2) * 20 vx += (dx / d2) * 20;
vy += (dy / d2) * 20 vy += (dy / d2) * 20;
} }
} }
} }
coin.vx += vx * strength;
coin.vx += vx * strength coin.vy += vy * strength;
coin.vy += vy * strength const s2 = coin.vx * coin.vx + coin.vy * coin.vy;
const s2 = coin.vx * coin.vx + coin.vy * coin.vy
if (s2 > gameState.baseSpeed * gameState.baseSpeed * 2) { if (s2 > gameState.baseSpeed * gameState.baseSpeed * 2) {
coin.vx *= 0.95 coin.vx *= 0.95;
coin.vy *= 0.95 coin.vy *= 0.95;
} }
if ((vx || vy) && particle) { if ((vx || vy) && particle) {
makeParticle(gameState, coin.x, coin.y, -vx*2,-vy*2, rainbowColor(), true) makeParticle(
gameState,
coin.x,
coin.y,
-vx * 2,
-vy * 2,
rainbowColor(),
true,
);
} }
} }

View file

@ -447,15 +447,11 @@ export function render(gameState: GameState) {
ctx.globalAlpha = 1; ctx.globalAlpha = 1;
let redLeftSide = let redLeftSide =
hasCombo && hasCombo && (gameState.perks.left_is_lava || gameState.perks.trampoline);
(gameState.perks.left_is_lava || gameState.perks.trampoline);
let redRightSide = let redRightSide =
hasCombo && hasCombo && (gameState.perks.right_is_lava || gameState.perks.trampoline);
(gameState.perks.right_is_lava || gameState.perks.trampoline);
let redTop = let redTop =
hasCombo && hasCombo && (gameState.perks.top_is_lava || gameState.perks.trampoline);
(gameState.perks.top_is_lava || gameState.perks.trampoline);
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
@ -466,7 +462,8 @@ export function render(gameState: GameState) {
gameState.offsetXRoundedDown - 1, gameState.offsetXRoundedDown - 1,
0, 0,
gameState.offsetXRoundedDown - 1, gameState.offsetXRoundedDown - 1,
height, 1, height,
1,
); );
drawStraightLine( drawStraightLine(

View file

@ -27,8 +27,7 @@ export function isBlackListedForStart(u: Upgrade) {
} }
export function isStartingPerk(u: Upgrade): boolean { export function isStartingPerk(u: Upgrade): boolean {
return ( return (
!isBlackListedForStart(u) && !isBlackListedForStart(u) && getSettingValue("start_with_" + u.id, u.gift)
getSettingValue("start_with_" + u.id, u.gift)
); );
} }

View file

@ -3,7 +3,6 @@ import {t} from "./i18n/i18n";
import { comboKeepingRate } from "./pure_functions"; import { comboKeepingRate } from "./pure_functions";
import { PerkId } from "./types"; import { PerkId } from "./types";
// Those perks are excluded from creative mode // Those perks are excluded from creative mode
export const noCreative: PerkId[] = [ export const noCreative: PerkId[] = [
"extra_levels", "extra_levels",
@ -12,12 +11,8 @@ export const noCreative: PerkId[] = [
"instant_upgrade", "instant_upgrade",
]; ];
// Those perks are excluded from the starting perks list // Those perks are excluded from the starting perks list
export const notStartingPerk: PerkId[] = [ export const notStartingPerk: PerkId[] = ["instant_upgrade"];
"instant_upgrade",
];
export const rawUpgrades = [ export const rawUpgrades = [
{ {
@ -825,7 +820,8 @@ export const rawUpgrades = [
id: "bricks_attract_ball", id: "bricks_attract_ball",
max: 3, max: 3,
name: t("upgrades.bricks_attract_ball.name"), name: t("upgrades.bricks_attract_ball.name"),
help: (lvl: number) => t("upgrades.bricks_attract_ball.tooltip", {count:lvl*3}), help: (lvl: number) =>
t("upgrades.bricks_attract_ball.tooltip", { count: lvl * 3 }),
fullHelp: t("upgrades.bricks_attract_ball.verbose_description"), fullHelp: t("upgrades.bricks_attract_ball.verbose_description"),
}, },
] as const; ] as const;