Getting Started

A Rayve program consists of objects for the engine, scenes, overlays and entities. Example code for each is given below as a starting point. See the reference section for documentation of individual objects and methods used in the examples.

PO2B = Rayve's power-of-2 buffered memory.

Windows Main

// Create the windows main entry point function.
void WinMain()
{
    // The API must be created first.
    API api(L"Raylogic", L"Lab");

    // Exit codes control the program flow between scenes.
    int exitCode = 2;
    
    // Create the engine after the API is created.
    Engine engine;

    // Set any desired engine parameters before the engine is started.
    engine.SetWindow(L"Lab", .5f, 0, 0, EngCfg::WINDOW_BORDERLESS);
    engine.SetProbeMode(EngCfg::ProbeMode::METRICS);
    engine.SetNormMapRange(30);

    // Start the engine. The main window should open if the engine started successfully.
    engine.Start();

    // The exit code directs the engine to the next scene or to the end the program.
    while (exitCode > 0)
        switch (exitCode)
        { 
        case 1:
            // Create a scene using PO2B syntax.
            new (engine.AllocScene()) Title::Scene;

            // Access the created scene using the predfined global SCN().
            // When a scene is run, the engine has control of execution until a non-zero exit code is set.
            exitCode = SCN().Run();

            break;
        case 2:
            // A new scene was requested by the previous scene.
            new (engine.AllocScene()) GameLevel::Scene;

            // Run the new scene
            exitCode = SCN().Run();

            break;
        }
        
    // A negative exit code was received and the program exits.
    // C++ will release the Rayve objects declared in this function in 
    // the reverse order they were created, enabling a clean shutdown.
}

Scene

Scene Header
// Recommend keeping all objects related to a game level in their own namespace.
namespace MyGameLevel
{
    // Define a scene class for the game level by subclassing the Ravye scene class.
    class Scene : public Rayve::Scene
    {
    public:
        // Constructor for the scene.
        Scene();
        
        // Destructor for the scene. Override the base Rayve scene class destructor.
        ~Scene() override;

    protected:
        // OnBgnUpd() is called each frame before entity updates begin.
        void OnBgnUpd() override;

        // OnEndUpd() is called each frame after entity updates end.
        void OnEndUpd() override;

    private:
        // This scene class is using logic states.
        RVSTATEFUNCS(Scene);

        // A state used by the scene to wait on the title overlay.
        void OnWaitTitle();
        
        // A state used by the scene for normal scene processing.
        void OnDefault();
    };
}
Scene Code
// The namespace this scene belongs to.
namespace MyGameLevel
{
    // Scene calls this for each entity during first update pass.
    void Scene::OnBgnUpd()
    {
        // Any global logic outside of states can go here.
        
        // Run current state.
        RVBGNUPDSTATE;
    }

    // This state waits on the title overlay to exit.
    void Scene::OnWaitTitle()
    {
        // Wait until overlay indicates an exit.
        if (OVL().GetExitCode() > 0)
        {
            // Delete the title overlay and create the game overlay using PO2B syntax.
            new (AllocOverlay()) Overlay();
            
            // Redirect updates to the OnDefault() state.
            SetBgnUpdState(&Scene::OnDefault);
            
            // Don't show the cursor in the game scene.
            Input::ShowCursor(false);
            
            // Want to see probe metrics.
            EnableProbe();
        }
    }

    // Normal game scene logic.
    void Scene::OnDefault()
    {
        // If escape is pressed, switch to title overlay.
        if (Input::PopKey(Key::ESCAPE))
        {
            // Show cursor in overlay.
            Input::ShowCursor();
            
            // Don't show probe in overlay.
            EnableProbe(false);
            
            // Create title overlay using PO2B syntax.
            new (AllocOverlay()) Title::Overlay(true);
            
            // Redirect updates to OnWaitTitle() state.
            SetBgnUpdState(&Scene::OnWaitTitle);
        }
    }

    // Scene constructor.
    Scene::Scene()
        // Set parameters for the static and dynamic entity lists provided by the scene.
        : Rayve::Scene(640, 64, 1024, 16)
    {
        // Clear all current assets. Don't clear if assets are shared between scenes.
        Assets::Clear();

        // Synchronously load assets from specific directories in the data folder. 
        // For big scenes with longer load times, asset loading can be done in an
        // overlay prior to creating a scene. The overlay can be coded to load
        // assets asynchronously while showing progress to the player, then start
        // the scene using an exit code.
        Assets::Load(L"common");
        Assets::Load(L"title");
        Assets::Load(L"gamestuff");

        // This must always be called after assets are loaded. Don't forget :)
        Finalize();

        // Create the game overlay using PO2B syntax.
        new (AllocOverlay()) Overlay;

        // Want to see probe metrics in game.
        EnableProbe();
        
        // Don't show the cursor.
        Input::ShowCursor(false);
        
        // Using lights in the scene, so need to create the light grid.
        SetLightGrid(100, 30, 100, 10, 1, 10, 0, 25, 0);
        
        // Load the background sky box.
        ShowSkybox(L"thesky");

        // Create an entity that contains a camera using PO2B syntax.
        new (GetDynamicEntities().Add()) Base::Camera(M4fTrans(0, 2, 9));
        
        // Create an entity that contains a light using PO2B syntax.
        new (GetStaticEntities().Add()) Base::Light(M4fTrans(20, 20, 20));

        // Create an entity that contains a character mesh and a sound using PO2B syntax.
        new (GetStaticEntities().Add()) Player(M4fIdent());

        // Direct updates to the OnDefault() state.
        SetBgnUpdState(&Scene::OnDefault);
    }

    // Destructor for the scene.
    Scene::~Scene()
    {
    }
}

Overlay

Overlay Header
// The namespace this overlay belongs to.
namespace MyOverlayNamespace
{
    // Derive an overlay class from the Rayve overlay class.
    class Overlay : public Rayve::Overlay
    {
    public:
        // Constructor.
        Overlay();
        
        // Override destructor from base class.
        ~Overlay() override;

    protected:
        // OnBgnUpd() is called in the first update pass when display is opened or resized.
        void OnBgnUpd();

        // OnEndUpd() is called in the second update pass in reverse entity order.
        void OnEndUpd();

    private:
        // This overlay class is using logic states.
        RVSTATEFUNCS(Overlay);

        // A state reserved for future use.
        void OnBgnUpdDefault();
        
        // Declare state for future use.
        void OnEndUpdDefault();
    };
}
Overlay Code
// The namespace this overlay belongs to.
namespace MyOverlayNamespace
{
    // Called on first pass of overlay update. This only gets called when scene needs to be redrawn.
    // Put drawing logic here.
    void Overlay::OnBgnUpd()
    {
        // Any global logic outside of states can go here.

        // Run current state.
        RVBGNUPDSTATE;
    }

    // Called on second pass of overlay update. This gets called every frame. Put UI event handling logic here.
    // OnEndUpd is called in reverse entity order. This causes sub entities to be updated before super entities,
    // which causes overlaying UI entities to be updated before underlying UI entities.
    void Overlay::OnEndUpd()
    {
        if (Input::PopKey(Key::ESCAPE))
            SetExitCode(1);

        // Run current state.
        RVENDUPDSTATE;
    }

    // State not implemented yet.
    void Overlay::OnBgnUpdDefault() {}
    
    // State not implemented yet.
    void Overlay::OnEndUpdDefault() {}

    // Constructor.
    Overlay::Overlay()
        // Set parameters for the dynamic entity list provided by the overlay.
        : Rayve::Overlay(512, 8)
    {
        // Create an entity that contains multiple resolution independent background images using PO2B syntax.
        new (GetEntities().Add()) Backdrop;

        // Create an entity using PO2B syntax that manages custom menus.
        new (GetEntities().Add()) Menus(S2f(.86f, .57f), L"fontname", escape);

        // Call BgnUpd() on this overlay to force a redraw of the overlay elements after they have been added.
        BgnUpd();
    }

    // Destructor.
    Overlay::~Overlay()
    {
        // This overlay changes display visuals, so the visual changes 
        // need to be invoked before the overlay object is destroyed.
        Visuals::Invoke();
    }
}

Entity

Entity Header
// The namespace this entity belongs to.
namespace MyGameLevel
{
    // Derive player class from Rayve entity class.
    class Player : public Rayve::Entity
    {
    public:
        // Expecting collision shape so this function was created to receive collsion shape.
        void AddCollShape(const CollShape &shape) { body.AddCollShape(shape); }

        // Constructor.
        Player(wcstr name, const M4f &pos);
        
        // Override destructor from base class.
        ~Player();

    protected:
        // OnBgnUpd() is called each frame before forward iteration through the entities begins.
        void OnBgnUpd() override;

    private:
        // This entity class is using logic states.
        RVSTATEFUNCS(Player);

        // Mesh component.
        Mesh mesh;
        
        // Physics component.
        Body body;
    };
}
Entity Code
// The namespace this entity belongs to.
namespace MyGameLevel
{
    // Called by scene each frame on first update pass. Not the way a player would normally be moved,
    // but is just a contrived example to show basic entity logic.
    void Player::OnBgnUpd()
    {
        Move player forward.
        if (Input::IsKey(Key::UP))
            body.ApplyForce(S3f(0, 0, -5000));

        Move player backward.
        if (Input::IsKey(Key::DOWN))
            body.ApplyForce(S3f(0, 0, 5000));

        Move player left.
        if (Input::IsKey(Key::LEFT))
            body.ApplyForce(S3f(5000, 0, 0));

        Move player right.
        if (Input::IsKey(Key::RIGHT))
            body.ApplyForce(S3f(-5000, 0, 0));

        // This code is a very important example to show that components do not automatically work together.
        // All components must be managed through connecting logic as the code below shows.
        
        // Set the mesh position to the body position. Body position is automatically updated each frame.
        mesh.SetPos(body.GetPos());
        
        // Update the mesh position in the scene using the scene global SCN().
        SCN<GameScene>().UpdateGeometry(mesh);

        // This normally calls current forward state, but no state is defined, so call is ignored.
        RVBGNUPDSTATE;
    }

    // Constructor.
    Player::Player(wcstr name, const M4f &pos)
        // Component parameters are given here.
        : mesh(GetKey(), name, pos), body(GetKey(), Body::Type::DYNAMIC, pos)
    {
        // Set mass.
        body.SetProps(.25f);
        
        // Set linear damping.
        body.SetLinDamp(S3f(2));
        
        // Important! Components are not automatically added to the scene.
        SCN().AddGeometry(mesh);
    }

    // Destructor.
    Player::~Player()
    {
        // Important! Components are not automatcally removed from the scene.
        SCN().RemoveGeometry(mesh);
    }
}