feat: HD Remaster toggle with 4x canvas render path
G.hdRemaster persisted in localStorage (meatslicer_hd_remaster), toggled from the title screen via H key or the bottom-left tag; activation reloads so the asset tier and canvas resolution swap at boot. draw() applies a uniform hdScale() transform, the room-layer cache renders at render scale, and image smoothing follows the tier.
This commit is contained in:
1 parent
24c1958f2b
commit
ea354d0153
3 files changed
+35
-7
No files matched your search
+25
-2
@@ -6,6 +6,7 @@ const PRESSURE_SLIDER_RECT = { x: 300, y: 470, w: 360, h: 46 };
|
|||||||
const MENU_EXIT_BUTTON = { x: W - 208, y: H - 48, w: 180, h: 28 };
|
const MENU_EXIT_BUTTON = { x: W - 208, y: H - 48, w: 180, h: 28 };
|
||||||
const PAUSE_MENU_BUTTON = { x: W / 2 - 75, y: 526, w: 150, h: 28 };
|
const PAUSE_MENU_BUTTON = { x: W / 2 - 75, y: 526, w: 150, h: 28 };
|
||||||
const PAUSE_EXIT_BUTTON = { x: W / 2 + 87, y: 526, w: 150, h: 28 };
|
const PAUSE_EXIT_BUTTON = { x: W / 2 + 87, y: 526, w: 150, h: 28 };
|
||||||
|
const HD_TOGGLE_BUTTON = { x: 28, y: H - 48, w: 220, h: 28 };
|
||||||
const CONFIRM_WINDOW = 3;
|
const CONFIRM_WINDOW = 3;
|
||||||
|
|
||||||
function pauseBars() {
|
function pauseBars() {
|
||||||
@@ -20,7 +21,11 @@ function pauseBars() {
|
|||||||
function init() {
|
function init() {
|
||||||
canvas = document.getElementById('game');
|
canvas = document.getElementById('game');
|
||||||
ctx = canvas.getContext('2d');
|
ctx = canvas.getContext('2d');
|
||||||
ctx.imageSmoothingEnabled = false;
|
try { G.hdRemaster = localStorage.getItem('meatslicer_hd_remaster') === '1'; } catch (e) {}
|
||||||
|
canvas.width = W * hdScale();
|
||||||
|
canvas.height = H * hdScale();
|
||||||
|
canvas.style.imageRendering = G.hdRemaster ? 'auto' : 'pixelated';
|
||||||
|
ctx.imageSmoothingEnabled = !G.hdRemaster;
|
||||||
G.devMode = debugEnabled();
|
G.devMode = debugEnabled();
|
||||||
initInput(canvas);
|
initInput(canvas);
|
||||||
Sprites.load();
|
Sprites.load();
|
||||||
@@ -67,6 +72,16 @@ function setAutoPerk(enabled) {
|
|||||||
Sfx.menu();
|
Sfx.menu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setHdRemaster(enabled) {
|
||||||
|
G.hdRemaster = !!enabled;
|
||||||
|
try { localStorage.setItem('meatslicer_hd_remaster', G.hdRemaster ? '1' : '0'); } catch (e) {}
|
||||||
|
}
|
||||||
|
function toggleHdRemaster() {
|
||||||
|
setHdRemaster(!G.hdRemaster);
|
||||||
|
Sfx.menu();
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
function buildAtmosphereLayer() {
|
function buildAtmosphereLayer() {
|
||||||
if (!document.createElement) return;
|
if (!document.createElement) return;
|
||||||
const layer = document.createElement('canvas');
|
const layer = document.createElement('canvas');
|
||||||
@@ -199,7 +214,8 @@ function update(dt) {
|
|||||||
setPressureDial(Math.round(((Input.mx - sl.x) / sl.w) * 20) - 10);
|
setPressureDial(Math.round(((Input.mx - sl.x) / sl.w) * 20) - 10);
|
||||||
}
|
}
|
||||||
if (!Input.mdown) G.menuDialDrag = false;
|
if (!Input.mdown) G.menuDialDrag = false;
|
||||||
if (keyPressed('enter', ' ') || (Input.mpressed && !inRect(Input.mx, Input.my, sl) && !exitClick)) startRun();
|
if (keyPressed('h') || (Input.mpressed && inRect(Input.mx, Input.my, HD_TOGGLE_BUTTON))) { toggleHdRemaster(); break; }
|
||||||
|
if (keyPressed('enter', ' ') || (Input.mpressed && !inRect(Input.mx, Input.my, sl) && !inRect(Input.mx, Input.my, HD_TOGGLE_BUTTON) && !exitClick)) startRun();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'play':
|
case 'play':
|
||||||
@@ -296,6 +312,7 @@ function update(dt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function draw() {
|
function draw() {
|
||||||
|
ctx.setTransform(hdScale(), 0, 0, hdScale(), 0, 0);
|
||||||
ctx.fillStyle = '#0a0506';
|
ctx.fillStyle = '#0a0506';
|
||||||
ctx.fillRect(0, 0, W, H);
|
ctx.fillRect(0, 0, W, H);
|
||||||
|
|
||||||
@@ -429,6 +446,12 @@ function drawMenu(ctx) {
|
|||||||
color: !desktopExit ? '#65595b' : (exitConfirm ? '#ffd36a' : (exitHover ? '#f5e9d6' : '#ad8f8c')),
|
color: !desktopExit ? '#65595b' : (exitConfirm ? '#ffd36a' : (exitHover ? '#f5e9d6' : '#ad8f8c')),
|
||||||
accent: !desktopExit ? '#3a2d31' : (exitConfirm ? '#d69a22' : (exitHover ? '#e22b46' : '#6e3843')),
|
accent: !desktopExit ? '#3a2d31' : (exitConfirm ? '#d69a22' : (exitHover ? '#e22b46' : '#6e3843')),
|
||||||
});
|
});
|
||||||
|
const hdHover = inRect(Input.mx, Input.my, HD_TOGGLE_BUTTON);
|
||||||
|
drawPixelTag(ctx, '[H] HD REMASTER // ' + (G.hdRemaster ? 'ON' : 'OFF'), HD_TOGGLE_BUTTON.x, HD_TOGGLE_BUTTON.y, {
|
||||||
|
width: HD_TOGGLE_BUTTON.w, height: HD_TOGGLE_BUTTON.h,
|
||||||
|
color: G.hdRemaster ? '#e0b94e' : (hdHover ? '#f5e9d6' : '#ad8f8c'),
|
||||||
|
accent: G.hdRemaster ? '#a47e25' : (hdHover ? '#e22b46' : '#6e3843'),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawPressureDial(ctx) {
|
function drawPressureDial(ctx) {
|
||||||
|
|||||||
+7
-5
@@ -393,17 +393,19 @@ function drawFloor(ctx, r) {
|
|||||||
// browser; headless tests keep the simple direct path.
|
// browser; headless tests keep the simple direct path.
|
||||||
const canCache = typeof document !== 'undefined' && document.createElement && G.imagesLoaded;
|
const canCache = typeof document !== 'undefined' && document.createElement && G.imagesLoaded;
|
||||||
if (!canCache) { drawFloorTiles(ctx, r); return; }
|
if (!canCache) { drawFloorTiles(ctx, r); return; }
|
||||||
const key = r.gx + ',' + r.gy + ':' + G.floor + ':' + r.shape + ':' + r.theme;
|
const key = r.gx + ',' + r.gy + ':' + G.floor + ':' + r.shape + ':' + r.theme + ':' + hdScale();
|
||||||
if (!G.roomLayer || G.roomLayerKey !== key) {
|
if (!G.roomLayer || G.roomLayerKey !== key) {
|
||||||
const a = roomBounds(r);
|
const a = roomBounds(r);
|
||||||
|
const rs = hdScale();
|
||||||
const layer = document.createElement('canvas');
|
const layer = document.createElement('canvas');
|
||||||
layer.width = Math.max(W, a.x1); layer.height = Math.max(H, a.y1);
|
layer.width = Math.max(W, a.x1) * rs; layer.height = Math.max(H, a.y1) * rs;
|
||||||
const lctx = layer.getContext('2d');
|
const lctx = layer.getContext('2d');
|
||||||
lctx.imageSmoothingEnabled = false;
|
lctx.setTransform(rs, 0, 0, rs, 0, 0);
|
||||||
drawFloorTiles(lctx, r, layer.width, layer.height);
|
lctx.imageSmoothingEnabled = !G.hdRemaster;
|
||||||
|
drawFloorTiles(lctx, r, layer.width / rs, layer.height / rs);
|
||||||
G.roomLayer = layer; G.roomLayerKey = key;
|
G.roomLayer = layer; G.roomLayerKey = key;
|
||||||
}
|
}
|
||||||
ctx.drawImage(G.roomLayer, 0, 0);
|
ctx.drawImage(G.roomLayer, 0, 0, G.roomLayer.width / hdScale(), G.roomLayer.height / hdScale());
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawRoom(ctx) {
|
function drawRoom(ctx) {
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ const G = {
|
|||||||
sfxVol: 0.45,
|
sfxVol: 0.45,
|
||||||
musicVol: 0.55,
|
musicVol: 0.55,
|
||||||
hudAlpha: 1,
|
hudAlpha: 1,
|
||||||
|
hdRemaster: false,
|
||||||
imagesLoaded: false,
|
imagesLoaded: false,
|
||||||
roomLayer: null,
|
roomLayer: null,
|
||||||
roomLayerKey: '',
|
roomLayerKey: '',
|
||||||
@@ -70,6 +71,8 @@ const PRESSURE_DROP_BASE = 3; // dial 0 == 0.03 relief base
|
|||||||
const DEATH_LOCK = 3;
|
const DEATH_LOCK = 3;
|
||||||
const PRESSURE_DIAL_MIN = -10, PRESSURE_DIAL_MAX = 10;
|
const PRESSURE_DIAL_MIN = -10, PRESSURE_DIAL_MAX = 10;
|
||||||
|
|
||||||
|
function hdScale() { return G.hdRemaster ? 4 : 1; }
|
||||||
|
|
||||||
// Preserve the old -5 / 0 / +5 balance while adding genuinely wider extremes.
|
// Preserve the old -5 / 0 / +5 balance while adding genuinely wider extremes.
|
||||||
function pressureGainUnits(dial) {
|
function pressureGainUnits(dial) {
|
||||||
const d = clamp(dial, PRESSURE_DIAL_MIN, PRESSURE_DIAL_MAX);
|
const d = clamp(dial, PRESSURE_DIAL_MIN, PRESSURE_DIAL_MAX);
|
||||||
|
|||||||
Reference in new issue
Block a user