mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-22 21:16:14 -04:00
wip
This commit is contained in:
parent
530e94f704
commit
d43dd90a86
23 changed files with 268 additions and 152 deletions
|
@ -1,5 +1,5 @@
|
|||
// The version of the cache.
|
||||
const VERSION = "29080170";
|
||||
const VERSION = "29083143";
|
||||
|
||||
// The name of the cache
|
||||
const CACHE_NAME = `breakout-71-${VERSION}`;
|
||||
|
|
|
@ -98,7 +98,11 @@ export async function openCreativeModePerksPicker() {
|
|||
} else if ("bricks" in choice) {
|
||||
setSettingValue("creativeModePerks", creativeModePerks);
|
||||
if (await confirmRestart(gameState)) {
|
||||
restart({ perks: creativeModePerks, level: choice });
|
||||
restart({
|
||||
perks: creativeModePerks,
|
||||
level: choice,
|
||||
isCreativeRun: true,
|
||||
});
|
||||
}
|
||||
return;
|
||||
} else if (choice) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
"29080170"
|
||||
"29083143"
|
||||
|
|
15
src/game.ts
15
src/game.ts
|
@ -113,7 +113,7 @@ export async function play() {
|
|||
export function pause(playerAskedForPause: boolean) {
|
||||
if (!gameState.running) return;
|
||||
if (gameState.pauseTimeout) return;
|
||||
if (gameState.computer_controlled) return;
|
||||
if (gameState.startParams.computer_controlled) return;
|
||||
|
||||
const stop = () => {
|
||||
gameState.running = false;
|
||||
|
@ -451,7 +451,8 @@ export function tick() {
|
|||
if (gameState.running) {
|
||||
gameState.levelTime += timeDeltaMs * frames;
|
||||
gameState.runStatistics.runTime += timeDeltaMs * frames;
|
||||
gameStateTick(gameState, frames);
|
||||
const steps = isOptionOn("precise_physics") ? 4 : 1;
|
||||
for (let i = 0; i < steps; i++) gameStateTick(gameState, frames / steps);
|
||||
}
|
||||
|
||||
if (gameState.running || gameState.needsRender) {
|
||||
|
@ -665,13 +666,14 @@ async function openSettingsMenu() {
|
|||
},
|
||||
});
|
||||
for (const key of Object.keys(options) as OptionId[]) {
|
||||
if (options[key])
|
||||
if (options[key]) {
|
||||
actions.push({
|
||||
icon: isOptionOn(key)
|
||||
? icons["icon:checkmark_checked"]
|
||||
: icons["icon:checkmark_unchecked"],
|
||||
? icons["icon:checkmark_checked"]
|
||||
: icons["icon:checkmark_unchecked"],
|
||||
text: options[key].name,
|
||||
help: options[key].help,
|
||||
disabled : (key=='extra_bright' && isOptionOn('basic')) || (key=='contrast' && isOptionOn('basic')) || false,
|
||||
value: () => {
|
||||
toggleOption(key);
|
||||
fitSize(gameState);
|
||||
|
@ -679,6 +681,7 @@ async function openSettingsMenu() {
|
|||
openSettingsMenu();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
actions.push({
|
||||
icon: icons["icon:download"],
|
||||
|
@ -1030,7 +1033,7 @@ document.addEventListener("keyup", async (e) => {
|
|||
!alertsOpen &&
|
||||
pageLoad < Date.now() - 500
|
||||
) {
|
||||
if (gameState.computer_controlled) {
|
||||
if (gameState.startParams.computer_controlled) {
|
||||
return startComputerControlledGame();
|
||||
}
|
||||
// When doing ctrl + R in dev to refresh, i don't want to instantly restart a run
|
||||
|
|
|
@ -15,6 +15,7 @@ import { asyncAlert } from "./asyncAlert";
|
|||
import { rawUpgrades } from "./upgrades";
|
||||
import { run } from "jest";
|
||||
import { editRawLevelList } from "./levelEditor";
|
||||
import { openCreativeModePerksPicker } from "./creative";
|
||||
|
||||
export function addToTotalPlayTime(ms: number) {
|
||||
setSettingValue(
|
||||
|
@ -32,8 +33,14 @@ export function gameOver(title: string, intro: string) {
|
|||
stopRecording();
|
||||
addToTotalPlayTime(gameState.runStatistics.runTime);
|
||||
|
||||
if (typeof gameState.isEditorTrialRun === "number") {
|
||||
editRawLevelList(gameState.isEditorTrialRun);
|
||||
if (typeof gameState.startParams.isEditorTrialRun === "number") {
|
||||
editRawLevelList(gameState.startParams.isEditorTrialRun);
|
||||
restart({});
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof gameState.startParams.isCreativeRun) {
|
||||
openCreativeModePerksPicker();
|
||||
restart({});
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ import { addToTotalScore } from "./addToTotalScore";
|
|||
import { hashCode } from "./getLevelBackground";
|
||||
|
||||
export function setMousePos(gameState: GameState, x: number) {
|
||||
if (gameState.computer_controlled) return;
|
||||
if (gameState.startParams.computer_controlled) return;
|
||||
gameState.puckPosition = x;
|
||||
|
||||
// Sets the puck position, and updates the ball position if they are supposed to follow it
|
||||
|
@ -638,7 +638,7 @@ export function schedulGameSound(
|
|||
) {
|
||||
if (!vol) return;
|
||||
if (!isOptionOn("sound")) return;
|
||||
if (gameState.computer_controlled) return;
|
||||
if (gameState.startParams.computer_controlled) return;
|
||||
x ??= gameState.offsetX + gameState.gameZoneWidth / 2;
|
||||
const ex = gameState.aboutToPlaySound[sound] as { vol: number; x: number };
|
||||
|
||||
|
@ -991,7 +991,7 @@ export function gameStateTick(
|
|||
frames = 1,
|
||||
) {
|
||||
// Ai movement of puck
|
||||
if (gameState.computer_controlled) computerControl(gameState);
|
||||
if (gameState.startParams.computer_controlled) computerControl(gameState);
|
||||
|
||||
gameState.runStatistics.max_combo = Math.max(
|
||||
gameState.runStatistics.max_combo,
|
||||
|
@ -1067,7 +1067,7 @@ export function gameStateTick(
|
|||
// instant win condition
|
||||
(gameState.levelTime && !remainingBricks && !liveCount(gameState.coins))
|
||||
) {
|
||||
if (gameState.computer_controlled) {
|
||||
if (gameState.startParams.computer_controlled) {
|
||||
startComputerControlledGame();
|
||||
} else if (gameState.currentLevel + 1 < max_levels(gameState)) {
|
||||
setLevel(gameState, gameState.currentLevel + 1);
|
||||
|
@ -1737,7 +1737,7 @@ export function ballTick(gameState: GameState, ball: Ball, frames: number) {
|
|||
ball.destroyed = true;
|
||||
gameState.runStatistics.balls_lost++;
|
||||
if (!gameState.balls.find((b) => !b.destroyed)) {
|
||||
if (gameState.computer_controlled) {
|
||||
if (gameState.startParams.computer_controlled) {
|
||||
startComputerControlledGame();
|
||||
} else {
|
||||
gameOver(
|
||||
|
|
|
@ -319,7 +319,6 @@ function isExcluded(id: PerkId) {
|
|||
}
|
||||
|
||||
export function getLevelUnlockCondition(levelIndex: number) {
|
||||
// Returns "" if level is unlocked, otherwise a string explaining how to unlock it
|
||||
let required: UpgradeLike[] = [],
|
||||
forbidden: UpgradeLike[] = [],
|
||||
minScore = Math.max(-1000 + 100 * levelIndex, 0);
|
||||
|
|
|
@ -190,6 +190,8 @@
|
|||
"settings.mobile_help": "يترك مساحة تحت المجداف.",
|
||||
"settings.pointer_lock": "قفل مؤشر الماوس",
|
||||
"settings.pointer_lock_help": "يقوم بقفل وإخفاء مؤشر الماوس.",
|
||||
"settings.precise_physics": "",
|
||||
"settings.precise_physics_help": "",
|
||||
"settings.record": "تسجيل مقاطع فيديو للعبة",
|
||||
"settings.record_download": "تنزيل الفيديو ({{size}} ميجابايت)",
|
||||
"settings.record_help": "احصل على فيديو لكل مستوى.",
|
||||
|
|
|
@ -6787,6 +6787,76 @@
|
|||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>precise_physics</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>ar-LB</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>de-DE</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-CL</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>ru-RU</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>tr-TR</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>precise_physics_help</name>
|
||||
<description/>
|
||||
<comment/>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>ar-LB</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>de-DE</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-CL</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-FR</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>ru-RU</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>tr-TR</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>record</name>
|
||||
<description/>
|
||||
|
|
|
@ -190,6 +190,8 @@
|
|||
"settings.mobile_help": "Lässt Platz unter dem Paddel.",
|
||||
"settings.pointer_lock": "Mauszeigersperre",
|
||||
"settings.pointer_lock_help": "Sperrt und versteckt den Mauszeiger.",
|
||||
"settings.precise_physics": "",
|
||||
"settings.precise_physics_help": "",
|
||||
"settings.record": "Spielvideos aufnehmen",
|
||||
"settings.record_download": "Video herunterladen ({{size}} MB)",
|
||||
"settings.record_help": "Holen Sie sich ein Video von jedem Level.",
|
||||
|
|
|
@ -190,6 +190,8 @@
|
|||
"settings.mobile_help": "Leaves space under the paddle.",
|
||||
"settings.pointer_lock": "Mouse pointer lock",
|
||||
"settings.pointer_lock_help": "Locks and hides the mouse cursor.",
|
||||
"settings.precise_physics": "More precise physics",
|
||||
"settings.precise_physics_help": "Compute fast ball motion in smaller steps, might reduce performance",
|
||||
"settings.record": "Record gameplay videos",
|
||||
"settings.record_download": "Download video ({{size}} MB)",
|
||||
"settings.record_help": "Get a video of each level.",
|
||||
|
|
|
@ -190,6 +190,8 @@
|
|||
"settings.mobile_help": "Deja espacio debajo de la paleta.",
|
||||
"settings.pointer_lock": "Bloqueo del puntero del ratón",
|
||||
"settings.pointer_lock_help": "Bloquea y oculta el cursor del mouse.",
|
||||
"settings.precise_physics": "",
|
||||
"settings.precise_physics_help": "",
|
||||
"settings.record": "Grabar vídeos de juego",
|
||||
"settings.record_download": "Descargar vídeo ({{size}} MB)",
|
||||
"settings.record_help": "Obtenga un vídeo de cada nivel.",
|
||||
|
|
|
@ -190,6 +190,8 @@
|
|||
"settings.mobile_help": "Laisse un espace sous la raquette.",
|
||||
"settings.pointer_lock": "Verrouillage du pointeur",
|
||||
"settings.pointer_lock_help": "Cache aussi le curseur de la souris.",
|
||||
"settings.precise_physics": "",
|
||||
"settings.precise_physics_help": "",
|
||||
"settings.record": "Enregistrer des vidéos de jeu",
|
||||
"settings.record_download": "Télécharger la vidéo ({{size}} MB)",
|
||||
"settings.record_help": "Obtenez une vidéo de chaque niveau.",
|
||||
|
|
|
@ -190,6 +190,8 @@
|
|||
"settings.mobile_help": "Оставляет место под лопаткой.",
|
||||
"settings.pointer_lock": "Блокировка указателя мыши",
|
||||
"settings.pointer_lock_help": "Фиксирует и скрывает курсор мыши.",
|
||||
"settings.precise_physics": "",
|
||||
"settings.precise_physics_help": "",
|
||||
"settings.record": "Запись видеороликов игрового процесса",
|
||||
"settings.record_download": "Скачать видео ({{size}} МБ)",
|
||||
"settings.record_help": "Получите видеозапись каждого уровня.",
|
||||
|
|
|
@ -190,6 +190,8 @@
|
|||
"settings.mobile_help": "Kürek altında boşluk bırakır.",
|
||||
"settings.pointer_lock": "Fare işaretçisi kilidi",
|
||||
"settings.pointer_lock_help": "Fare imlecini kilitler ve gizler.",
|
||||
"settings.precise_physics": "",
|
||||
"settings.precise_physics_help": "",
|
||||
"settings.record": "Oyun videolarını kaydedin",
|
||||
"settings.record_download": "Videoyu indir ({{size}} MB)",
|
||||
"settings.record_help": "Her seviyenin videosunu edinin.",
|
||||
|
|
|
@ -65,6 +65,7 @@ export function newGameState(params: RunParams): GameState {
|
|||
const runLevels = getRunLevels(params, randomGift);
|
||||
|
||||
const gameState: GameState = {
|
||||
startParams: params,
|
||||
runLevels,
|
||||
level: runLevels[0],
|
||||
currentLevel: 0,
|
||||
|
@ -141,9 +142,7 @@ export function newGameState(params: RunParams): GameState {
|
|||
creative:
|
||||
params?.computer_controlled ||
|
||||
sumOfValues(params.perks) > 1 ||
|
||||
(params.level && !params.level.name.startsWith("icon:")),
|
||||
computer_controlled: params?.computer_controlled || false,
|
||||
isEditorTrialRun: params?.isEditorTrialRun,
|
||||
(params.level && !params.level.name.startsWith("icon:"))
|
||||
};
|
||||
resetBalls(gameState);
|
||||
|
||||
|
|
|
@ -55,6 +55,11 @@ export const options = {
|
|||
name: t("settings.kid"),
|
||||
help: t("settings.kid_help"),
|
||||
},
|
||||
precise_physics: {
|
||||
default: true,
|
||||
name: t("settings.precise_physics"),
|
||||
help: t("settings.precise_physics_help"),
|
||||
},
|
||||
// Could not get the sharing to work without loading androidx and all the modern android things so for now I'll just disable sharing in the android app
|
||||
record: {
|
||||
default: false,
|
||||
|
|
|
@ -75,7 +75,7 @@ export function render(gameState: GameState) {
|
|||
: 1;
|
||||
startWork("render:scoreDisplay");
|
||||
scoreDisplay.innerHTML =
|
||||
(isOptionOn("show_fps") || gameState.computer_controlled
|
||||
(isOptionOn("show_fps") || gameState.startParams.computer_controlled
|
||||
? `
|
||||
<span>
|
||||
${Math.floor((liveCount(gameState.coins) / getCurrentMaxCoins()) * 100)} %
|
||||
|
@ -105,7 +105,7 @@ export function render(gameState: GameState) {
|
|||
`<span class="score" data-tooltip="${t("play.score_tooltip")}">$${gameState.score}</span>`;
|
||||
|
||||
scoreDisplay.className =
|
||||
(gameState.computer_controlled && "computer_controlled") ||
|
||||
(gameState.startParams.computer_controlled && "computer_controlled") ||
|
||||
(gameState.lastScoreIncrease > gameState.levelTime - 500 && "active") ||
|
||||
"";
|
||||
// Clear
|
||||
|
@ -578,7 +578,7 @@ export function render(gameState: GameState) {
|
|||
startWork("render:text_under_puck");
|
||||
ctx.globalCompositeOperation = "source-over";
|
||||
ctx.globalAlpha = 1;
|
||||
if (isOptionOn("mobile-mode") && gameState.computer_controlled) {
|
||||
if (isOptionOn("mobile-mode") && gameState.startParams.computer_controlled) {
|
||||
drawText(
|
||||
ctx,
|
||||
"breakout.lecaro.me?autoplay",
|
||||
|
@ -1155,7 +1155,7 @@ export function getDashOffset(gameState: GameState) {
|
|||
let wakeLock = null,
|
||||
wakeLockPending = false;
|
||||
function askForWakeLock(gameState: GameState) {
|
||||
if (gameState.computer_controlled && !wakeLock && !wakeLockPending) {
|
||||
if (gameState.startParams.computer_controlled && !wakeLock && !wakeLockPending) {
|
||||
wakeLockPending = true;
|
||||
try {
|
||||
navigator.wakeLock.request("screen").then((lock) => {
|
||||
|
|
4
src/types.d.ts
vendored
4
src/types.d.ts
vendored
|
@ -281,8 +281,7 @@ export type GameState = {
|
|||
};
|
||||
rerolls: number;
|
||||
creative: boolean;
|
||||
computer_controlled: boolean;
|
||||
isEditorTrialRun?: number;
|
||||
startParams: RunParams;
|
||||
};
|
||||
|
||||
export type RunParams = {
|
||||
|
@ -292,6 +291,7 @@ export type RunParams = {
|
|||
perks?: Partial<PerksMap>;
|
||||
computer_controlled?: boolean;
|
||||
isEditorTrialRun?: number;
|
||||
isCreativeRun?: boolean;
|
||||
};
|
||||
export type OptionDef = {
|
||||
default: boolean;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue