DEV Community

Cover image for How I Built a Block Puzzle Game with React Native and Expo
Muhammad Akbar
Muhammad Akbar

Posted on

How I Built a Block Puzzle Game with React Native and Expo

How I Built a Block Puzzle Game with React Native and Expo

A few weeks ago, I launched my first mobile game — a block puzzle called Blockbeam. It's an 8x8 grid where you drag colorful blocks, fill rows and columns, and chase high scores. Simple concept, but building it taught me a lot about React Native's capabilities beyond typical CRUD apps.

Here's what I learned.

Why React Native for Games?

Most mobile games are built with Unity or native code. But for a 2D puzzle game, React Native is surprisingly capable. The game doesn't need 60fps 3D rendering — it needs gesture handling, state management, and smooth animations. React Native handles all three well.

The key stack:

  • Expo SDK 54 — managed workflow, over-the-air updates, zero native config
  • react-native-reanimated — 60fps drag animations
  • react-native-gesture-handler — PanResponder for drag-and-drop
  • react-native-svg — block rendering
  • AsyncStorage — game state persistence

The Puzzle Engine

The core of any block puzzle is the board state. I used a flat 64-element array for the 8x8 grid:

const BOARD = 8;
const CELLS = BOARD * BOARD; // 64
type Board = number[]; // 0 = empty, 1-7 = block colors
Enter fullscreen mode Exit fullscreen mode

Piece placement is straightforward: check if all target cells are empty, fill them, then scan for complete rows and columns to clear.

The interesting part was the "greedy solver" I built for the auto-play bot. It tries every piece in every position and picks the move that clears the most lines:

for (const piece of tray) {
  for (let r = 0; r <= BOARD - piece.h; r++) {
    for (let c = 0; c <= BOARD - piece.w; c++) {
      if (!canPlace(board, piece, r, c)) continue;
      const score = simulateClear(board, piece, r, c);
      if (score > bestScore) { /* pick this move */ }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Drag and Drop with PanResponder

The trickiest part was the drag mechanic. Each tray piece has a PanResponder that tracks touch position and renders a floating ghost. On release, it calculates the nearest cell position:

const anchor = {
  col: Math.round((drag.x - boardLayout.x) / cell),
  row: Math.round((drag.y - LIFT - piece.h * cell - boardLayout.y) / cell),
};
Enter fullscreen mode Exit fullscreen mode

The LIFT offset accounts for the finger being above the piece — a subtle UX detail that makes dragging feel natural.

What I'd Do Differently

  1. Start with TypeScript — Caught dozens of bugs at compile time
  2. Test on real devices early — Emulators don't reveal performance issues
  3. Plan the theme system earlier — Adding palette switching after the fact was messy

The Result

The game is live on Google Play, completely free with no paywalls. 100% offline, 6 color themes, daily rewards, and power-ups.

If you're building a casual game, don't overthink the tech stack. React Native + Expo can take you surprisingly far.

Check it out: https://play.google.com/store/apps/details?id=com.magstudios.blockpuzzle


Built with React Native, Expo, and way too much coffee. Solo dev from Pakistan.

Top comments (0)