This commit is contained in:
Renan LE CARO 2025-04-20 13:12:10 +02:00
parent 4d7d57f17f
commit b3949d8c41
11 changed files with 139 additions and 79 deletions

View file

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

File diff suppressed because one or more lines are too long

79
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.
const VERSION = "29085612";
const VERSION = "29085783";
// The name of the cache
const CACHE_NAME = `breakout-71-${VERSION}`;

View file

@ -1 +1 @@
"29085612"
"29085783"

View file

@ -37,7 +37,8 @@ import { getCurrentLang, languages, t } from "./i18n/i18n";
import {
commitSettingsChangesToLocalStorage,
cycleMaxCoins,
getCurrentMaxCoins, getCurrentMaxParticles,
getCurrentMaxCoins,
getCurrentMaxParticles,
getSettingValue,
getTotalScore,
setSettingValue,
@ -114,7 +115,7 @@ export function pause(playerAskedForPause: boolean) {
if (!gameState.running) return;
if (gameState.pauseTimeout) return;
if (gameState.startParams.computer_controlled) {
if (gameState.startParams?.computer_controlled) {
if (gameState.startParams?.computer_controlled) {
play();
}
return;
@ -496,7 +497,6 @@ export function startWork(what) {
doing = what;
}
setInterval(() => {
lastMeasuredFPS = FPSCounter;
FPSCounter = 0;
@ -512,7 +512,7 @@ setInterval(() => {
<div>
${lastMeasuredFPS} FPS -
${liveCount(gameState.coins)} / ${getCurrentMaxCoins()} Coins -
${liveCount(gameState.particles) + liveCount(gameState.lights) + liveCount(gameState.texts)} / ${getCurrentMaxParticles()*3} particles
${liveCount(gameState.particles) + liveCount(gameState.lights) + liveCount(gameState.texts)} / ${getCurrentMaxParticles() * 3} particles
</div>

View file

@ -9,7 +9,12 @@ import {
pickedUpgradesHTMl,
reasonLevelIsLocked,
} from "./game_utils";
import {askForPersistentStorage, getSettingValue, getTotalScore, setSettingValue} from "./settings";
import {
askForPersistentStorage,
getSettingValue,
getTotalScore,
setSettingValue,
} from "./settings";
import { stopRecording } from "./recording";
import { asyncAlert } from "./asyncAlert";
import { rawUpgrades } from "./upgrades";
@ -30,7 +35,7 @@ export function gameOver(title: string, intro: string) {
gameState.isGameOver = true;
pause(true);
askForPersistentStorage()
askForPersistentStorage();
stopRecording();
addToTotalPlayTime(gameState.runStatistics.runTime);

View file

@ -423,3 +423,4 @@ export function getCornerOffset(gameState: GameState) {
}
export const isInWebView = !!window.location.href.includes("isInWebView=true");
console.log({isInWebView})

View file

@ -4,6 +4,7 @@ import { getAudioRecordingTrack } from "./sounds";
import { t } from "./i18n/i18n";
import { GameState } from "./types";
import { isOptionOn } from "./options";
import { toast } from "./toast";
let mediaRecorder: MediaRecorder | null,
captureStream: MediaStream,
@ -12,7 +13,7 @@ let mediaRecorder: MediaRecorder | null,
recordCanvasCtx: CanvasRenderingContext2D;
export function recordOneFrame(gameState: GameState) {
if (!isOptionOn("record") ) {
if (!isOptionOn("record")) {
return;
}
// if (!gameState.running) return;
@ -59,7 +60,7 @@ export function drawMainCanvasOnSmallCanvas(gameState: GameState) {
}
export function startRecordingGame(gameState: GameState) {
if (!isOptionOn("record") ) {
if (!isOptionOn("record")) {
return;
}
if (mediaRecorder) return;
@ -107,6 +108,7 @@ export function startRecordingGame(gameState: GameState) {
) {
await new Promise((r) => setTimeout(r, 200));
}
const video = document.createElement("video");
video.autoplay = true;
video.controls = false;
@ -125,15 +127,38 @@ export function startRecordingGame(gameState: GameState) {
a.download = captureFileName("webm");
a.target = "_blank";
a.href = video.src;
if (isInWebView) {
a.href = await blobToBase64(blob);
} else {
a.href = video.src;
}
a.textContent = t("settings.record_download", {
size: (blob.size / 1000000).toFixed(2),
});
targetDiv.appendChild(a);
};
}
function blobToBase64(blob: Blob): Promise<string> {
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.onload = function () {
console.log(reader.result);
resolve(reader.result);
};
reader.onerror = function () {
const e = reader.error;
console.error(e);
toast(e?.message || "Failed to convert the video to a data url");
reject(new Error("Failed to readAsDataURL of the video "));
};
reader.readAsDataURL(blob);
});
}
export function pauseRecording() {
if (!isOptionOn("record")) {
return;

View file

@ -6,66 +6,72 @@ import {t} from "./i18n/i18n";
let cachedSettings: { [key: string]: unknown } = {};
try {
for (let key in localStorage) {
try {
cachedSettings[key] = JSON.parse(localStorage.getItem(key) || "null");
} catch (e) {
console.warn(e);
for (let key in localStorage) {
try {
cachedSettings[key] = JSON.parse(localStorage.getItem(key) || "null");
} catch (e) {
console.warn(e);
}
}
}
} catch (e) {
console.warn(e);
console.warn(e);
}
export function getSettingValue<T>(key: string, defaultValue: T) {
return (cachedSettings[key] as T) ?? defaultValue;
return (cachedSettings[key] as T) ?? defaultValue;
}
// We avoid using localstorage synchronously for perf reasons
let needsSaving: Set<string> = new Set();
export function setSettingValue<T>(key: string, value: T) {
needsSaving.add(key);
cachedSettings[key] = value;
needsSaving.add(key);
cachedSettings[key] = value;
}
export function commitSettingsChangesToLocalStorage() {
try {
for (let key of needsSaving) {
localStorage.setItem(key, JSON.stringify(cachedSettings[key]));
try {
for (let key of needsSaving) {
localStorage.setItem(key, JSON.stringify(cachedSettings[key]));
}
needsSaving.clear();
} catch (e) {
console.warn(e);
}
needsSaving.clear();
} catch (e) {
console.warn(e);
}
}
setInterval(() => commitSettingsChangesToLocalStorage(), 500);
export function getTotalScore() {
return getSettingValue("breakout_71_total_score", 0);
return getSettingValue("breakout_71_total_score", 0);
}
export function getCurrentMaxCoins() {
return Math.pow(2, getSettingValue("max_coins", 2)) * 200;
return Math.pow(2, getSettingValue("max_coins", 2)) * 200;
}
export function getCurrentMaxParticles() {
return getCurrentMaxCoins();
return getCurrentMaxCoins();
}
export function cycleMaxCoins() {
setSettingValue("max_coins", (getSettingValue("max_coins", 2) + 1) % 7);
setSettingValue("max_coins", (getSettingValue("max_coins", 2) + 1) % 7);
}
let asked=false
export function askForPersistentStorage(){
if(asked) return
asked=true
if (navigator.storage && navigator.storage.persist) {
navigator.storage.persist().then((persistent) => {
if (persistent) {
toast(t('settings.storage_granted'))
} else {
toast(t('settings.storage_refused'))
}
});
}
}
let asked = false;
export async function askForPersistentStorage() {
if (asked) return;
asked = true;
if (!navigator.storage) return
if (!navigator.storage.persist) return
if (!navigator.storage.persisted) return
if (await navigator.storage.persisted()) {
return
}
const persistent = await navigator.storage.persist()
if (!persistent) {
toast(t("settings.storage_refused"));
}
}

View file

@ -2,7 +2,7 @@ let div = document.createElement("div");
div.classList = "hidden toast";
document.body.appendChild(div);
let timeout: NodeJS.Timeout | undefined;
export function toast(html) {
export function toast(html: string) {
div.classList = "toast visible";
div.innerHTML = html;
if (timeout) {