Jump to content

3D Salem-GDK


Oddly

Recommended Posts

adf05b3d11afac8daf00d5f68e74853a.png

Repository Link:

https://gitlab.com/oddly-doddly/salem-gdk/

 

Discord Link, (we're community development drive):

https://discordapp.com/invite/0wtBMrHuLTjsfsoH

For the past 4 months I have been working on a library for developing games and game engines. I am writing this engine to develop my upcoming game project, OddlyDoddly's The InBetween.

The system is very simple to how many already existing game engines work, and even though it is very young, it is becoming a very powerful tool. Salem GDK is written with raw OpenGL in C++.

It uses GLFW for window and input management.


Here are some features i've currently finished developing:

Basic TCP Network, soon will be rewritten as a modular network supporting both TCP and UDP protocols. Will also have match making servers.

 

GUI ENGINE

with capabilities of scripting user interfaces through JSON files.
An example json script and its output

 

{
  "interface": {
    "fonts": [
      {
        "id": "arial",
        "source": "./resource/fonts/arial.ttf"
      }
    ],
    "objects": [
      {
        "type": "image",
        "id": "img_sanic",
        "textures": [
          {
            "id": "source",
            "texture": "./resource/gui/images/sanic.png"
          }
        ],
        "text": "Exit",
        "position": {
          "x": -1.0,
          "y": -1.0
        },
        "size": {
          "width": 0.4,
          "height": 0.6
        },
        "shader": "ui"
      },
      {
        "type": "button",
        "id": "btn_exit",
        "textures": [
          {
            "id": "inactive",
            "texture": "./resource/gui/buttons/btn_exit_inactive.png"
          },
          {
            "id": "hover",
            "texture": "./resource/gui/buttons/btn_exit_hover.png"
          },
          {
            "id": "click",
            "texture": "./resource/gui/buttons/btn_exit_click.png"
          }
        ],
        "text": "Exit",
        "position": {
          "x": 0.0,
          "y": 0.3
        },
        "size": {
          "width": 0.4,
          "height": 0.2
        },
        "attributes": {
          "anchor": "left",
          "text-align": "center"
        },
        "shader": "ui"
      },
      {
        "type": "textbox",
        "id": "txt_username",
        "textures": [
          {
            "id": "inactive",
            "texture": "./resource/gui/textboxes/textbox_inactive.png"
          },
          {
            "id": "focus",
            "texture": "./resource/gui/textboxes/textbox_focus.png"
          }
        ],
        "size": {
          "width": 0.4,
          "height": 0.05
        },
        "position": {
          "x": 0.0,
          "y": 0.1
        },
        "attributes": {
          "font": "arial",
          "text-align": "left",
          "anchor": "center",
          "place-holder": "Email/Username",
          "font-size": 0.5,
          "font-color": "#ffffff"
        }
      },
      {
        "type": "textbox",
        "id": "txt_password",
        "textures": [
          {
            "id": "inactive",
            "texture": "./resource/gui/textboxes/textbox_inactive.png"
          },
          {
            "id": "focus",
            "texture": "./resource/gui/textboxes/textbox_focus.png"
          }
        ],
        "size": {
          "width": 0.4,
          "height": 0.05
        },
        "position": {
          "x": 0.0,
          "y": 0.0
        },
        "attributes": {
          "font": "arial",
          "text-align": "left",
          "anchor": "center",
          "place-holder": "Password",
          "font-size": 0.5,
          "font-color": "#ffffff",
          "is-password": true
        }
      }
    ]
  }
}


Output Render:
a900bca0ab3e1abb84d47d6d2cd44261.png

 

All ui objects are interactable and can be grabbed through the gameview's ui engine

auto myControl = getView()->ui()->getControl("txt_username");


returns a pinter to the textbox username

myControl->value();


Will even get the value of what is in the textbox.


Events can be bound to ui buttons through lambda functions. If i want to link an event to btn_exit that prints out the value of email and username to the debug console I can do so like this:

// Load GUI

loadGui("./resource/gui/views/MainMenu.json"); 

auto btnExit = gui().findUiControlById<Salem::Graphics::Controls::uiButton>("btn_exit");
auto txtUsername = gui().findUiControlById<Salem::Graphics::Controls::uiTextBox>("txt_username"); 
auto txtPassword = gui().findUiControlById<Salem::Graphics::Controls::uiTextBox>("txt_password");

btnExit->on_click = []() { 
    std::string username = GAMELOOP_PTR->GetView()->gui().findUiControlById<Salem::Graphics::Controls::uiTextBox>("txt_username")->value();

    std::string password = GAMELOOP_PTR->GetView()->gui().findUiControlById<Salem::Graphics::Controls::uiTextBox>("txt_password")->value(); 

    std::cout << "Login: {" << username.c_str() << " : " << password.c_str() << "}" << std::endl; 
};

 

Here is an example of a gameview, basically a scene in your game:

//
// Created by ddodds on 10/24/17.
//

#ifndef TEST_CLIENT_MAINMENUVIEW_HPP
#define TEST_CLIENT_MAINMENUVIEW_HPP

#include "system/GameLoop.hpp"
#include "system/interface/GameView.hpp"
#include "views/controllers/MainMenuController.hpp"
#include "behaviours/TestBehaviour.hpp"

#include "physics/PhysicsTypes.hpp"
#include "physics/types/Transform.hpp"
#include <graphics/objects/Model.hpp>
#include "graphics/controls/uiButton.hpp"
#include "graphics/controls/uiTextBox.hpp"

extern Salem::System::GameLoop *GAMELOOP_PTR;
namespace TestClient::Views {
    class MainMenuView
            : public Salem::System::Interface::GameView {
    public:
        explicit MainMenuView(Controllers::MainMenuController &p_view_controller)
                : GameView(p_view_controller)
        {}

        void Initialize() override
        {
            // Load GUI
            loadGui("./resource/gui/views/MainMenu.json");
            // Create and bind a Camera
            Salem::Physics::Types::Transform camera_transform(
                    Salem::Physics::Vector3(0.0f, 0.0f, 0.0f),
                    Salem::Physics::Quaternion(),
                    Salem::Physics::Vector3(1.0f, 1.0f, 1.0f));

            GameView::camera(new Salem::Graphics::Objects::Camera(camera_transform, 45.0f, GAMELOOP_PTR->vp_width(), GAMELOOP_PTR->vp_height(), 0.0f, 100.0f));

            auto btnExit = gui().findUiControlById<Salem::Graphics::Controls::uiButton>("btn_exit");
            auto txtUsername = gui().findUiControlById<Salem::Graphics::Controls::uiTextBox>("txt_username");
            auto txtPassword = gui().findUiControlById<Salem::Graphics::Controls::uiTextBox>("txt_password");

            btnExit->on_click = []() {
                std::string username = GAMELOOP_PTR->GetView()->gui().findUiControlById<Salem::Graphics::Controls::uiTextBox>("txt_username")->value();
                std::string password = GAMELOOP_PTR->GetView()->gui().findUiControlById<Salem::Graphics::Controls::uiTextBox>("txt_password")->value();
                std::cout << "Login: {" << username.c_str() << " : "  << password.c_str() << "}" << std::endl;
            };

            Salem::Physics::Types::Transform transform(
                    Salem::Physics::Vector3(0.0f, 0.0f, 0.0f),
                    Salem::Physics::Quaternion(),
                    Salem::Physics::Vector3(1.0f, 1.0f, 1.0f)
            );

            // Game Objects do not get initalized until you add them to a view now.
            Salem::Graphics::Objects::Model* model = new Salem::Graphics::Objects::Model(transform, "./resource/models/nanosuit/nanosuit.obj");
            // Mono Behaviour Initialize Functions get called during the game object's initialization
            model->AddBehaviour(new Behaviours::TestBehaviour(model->transform()));
            // Append GameObject to the view
            addGameObject(model);
        }

        void Update() override {
            // Some Update Logic
            GameView::Update();
        }
    };
}

#endif //TEST_CLIENT_MAINMENUVIEW_HPP

 

And a script to start a scene: The main function of the game itself:

We create a game loop, and instruct it to load our Main Menu View, which is defined above.

//
// Created by ddodds on 10/21/17.
//

#include <iostream>
#include <boost/asio.hpp>
#include <views/controllers/MainMenuController.hpp>

#include "system/GameLoop.hpp"

#include "views/MainMenuView.hpp"
#include "views/controllers/MainMenuController.hpp"

int main(int argc, char *argv[])
{
    TestClient::Controllers::MainMenuController mainMenuController;
    auto mainMenuViewPtr = std::make_unique<TestClient::Views::MainMenuView>(mainMenuController);

    Salem::System::GameLoop gameLoop;
    gameLoop.LoadView(std::move(mainMenuViewPtr));
    gameLoop.Run();

    return 0;
}

And of course, a game controller to handle user input:

//
// Created by ddodds on 1/22/18.
//

#ifndef TEST_CLIENT_MAINMENUCONTROLLER_HPP
#define TEST_CLIENT_MAINMENUCONTROLLER_HPP

#include <system/interface/ViewController.hpp>
#include <physics/PhysicsTypes.hpp>

#include "system/GameLoop.hpp"

extern Salem::System::GameLoop *GAMELOOP_PTR;
namespace TestClient::Controllers {
    class MainMenuController
            : public Salem::System::Interface::ViewController {
    public:
        void on_keypress(GLFWwindow *window, int key, int scancode, int action, int mods) override
        {
            if(key == GLFW_KEY_W)
            {
                Salem::Physics::Vector3 move_transform(0.0f, 0.0f, 1.0f);
                GAMELOOP_PTR->GetView()->camera()->transform().Translate(move_transform);
            }
            if(key == GLFW_KEY_S)
            {
                Salem::Physics::Vector3 move_transform(0.0f, 0.0f, -1.0f);
                GAMELOOP_PTR->GetView()->camera()->transform().Translate(move_transform);
            }
            if(key == GLFW_KEY_A)
            {
                Salem::Physics::Vector3 move_transform(1.0f, 0.0f, 0.0f);
                GAMELOOP_PTR->GetView()->camera()->transform().Translate( move_transform);
            }
            if(key == GLFW_KEY_D)
            {
                Salem::Physics::Vector3 move_transform(-1.0f, 0.0f, 0.0f);
                GAMELOOP_PTR->GetView()->camera()->transform().Translate(move_transform);
            }
        }

        void on_cursor_move(GLFWwindow *p_window, double p_xpos, double p_ypos) override {
            double x_offset = p_xpos - m_last_x;
            double y_offset = p_ypos - m_last_y;

            GAMELOOP_PTR->GetView()->camera()->transform().Rotate(0.05f*x_offset, Salem::Physics::Vector3(0.0f, 1.0f, 0.0f));
            GAMELOOP_PTR->GetView()->camera()->transform().Rotate(0.05f*y_offset, Salem::Physics::Vector3(1.0f, 0.0f, 0.0f));
            m_last_x = p_xpos;
            m_last_y = p_ypos;
        };
    private:
        double m_last_x, m_last_y = 0;
    };
}

#endif //TEST_CLIENT_MAINMENUCONTROLLER_HPP

 

The library supports camera views and transforms:

(for this test i just converted all 2d interface objects into 3d world objects.)

583d16cf265a5e8900cc81f0c4fa1f8c.gif

 

Of course, 3D model loading at its very basics....

19002edc578f4ffb26a18b04268fe665.gif

 

Game Object behaviours. You can bind as many scripted behaviours as you'd like to a game object, and the system runs them when necessary:

6baa16bccb984a3a3e3a6a60865e6a01.png

 

If you've ever used unity, they are very similar to MonoBehaviours, but these are not scripted or injected, they get baked into the final application compilation.

 

Also support GLSL shader language

 

Coming up in the project's todo;

Audio Engine (being developed by a Salem-GDK community member)

Animation Engine (will be developed by me)

UDP Network (developed by me)

Witchcraft Engine;World (engine used to generate 3D worlds and maps for SalemGDK, in development next, by me)

 

More screenshots to come.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...