Structure

A Rayve program is made up of an engine, scenes, overlays, prefabs 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.

To use Rayve in a project, include rayve.hpp and link to rayved.lib (debug) or rayve.lib (release). The DLL's needed by Rayve can be copied to Windows/System32, or can be placed in another location and added to the path environment variable, or located with the executable. See the contents topic for files that need to be accessable to an executable that uses Rayve.

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:
        // OnForward() is called each frame before forward iteration through the entities begins.
        void OnForward() 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
{
    // Handle forward update.
    void Scene::OnForward()
    {
        // Any global logic outside of states can go here.
        
        // Run current state.
        RVFWDSTATE;
    }

    // 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.
            SetFwdState(&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.
            SetFwdState(&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.
        SetFwdState(&Scene::OnDefault);
    }

    // Destructor for the overlay. Override the base Rayve overlay class destructor.
    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:
        // OnForward() is called when display is resized before forward iteration through the entities begins.
        void OnForward();

        // OnReverse() is called each frame before reverse iteration through the entities begins.
        void OnReverse();

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

        // A state reserved for future use.
        void OnFwdDefault();
        
        // A state reserved for future use.
        void OnRevDefault();
    };
}
Overlay Code
// The namespace this overlay belongs to.
namespace MyOverlayNamespace
{
    // Handle forward update. This only gets called when scene needs to be redrawn.
    // Put drawing logic here.
    void Overlay::OnForward()
    {
        // Any global logic outside of states can go here.

        // Run current state.
        RVFWDSTATE;
    }

    // Handle reverse update. This gets called every frame. Put UI event handling logic here.
    // Reverse iteration causes sub entities to be updated before super entities,
    // which causes overlaying UI entities to be updated before underlying UI entities.
    void Overlay::OnReverse()
    {
        if (Input::PopKey(Key::ESCAPE))
            SetExitCode(1);

        // Run current state.
        RVREVSTATE;
    }

    // State not implemented yet.
    void Overlay::OnFwdDefault() {}
    
    // State not implemented yet.
    void Overlay::OnRevDefault() {}

    // 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 Forward() on this overlay to force a redraw of the overlay elements after they have been added.
        Forward();
    }

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

Prefab

Prefab Header
// The namespace this prefab belongs to.
namespace MyGameLevel
{
    // Derive prefab class from Rayve prefab class.
    class Town : public Rayve::Prefab
    {
    public:
        // Constructor.
        Town();
        
        // Override destructor from base class.
        ~Town() override;

    protected:
        // OnLoadObject() gets called for unknown object types as the prefab walks the object tree.
        // Known object types are handled automatically by the prefab loader.
        void OnLoadObject() override;

    private:
    };
}
Prefab Code
// The namespace this prefab belongs to.
namespace MyGameLevel
{
    // Handle custom defined object types coming from the 3D modelling tool.
    // The name of the prefab being loaded is 'town'.
    void Town::OnLoadObject()
    {
        // Check if the object type matches. Object types do not have the prefab name prefix.
        if (IsObjType(L"player"))
            // Check if the object name matches. Object names have the prefab name prefix.
            if (IsObjName(L"town:player"))
                // Create the entity using PO2B syntax and the object name and object position from the prefab object node.
                // Then pass the entity to SetObjEnt() to add the key to this entity to this prefab object node.
                SetObjEnt(new (SCN().GetDynamicEntities().Add()) Player(GetObjName(), GetObjPos()));
            else
                // Check if the collision shape name matches.
                if (IsObjName(L"town:customsphere"))
                    // This collision shape is -1 (top) on the node stack so the player entity it belongs to is -2 on the stack. 
                    // Add the collision shape to the player entity added in the step above using the position from the prefab object node.
                    // Note that this matrix will be a TRS matrix that the CollSphere() constructor expects. (See collision shapes).
                    // Note that CollSphere() is allocated on the stack and not with PO2B memory.
                    ((Player &)GetObjEnt(-2)).AddCollShape(CollSphere(GetObjPos()));
    }

    // Constructor.
    Town::Town()
    {
    }
    
    // Destructor.
    Town::~Town()
    {
    }
}

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 from prefab.
        void AddCollShape(const CollShape &shape) { body.AddCollShape(shape); }

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

    protected:
        // OnForward() is called each frame before forward iteration through the entities begins.
        void OnForward() 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
{
    // Handle forward logic. Not the way a player would normally be moved,
    // but is just a contrived example to show basic entity logic.
    void Player::OnForward()
    {
        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.
        RVFWDSTATE;
    }

    // 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);
    }
}