Skip to content

FrodoAlaska/Freya

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

196 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

The Freya Game Engine

A very capable, yet simple 2D game engine made entirely for hobby purposes. It is full of features that target 2D games/applications, with no plans to target 3D any time soon. It is purely a 2D game engine. It currently fully supports Windows, Linux, and the Web.

Features

  • Cross-platform window creation with OpenGL4.3 and GLES3 using SOKOL.
  • Gamepad, keyboard, and mouse input support.
  • A flexible and configurable 2D renderer
  • A fully-fledged audio system with both 2D and 3D spatialized audio.
  • A robust and easy-to-use game UI system, using HTML and CSS to decalre and style widgets.
  • A robust 2D physics engine, using the fantastic Box2D library.
  • A flexible Entity Component System (ECS) module, using the EnTT library.
  • Integrated ImGui support, featuring an abstracted gui layer for editing engine-specific types through a GUI.
  • A durable, but simple noise generation module for both 2D and 3D.
  • A simple tile map system for easily editing and adding tile maps.

Dependencies:

Build Instructions

Before proceeding with any build or compilation step, Freya needs to be cloned from the Git repo.

git clone https://github.com/FrodoAlaska/Freya.git

And now that Freya is cloned, we can start the build process...

In general there are two ways to build Freya. The first to use CMake commands just like any other C++ project. The second way is to use a handy build script to manage the build project for you.

Raw CMake

There are two main ways to build Freya. The first is to use the traditional CMake commands below:

mkdir build 
cd build 
cmake .. 

CMake will generate the required build files, but it will also fetch all of the dependencies mentioned above. This is all handled by CMake itself, so you don't have to worry about any specifics.

And then to build Freya you can use:

cmake --build . --config Debug --parallel 12

The command above will build Freya in the debug configuration, using 12 worker threads. You can omit the --parallel flag if you so wish. However, since Freya will build all of the dependencies itself, it might take a while.

The Build Script

Now the second way to build Freya is to use the build scripts found in the scripts directory. There are a few build scripts but there are only two important ones: build-freya.sh for Linux and build-freya.ps1 for Windows. Each script takes in a few flags to make both the development and build process easier.

[Usage]: .\build-freya.ps1 [options]
An easy to use build script to build Freya on Windows
   -clean          = Have a new fresh build
   -debug          = Build for the debug configuration
   -rel            = Build for the release configuration
   -jobs [threads] = Threads to use when building
   -run-testbed    = Run the testbed examples
   -help           = Display this help message

Currently, the -run flag can only run a single testbed, but there are plans to expand on this in the future.

The -debug and -rel must be used independently. Moreover, one of the flags have to be used to know which configuration to build for. If none of them are used, the script will default to a Debug build. Depending on which flag is passed to the build script, a build-debug and/or build-release will be created in the main directory. Any build artifacts generated by -run will be dumped into one of the previously mentioned directories.

Of course, the project can be built regardless of this build script. This is not a necessary step. It is only a convenience for the development process on our end.

Simple Example

Below is a simple example of the Freya Engine being used.

If the exmaple below is too simple, you can check out the testbed directory where more extensive examples exist. However, they are not as "educational" as the example below. Despite that, they do have a variety of use cases of Freya.

#include <freya.h>

struct App {
  freya::Window* window; 
  freya::AssetGroupID group_id;

  freya::EntityWorld world;
};
static App s_app;

bool app_init(const freya::Args& args, freya::Window* window) {
  // Carry the window just in case
  s_app.window = window;
  
  // Initialize the GUI
  freya::gui_init(window);
  
  // Create the application's asset group
  s_app.group_id = freya::asset_group_create("app_assets");

  // Build an asset package, pointing to a `assets_list.lua` file, spiting out `assets.frpkg`
  // 
  // @NOTE: This function will only build the package if there was any change from last time. 
  // It should be kept at minimum usage on dev-builds only. 
  //
  freya::asset_group_build(s_app.group_id, "../assets/assets_list.lua", "assets.frpkg");

  // Load the asset package that was built by the previous function. 
  // 
  // @NOTE: The `frpkg` format is specifically built for this engine. 
  // It embeds all of the assets gathered and built by the previous function 
  // and builds them into a neat binary package. On load, the package's content 
  // is loaded and the given asset group is populated with the assets. 
  //
  // Unlike the previous function, loading the packages should occur at least once 
  // on the application's initialization to use any assets.
  //
  freya::asset_group_load_package(s_app.group_id, "assets.frpkg");

  // Give our entity world to the renderer so that it can process any rendering 
  // commands that gets issued from the application. 
  freya::renderer_sumbit_world(&s_app.world);

  //
  // Create entities or do other initialization stuff here...
  //

  // Nothing went wrong. Return true.
  return true;
}

void app_shutdown() {
  freya::entity_world_clear(s_app.world);
  freya::asset_group_destroy(s_app.group_id);
  freya::gui_shutdown();
  
  //
  // Do other shutdown/cleanup stuff here...
  //
}

void app_update(freya::f32 dt) {
  // Quit the application when the specified exit key is pressed
  
  if(freya::input_key_pressed(freya::KEY_ESCAPE)) {
    freya::event_dispatch(freya::Event{.type = freya::EVENT_APP_QUIT});
    return;
  }
  
  // Enable/disable the GUI using the F1 key

  if(freya::input_key_pressed(freya::KEY_F1)) {
    freya::gui_toggle_active();
  }

  // Update the entity world 
  freya::entity_world_update(s_app.world, dt);

  //
  // Update other stuff before here...
  //
}

void app_render_gui() {
  if(!freya::gui_is_active()) {
    return;
  }

  // 
  // GUI commands 
  //

  freya::gui_begin(); 
  freya::gui_edit_entity_world("Main", s_app.world);
  freya::gui_end(); 
}

// Main function _must_ have this exact signature, since the `FREYA_MAIN` macro will 
// expect it. However, if you wish to make a console application or do not want Freya to 
// hijack the main function, you can use the regular `main` function and omit `FREYA_MAIN` 
// at the bottom.
int engine_main(int argc, char* argv[]) {
  freya::AppDesc app_desc {
    .init_fn     = app_init,
    .shutdown_fn = app_shutdown,
    .update_fn   = app_update, 
    .gui_fn      = app_render_gui, 

    .window_title  = "Freya Example", 
    .window_width  = 800, 
    .window_height = 600, 
    .window_flags  = (freya::i32)(freya::WINDOW_FLAGS_CENTER_MOUSE),

    .samples_count = 1,
    .has_vsync     = false,

    .args_values = argv, 
    .args_count  = argc,
  };

  // Run the application in a loop and return the 
  // result once the application exists.
  return freya::engine_run(app_desc);
}

// A macro to specify a main entry function depending on the platform.
// The given `engine_main` will be called inside the entry function.
FREYA_MAIN(engine_main)

Contributors

Languages