Skip to main content

Quickstart Guide

This guide will walk you through creating your first Atlas Engine application. You’ll create a window, set up a camera, add 3D objects, and implement basic lighting.

Prerequisites

Before starting, ensure you have:
  • Atlas Engine installed (Installation Guide)
  • A C++ compiler with C++20 support
  • CMake 3.15 or higher

Project Setup

1

Create a New Project

Create a new directory for your project:
mkdir my-atlas-game
cd my-atlas-game
2

Create CMakeLists.txt

Create a CMakeLists.txt file:
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(MyAtlasGame)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Find Atlas Engine (adjust path as needed)
find_package(atlas REQUIRED)

add_executable(my_game main.cpp)
target_link_libraries(my_game PRIVATE atlas)
3

Create the Main Source File

Create main.cpp with a basic structure:
main.cpp
#include "atlas/window.h"
#include "atlas/scene.h"
#include "atlas/camera.h"

int main() {
    // Your code will go here
    return 0;
}

Creating Your First Window

Let’s create a basic window with Atlas Engine:
main.cpp
#include "atlas/window.h"
#include "atlas/scene.h"
#include "atlas/camera.h"
#include "atlas/object.h"
#include "atlas/light.h"

int main() {
    // Configure the window
    Window window({
        .title = "My First Atlas Game",
        .width = 1280,
        .height = 720,
        .renderScale = 0.75f,
        .mouseCaptured = true,
        .multisampling = true
    });
    
    // Start the main loop
    window.run();
    
    return 0;
}
The .renderScale parameter controls internal rendering resolution. Values below 1.0 improve performance by rendering at a lower resolution and upscaling.

Creating a Scene

Scenes organize your game objects, lights, and environment. Let’s create a custom scene:
main.cpp
#include "atlas/window.h"
#include "atlas/scene.h"
#include "atlas/camera.h"
#include "atlas/object.h"
#include "atlas/light.h"

class GameScene : public Scene {
    Camera camera;
    CoreObject ground;
    CoreObject cube;
    DirectionalLight sun;
    
public:
    void initialize(Window &window) override {
        // Set up camera
        camera = Camera();
        camera.setPosition({0.0f, 2.0f, 5.0f});
        camera.lookAt({0.0f, 0.0f, 0.0f});
        window.setCamera(&camera);
        
        // Create ground plane
        ground = createBox({10.0f, 0.1f, 10.0f}, Color::white());
        ground.setPosition({0.0f, -0.1f, 0.0f});
        ground.initialize();
        window.addObject(&ground);
        
        // Create a cube
        cube = createBox({1.0f, 1.0f, 1.0f}, Color(1.0f, 0.5f, 0.2f));
        cube.setPosition({0.0f, 0.5f, 0.0f});
        cube.initialize();
        window.addObject(&cube);
        
        // Add directional light (sun)
        sun = DirectionalLight();
        sun.direction = {-0.3f, -1.0f, -0.5f};
        sun.setColor(Color(1.0f, 0.95f, 0.9f));
        sun.intensity = 1.5f;
        this->addDirectionalLight(&sun);
        
        // Set ambient lighting
        this->setAmbientIntensity(0.3f);
    }
    
    void update(Window &window) override {
        // Update camera with WASD controls
        camera.update(window);
        
        // Rotate the cube
        cube.rotate({0.0f, window.getDeltaTime() * 45.0f, 0.0f});
    }
    
    void onMouseMove(Window &window, Movement2d movement) override {
        // Update camera look direction
        camera.updateLook(window, movement);
    }
};

int main() {
    Window window({
        .title = "My First Atlas Game",
        .width = 1280,
        .height = 720,
        .renderScale = 0.75f,
        .mouseCaptured = true
    });
    
    GameScene scene;
    window.setScene(&scene);
    window.run();
    
    return 0;
}
Objects added to the window (like ground and cube) must remain valid for the entire lifetime of the window. Declare them as class members, not local variables in initialize().

Adding Multiple Objects

You can create more complex scenes with multiple objects:
class GameScene : public Scene {
    Camera camera;
    CoreObject ground;
    std::vector<CoreObject> cubes;
    DirectionalLight sun;
    
public:
    void initialize(Window &window) override {
        // Camera setup
        camera.setPosition({0.0f, 3.0f, 8.0f});
        camera.lookAt({0.0f, 0.0f, 0.0f});
        window.setCamera(&camera);
        
        // Ground
        ground = createBox({15.0f, 0.1f, 15.0f}, Color::white());
        ground.setPosition({0.0f, -0.1f, 0.0f});
        ground.initialize();
        window.addObject(&ground);
        
        // Create a grid of cubes
        for (int x = -2; x <= 2; x++) {
            for (int z = -2; z <= 2; z++) {
                CoreObject cube = createBox(
                    {0.8f, 0.8f, 0.8f},
                    Color(0.2f + x * 0.2f, 0.5f, 0.2f + z * 0.2f)
                );
                cube.setPosition({x * 2.0f, 0.4f, z * 2.0f});
                cube.initialize();
                cubes.push_back(cube);
                window.addObject(&cubes.back());
            }
        }
        
        // Lighting
        sun.direction = {-0.3f, -1.0f, -0.5f};
        sun.setColor(Color::white());
        sun.intensity = 1.5f;
        this->addDirectionalLight(&sun);
        this->setAmbientIntensity(0.3f);
    }
    
    void update(Window &window) override {
        camera.update(window);
        
        // Animate cubes
        float time = window.getTime();
        for (size_t i = 0; i < cubes.size(); i++) {
            float offset = i * 0.5f;
            float height = 0.4f + sin(time + offset) * 0.3f;
            Position3d pos = cubes[i].getPosition();
            pos.y = height;
            cubes[i].setPosition(pos);
        }
    }
    
    void onMouseMove(Window &window, Movement2d movement) override {
        camera.updateLook(window, movement);
    }
};

Creating Spheres and Other Shapes

Atlas Engine provides several built-in shape creation functions:
// Create a sphere
CoreObject sphere = createSphere(
    0.5,    // radius
    36,     // sector count (longitude divisions)
    18,     // stack count (latitude divisions)
    Color(0.8f, 0.2f, 0.2f)
);
sphere.setPosition({2.0f, 1.0f, 0.0f});
sphere.initialize();
window.addObject(&sphere);

// Create a plane
CoreObject plane = createPlane(
    {5.0f, 5.0f},  // size
    Color(0.3f, 0.7f, 0.3f)
);
plane.initialize();
window.addObject(&plane);

// Create a pyramid
CoreObject pyramid = createPyramid(
    {1.0f, 1.5f, 1.0f},  // size
    Color(0.9f, 0.7f, 0.2f)
);
pyramid.setPosition({-2.0f, 0.75f, 0.0f});
pyramid.initialize();
window.addObject(&pyramid);

Using Instanced Rendering

For rendering many copies of the same object efficiently, use instanced rendering:
CoreObject cube = createBox({0.5f, 0.5f, 0.5f}, Color::red());
cube.setPosition({0.0f, 0.25f, 0.0f});

// Create instances
for (int i = 0; i < 10; i++) {
    Instance &instance = cube.createInstance();
    instance.move({0.0f, i * 0.6f, 0.0f});
}

cube.initialize();
window.addObject(&cube);
Instanced rendering dramatically improves performance when rendering many identical objects. All instances share the same geometry and material but can have unique transforms.

Building and Running

1

Configure with CMake

mkdir build
cd build
cmake ..
2

Build the Project

make
On Windows with Visual Studio:
cmake --build . --config Release
3

Run Your Game

./my_game
You should see a window with your 3D scene!

Camera Controls

The default camera implementation supports:
  • WASD - Move forward/left/backward/right
  • Space - Move up
  • Left Shift - Move down
  • Mouse - Look around (when mouse is captured)
  • Escape - Release mouse capture
You can customize camera movement speed:
camera.movementSpeed = 5.0f;      // Default is 2.0
camera.mouseSensitivity = 0.15f;  // Default is 0.1

Adding Materials

Customize object appearance with PBR materials:
CoreObject metalCube = createBox({1.0f, 1.0f, 1.0f});
metalCube.material.albedo = Color(0.8f, 0.8f, 0.8f);
metalCube.material.metallic = 1.0f;   // Fully metallic
metalCube.material.roughness = 0.2f;  // Smooth surface
metalCube.material.ao = 1.0f;         // No ambient occlusion
metalCube.initialize();

Next Steps

Now that you have a basic scene running, explore more features:

Physics

Add rigid body physics and collisions to your objects

Audio

Integrate spatial 3D audio into your scene

Textures

Apply textures and normal maps to objects

Advanced Lighting

Use point lights, spotlights, and shadows

Common Patterns

Here are some useful patterns from the Atlas Engine test suite:

FPS Counter

class FPSTextUpdater : public TraitComponent<Text> {
public:
    void updateComponent(Text *object) override {
        int fps = static_cast<int>(getWindow()->getFramesPerSecond());
        object->content = "FPS: " + std::to_string(fps);
    }
};

// In your scene:
Text fpsText = Text(
    "FPS: 0",
    Font::fromResource("Arial", fontResource, 24),
    {25.0, 25.0},
    Color::white()
);
fpsText.addTraitComponent<Text>(FPSTextUpdater());
window.addUIObject(&fpsText);

Compound Objects

class SphereCube : public CompoundObject {
    CoreObject sphere;
    CoreObject cube;
    
public:
    void init() override {
        cube = createDebugBox({0.5f, 0.5f, 0.5f});
        cube.setPosition({-1.0f, 0.0f, 0.0f});
        cube.initialize();
        this->addObject(&cube);
        
        sphere = createDebugSphere(0.25f);
        sphere.setPosition({1.0f, 0.0f, 0.0f});
        sphere.initialize();
        this->addObject(&sphere);
    }
};
Congratulations! You’ve created your first Atlas Engine application. Check out the API reference for more advanced features.

Build docs developers (and LLMs) love