mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-21 12:36:15 -04:00
Prob lighting
This commit is contained in:
parent
6adab3d07f
commit
a386c5f3d2
14 changed files with 160 additions and 44 deletions
|
@ -27,8 +27,9 @@ Other translation are very welcome, contact me if you'd like to submit one.
|
||||||
|
|
||||||
## Done
|
## Done
|
||||||
|
|
||||||
|
- option: reuse past frame's light in new frame lighting computation when there are 150+ coins on screen, to limit the performance impact of rendering lots of lights
|
||||||
|
|
||||||
## 29084571
|
## 29084606
|
||||||
|
|
||||||
- simpler and more readable encoding for save files
|
- simpler and more readable encoding for save files
|
||||||
- removed check of payload signature on save file, seemed to fail because of the poor encoding of the name of the "côte d'ivoire" level
|
- removed check of payload signature on save file, seemed to fail because of the poor encoding of the name of the "côte d'ivoire" level
|
||||||
|
|
66
dist/index.html
vendored
66
dist/index.html
vendored
File diff suppressed because one or more lines are too long
|
@ -67,7 +67,7 @@ export async function openCreativeModePerksPicker() {
|
||||||
value: u,
|
value: u,
|
||||||
className: creativeModePerks[u.id]
|
className: creativeModePerks[u.id]
|
||||||
? "sandbox highlight"
|
? "sandbox highlight"
|
||||||
: "sandbox grey-out-unless-hovered",
|
: "sandbox ",
|
||||||
tooltip: u.help(creativeModePerks[u.id] || 1),
|
tooltip: u.help(creativeModePerks[u.id] || 1),
|
||||||
})),
|
})),
|
||||||
t("lab.select_level"),
|
t("lab.select_level"),
|
||||||
|
|
|
@ -692,6 +692,7 @@ async function openSettingsMenu() {
|
||||||
"contrast",
|
"contrast",
|
||||||
"smooth_lighting",
|
"smooth_lighting",
|
||||||
"precise_lighting",
|
"precise_lighting",
|
||||||
|
"probabilistic_lighting",
|
||||||
].includes(key)) ||
|
].includes(key)) ||
|
||||||
false,
|
false,
|
||||||
value: () => {
|
value: () => {
|
||||||
|
|
|
@ -194,6 +194,8 @@
|
||||||
"settings.pointer_lock_help": "يقوم بقفل وإخفاء مؤشر الماوس.",
|
"settings.pointer_lock_help": "يقوم بقفل وإخفاء مؤشر الماوس.",
|
||||||
"settings.precise_lighting": "",
|
"settings.precise_lighting": "",
|
||||||
"settings.precise_lighting_help": "",
|
"settings.precise_lighting_help": "",
|
||||||
|
"settings.probabilistic_lighting": "",
|
||||||
|
"settings.probabilistic_lighting_help": "",
|
||||||
"settings.record": "تسجيل مقاطع فيديو للعبة",
|
"settings.record": "تسجيل مقاطع فيديو للعبة",
|
||||||
"settings.record_download": "تنزيل الفيديو ({{size}} ميجابايت)",
|
"settings.record_download": "تنزيل الفيديو ({{size}} ميجابايت)",
|
||||||
"settings.record_help": "احصل على فيديو لكل مستوى.",
|
"settings.record_help": "احصل على فيديو لكل مستوى.",
|
||||||
|
|
|
@ -6927,6 +6927,76 @@
|
||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>probabilistic_lighting</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>probabilistic_lighting_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>
|
<concept_node>
|
||||||
<name>record</name>
|
<name>record</name>
|
||||||
<description/>
|
<description/>
|
||||||
|
|
|
@ -194,6 +194,8 @@
|
||||||
"settings.pointer_lock_help": "Sperrt und versteckt den Mauszeiger.",
|
"settings.pointer_lock_help": "Sperrt und versteckt den Mauszeiger.",
|
||||||
"settings.precise_lighting": "",
|
"settings.precise_lighting": "",
|
||||||
"settings.precise_lighting_help": "",
|
"settings.precise_lighting_help": "",
|
||||||
|
"settings.probabilistic_lighting": "",
|
||||||
|
"settings.probabilistic_lighting_help": "",
|
||||||
"settings.record": "Spielvideos aufnehmen",
|
"settings.record": "Spielvideos aufnehmen",
|
||||||
"settings.record_download": "Video herunterladen ({{size}} MB)",
|
"settings.record_download": "Video herunterladen ({{size}} MB)",
|
||||||
"settings.record_help": "Holen Sie sich ein Video von jedem Level.",
|
"settings.record_help": "Holen Sie sich ein Video von jedem Level.",
|
||||||
|
|
|
@ -194,6 +194,8 @@
|
||||||
"settings.pointer_lock_help": "Locks and hides the mouse cursor.",
|
"settings.pointer_lock_help": "Locks and hides the mouse cursor.",
|
||||||
"settings.precise_lighting": "Precise lighting",
|
"settings.precise_lighting": "Precise lighting",
|
||||||
"settings.precise_lighting_help": "Use a smaller grid for background light effect",
|
"settings.precise_lighting_help": "Use a smaller grid for background light effect",
|
||||||
|
"settings.probabilistic_lighting": "Persistence of vision",
|
||||||
|
"settings.probabilistic_lighting_help": "Improve performance when there are more than 150 coins by reusing some of the light of the previous frame",
|
||||||
"settings.record": "Record gameplay videos",
|
"settings.record": "Record gameplay videos",
|
||||||
"settings.record_download": "Download video ({{size}} MB)",
|
"settings.record_download": "Download video ({{size}} MB)",
|
||||||
"settings.record_help": "Get a video of each level.",
|
"settings.record_help": "Get a video of each level.",
|
||||||
|
|
|
@ -194,6 +194,8 @@
|
||||||
"settings.pointer_lock_help": "Bloquea y oculta el cursor del mouse.",
|
"settings.pointer_lock_help": "Bloquea y oculta el cursor del mouse.",
|
||||||
"settings.precise_lighting": "",
|
"settings.precise_lighting": "",
|
||||||
"settings.precise_lighting_help": "",
|
"settings.precise_lighting_help": "",
|
||||||
|
"settings.probabilistic_lighting": "",
|
||||||
|
"settings.probabilistic_lighting_help": "",
|
||||||
"settings.record": "Grabar vídeos de juego",
|
"settings.record": "Grabar vídeos de juego",
|
||||||
"settings.record_download": "Descargar vídeo ({{size}} MB)",
|
"settings.record_download": "Descargar vídeo ({{size}} MB)",
|
||||||
"settings.record_help": "Obtenga un vídeo de cada nivel.",
|
"settings.record_help": "Obtenga un vídeo de cada nivel.",
|
||||||
|
|
|
@ -194,6 +194,8 @@
|
||||||
"settings.pointer_lock_help": "Cache aussi le curseur de la souris.",
|
"settings.pointer_lock_help": "Cache aussi le curseur de la souris.",
|
||||||
"settings.precise_lighting": "",
|
"settings.precise_lighting": "",
|
||||||
"settings.precise_lighting_help": "",
|
"settings.precise_lighting_help": "",
|
||||||
|
"settings.probabilistic_lighting": "",
|
||||||
|
"settings.probabilistic_lighting_help": "",
|
||||||
"settings.record": "Enregistrer des vidéos de jeu",
|
"settings.record": "Enregistrer des vidéos de jeu",
|
||||||
"settings.record_download": "Télécharger la vidéo ({{size}} MB)",
|
"settings.record_download": "Télécharger la vidéo ({{size}} MB)",
|
||||||
"settings.record_help": "Obtenez une vidéo de chaque niveau.",
|
"settings.record_help": "Obtenez une vidéo de chaque niveau.",
|
||||||
|
|
|
@ -194,6 +194,8 @@
|
||||||
"settings.pointer_lock_help": "Фиксирует и скрывает курсор мыши.",
|
"settings.pointer_lock_help": "Фиксирует и скрывает курсор мыши.",
|
||||||
"settings.precise_lighting": "",
|
"settings.precise_lighting": "",
|
||||||
"settings.precise_lighting_help": "",
|
"settings.precise_lighting_help": "",
|
||||||
|
"settings.probabilistic_lighting": "",
|
||||||
|
"settings.probabilistic_lighting_help": "",
|
||||||
"settings.record": "Запись видеороликов игрового процесса",
|
"settings.record": "Запись видеороликов игрового процесса",
|
||||||
"settings.record_download": "Скачать видео ({{size}} МБ)",
|
"settings.record_download": "Скачать видео ({{size}} МБ)",
|
||||||
"settings.record_help": "Получите видеозапись каждого уровня.",
|
"settings.record_help": "Получите видеозапись каждого уровня.",
|
||||||
|
|
|
@ -194,6 +194,8 @@
|
||||||
"settings.pointer_lock_help": "Fare imlecini kilitler ve gizler.",
|
"settings.pointer_lock_help": "Fare imlecini kilitler ve gizler.",
|
||||||
"settings.precise_lighting": "",
|
"settings.precise_lighting": "",
|
||||||
"settings.precise_lighting_help": "",
|
"settings.precise_lighting_help": "",
|
||||||
|
"settings.probabilistic_lighting": "",
|
||||||
|
"settings.probabilistic_lighting_help": "",
|
||||||
"settings.record": "Oyun videolarını kaydedin",
|
"settings.record": "Oyun videolarını kaydedin",
|
||||||
"settings.record_download": "Videoyu indir ({{size}} MB)",
|
"settings.record_download": "Videoyu indir ({{size}} MB)",
|
||||||
"settings.record_help": "Her seviyenin videosunu edinin.",
|
"settings.record_help": "Her seviyenin videosunu edinin.",
|
||||||
|
|
|
@ -40,6 +40,11 @@ export const options = {
|
||||||
name: t("settings.precise_lighting"),
|
name: t("settings.precise_lighting"),
|
||||||
help: t("settings.precise_lighting_help"),
|
help: t("settings.precise_lighting_help"),
|
||||||
},
|
},
|
||||||
|
probabilistic_lighting: {
|
||||||
|
default: false,
|
||||||
|
name: t("settings.probabilistic_lighting"),
|
||||||
|
help: t("settings.probabilistic_lighting_help"),
|
||||||
|
},
|
||||||
contrast: {
|
contrast: {
|
||||||
default: false,
|
default: false,
|
||||||
name: t("settings.contrast"),
|
name: t("settings.contrast"),
|
||||||
|
|
|
@ -55,7 +55,9 @@ export function getHaloScale() {
|
||||||
return 16 * (isOptionOn("precise_lighting") ? 1 : 2);
|
return 16 * (isOptionOn("precise_lighting") ? 1 : 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let framesCounter=0
|
||||||
export function render(gameState: GameState) {
|
export function render(gameState: GameState) {
|
||||||
|
framesCounter++
|
||||||
startWork("render:init");
|
startWork("render:init");
|
||||||
const level = currentLevelInfo(gameState);
|
const level = currentLevelInfo(gameState);
|
||||||
|
|
||||||
|
@ -109,11 +111,15 @@ export function render(gameState: GameState) {
|
||||||
"";
|
"";
|
||||||
// Clear
|
// Clear
|
||||||
if (!isOptionOn("basic") && level.svg && level.color === "#000000") {
|
if (!isOptionOn("basic") && level.svg && level.color === "#000000") {
|
||||||
|
// TODO only if many coins on screen
|
||||||
|
const skipN = isOptionOn('probabilistic_lighting') && liveCount(gameState.coins)> 150? 3 : 0
|
||||||
|
const shouldSkip = index=> skipN ? (framesCounter + index) % (skipN+1) !==0 : false
|
||||||
|
|
||||||
const haloScale = getHaloScale();
|
const haloScale = getHaloScale();
|
||||||
startWork("render:halo:clear");
|
startWork("render:halo:clear");
|
||||||
|
|
||||||
haloCanvasCtx.globalCompositeOperation = "source-over";
|
haloCanvasCtx.globalCompositeOperation = "source-over";
|
||||||
haloCanvasCtx.globalAlpha = 0.99;
|
haloCanvasCtx.globalAlpha = skipN ? 0.1:0.99
|
||||||
haloCanvasCtx.fillStyle = level.color;
|
haloCanvasCtx.fillStyle = level.color;
|
||||||
haloCanvasCtx.fillRect(0, 0, width / haloScale, height / haloScale);
|
haloCanvasCtx.fillRect(0, 0, width / haloScale, height / haloScale);
|
||||||
|
|
||||||
|
@ -122,7 +128,8 @@ export function render(gameState: GameState) {
|
||||||
haloCanvasCtx.globalAlpha =
|
haloCanvasCtx.globalAlpha =
|
||||||
0.1 + (0.5 * 10) / (liveCount(gameState.coins) + 10);
|
0.1 + (0.5 * 10) / (liveCount(gameState.coins) + 10);
|
||||||
startWork("render:halo:coins");
|
startWork("render:halo:coins");
|
||||||
forEachLiveOne(gameState.coins, (coin) => {
|
forEachLiveOne(gameState.coins, (coin,index) => {
|
||||||
|
if(shouldSkip(index)) return
|
||||||
const color = getCoinRenderColor(gameState, coin);
|
const color = getCoinRenderColor(gameState, coin);
|
||||||
drawFuzzyBall(
|
drawFuzzyBall(
|
||||||
haloCanvasCtx,
|
haloCanvasCtx,
|
||||||
|
@ -134,7 +141,8 @@ export function render(gameState: GameState) {
|
||||||
});
|
});
|
||||||
|
|
||||||
startWork("render:halo:balls");
|
startWork("render:halo:balls");
|
||||||
gameState.balls.forEach((ball) => {
|
gameState.balls.forEach((ball,index) => {
|
||||||
|
if(shouldSkip(index)) return
|
||||||
haloCanvasCtx.globalAlpha = 0.3 * (1 - ballTransparency(ball, gameState));
|
haloCanvasCtx.globalAlpha = 0.3 * (1 - ballTransparency(ball, gameState));
|
||||||
drawFuzzyBall(
|
drawFuzzyBall(
|
||||||
haloCanvasCtx,
|
haloCanvasCtx,
|
||||||
|
@ -149,6 +157,7 @@ export function render(gameState: GameState) {
|
||||||
haloCanvasCtx.globalAlpha = 0.05;
|
haloCanvasCtx.globalAlpha = 0.05;
|
||||||
gameState.bricks.forEach((color, index) => {
|
gameState.bricks.forEach((color, index) => {
|
||||||
if (!color) return;
|
if (!color) return;
|
||||||
|
if(shouldSkip(index)) return
|
||||||
const x = brickCenterX(gameState, index),
|
const x = brickCenterX(gameState, index),
|
||||||
y = brickCenterY(gameState, index);
|
y = brickCenterY(gameState, index);
|
||||||
drawFuzzyBall(
|
drawFuzzyBall(
|
||||||
|
@ -163,7 +172,8 @@ export function render(gameState: GameState) {
|
||||||
|
|
||||||
startWork("render:halo:particles");
|
startWork("render:halo:particles");
|
||||||
haloCanvasCtx.globalCompositeOperation = "screen";
|
haloCanvasCtx.globalCompositeOperation = "screen";
|
||||||
forEachLiveOne(gameState.particles, (flash) => {
|
forEachLiveOne(gameState.particles, (flash,index) => {
|
||||||
|
if(shouldSkip(index)) return
|
||||||
const { x, y, time, color, size, duration } = flash;
|
const { x, y, time, color, size, duration } = flash;
|
||||||
const elapsed = gameState.levelTime - time;
|
const elapsed = gameState.levelTime - time;
|
||||||
haloCanvasCtx.globalAlpha =
|
haloCanvasCtx.globalAlpha =
|
||||||
|
@ -567,12 +577,19 @@ export function render(gameState: GameState) {
|
||||||
) {
|
) {
|
||||||
ctx.imageSmoothingEnabled = isOptionOn("smooth_lighting") || false;
|
ctx.imageSmoothingEnabled = isOptionOn("smooth_lighting") || false;
|
||||||
|
|
||||||
haloCanvasCtx.fillStyle = "#FFFFFF";
|
if(isOptionOn('probabilistic_lighting')) {
|
||||||
haloCanvasCtx.globalAlpha = 0.25;
|
ctx.globalAlpha = 1;
|
||||||
haloCanvasCtx.globalCompositeOperation = "screen";
|
ctx.globalCompositeOperation = "soft-light";
|
||||||
haloCanvasCtx.fillRect(0, 0, haloCanvas.width, haloCanvas.height);
|
}else{
|
||||||
ctx.globalAlpha = 1;
|
|
||||||
|
haloCanvasCtx.fillStyle = "#FFFFFF";
|
||||||
|
haloCanvasCtx.globalAlpha = 0.25;
|
||||||
|
haloCanvasCtx.globalCompositeOperation = "screen";
|
||||||
|
haloCanvasCtx.fillRect(0, 0, haloCanvas.width, haloCanvas.height);
|
||||||
|
ctx.globalAlpha = 1;
|
||||||
ctx.globalCompositeOperation = "overlay";
|
ctx.globalCompositeOperation = "overlay";
|
||||||
|
}
|
||||||
|
|
||||||
ctx.drawImage(haloCanvas, 0, 0, width, height);
|
ctx.drawImage(haloCanvas, 0, 0, width, height);
|
||||||
|
|
||||||
ctx.imageSmoothingEnabled = false;
|
ctx.imageSmoothingEnabled = false;
|
||||||
|
@ -604,13 +621,6 @@ export function render(gameState: GameState) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(isOptionOn('mobile-mode')) {
|
|
||||||
// ctx.globalCompositeOperation = "source-over";
|
|
||||||
// ctx.globalAlpha = 0.5;
|
|
||||||
// ctx.fillStyle = 'black'
|
|
||||||
// ctx.fillRect(0,gameState.gameZoneHeight, gameState.canvasWidth, gameState.canvasHeight-gameState.gameZoneHeight)
|
|
||||||
// }
|
|
||||||
// ctx.globalAlpha=1
|
|
||||||
startWork("render:askForWakeLock");
|
startWork("render:askForWakeLock");
|
||||||
askForWakeLock(gameState);
|
askForWakeLock(gameState);
|
||||||
|
|
||||||
|
@ -958,6 +968,7 @@ export function drawFuzzyBall(
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
) {
|
) {
|
||||||
|
width=Math.max(width,2)
|
||||||
const key = "fuzzy-circle" + color + "_" + width;
|
const key = "fuzzy-circle" + color + "_" + width;
|
||||||
if (!color?.startsWith("#")) debugger;
|
if (!color?.startsWith("#")) debugger;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue