From 3a88ebc626512b9c5aefc9037983e7d564499eeb Mon Sep 17 00:00:00 2001 From: Brian Fertig Date: Fri, 10 Jul 2026 16:30:29 -0600 Subject: [PATCH] feat(balatro): introduce m6x11 pixel font as primary font face Add m6x11.ttf and register it via @font-face in styles.css. Use it as the primary font throughout BalatroGame.js and BalatroViews.js (with Julius Sans One as fallback), giving the game a consistent pixel-art aesthetic. Update PreloadScene to warm the new font alongside YummyCupcakes. --- assets/fonts/m6x11.ttf | Bin 0 -> 13068 bytes src/games/balatro/BalatroGame.js | 60 +++++++++++++++--------------- src/games/balatro/BalatroViews.js | 12 +++--- src/scenes/PreloadScene.js | 7 ++-- styles.css | 7 ++++ 5 files changed, 47 insertions(+), 39 deletions(-) create mode 100644 assets/fonts/m6x11.ttf diff --git a/assets/fonts/m6x11.ttf b/assets/fonts/m6x11.ttf new file mode 100644 index 0000000000000000000000000000000000000000..cb2122489c6d375e5c4ff4a99157e7245b067c83 GIT binary patch literal 13068 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 literal 0 HcmV?d00001 diff --git a/src/games/balatro/BalatroGame.js b/src/games/balatro/BalatroGame.js index d1dbbb7..b30d00f 100644 --- a/src/games/balatro/BalatroGame.js +++ b/src/games/balatro/BalatroGame.js @@ -239,7 +239,7 @@ export default class BalatroGame extends Phaser.Scene { text(x, y, str, size, color = C.ink, opts = {}) { const t = this.add.text(x, y, str, { - fontFamily: opts.font || '"Julius Sans One"', fontSize: `${size}px`, color, + fontFamily: opts.font || 'm6x11, "Julius Sans One"', fontSize: `${size}px`, color, align: opts.align || 'left', wordWrap: opts.wrap ? { width: opts.wrap } : undefined, fontStyle: opts.bold ? 'bold' : 'normal', }).setOrigin(opts.ox ?? 0, opts.oy ?? 0); @@ -266,7 +266,7 @@ export default class BalatroGame extends Phaser.Scene { toast(msg) { if (this._toastText) this._toastText.destroy(); const t = this.add.text(GAME_WIDTH / 2, 640, msg, { - fontFamily: '"Julius Sans One"', fontSize: '30px', color: '#ffd2c8', + fontFamily: 'm6x11, "Julius Sans One"', fontSize: '30px', color: '#ffd2c8', backgroundColor: '#301418', padding: { x: 18, y: 10 }, }).setOrigin(0.5).setDepth(90); this.fxLayer.add(t); @@ -326,22 +326,22 @@ export default class BalatroGame extends Phaser.Scene { if (enh !== 'stone') { const color = SUIT_COLOR[card.suit]; const rank = this.add.text(-w / 2 + 10, -h / 2 + 6, RANK_NAMES[card.rank], { - fontFamily: 'Georgia, serif', fontSize: `${Math.round(h * 0.21)}px`, color, fontStyle: 'bold', + fontFamily: 'm6x11, Georgia, serif', fontSize: `${Math.round(h * 0.21)}px`, color, fontStyle: 'bold', }); const suitSm = this.add.text(-w / 2 + 12, -h / 2 + 8 + h * 0.21, SUIT_GLYPH[card.suit], { - fontFamily: 'Georgia, serif', fontSize: `${Math.round(h * 0.16)}px`, color, + fontFamily: 'm6x11, Georgia, serif', fontSize: `${Math.round(h * 0.16)}px`, color, }); const suitBig = this.add.text(w * 0.16, h * 0.16, SUIT_GLYPH[card.suit], { - fontFamily: 'Georgia, serif', fontSize: `${Math.round(h * 0.42)}px`, color, + fontFamily: 'm6x11, Georgia, serif', fontSize: `${Math.round(h * 0.42)}px`, color, }).setOrigin(0.5).setAlpha(0.9); cont.add([rank, suitSm, suitBig]); if (enh === 'wild') { - const wl = this.add.text(0, h * 0.38, 'WILD', { fontFamily: '"Julius Sans One"', fontSize: `${Math.round(h * 0.1)}px`, color: '#5a3a10', fontStyle: 'bold' }).setOrigin(0.5); + const wl = this.add.text(0, h * 0.38, 'WILD', { fontFamily: 'm6x11, "Julius Sans One"', fontSize: `${Math.round(h * 0.1)}px`, color: '#5a3a10', fontStyle: 'bold' }).setOrigin(0.5); cont.add(wl); } } else { - const st = this.add.text(0, 0, '◼', { fontFamily: 'Georgia, serif', fontSize: `${Math.round(h * 0.32)}px`, color: '#4c4a45' }).setOrigin(0.5); - const lbl = this.add.text(0, h * 0.3, 'STONE', { fontFamily: '"Julius Sans One"', fontSize: `${Math.round(h * 0.1)}px`, color: '#3d3b37' }).setOrigin(0.5); + const st = this.add.text(0, 0, '◼', { fontFamily: 'm6x11, Georgia, serif', fontSize: `${Math.round(h * 0.32)}px`, color: '#4c4a45' }).setOrigin(0.5); + const lbl = this.add.text(0, h * 0.3, 'STONE', { fontFamily: 'm6x11, "Julius Sans One"', fontSize: `${Math.round(h * 0.1)}px`, color: '#3d3b37' }).setOrigin(0.5); cont.add([st, lbl]); } if (card.seal) { @@ -351,19 +351,19 @@ export default class BalatroGame extends Phaser.Scene { } if (card.edition) { const tag = this.add.text(0, -h / 2 + 4, EDITIONS[card.edition].name.toUpperCase(), { - fontFamily: '"Julius Sans One"', fontSize: `${Math.round(h * 0.07)}px`, color: '#ffffff', + fontFamily: 'm6x11, "Julius Sans One"', fontSize: `${Math.round(h * 0.07)}px`, color: '#ffffff', }).setOrigin(0.5, 0).setAlpha(0.85); cont.add(tag); } if (card.permaChips) { const pc = this.add.text(-w / 2 + 8, h / 2 - 26, `+${card.permaChips}`, { - fontFamily: '"Julius Sans One"', fontSize: `${Math.round(h * 0.09)}px`, color: C.chipsHex, + fontFamily: 'm6x11, "Julius Sans One"', fontSize: `${Math.round(h * 0.09)}px`, color: C.chipsHex, }); cont.add(pc); } if (debuffed) { const shade = this.add.rectangle(0, 0, w, h, 0x1a1420, 0.62); - const xg = this.add.text(0, 0, '✕', { fontFamily: 'Georgia, serif', fontSize: `${Math.round(h * 0.3)}px`, color: '#8a4550' }).setOrigin(0.5); + const xg = this.add.text(0, 0, '✕', { fontFamily: 'm6x11, Georgia, serif', fontSize: `${Math.round(h * 0.3)}px`, color: '#8a4550' }).setOrigin(0.5); cont.add([shade, xg]); } cont.setSize(w, h); @@ -387,11 +387,11 @@ export default class BalatroGame extends Phaser.Scene { g.lineStyle(2, C.rarity[def.rarity], 1); g.strokeRoundedRect(-w / 2, -h / 2, w, h, 10); cont.add(g); const name = this.add.text(0, -h / 2 + 15, def.name, { - fontFamily: '"Julius Sans One"', fontSize: `${Math.min(17, Math.round(280 / def.name.length))}px`, color: '#141019', fontStyle: 'bold', + fontFamily: 'm6x11, "Julius Sans One"', fontSize: `${Math.min(17, Math.round(280 / def.name.length))}px`, color: '#141019', fontStyle: 'bold', }).setOrigin(0.5); const desc = typeof def.desc === 'function' ? def.desc(opts.inst || { state: def.initState ? def.initState() : {} }) : def.desc; const body = this.add.text(0, 8, desc, { - fontFamily: '"Julius Sans One"', fontSize: '15px', color: C.ink, align: 'center', + fontFamily: 'm6x11, "Julius Sans One"', fontSize: '15px', color: C.ink, align: 'center', wordWrap: { width: w - 16 }, }).setOrigin(0.5); cont.add([name, body]); @@ -403,14 +403,14 @@ export default class BalatroGame extends Phaser.Scene { eg.lineStyle(4, edColor, 0.95); eg.strokeRoundedRect(-w / 2, -h / 2, w, h, 10); cont.add(eg); const tag = this.add.text(0, h / 2 - 16, EDITIONS[edition].name.toUpperCase(), { - fontFamily: '"Julius Sans One"', fontSize: '11px', color: '#ffffff', + fontFamily: 'm6x11, "Julius Sans One"', fontSize: '11px', color: '#ffffff', }).setOrigin(0.5).setAlpha(0.9); cont.add(tag); if (edition === 'negative') cont.setAlpha(0.8); } if (opts.inst && opts.inst.debuffedByBoss) { cont.add(this.add.rectangle(0, 0, w, h, 0x1a1420, 0.6)); - cont.add(this.add.text(0, 0, 'DISABLED', { fontFamily: '"Julius Sans One"', fontSize: '16px', color: '#c86a6a' }).setOrigin(0.5)); + cont.add(this.add.text(0, 0, 'DISABLED', { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '16px', color: '#c86a6a' }).setOrigin(0.5)); } cont.setSize(w, h); return cont; @@ -433,16 +433,16 @@ export default class BalatroGame extends Phaser.Scene { g.lineStyle(1, tint, 0.6); g.strokeRoundedRect(-w / 2 + 6, -h / 2 + 6, w - 12, h - 12, 8); cont.add(g); const name = this.add.text(0, -h / 2 + 20, def.name, { - fontFamily: '"Julius Sans One"', fontSize: `${Math.min(16, Math.round(300 / def.name.length))}px`, + fontFamily: 'm6x11, "Julius Sans One"', fontSize: `${Math.min(16, Math.round(300 / def.name.length))}px`, color: `#${tint.toString(16).padStart(6, '0')}`, fontStyle: 'bold', align: 'center', wordWrap: { width: w - 14 }, }).setOrigin(0.5, 0); const descText = kind === 'planet' ? `+1 level: ${HAND_BY_ID[def.hand].name}` : def.desc; const body = this.add.text(0, 16, descText, { - fontFamily: '"Julius Sans One"', fontSize: '14px', color: C.ink, align: 'center', wordWrap: { width: w - 18 }, + fontFamily: 'm6x11, "Julius Sans One"', fontSize: '14px', color: C.ink, align: 'center', wordWrap: { width: w - 18 }, }).setOrigin(0.5); cont.add([name, body]); const glyph = { tarot: '☽', planet: '✶', spectral: '✧' }[kind]; - cont.add(this.add.text(0, h / 2 - 22, glyph, { fontFamily: 'Georgia, serif', fontSize: '20px', color: `#${tint.toString(16).padStart(6, '0')}` }).setOrigin(0.5)); + cont.add(this.add.text(0, h / 2 - 22, glyph, { fontFamily: 'm6x11, Georgia, serif', fontSize: '20px', color: `#${tint.toString(16).padStart(6, '0')}` }).setOrigin(0.5)); } cont.setSize(w, h); return cont; @@ -460,14 +460,14 @@ export default class BalatroGame extends Phaser.Scene { this.fxLayer.add(cont); let y = PAD; const title = this.add.text(PAD, y, info.title, { - fontFamily: '"Julius Sans One"', fontSize: '22px', color: info.titleColor || C.ink, + fontFamily: 'm6x11, "Julius Sans One"', fontSize: '22px', color: info.titleColor || C.ink, fontStyle: 'bold', wordWrap: { width: W - PAD * 2 }, }); cont.add(title); y += title.height + 4; if (info.tag) { const tag = this.add.text(PAD, y, info.tag, { - fontFamily: '"Julius Sans One"', fontSize: '14px', color: info.tagColor || C.muted, + fontFamily: 'm6x11, "Julius Sans One"', fontSize: '14px', color: info.tagColor || C.muted, }); cont.add(tag); y += tag.height + 8; @@ -476,7 +476,7 @@ export default class BalatroGame extends Phaser.Scene { } for (const line of info.lines || []) { const t = this.add.text(PAD, y, line.text, { - fontFamily: '"Julius Sans One"', fontSize: '16px', color: line.color || C.muted, + fontFamily: 'm6x11, "Julius Sans One"', fontSize: '16px', color: line.color || C.muted, wordWrap: { width: W - PAD * 2 }, }); cont.add(t); @@ -701,7 +701,7 @@ export default class BalatroGame extends Phaser.Scene { g.fillStyle(C.panel, 0.97); g.fillRoundedRect(GAME_WIDTH / 2 - 240, 360, 480, 360, 16); g.lineStyle(2, C.panelEdge, 1); g.strokeRoundedRect(GAME_WIDTH / 2 - 240, 360, 480, 360, 16); ov.add([shade, g]); - const t = this.add.text(GAME_WIDTH / 2, 400, 'Options', { fontFamily: '"Julius Sans One"', fontSize: '32px', color: C.ink }).setOrigin(0.5); + const t = this.add.text(GAME_WIDTH / 2, 400, 'Options', { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '32px', color: C.ink }).setOrigin(0.5); ov.add(t); const mk = (y, label, cb) => { const b = new Button(this, GAME_WIDTH / 2, y, label, cb, { width: 320, height: 56, fontSize: 22 }); @@ -775,8 +775,8 @@ export default class BalatroGame extends Phaser.Scene { g.lineStyle(2, C.rarity[def.rarity], 1); g.strokeRoundedRect(px, py, pw, ph, 12); cont.add(g); const desc = typeof def.desc === 'function' ? def.desc(inst) : def.desc; - cont.add(this.add.text(px + 20, py + 14, `${def.name}${inst.edition ? ` (${EDITIONS[inst.edition].name})` : ''}`, { fontFamily: '"Julius Sans One"', fontSize: '24px', color: C.ink })); - cont.add(this.add.text(px + 20, py + 52, desc, { fontFamily: '"Julius Sans One"', fontSize: '17px', color: C.muted, wordWrap: { width: pw - 40 } })); + cont.add(this.add.text(px + 20, py + 14, `${def.name}${inst.edition ? ` (${EDITIONS[inst.edition].name})` : ''}`, { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '24px', color: C.ink })); + cont.add(this.add.text(px + 20, py + 52, desc, { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '17px', color: C.muted, wordWrap: { width: pw - 40 } })); const sell = new Button(this, px + pw - 110, py + ph - 40, `Sell $${inst.sellValue}`, () => { const r = sellJoker(this.run, inst.uid); if (r.ok) { playSound(this, SFX.COINS); this.save(); this.renderView(); } @@ -823,11 +823,11 @@ export default class BalatroGame extends Phaser.Scene { const tint = { tarot: C.tarot, planet: C.planet, spectral: C.spectral }[inst.kind]; g.lineStyle(2, tint, 1); g.strokeRoundedRect(px, py, pw, ph, 12); cont.add(g); - cont.add(this.add.text(px + 20, py + 14, def.name, { fontFamily: '"Julius Sans One"', fontSize: '24px', color: C.ink })); + cont.add(this.add.text(px + 20, py + 14, def.name, { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '24px', color: C.ink })); const descText = inst.kind === 'planet' ? `+1 level: ${HAND_BY_ID[def.hand].name}` : def.desc; - cont.add(this.add.text(px + 20, py + 52, descText, { fontFamily: '"Julius Sans One"', fontSize: '17px', color: C.muted, wordWrap: { width: pw - 40 } })); + cont.add(this.add.text(px + 20, py + 52, descText, { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '17px', color: C.muted, wordWrap: { width: pw - 40 } })); const needs = def.targets || 0; - if (needs) cont.add(this.add.text(px + 20, py + ph - 96, `Select up to ${needs} card${needs > 1 ? 's' : ''} in hand first`, { fontFamily: '"Julius Sans One"', fontSize: '15px', color: '#a8d8ff' })); + if (needs) cont.add(this.add.text(px + 20, py + ph - 96, `Select up to ${needs} card${needs > 1 ? 's' : ''} in hand first`, { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '15px', color: '#a8d8ff' })); const use = new Button(this, px + pw - 110, py + ph - 40, 'Use', () => { const r = useConsumable(this.run, inst.uid, this.selected.slice(0, Math.max(needs, 2))); if (!r.ok) { this.toast(r.error); return; } @@ -897,7 +897,7 @@ export default class BalatroGame extends Phaser.Scene { cont.add(glow); } if (run.bossState && run.bossState.forcedUid === card.uid) { - const lock = this.add.text(0, -h / 2 - 20, '⛓ forced', { fontFamily: '"Julius Sans One"', fontSize: '15px', color: '#ff8a6a' }).setOrigin(0.5); + const lock = this.add.text(0, -h / 2 - 20, '⛓ forced', { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '15px', color: '#ff8a6a' }).setOrigin(0.5); cont.add(lock); } if (!frozen) { @@ -1140,7 +1140,7 @@ export default class BalatroGame extends Phaser.Scene { const x = sprite ? this.fxX(sprite) : 980; const y = sprite ? this.fxY(sprite) - 90 : 400; const t = this.add.text(x, y, textStr, { - fontFamily: '"Julius Sans One"', fontSize: '34px', color, fontStyle: 'bold', + fontFamily: 'm6x11, "Julius Sans One"', fontSize: '34px', color, fontStyle: 'bold', stroke: '#141019', strokeThickness: 5, }).setOrigin(0.5).setDepth(85); this.fxLayer.add(t); @@ -1189,7 +1189,7 @@ export default class BalatroGame extends Phaser.Scene { const score = res.trace.score; // Slam: big score text at the played row. const slam = this.add.text(centerX, py - 170, fmtChips(score), { - fontFamily: '"Julius Sans One"', fontSize: '72px', color: '#ffffff', fontStyle: 'bold', + fontFamily: 'm6x11, "Julius Sans One"', fontSize: '72px', color: '#ffffff', fontStyle: 'bold', stroke: '#c8342c', strokeThickness: 8, }).setOrigin(0.5).setScale(1.6).setAlpha(0).setDepth(86); this.fxLayer.add(slam); diff --git a/src/games/balatro/BalatroViews.js b/src/games/balatro/BalatroViews.js index 2c8ccdf..19067ac 100644 --- a/src/games/balatro/BalatroViews.js +++ b/src/games/balatro/BalatroViews.js @@ -64,7 +64,7 @@ function confirmNewRun(scene) { g.fillStyle(C.panel, 0.97); g.fillRoundedRect(CX - 280, 420, 560, 240, 16); g.lineStyle(2, C.panelEdge, 1); g.strokeRoundedRect(CX - 280, 420, 560, 240, 16); ov.add([shade, g]); - ov.add(scene.add.text(CX, 470, 'Abandon the saved run?', { fontFamily: '"Julius Sans One"', fontSize: '28px', color: C.ink }).setOrigin(0.5)); + ov.add(scene.add.text(CX, 470, 'Abandon the saved run?', { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '28px', color: C.ink }).setOrigin(0.5)); const yes = scene.button(CX - 110, 590, 'Yes', () => { scene._savedRun = null; store.write('balatro:run', null); ov.destroy(); scene.setView('deckselect'); }, { width: 160, height: 54, fontSize: 22 }); const no = scene.button(CX + 110, 590, 'No', () => ov.destroy(), { width: 160, height: 54, fontSize: 22, variant: 'ghost' }); ov.add([yes, no]); @@ -94,8 +94,8 @@ export function renderDeckSelect(scene) { bg.lineStyle(1, 0xffffff, 0.25); bg.strokeRoundedRect(-48, -130, 96, 140, 6); cont.add(bg); } - cont.add(scene.add.text(0, 52, deck.name, { fontFamily: '"Julius Sans One"', fontSize: '26px', color: C.ink, fontStyle: 'bold' }).setOrigin(0.5)); - cont.add(scene.add.text(0, 108, deck.desc, { fontFamily: '"Julius Sans One"', fontSize: '17px', color: C.muted, align: 'center', wordWrap: { width: w - 30 } }).setOrigin(0.5)); + cont.add(scene.add.text(0, 52, deck.name, { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '26px', color: C.ink, fontStyle: 'bold' }).setOrigin(0.5)); + cont.add(scene.add.text(0, 108, deck.desc, { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '17px', color: C.muted, align: 'center', wordWrap: { width: w - 30 } }).setOrigin(0.5)); cont.setSize(w, h); scene.add2(cont); scene.addHoverTilt(cont); @@ -248,7 +248,7 @@ export function renderShop(scene) { g.lineStyle(3, 0xffffff, 0.5); g.strokeRoundedRect(-90, -120, 180, 240, 12); g.fillStyle(0x141019, 0.35); g.fillRoundedRect(-90, -30, 180, 60, 0); cont.add(g); - cont.add(scene.add.text(0, 0, def.name.replace(' Pack', '\nPack'), { fontFamily: '"Julius Sans One"', fontSize: '22px', color: '#ffffff', align: 'center', fontStyle: 'bold' }).setOrigin(0.5)); + cont.add(scene.add.text(0, 0, def.name.replace(' Pack', '\nPack'), { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '22px', color: '#ffffff', align: 'center', fontStyle: 'bold' }).setOrigin(0.5)); } cont.setSize(180, 240); scene.add2(cont); @@ -284,8 +284,8 @@ export function renderShop(scene) { g.lineStyle(3, C.voucher, 1); g.strokeRoundedRect(-95, -125, 190, 250, 10); g.lineStyle(1, C.voucher, 0.5); g.strokeRoundedRect(-85, -115, 170, 230, 8); cont.add(g); - cont.add(scene.add.text(0, -80, v.name, { fontFamily: '"Julius Sans One"', fontSize: '22px', color: '#7ce0c0', align: 'center', fontStyle: 'bold', wordWrap: { width: 170 } }).setOrigin(0.5)); - cont.add(scene.add.text(0, 20, v.desc, { fontFamily: '"Julius Sans One"', fontSize: '16px', color: C.ink, align: 'center', wordWrap: { width: 165 } }).setOrigin(0.5)); + cont.add(scene.add.text(0, -80, v.name, { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '22px', color: '#7ce0c0', align: 'center', fontStyle: 'bold', wordWrap: { width: 170 } }).setOrigin(0.5)); + cont.add(scene.add.text(0, 20, v.desc, { fontFamily: 'm6x11, "Julius Sans One"', fontSize: '16px', color: C.ink, align: 'center', wordWrap: { width: 165 } }).setOrigin(0.5)); } cont.setSize(190, 250); scene.add2(cont); diff --git a/src/scenes/PreloadScene.js b/src/scenes/PreloadScene.js index 4a91139..99558c7 100644 --- a/src/scenes/PreloadScene.js +++ b/src/scenes/PreloadScene.js @@ -261,9 +261,10 @@ export default class PreloadScene extends Phaser.Scene { }); } - // Warm the handwritten Scrabble notepad font so its first paint isn't a - // fallback face. Best effort — never block startup on it. - try { await Promise.race([document.fonts.load('48px YummyCupcakes'), new Promise(r => setTimeout(r, 1500))]); } catch { /* ignore */ } + // Warm the handwritten Scrabble notepad font and Balatro's pixel font so + // their first paint isn't a fallback face. Best effort — never block + // startup on them. + try { await Promise.race([Promise.all([document.fonts.load('48px YummyCupcakes'), document.fonts.load('48px m6x11')]), new Promise(r => setTimeout(r, 1500))]); } catch { /* ignore */ } await auth.refresh(); this.scene.start('Landing'); diff --git a/styles.css b/styles.css index 98c85dd..e4d5b37 100644 --- a/styles.css +++ b/styles.css @@ -26,6 +26,13 @@ font-style: normal; } +@font-face { + font-family: 'm6x11'; + src: url('assets/fonts/m6x11.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + html, body { margin: 0; padding: 0;