Setting Up a Data Driven Babylon.js Game with Vite and TypeScript

Ready to dive into the world of 3D game development with Babylon.js? Awesome! We'll get you up and running with a brand-new project using Vite for lightning-fast development, TypeScript for type safety, and of course, the powerful Babylon.js framework. We'll even set up a simple data structure to hold information about our game world.

Project Setup: A Breeze with Vite

First things first, let's create our project using Vite. Open your terminal and run:

npm create vite@latest my-babylon-game --template typescript

Replace "my-babylon-game" with your preferred project name. This command will create a new folder with all the basic project files.

Next, navigate into your new project directory:

cd my-babylon-game

Now, install the essential dependencies:

npm install babylonjs @babylonjs/core @babylonjs/loaders

Configuring Vite for TypeScript and Babylon.js

Open your vite.config.ts file and update it to include Babylon.js:

import { defineConfig } from 'vite';

export default defineConfig({
  root: './',
  publicDir: 'public',
  build: {
    outDir: 'dist',
    emptyOutDir: true,
  },
  server: {
    host: true
  }
});

Setting Up Your Scene Data

Let's create a "data" folder in the root of your project and add a scene.json file inside it. This file will hold information about our game world. Here's a simple structure:

{
  "entities": {
    "World": {
      "components": {
        "Asset": {
          "name": "World",
          "path": "glbs/world.glb"
        },
        "World": {
          "gravity": -9.81
        }
      }
    },
    "Player": {
      "components": {
        "Asset": {
          "name": "Player",
          "path": "glbs/player.glb"
        },
        "Player": {
          "lives": 3,
          "inputType": "keyboard"
        },
        "InputKeyboard": {
          "keyMappings": {
            "w": "forward",
            "s": "backward",
            "a": "left",
            "d": "right",
            " ": "spacebar",
            "control": "control",
            "shift": "shift",
            "alt": "alt",
          }
        },
        "Movement": {
          "position": [0, 0, 0],
          "walkingSpeed": 1,
          "runningSpeed": 800,
          "jumpingSpeed": 5,
          "rotationSpeed": 50
        },
      }
    }
}

Creating Your First Babylon.js Scene

Now, let's create a simple Babylon.js scene. Open your main.ts file and replace its content with the following:

// File: main.ts
import { Engine } from "@babylonjs/core";
import { DD } from "./lib/DD";
import "@babylonjs/core/Debug/debugLayer"; // Import the debug layer
import "@babylonjs/inspector"; // Import the inspector

document.addEventListener("DOMContentLoaded", async () => {
  // Ensure the DOM is fully loaded before attempting to access the canvas
  const canvas = document.getElementById("renderCanvas") as HTMLCanvasElement; // Adjust the ID as needed
  const engine = new Engine(canvas, true, {
    deterministicLockstep: true,
    lockstepMaxSteps: 4,
  });

  // Create the game instance and initialize the scene
  const game = new DD(engine, "RPG");
  const scene = game.sceneManager.currentScene;

  window.addEventListener("keydown", (event) => {
    if (event.key === "i") {
      if (scene.debugLayer.isVisible()) {
        scene.debugLayer.hide();
      } else {
        scene.debugLayer.show();
      }
    }
  });

  let lastTime = performance.now();

  engine.runRenderLoop(() => {
    // Calculate deltaTime in seconds
    const now = performance.now();
    const deltaTime = (now - lastTime) / 1000.0;
    lastTime = now;

    // Update game systems with deltaTime
    // Assuming RPG class has a method to update all game systems
    game.sceneManager.updateSystems(deltaTime);
    if (scene.activeCamera) scene.render();
  });

  window.addEventListener("resize", () => {
    engine.resize();
  });
});

What's Next?

You now have a solid foundation for your Babylon.js game! Next steps? We'll load scene data from scene.json, create entities, add components, and systems to bring your game world to life!