Parrot is a game engine written in C++ created for educational purposes. The engine lets you develop games using custom asset formats and C++ scripts.
technologies used:
- window-api: glfw
- graphics-api: opengl using glad
- assets: nlohmann/json, nothings/stb, tinyobjloader/tinyobjloader
modules:
core
create, run and destroy apps and playing-units + connect to client codewindow
create, update and destroy physical windowsecs
provide ecs api with scenes, entities and componentsgraphics
handle graphics data like meshes or materials and communicate with the gpuasset-manager
manage the client asset-directory and handle the assets lifetimes
besides the
core
module, no modules depend on each other
In order to have logic in your game, you can add scripts written in C++.
#include "path/to/src/client.hh"
class ScriptName : public Script {
ScriptName(Entity& entity)
: entity(entity) {}
virtual bool resolveEvent(const Event& e) override {
if (auto* mouse_move = e.getMouseMove()) {
std::cout << "Mouse was moved!" << std::endl;
}
return false;
}
virtual void onUpdate(float32 delta_time) override {
std::cout << "I'm getting updated!" << std::endl;
}
Entity& entity;
}
this is a script that you can attach to entities.
You can add scripts to
- Apps
- Playing-Units (Window, Scene)
- Entities
Important
in the current development state you can only attach scripts to entities
For now, all assets are stored in a .json format.
handles can be either uuids (i.e. numbers), filepaths (i.e. strings) or inlined (i.e. objects)
{
// general
"name": "App Name", // default: "Unnamed App"
"main": [
"<window-handle>",
"<scene-handle>",
[ "ScriptName1", /* ... */ ] // optional
],
// assets
"loading-policy": "app|scene|lazy", // default: "lazy"
"unloading-policy": "app|scene|unused" // default: "app"
// scripts
"scripts": [ // default: []
"ScriptName1", /* ... */
]
}
{
"uuid": 1234567889,
"title": "Window Title", // default: "Untitled Window"
"size": [ 1080, 720 ], // default: [ 1080, 720 ]
}
{
// general
"uuid": 1234567889,
"name": "Scene Name", // default: "Unnamed Scene"
// hierarchy
"root": "<entity-handle>" // default: null
}
{
// general
"uuid": 1234567889,
"tag": "Entity Tag", // default: "Entity"
// transform
"transform": { // default: {}
"position": [ 0, 0, 0 ], // default: [ 0, 0, 0 ]
"rotation": [ 0, 0, 0 ], // default: [ 0, 0, 0 ]
"scale": [ 1, 1, 1 ] // default: [ 1, 1, 1 ]
},
// children
"children": [ // default: []
"<entity-handle>", /* ... */
],
// components
"components": { // default: {}
"component_name": {
/* data depends on component */
}, /* ... */
},
// scripts
"scripts": [ // default: []
"ScriptName1", /* ... */
]
}
{
// general
"uuid": 1234567889,
"resource": "path/to/mesh.obj"
}
{
// general
"uuid": 1234567889,
"vertex": {
"resource": "path/to/vertex_shader.vs.glsl"
},
"fragment": {
"resource": "path/to/fragment_shader.fs.glsl"
}
}