DEV Community

Cover image for v0.1.0 Done
Weird Codes
Weird Codes

Posted on

v0.1.0 Done

Mobile performance optimization patch.

ЁЯХЙя╕П рдореЛрдХреНрд╖ Devlog тАФ v0.1.1 Milestone

рджрд┐рдирд╛рдВрдХ: 17 рдЕрдЧрд╕реНрдд 2026
рдмрд┐рд▓реНрдб: v0.1.1 (upcoming patch)
рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо: itch.io ┬╖ GitHub


ЁЯОп v0.1.1 рдХреНрдпрд╛ рд╣реИ?

v0.1 milestone 100% complete рд╣реБрдЖ тАФ 95/95 issues closedред ЁЯОЙ

рдЕрдЧрд▓рд╛ рдкрдбрд╝рд╛рд╡ рд╣реИ v0.1.1 тАФ рдПрдХ focused performance patch рдЬреЛ mobile devices рдкрд░
рдореЛрдХреНрд╖ рдХреЛ smoother рдмрдирд╛рдПрдЧрд╛ред рдХреЛрдИ рдирдпрд╛ feature рдирд╣реАрдВ тАФ рд╕рд┐рд░реНрдл optimizationред

v0.1 milestone is 100% complete тАФ 95/95 issues closed.
Next up is v0.1.1 тАФ a focused performance patch to make Moksha smoother on mobile.
No new features тАФ pure optimization.


ЁЯФН рд╕рдорд╕реНрдпрд╛ рдХреА рдЬрдбрд╝ / Root of the Problem

рдореЛрдХреНрд╖ рдкреВрд░реА рддрд░рд╣ HTML5 Canvas 2D рдкрд░ рдмрдирд╛ рд╣реИ тАФ рдХреЛрдИ game engine рдирд╣реАрдВред
рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣рд░ frame рдореЗрдВ рд╣рдо рдЦреБрдж GPU рдХреЛ instructions рджреЗрддреЗ рд╣реИрдВред

рддреАрди operations рд╣реИрдВ рдЬреЛ mobile GPU рдкрд░ рд╕рдмрд╕реЗ рдЬрд╝реНрдпрд╛рджрд╛ cost рдХрд░рддреЗ рд╣реИрдВ:

Moksha is built entirely on HTML5 Canvas 2D тАФ no game engine.
This means every frame we give instructions to the GPU directly.
Three operations are the heaviest on mobile GPU:


ЁЯРЫ Issue #96 тАФ shadowBlur per-frame GPU cost

рд╕рдорд╕реНрдпрд╛

render.js рдореЗрдВ shadowBlur рд╣рд░ frame 77 рдмрд╛рд░ set рд╣реЛрддрд╛ рд╣реИред

shadowBlur рдПрдХ expensive GPU operation рд╣реИ тАФ рд╣рд░ рдмрд╛рд░ рдПрдХ blur pass trigger рд╣реЛрддрд╛ рд╣реИред
Mobile рдкрд░ (рд╡рд┐рд╢реЗрд╖рдХрд░ Firefox рдкрд░) рдпрд╣реА FPS drop рдХрд╛ рд╕рдмрд╕реЗ рдмрдбрд╝рд╛ рдХрд╛рд░рдг рд╣реИред

// рдпрд╣ 77 рдмрд╛рд░ рд╣рд░ frame рд╣реЛрддрд╛ рд╣реИ тАФ рдмрд╣реБрдд рдЬрд╝реНрдпрд╛рджрд╛
ctx.shadowBlur = 18;
// ... draw ...
ctx.shadowBlur = 0;
Enter fullscreen mode Exit fullscreen mode

рд╣рд▓ (planned)

  • Low-end device рдкрд░ shadowBlur = 0 (quality tier system)
  • рд╣рд░ draw block рдореЗрдВ ctx.save() / ctx.restore() рд╕реЗ leak рд░реЛрдХреЗрдВ
  • Critical visuals рдкрд░ рд╣реА shadowBlur рд░рдЦреЗрдВ, рдмрд╛рдХреА рд╣рдЯрд╛рдПрдБ

ЁЯРЫ Issue #97 тАФ Per-frame uncached gradients

рд╕рдорд╕реНрдпрд╛

рдиреАрдЪреЗ рджрд┐рдП gradients рд╣рд░ frame рдирдП рдмрдирддреЗ рд╣реИрдВ тАФ GC pressure + GPU cost:

Location Gradient рд╣рд░ frame рдХрд┐рддрдиреА рдмрд╛рд░
drawPickupGlowIcon() Radial рд╣рд░ maya entity рдкрд░
Rein draw Linear рд╣рд░ 6 рдШреЛрдбрд╝реЛрдВ рдкрд░
Naama maya Radial рд╣рд░ naama entity рдкрд░
Chakravaata Radial рд╣рд░ chakravaata рдкрд░
// рдпрд╣ рд╣рд░ frame naama рдХреЗ рд▓рд┐рдП рдирдпрд╛ рдмрдирддрд╛ рд╣реИ тАФ wasteful
let nGrad = ctx.createRadialGradient(ncx, ncy, 0, ncx, ncy, r + pulse * 4);
Enter fullscreen mode Exit fullscreen mode

рд╣рд▓ (planned)

  • drawPickupGlowIcon() тЖТ offscreen sprite cache рдореЗрдВ bake рдХрд░реЗрдВ
  • Naama, chakravaata gradients тЖТ bucket-cached (size key рд╕реЗ)
  • Rein gradient тЖТ karma ratio bucket рд╕реЗ cache рдХрд░реЗрдВ

ЁЯРЫ Issue #98 тАФ Trig caching for orbit rendering

рд╕рдорд╕реНрдпрд╛

outerOrbits рдФрд░ innerOrbit rendering рдореЗрдВ Math.sin / Math.cos
рд╣рд░ frame, рд╣рд░ entity рдкрд░ compute рд╣реЛрддрд╛ рд╣реИред

// рд╣рд░ orbit entity рдкрд░ рд╣рд░ frame рдпрд╣ рдЪрд▓рддрд╛ рд╣реИ
let angle = (renderTime * orbit.speed) + (i * (Math.PI * 2 / orbit.count));
let dx = cx + Math.cos(angle) * actualDist;  // тЖР expensive
let dy = cy + Math.sin(angle) * actualDist;  // тЖР expensive
Enter fullscreen mode Exit fullscreen mode

рд╣рд▓ (planned)

360-entry lookup table (LUT) рдЬреЛ рдПрдХ рдмрд╛рд░ pre-compute рд╣реЛ:

// рдПрдХ рдмрд╛рд░ тАФ startup рдкрд░
const SIN_LUT = new Float32Array(360);
const COS_LUT = new Float32Array(360);
for (let i = 0; i < 360; i++) {
    SIN_LUT[i] = Math.sin((i * Math.PI) / 180);
    COS_LUT[i] = Math.cos((i * Math.PI) / 180);
}

// рд╣рд░ frame тАФ O(1) lookup, zero trig cost
const idx = Math.round(angleDeg) % 360;
const x = cx + COS_LUT[idx] * dist;
const y = cy + SIN_LUT[idx] * dist;
Enter fullscreen mode Exit fullscreen mode

ЁЯУЛ v0.1.1 Milestone Issues

Issue Title Label
#96 perf: reduce shadowBlur calls performance
#97 perf: cache per-frame gradients performance
#98 perf: sin/cos LUT for orbit rendering performance

ЁЯОп Expected Impact

Metric рдЕрднреА / Now рдмрд╛рдж / After
shadowBlur calls/frame ~77 ~15
Gradient allocations/frame ~6 ~0
Trig calls/frame (orbits) ~200+ ~0
Mobile FPS (target) 30-45fps 60fps

ЁЯФЧ Links

ЁЯОо itch.io weirdcodes.itch.io/moksha
ЁЯТ╗ GitHub github.com/weirdcodesofficial/MOKSHA
ЁЯРШ Mastodon @pjatmasto
ЁЭХП X @weirdcodesx
тЦ╢я╕П YouTube @weirdcodes-official

Human-designed, AI-assisted. рд╕рднреА рд╢рд╛рд╕реНрддреНрд░реАрдп рдФрд░ рд░рдЪрдирд╛рддреНрдордХ рдирд┐рд░реНрдгрдп Weired Codes рджреНрд╡рд╛рд░рд╛ред

Top comments (0)