This commit is contained in:
Renan LE CARO 2025-03-19 21:58:50 +01:00
parent dce41a43ec
commit d2266de792
13 changed files with 2155 additions and 2103 deletions

View file

@ -11,8 +11,8 @@ android {
applicationId = "me.lecaro.breakout"
minSdk = 21
targetSdk = 34
versionCode = 29040074
versionName = "29040074"
versionCode = 29040298
versionName = "29040298"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true

File diff suppressed because one or more lines are too long

6
dist/index.html vendored
View file

@ -1270,7 +1270,7 @@ const upgrades = (0, _upgrades.rawUpgrades).map((u)=>({
}));
},{"./data/palette.json":"ktRBU","./data/levels.json":"8JSUc","./data/version.json":"iyP6E","./getLevelBackground":"7OIPf","./levelIcon":"6rQoT","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3","./upgrades":"1u3Dx"}],"iyP6E":[function(require,module,exports,__globalThis) {
module.exports = JSON.parse("\"29040074\"");
module.exports = JSON.parse("\"29040298\"");
},{}],"6rQoT":[function(require,module,exports,__globalThis) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
@ -2402,7 +2402,7 @@ function spawnExplosion(gameState, count, x, y, color) {
for(let i = 0; i < count; i++)makeParticle(gameState, x + (Math.random() - 0.5) * gameState.brickWidth / 2, y + (Math.random() - 0.5) * gameState.brickWidth / 2, (Math.random() - 0.5) * 30, (Math.random() - 0.5) * 30, color, false);
}
function explosionAt(gameState, index, x, y, ball) {
if (gameState.bricks[index] == 'black') delete gameState.bricks[index];
if (gameState.bricks[index] == "black") delete gameState.bricks[index];
schedulGameSound(gameState, "explode", ball.x, 1);
const col = index % gameState.gridSize;
const row = Math.floor(index / gameState.gridSize);
@ -2710,7 +2710,7 @@ frames = 1) {
if (!gameState.perks.etherealcoins) {
const flip = gameState.perks.helium > 0 && Math.abs(coin.x - gameState.puckPosition) * 2 > gameState.puckWidth + coin.size;
coin.vy += frames * coin.weight * 0.8 * (flip ? -1 : 1);
if (flip && !(0, _options.isOptionOn)('basic') && Math.random() < 0.1) makeParticle(gameState, coin.x, coin.y, 0, gameState.baseSpeed, rainbowColor(), true, 5, 250);
if (flip && !(0, _options.isOptionOn)("basic") && Math.random() < 0.1) makeParticle(gameState, coin.x, coin.y, 0, gameState.baseSpeed, rainbowColor(), true, 5, 250);
}
const speed = Math.abs(coin.sx) + Math.abs(coin.sx);
const hitBorder = bordersHitCheck(gameState, coin, coin.size / 2, frames);

View file

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

View file

@ -1 +1 @@
"29040074"
"29040298"

View file

@ -1,4 +1,4 @@
import {allLevels, appVersion, icons, upgrades} from "./loadGameData";
import { allLevels, appVersion, icons, upgrades } from "./loadGameData";
import {
Ball,
Coin,
@ -11,12 +11,17 @@ import {
TextFlash,
Upgrade,
} from "./types";
import {getAudioContext, playPendingSounds} from "./sounds";
import {currentLevelInfo, getRowColIndex, max_levels, pickedUpgradesHTMl,} from "./game_utils";
import { getAudioContext, playPendingSounds } from "./sounds";
import {
currentLevelInfo,
getRowColIndex,
max_levels,
pickedUpgradesHTMl,
} from "./game_utils";
import "./PWA/sw_loader";
import {getCurrentLang, t} from "./i18n/i18n";
import {getSettingValue, getTotalScore, setSettingValue} from "./settings";
import { getCurrentLang, t } from "./i18n/i18n";
import { getSettingValue, getTotalScore, setSettingValue } from "./settings";
import {
forEachLiveOne,
gameStateTick,
@ -25,12 +30,28 @@ import {
setLevel,
setMousePos,
} from "./gameStateMutators";
import {backgroundCanvas, ctx, gameCanvas, render, scoreDisplay,} from "./render";
import {pauseRecording, recordOneFrame, resumeRecording, startRecordingGame,} from "./recording";
import {newGameState} from "./newGameState";
import {alertsOpen, asyncAlert, AsyncAlertAction, closeModal,} from "./asyncAlert";
import {isOptionOn, options, toggleOption} from "./options";
import {hashCode} from "./getLevelBackground";
import {
backgroundCanvas,
ctx,
gameCanvas,
render,
scoreDisplay,
} from "./render";
import {
pauseRecording,
recordOneFrame,
resumeRecording,
startRecordingGame,
} from "./recording";
import { newGameState } from "./newGameState";
import {
alertsOpen,
asyncAlert,
AsyncAlertAction,
closeModal,
} from "./asyncAlert";
import { isOptionOn, options, toggleOption } from "./options";
import { hashCode } from "./getLevelBackground";
export function play() {
if (gameState.running) return;
@ -406,8 +427,7 @@ async function openScorePanel() {
async function openSettingsPanel() {
pause(true);
const actions: AsyncAlertAction<() => void>[] = [
];
const actions: AsyncAlertAction<() => void>[] = [];
for (const key of Object.keys(options) as OptionId[]) {
if (options[key])
@ -449,21 +469,18 @@ async function openSettingsPanel() {
});
}
}
actions.push(
{
text: t("main_menu.resume"),
help: t("main_menu.resume_help"),
value() {},
})
actions.push({
text: t("main_menu.unlocks"),
help: t("main_menu.unlocks_help"),
value() {
openUnlocksList();
},
})
text: t("main_menu.resume"),
help: t("main_menu.resume_help"),
value() {},
});
actions.push({
text: t("main_menu.unlocks"),
help: t("main_menu.unlocks_help"),
value() {
openUnlocksList();
},
});
actions.push({
text: t("sandbox.title"),

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
import {Ball, GameState, PerkId, PerksMap} from "./types";
import {icons, upgrades} from "./loadGameData";
import { Ball, GameState, PerkId, PerksMap } from "./types";
import { icons, upgrades } from "./loadGameData";
export function getMajorityValue(arr: string[]): string {
const count: { [k: string]: number } = {};
@ -72,10 +72,10 @@ export function currentLevelInfo(gameState: GameState) {
}
export function isTelekinesisActive(gameState: GameState, ball: Ball) {
return gameState.perks.telekinesis && ball.vy < 0;
return gameState.perks.telekinesis && ball.vy < 0;
}
export function isYoyoActive(gameState: GameState, ball: Ball) {
return gameState.perks.yoyo && ball.vy > 0;
return gameState.perks.yoyo && ball.vy > 0;
}
export function findLast<T>(
@ -103,9 +103,8 @@ export function distanceBetween(
return Math.sqrt(distance2(a, b));
}
export function clamp(value, min, max){
return Math.max(min, Math.min(value, max))
export function clamp(value: number, min: number, max: number) {
return Math.max(min, Math.min(value, max));
}
export function defaultSounds() {
return {
@ -123,29 +122,29 @@ export function defaultSounds() {
}
export function shouldPierceByColor(
gameState: GameState,
vhit: number | undefined,
hhit: number | undefined,
chit: number | undefined,
gameState: GameState,
vhit: number | undefined,
hhit: number | undefined,
chit: number | undefined,
) {
if (!gameState.perks.pierce_color) return false;
if (
typeof vhit !== "undefined" &&
gameState.bricks[vhit] !== gameState.ballsColor
) {
return false;
}
if (
typeof hhit !== "undefined" &&
gameState.bricks[hhit] !== gameState.ballsColor
) {
return false;
}
if (
typeof chit !== "undefined" &&
gameState.bricks[chit] !== gameState.ballsColor
) {
return false;
}
return true;
if (!gameState.perks.pierce_color) return false;
if (
typeof vhit !== "undefined" &&
gameState.bricks[vhit] !== gameState.ballsColor
) {
return false;
}
if (
typeof hhit !== "undefined" &&
gameState.bricks[hhit] !== gameState.ballsColor
) {
return false;
}
if (
typeof chit !== "undefined" &&
gameState.bricks[chit] !== gameState.ballsColor
) {
return false;
}
return true;
}

File diff suppressed because it is too large Load diff

2
src/types.d.ts vendored
View file

@ -244,7 +244,7 @@ export type GameState = {
runStatistics: RunStats;
lastOffered: Partial<{ [k in PerkId]: number }>;
levelTime: number;
noBricksSince: number ;
noBricksSince: number;
levelWallBounces: number;
autoCleanUses: number;
aboutToPlaySound: {

View file

@ -1,11 +1,11 @@
import _rawLevelsList from "./data/levels.json";
import {rawUpgrades} from "./upgrades";
import { rawUpgrades } from "./upgrades";
describe("rawUpgrades", ()=>{
it('has an icon for each upgrade',()=>{
const missingIcon = rawUpgrades.map(u=>u.id).filter(id=>!_rawLevelsList.find(l=>l.name === 'icon:'+id))
expect(missingIcon.join(', ')).toEqual('')
})
})
describe("rawUpgrades", () => {
it("has an icon for each upgrade", () => {
const missingIcon = rawUpgrades
.map((u) => u.id)
.filter((id) => !_rawLevelsList.find((l) => l.name === "icon:" + id));
expect(missingIcon.join(", ")).toEqual("");
});
});

View file

@ -383,7 +383,7 @@ export const rawUpgrades = [
},
{
requires: "",
threshold:70000,
threshold: 70000,
giftable: false,
id: "asceticism",
max: 1,
@ -393,7 +393,7 @@ export const rawUpgrades = [
},
{
requires: "",
threshold:75000,
threshold: 75000,
giftable: false,
id: "unbounded",
max: 1,
@ -403,7 +403,7 @@ export const rawUpgrades = [
},
{
requires: "",
threshold:80000,
threshold: 80000,
giftable: false,
id: "shunt",
max: 1,
@ -413,7 +413,7 @@ export const rawUpgrades = [
},
{
requires: "",
threshold:85000,
threshold: 85000,
giftable: false,
id: "yoyo",
max: 2,
@ -423,17 +423,17 @@ export const rawUpgrades = [
},
{
requires: "",
threshold:90000,
threshold: 90000,
giftable: false,
id: "nbricks",
max: 3,
name: t("upgrades.nbricks.name"),
help: (lvl: number) => t("upgrades.nbricks.help",{lvl}),
help: (lvl: number) => t("upgrades.nbricks.help", { lvl }),
fullHelp: t("upgrades.nbricks.fullHelp"),
},
{
requires: "",
threshold:95000,
threshold: 95000,
giftable: false,
id: "etherealcoins",
max: 1,
@ -443,7 +443,7 @@ export const rawUpgrades = [
},
{
requires: "multiball",
threshold:100000,
threshold: 100000,
giftable: false,
id: "shocks",
max: 1,
@ -453,7 +453,7 @@ export const rawUpgrades = [
},
{
requires: "",
threshold:105000,
threshold: 105000,
giftable: false,
id: "zen",
max: 1,
@ -463,7 +463,7 @@ export const rawUpgrades = [
},
{
requires: "extra_life",
threshold:110000,
threshold: 110000,
giftable: false,
id: "sacrifice",
max: 1,
@ -474,27 +474,27 @@ export const rawUpgrades = [
{
requires: "",
threshold:115000,
threshold: 115000,
giftable: false,
id: "trampoline",
max: 3,
name: t("upgrades.trampoline.name"),
help: (lvl: number) => t("upgrades.trampoline.help",{lvl}),
help: (lvl: number) => t("upgrades.trampoline.help", { lvl }),
fullHelp: t("upgrades.trampoline.fullHelp"),
},
{
requires: "",
threshold:120000,
threshold: 120000,
giftable: false,
id: "ghost_coins",
max: 1,
name: t("upgrades.ghost_coins.name"),
help: (lvl: number) => t("upgrades.ghost_coins.help",{lvl}),
help: (lvl: number) => t("upgrades.ghost_coins.help", { lvl }),
fullHelp: t("upgrades.ghost_coins.fullHelp"),
},
{
requires: "",
threshold:125000,
threshold: 125000,
giftable: false,
id: "forgiving",
max: 1,
@ -504,7 +504,7 @@ export const rawUpgrades = [
},
{
requires: "",
threshold:130000,
threshold: 130000,
giftable: false,
id: "ball_attracts_coins",
max: 3,
@ -512,5 +512,4 @@ export const rawUpgrades = [
help: (lvl: number) => t("upgrades.ball_attracts_coins.help"),
fullHelp: t("upgrades.ball_attracts_coins.fullHelp"),
},
] as const;