You are browsing as a guest. Sign up (or log in) to start making projects!

GameFrame

  • 1 Devlogs
  • 8 Total hours

A 3d game engine that runs in your browser!

Open comments for this post

8h 19m 8s logged

Devlog-1:

Making the canva for video games!!!

The Tech Stack

I wanted this engine to run natively in the browser without massive downloads, so I chose:

  • React + Vite for the frontend UI and state management.

  • Three.js & React-Three-Fiber (R3F) for the 3D rendering pipeline.

  • Cannon-es (@react-three/cannon) for rigid-body physics.

  • Zustand for lightweight, blazing-fast state management.

  • React Flow (@xyflow/react) for the Visual Scripting node editor.

    1. Building the ECS (Entity-Component System) in Zustand

Most React apps map data to UI components linearly, but game engines need an Entity-Component System (ECS) to handle hundreds of objects dynamically. I built a custom ECS using Zustand.

    // The core engine state powering the ECS
    interface EngineState {
      entities: Record<string, Entity>;
      addEntity: (name: string) => string;
      addComponent: (entityId: string, componentType: ComponentType) => void;
      updateComponent: (entityId: string, componentType: ComponentType, data: any) => void;
    }

This allows the engine’s Outliner and Inspector panels to dynamically edit any object in the scene in real-time, just like Unity or Unreal.

2. The Visual Scripting Compiler

The coolest feature I got working today was the Visual Script Editor. I used React Flow to let users connect nodes (like “On Update” -> “Move To Player”). But how does a node graph become executable game?

I wrote a compiler that traverses the node graph and translates it into a raw JavaScript string. This string is saved into the entity’s script component and executed dynamically in the game loop using a
Function constructor!

    // A snippet of the compiler output injected into the game loop
    } else if (node.data.label === 'Enemy: Move To Player') {
      output += `
        if (api.velocity) {
          const toPlayer = camera.position.clone().sub(mesh.position);
          toPlayer.y = 0;
          toPlayer.normalize();
          api.velocity.set(toPlayer.x * 4, -1, toPlayer.z * 4);
        }
      `;
    }

3. Bypassing React for Performance

The biggest hurdle today was the physics loop. Initially, the enemy tracking script updated the Zustand state every frame. With 15 enemies running at 60fps, it was triggering 900 React state updates a second, completely freezing the browser!

The novel solution for this was bypassing React’s render lifecycle entirely for physics. Instead of updating the state.entities transform data, the compiled scripts now directly tap into the raw Cannon-es physics
API (api.velocity.set()), mutating the physics hull natively. The performance skyrocketed from a frozen screen to a buttery smooth 60fps.

0
0
24

Delete project?

Are you sure you want to permanently delete this project? This action cannot be undone.

All devlogs, followers, and associated data will be removed.

Followers

Loading…