Skip to content
Work in Progress

Pixel Art Game Development: What I Learned Hitting the Walls

These are my honest notes from building a pixel-art game inside a Next.js portfolio, with AI assisting much of the code. The game started as a fork of another developer's portfolio, and the hardest unsolved problems turned out to be in the art, not the code. AI-generated character sprites kept coming out with the wrong proportions at small sizes like 16×16 and 32×32: heads too big, limbs misaligned, walk cycles that looked robotic. Keeping a tileset cohesive was a systems problem too, because everything has to share one palette, one pixel density, and one art style, or the whole scene reads inconsistent. Even the code had friction: running a game engine (Phaser) inside a framework that server-renders by default meant every import crashed the build until I isolated it with a no-SSR dynamic import.

The game itself is a Pokemon-style world you walk through to explore my career story: themed buildings, NPC dialogue, grid-based movement, and collision. It works, and you can play the current version. But this stays the most honest page on the site, because that honesty is the point. What follows is what works, what still looks like a prototype rather than a finished piece, and what I actually learned about where AI-assisted game development falls short.

Play the current version

Game mechanics that work

  • Grid-based character movement with 4-directional walking
  • Overworld map with themed buildings (Innovation Labs, Leadership Tower, Tech Hub)
  • Building interaction system, walk up, press Enter, get dialogue
  • Pokemon-style dialogue box with professional content
  • Animated water with wave effects
  • Mobile touch controls (D-pad overlay)
  • Dynamic loading via Next.js dynamic import (no SSR for Phaser)

Pixel art for game developers: where AI and small sprites break down

Building a game inside a web framework designed for documents is full of friction. Here's every major problem encountered, solved or not.

Phaser.js + Next.js SSR conflict

Solved

Phaser requires the DOM and window object. Next.js server-renders by default. Every Phaser import crashed the build. Solution: dynamic(() => import(...), { ssr: false }) wrapper. Took multiple iterations to get right.

Programmatic vs hand-drawn pixel art sprites

Open

The initial approach generated pixel art via HTML5 Canvas at runtime, colored rectangles for buildings, basic shapes for the character. It works technically but looks like a prototype, not a portfolio piece. Professional tilesets are needed.

Pixel art character sprite proportions (16×16, 32×32)

Open

AI-generated pixel art characters kept having wrong proportions, heads too big, limbs misaligned, walk cycles that looked robotic. Pixel art is a specialized skill that current AI tools struggle with at small sprite sizes (16×16, 32×32).

Tileset consistency: shared palette and pixel density

Open

Mixing programmatic sprites with hand-drawn or AI-generated tiles creates visual inconsistency. Everything needs to share the same palette, pixel density, and art style. This requires either commissioning a tileset or finding a cohesive free pack.

Mobile performance

Managed

Phaser.js game engine running inside a React app inside a mobile browser is three layers of overhead. Touch controls need to be responsive without interfering with browser gestures (scroll, back swipe). Ongoing tuning.

Name attribution in forked assets

Solved

The game was initially forked from another developer's portfolio. Original names were embedded deep in sprite filenames, frame references, and game config. Required a full audit to rename every reference, 15+ files touched.

Choosing the stack: Phaser over CSS, and running it in Next.js

Phaser.js over CSS animations

Needed real game mechanics: collision detection, sprite management, camera following, tile maps. CSS can't do this.

Dynamic import, no SSR

Phaser needs window/DOM. Wrapping in dynamic(() => import(), { ssr: false }) isolates it from Next.js server rendering.

Programmatic sprites (for now)

Faster to iterate than managing sprite sheets. Will replace with professional assets once the game mechanics are solid.

Separate /game route

Game is heavy (~200KB component). Isolating it prevents impact on homepage load performance and SEO.

How the game is built

01

Game Engine

Phaser.js 3

Handles rendering, physics, input, sprites, camera. Runs in a canvas element inside the React tree.

02

React Wrapper

Next.js dynamic import

HomepageGame component (208 lines) loaded client-side only. Manages Phaser lifecycle within React.

03

Assets

Programmatic (Canvas API)

Sprites generated at runtime via Canvas. No external sprite sheets yet, this is the main quality bottleneck.

04

Interaction

Keyboard + Touch

Arrow keys on desktop, virtual D-pad on mobile. Enter key triggers building dialogues.

What's next for the game

  • Professional tileset, cohesive 16-bit art style
  • Proper character sprite with smooth walk animation
  • Interactive career exploration, enter buildings to learn about each role
  • NPC dialogues with career highlights
  • Sound design, ambient music, interaction sounds

More build logs