Skip to content

Hello, Dynamo

Keith Leonardo edited this page May 20, 2020 · 8 revisions

First Dynamo program

All Dynamo components can be accessed from a single header under the namespace Dynamo. The main() function acts merely as an entry point for the application as the state changes happen in an individual Scene. These scenes are updated and managed internally by Dynamo::Engine.

#include <Dynamo.h>

int main(int argc, char **argv) {
    // Initial window size and logical dimensions
    int width = 640, height = 480;

    Dynamo::Engine engine("Hello, world!", width, height);

    // Game loop
    while(engine.is_running()) {
        engine.run();
    }
    return 0;
}

This program should initialize a blank window and immediately terminate. This is because there are no scenes to update. In order for the program to persist, a new Scene must be created.

If the program does not compile, make sure that all dependencies have been installed. Refer to the Home page and README for this list.

Creating a new Scene

class MyScene : public Dynamo::Scene {
public:
    void load(Dynamo::Core &core) override;
    
    void unload(Dynamo::Core &core) override;
    
    void update(Dynamo::Core &core) override;

    void draw(Dynamo::Renderer &renderer) override;
};

This class will be the first scene. It is recommended to forward declare scenes to prevent circular dependencies in transitioning between them. There are four virtual methods that can be implemented:

  • load() is called on scene entry and is responsible for resource allocation.
  • unload() is called on scene termination; deallocate resources here.
  • update() handles all internal state changes such as input handling and game logic.
  • draw() renders all drawable objects to the display.

Notice that draw() only takes a single Dynamo::Renderer. It does not have access to the other core modules. Similarly, update(), load(), and unload() do not have access to Dynamo::Renderer.

This is because Dynamo enforces a strict single-responsibility principle by separating updating and rendering. Hence, any shared state should be initialized in load(), calculated in update(), then stored within the Scene object itself so it can be accessed by draw().

Doing stuff in a Scene

Let's make this first application simply fill the display with a color.

void MyScene::load(Dynamo::Core &core) {}

void MyScene::unload(Dynamo::Core &core) {}

void MyScene::update(Dynamo::Core &core) {}

void MyScene::draw(Dynamo::Renderer &renderer) {
    Dynamo::Color white = {255, 255, 255};
    renderer.set_fill(white);
}

Defining these functions, it should simply fill the display with white.

Setting the initial Scene

Finally, this scene needs to be pushed as the starting point of the application. This is done using the engine's push_scene() template method.

int main(int argc, char **argv) {
    // Initial window size and logical dimensions
    int width = 640, height = 480;

    Dynamo::Engine engine("Hello, world!", width, height);
    engine.push_scene<MyScene>(); // Load the initial scene

    // Game loop
    while(engine.is_running()) {
        engine.run();
    }
    return 0;
}

Congratulations! You have created your first Dynamo application. The full source code from this tutorial can be found in initialize.cpp in the demos folder. Refer to this wiki for documentation on all other aspects of the engine.

Clone this wiki locally