Compare commits

...

2 Commits

Author SHA1 Message Date
En Yi bef2ee2813 Expose initial window size to scene
This is so that each scene does not need to hardcode render layer size
2024-05-04 18:28:53 +08:00
En Yi 75d019aa34 Rework rendering to allow multi-layer render
Internal Changelog:
- A scene now has a maximum amount of render texture. It is to be
  rendered in order of the array by the engine.
- A scene now needs an explicit render system to draw onto the render
  textures. The scene will also init the number of render layers
  needed.
- The change is to allow more separate of concerns when it comes to
  rendering. A scene can also now compartmentalise the rendered items,
  which hopefully make understanding the code easier.
- Update all exisiting code to use the new render system.
2024-05-04 17:57:07 +08:00
12 changed files with 145 additions and 95 deletions

View File

@ -1,7 +1,7 @@
#include "engine.h"
#include "mempool.h"
void init_engine(GameEngine_t* engine)
void init_engine(GameEngine_t* engine, Vector2 starting_win_size)
{
InitAudioDevice();
sc_queue_init(&engine->key_buffer);
@ -9,6 +9,8 @@ void init_engine(GameEngine_t* engine)
memset(engine->sfx_list.sfx, 0, engine->sfx_list.n_sfx * sizeof(SFX_t));
init_memory_pools();
init_assets(&engine->assets);
engine->intended_window_size = starting_win_size;
InitWindow(starting_win_size.x, starting_win_size.y, "raylib");
}
void deinit_engine(GameEngine_t* engine)
@ -17,6 +19,7 @@ void deinit_engine(GameEngine_t* engine)
free_memory_pools();
sc_queue_term(&engine->key_buffer);
CloseAudioDevice();
CloseWindow();
}
void process_inputs(GameEngine_t* engine, Scene_t* scene)
@ -152,15 +155,32 @@ void init_scene(Scene_t* scene, render_func_t render_func, action_func_t action_
//scene->scene_type = scene_type;
scene->render_function = render_func;
scene->layers.n_layers = 0;
scene->bg_colour = WHITE;
scene->action_function = action_func;
scene->state = SCENE_ENDED;
scene->time_scale = 1.0f;
}
bool add_scene_layer(Scene_t* scene, int width, int height, Rectangle render_area)
{
if (scene->layers.n_layers >= MAX_RENDER_LAYERS) return false;
scene->layers.render_layers[scene->layers.n_layers].layer_tex = LoadRenderTexture(width, height);
scene->layers.render_layers[scene->layers.n_layers].render_area = render_area;
scene->layers.n_layers++;
return true;
}
void free_scene(Scene_t* scene)
{
sc_map_term_64(&scene->action_map);
sc_array_term(&scene->systems);
for (uint8_t i = 0; i < scene->layers.n_layers; ++i)
{
UnloadRenderTexture(scene->layers.render_layers[i].layer_tex);
}
free_entity_manager(&scene->ent_manager);
deinit_particle_system(&scene->part_sys);
}
@ -178,10 +198,24 @@ inline void update_scene(Scene_t* scene, float delta_time)
inline void render_scene(Scene_t* scene)
{
if (scene->render_function != NULL)
BeginDrawing();
ClearBackground(scene->bg_colour);
for (uint8_t i = 0; i < scene->layers.n_layers; ++i)
{
scene->render_function(scene);
RenderLayer_t* layer = scene->layers.render_layers + i;
Rectangle draw_rec = layer->render_area;
Vector2 draw_pos = {draw_rec.x, draw_rec.y};
draw_rec.x = 0;
draw_rec.y = 0;
draw_rec.height *= -1;
DrawTextureRec(
layer->layer_tex.texture,
draw_rec,
draw_pos,
WHITE
);
}
EndDrawing();
}
inline void do_action(Scene_t* scene, ActionType_t action, bool pressed)

View File

@ -24,6 +24,10 @@ typedef struct GameEngine {
SFXList_t sfx_list;
// Maintain own queue to handle key presses
struct sc_queue_32 key_buffer;
// This is the original size of the window.
// This is in case of window scaling, where there needs to be
// an absolute reference
Vector2 intended_window_size;
} GameEngine_t;
//typedef enum SceneType {
@ -42,9 +46,22 @@ typedef void(*system_func_t)(Scene_t*);
typedef void(*action_func_t)(Scene_t*, ActionType_t, bool);
sc_array_def(system_func_t, systems);
typedef struct RenderLayer {
RenderTexture2D layer_tex;
Rectangle render_area;
}RenderLayer_t;
typedef struct SceneRenderLayers {
RenderLayer_t render_layers[MAX_RENDER_LAYERS];
uint8_t n_layers;
} SceneRenderLayers_t;
struct Scene {
struct sc_map_64 action_map; // key -> actions
struct sc_array_systems systems;
SceneRenderLayers_t layers;
Color bg_colour;
// TODO: Render function is obsolete and should be treated like a system
render_func_t render_function;
action_func_t action_function;
EntityManager_t ent_manager;
@ -57,7 +74,8 @@ struct Scene {
GameEngine_t *engine;
};
void init_engine(GameEngine_t* engine);
void init_engine(GameEngine_t* engine, Vector2 starting_win_size);
void deinit_engine(GameEngine_t* engine);
void process_inputs(GameEngine_t* engine, Scene_t* scene);
@ -74,6 +92,7 @@ extern void do_action(Scene_t* scene, ActionType_t action, bool pressed);
//void init_scene(Scene_t* scene, SceneType_t scene_type, system_func_t render_func, action_func_t action_func);
void init_scene(Scene_t* scene, render_func_t render_func, action_func_t action_func);
bool add_scene_layer(Scene_t* scene, int width, int height, Rectangle render_area);
void free_scene(Scene_t* scene);
#endif // __ENGINE_H

View File

@ -1,6 +1,7 @@
#ifndef _ENGINE_CONF_H
#define _ENGINE_CONF_H
#define MAX_RENDER_LAYERS 4
#define MAX_ENTITIES 2048
#define MAX_TEXTURES 16
#define MAX_SPRITES 64
@ -16,7 +17,6 @@
#define MAX_PARTICLES 64
#define MAX_TILE_TYPES 16
#define N_TAGS 10
#define N_COMPONENTS 20
#define MAX_COMP_POOL_SIZE MAX_ENTITIES

View File

@ -19,8 +19,7 @@ static GameEngine_t engine =
int main(void)
{
init_engine(&engine);
InitWindow(1280, 640, "raylib");
init_engine(&engine, (Vector2){1280,640});
SetTargetFPS(60);
load_from_infofile("res/test_assets.info", &engine.assets);
@ -62,6 +61,5 @@ int main(void)
}
free_scene(&scene.scene);
term_level_scene_data(&scene.data);
CloseWindow();
deinit_engine(&engine);
}

4
main.c
View File

@ -25,8 +25,7 @@ int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
init_engine(&engine);
InitWindow(screenWidth, screenHeight, "raylib");
init_engine(&engine, (Vector2){screenWidth, screenHeight});
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
#ifndef NDEBUG
load_from_infofile("res/assets.info.raw", &engine.assets);
@ -114,5 +113,4 @@ int main(void)
free_game_scene(&level_scene);
free_menu_scene(&menu_scene);
deinit_engine(&engine);
CloseWindow();
}

View File

@ -39,9 +39,8 @@ void update_loop(void)
int main(void)
{
InitWindow(1280, 640, "raylib");
init_engine(&engine, (Vector2){1280,640});
SetTargetFPS(60);
init_engine(&engine);
#ifndef NDEBUG
load_from_infofile("res/assets.info.raw", &engine.assets);
@ -100,6 +99,4 @@ int main(void)
#endif
free_sandbox_scene(&scene);
deinit_engine(&engine);
CloseWindow();
}

View File

@ -40,6 +40,9 @@ static bool crate_activation = false;
#define SELECTION_REGION_WIDTH (SELECTION_TILE_SIZE * MAX_SPAWN_TYPE)
#define SELECTION_REGION_HEIGHT SELECTION_TILE_SIZE
#define GAME_LAYER 0
#define SELECTION_LAYER 1
#define CONTROL_LAYER 2
static char* get_spawn_selection_string(enum EntitySpawnSelection sel)
{
switch(sel)
@ -80,41 +83,19 @@ static inline unsigned int get_tile_idx(int x, int y, const TileGrid_t* tilemap)
}
// This means you might be able to have two editor scene without running into problems
static RenderTexture2D selection_section;
#define SELECTION_RENDER_HEIGHT (SELECTION_REGION_HEIGHT * 3)
static void level_scene_render_func(Scene_t* scene)
{
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
Entity_t* p_ent;
Rectangle draw_rec = data->game_rec;
draw_rec.x = 0;
draw_rec.y = 0;
draw_rec.height *= -1;
static char buffer[512];
BeginDrawing();
ClearBackground(LIGHTGRAY);
DrawTextureRec(
data->game_viewport.texture,
draw_rec,
(Vector2){data->game_rec.x, data->game_rec.y},
WHITE
);
draw_rec.width = SELECTION_REGION_WIDTH;
draw_rec.height = -SELECTION_RENDER_HEIGHT;
Vector2 draw_pos = {data->game_rec.x, data->game_rec.y + data->game_rec.height + SELECTION_GAP};
DrawTextureRec(
selection_section.texture,
draw_rec,
draw_pos,
WHITE
);
draw_pos.x = data->game_rec.x + current_spawn_selection * SELECTION_TILE_SIZE;
Vector2 draw_pos = {data->game_rec.x, data->game_rec.y + data->game_rec.height + SELECTION_GAP};
BeginTextureMode(scene->layers.render_layers[CONTROL_LAYER].layer_tex);
ClearBackground(BLANK);
DrawRectangleLines(
draw_pos.x, draw_pos.y,
data->game_rec.x + current_spawn_selection * SELECTION_TILE_SIZE, draw_pos.y,
SELECTION_TILE_SIZE, SELECTION_TILE_SIZE, GREEN
);
@ -185,10 +166,10 @@ static void level_scene_render_func(Scene_t* scene)
print_mempool_stats(buffer);
DrawText(buffer, gui_x, gui_y, 12, BLACK);
gui_y += 300;
gui_y += 330;
sprintf(buffer, "Chests: %u / %u", data->coins.current, data->coins.total);
DrawText(buffer, gui_x, gui_y, 24, BLACK);
EndDrawing();
EndTextureMode();
}
static void render_editor_game_scene(Scene_t* scene)
@ -212,7 +193,7 @@ static void render_editor_game_scene(Scene_t* scene)
max.x = (int)fmin(tilemap.width, max.x + 1);
max.y = (int)fmin(tilemap.height, max.y + 1);
BeginTextureMode(data->game_viewport);
BeginTextureMode(scene->layers.render_layers[GAME_LAYER].layer_tex);
ClearBackground(WHITE);
BeginMode2D(data->camera.cam);
for (int tile_y = min.y; tile_y < max.y; tile_y++)
@ -837,7 +818,7 @@ static void level_do_action(Scene_t* scene, ActionType_t action, bool pressed)
if (!pressed) metal_toggle = !metal_toggle;
const Color crate_colour = metal_toggle ? GRAY : BROWN;
Vector2 draw_pos = {SPAWN_CRATE * SELECTION_TILE_SIZE , 0};
BeginTextureMode(selection_section);
BeginTextureMode(scene->layers.render_layers[SELECTION_LAYER].layer_tex);
for (uint8_t i = SPAWN_CRATE; i <= SPAWN_CRATE_BOMB; ++i)
{
DrawRectangle(draw_pos.x, draw_pos.y, SELECTION_TILE_SIZE, SELECTION_TILE_SIZE, crate_colour);
@ -1015,9 +996,30 @@ void init_sandbox_scene(LevelScene_t* scene)
unsigned int tile_idx = (scene->data.tilemap.height - 1) * scene->data.tilemap.width + i;
change_a_tile(&scene->data.tilemap, tile_idx, SOLID_TILE);
}
selection_section = LoadRenderTexture(SELECTION_REGION_WIDTH, SELECTION_RENDER_HEIGHT);
BeginTextureMode(selection_section);
scene->scene.bg_colour = LIGHTGRAY;
add_scene_layer(
&scene->scene, scene->data.game_rec.width, scene->data.game_rec.height,
scene->data.game_rec
);
add_scene_layer(
&scene->scene, SELECTION_REGION_WIDTH, SELECTION_REGION_HEIGHT,
(Rectangle){
scene->data.game_rec.x, scene->data.game_rec.y + scene->data.game_rec.height + SELECTION_GAP,
SELECTION_REGION_WIDTH, SELECTION_REGION_HEIGHT
}
);
add_scene_layer(
&scene->scene, scene->scene.engine->intended_window_size.x,
scene->scene.engine->intended_window_size.y,
(Rectangle){
0, 0,
scene->scene.engine->intended_window_size.x,
scene->scene.engine->intended_window_size.y
}
);
BeginTextureMode(scene->scene.layers.render_layers[SELECTION_LAYER].layer_tex);
ClearBackground(LIGHTGRAY);
Vector2 draw_pos = {0, 0};
const Color crate_colour = metal_toggle ? GRAY : BROWN;
@ -1228,6 +1230,7 @@ void init_sandbox_scene(LevelScene_t* scene)
sc_array_add(&scene->scene.systems, &player_respawn_system);
sc_array_add(&scene->scene.systems, &level_end_detection_system);
sc_array_add(&scene->scene.systems, &render_editor_game_scene);
sc_array_add(&scene->scene.systems, &level_scene_render_func);
// This avoid graphical glitch, not essential
//sc_array_add(&scene->scene.systems, &update_tilemap_system);
@ -1260,5 +1263,4 @@ void free_sandbox_scene(LevelScene_t* scene)
{
free_scene(&scene->scene);
term_level_scene_data(&scene->data);
UnloadRenderTexture(selection_section); // Unload render texture
}

View File

@ -10,24 +10,15 @@
static Tile_t all_tiles[MAX_N_TILES] = {0};
#define GAME_LAYER 0
#define CONTROL_LAYER 1
static void level_scene_render_func(Scene_t* scene)
{
LevelSceneData_t* data = &(CONTAINER_OF(scene, LevelScene_t, scene)->data);
Rectangle draw_rec = data->game_rec;
draw_rec.x = 0;
draw_rec.y = 0;
draw_rec.height *= -1;
static char buffer[512];
BeginDrawing();
ClearBackground(LIGHTGRAY);
DrawTextureRec(
data->game_viewport.texture,
draw_rec,
(Vector2){data->game_rec.x, data->game_rec.y},
WHITE
);
BeginTextureMode(scene->layers.render_layers[CONTROL_LAYER].layer_tex);
ClearBackground(BLANK);
Entity_t* p_ent;
sc_map_foreach_value(&scene->ent_manager.entities_map[PLAYER_ENT_TAG], p_ent)
@ -45,13 +36,13 @@ static void level_scene_render_func(Scene_t* scene)
//sprintf(buffer, "Spawn Entity: %s", get_spawn_selection_string(current_spawn_selection));
//DrawText(buffer, gui_x, 240, 12, BLACK);
sprintf(buffer, "Number of Entities: %u", sc_map_size_64v(&scene->ent_manager.entities));
DrawText(buffer, gui_x, 270, 12, BLACK);
DrawText(buffer, gui_x, 70, 12, BLACK);
sprintf(buffer, "FPS: %u", GetFPS());
DrawText(buffer, gui_x, 320, 12, BLACK);
DrawText(buffer, gui_x, 120, 12, BLACK);
print_mempool_stats(buffer);
DrawText(buffer, gui_x, 350, 12, BLACK);
EndDrawing();
DrawText(buffer, gui_x, 150, 12, BLACK);
EndTextureMode();
}
static void level_do_action(Scene_t* scene, ActionType_t action, bool pressed)
@ -130,7 +121,7 @@ static void render_regular_game_scene(Scene_t* scene)
max.x = (int)fmin(tilemap.width, max.x + 1);
max.y = (int)fmin(tilemap.height, max.y + 1);
BeginTextureMode(data->game_viewport);
BeginTextureMode(scene->layers.render_layers[GAME_LAYER].layer_tex);
ClearBackground(WHITE);
BeginMode2D(data->camera.cam);
@ -369,10 +360,24 @@ void init_game_scene(LevelScene_t* scene)
(Rectangle){25, 25, 32*TILE_SIZE, 18*TILE_SIZE}
);
scene->scene.bg_colour = LIGHTGRAY;
add_scene_layer(
&scene->scene, scene->data.game_rec.width, scene->data.game_rec.height,
scene->data.game_rec
);
add_scene_layer(
&scene->scene, scene->scene.engine->intended_window_size.x,
scene->scene.engine->intended_window_size.y,
(Rectangle){
0, 0,
scene->scene.engine->intended_window_size.x,
scene->scene.engine->intended_window_size.y
}
);
create_player(&scene->scene.ent_manager);
update_entity_manager(&scene->scene.ent_manager);
// insert level scene systems
sc_array_add(&scene->scene.systems, &update_tilemap_system);
sc_array_add(&scene->scene.systems, &player_movement_input_system);
sc_array_add(&scene->scene.systems, &player_bbox_update_system);
@ -401,6 +406,7 @@ void init_game_scene(LevelScene_t* scene)
sc_array_add(&scene->scene.systems, &player_respawn_system);
sc_array_add(&scene->scene.systems, &update_water_runner_system);
sc_array_add(&scene->scene.systems, &render_regular_game_scene);
sc_array_add(&scene->scene.systems, &level_scene_render_func);
// This avoid graphical glitch, not essential
//sc_array_add(&scene->scene.systems, &update_tilemap_system);

View File

@ -6,14 +6,14 @@
static void menu_scene_render_func(Scene_t* scene)
{
MenuSceneData_t* data = &(CONTAINER_OF(scene, MenuScene_t, scene)->data);
BeginDrawing();
BeginTextureMode(scene->layers.render_layers[0].layer_tex);
ClearBackground(RAYWHITE);
DrawText("This is a game", 25, 220, 12, BLACK);
UI_button(data->buttons, "Start");
UI_button(data->buttons + 1, "Sandbox");
UI_button(data->buttons + 2, "Continue");
UI_button(data->buttons + 3, "Exit");
EndDrawing();
EndTextureMode();
}
static void exec_component_function(Scene_t* scene, int sel)
@ -132,10 +132,10 @@ static void gui_loop(Scene_t* scene)
void init_menu_scene(MenuScene_t* scene)
{
//init_scene(&scene->scene, MENU_SCENE, &menu_scene_render_func, &menu_do_action);
init_scene(&scene->scene, &menu_scene_render_func, &menu_do_action);
sc_array_add(&scene->scene.systems, &gui_loop);
sc_array_add(&scene->scene.systems, &menu_scene_render_func);
scene->data.buttons[0] = (UIComp_t) {
.bbox = {25,255,125,30},
@ -160,6 +160,15 @@ void init_menu_scene(MenuScene_t* scene)
scene->data.max_comp = 4;
scene->data.selected_comp = 0;
scene->data.mode = MOUSE_MODE;
add_scene_layer(
&scene->scene, scene->scene.engine->intended_window_size.x,
scene->scene.engine->intended_window_size.y,
(Rectangle){
0, 0,
scene->scene.engine->intended_window_size.x,
scene->scene.engine->intended_window_size.y
}
);
sc_map_put_64(&scene->scene.action_map, KEY_UP, ACTION_UP);
sc_map_put_64(&scene->scene.action_map, KEY_DOWN, ACTION_DOWN);

View File

@ -40,7 +40,7 @@ typedef struct LevelCamera {
typedef struct LevelSceneData {
TileGrid_t tilemap;
RenderTexture2D game_viewport;
// TODO: game_rec is actually obsolete since this is in the scene game layer
Rectangle game_rec;
LevelCamera_t camera;
Sprite_t* tile_sprites[MAX_TILE_SPRITES];
@ -60,7 +60,6 @@ void free_game_scene(LevelScene_t* scene);
void init_sandbox_scene(LevelScene_t* scene);
void free_sandbox_scene(LevelScene_t* scene);
void init_level_scene_data(LevelSceneData_t* data, uint32_t max_tiles, Tile_t* tiles, Rectangle view_zone);
//void init_level_scene_data(LevelSceneData_t* data, uint32_t max_tiles, Tile_t* tiles);
void term_level_scene_data(LevelSceneData_t* data);
void reload_level_tilemap(LevelScene_t* scene);
void load_next_level_tilemap(LevelScene_t* scene);

View File

@ -4,13 +4,8 @@
#include "constants.h"
void init_level_scene_data(LevelSceneData_t* data, uint32_t max_tiles, Tile_t* tiles, Rectangle view_zone)
//void init_level_scene_data(LevelSceneData_t* data, uint32_t max_tiles, Tile_t* tiles)
{
//data->game_viewport = LoadRenderTexture(VIEWABLE_MAP_WIDTH*TILE_SIZE, VIEWABLE_MAP_HEIGHT*TILE_SIZE);
//data->game_rec = (Rectangle){25, 25, VIEWABLE_MAP_WIDTH*TILE_SIZE, VIEWABLE_MAP_HEIGHT*TILE_SIZE};
data->game_viewport = LoadRenderTexture(view_zone.width, view_zone.height);
data->game_rec = view_zone;
//data->camera.cam = (Camera2D){0};
memset(&data->camera, 0, sizeof(LevelCamera_t));
data->camera.cam.rotation = 0.0f;
data->camera.cam.zoom = 1.0f;
@ -53,7 +48,6 @@ void term_level_scene_data(LevelSceneData_t* data)
{
sc_map_term_64v(&data->tilemap.tiles[i].entities_set);
}
UnloadRenderTexture(data->game_viewport); // Unload render texture
}
bool load_level_tilemap(LevelScene_t* scene, unsigned int level_num)

View File

@ -23,6 +23,7 @@ static GameEngine_t engine =
};
static bool water_toggle = false;
#define GAME_LAYER 0
static void level_scene_render_func(Scene_t* scene)
{
@ -31,7 +32,7 @@ static void level_scene_render_func(Scene_t* scene)
Entity_t* p_ent;
BeginTextureMode(data->game_viewport);
BeginTextureMode(scene->layers.render_layers[GAME_LAYER].layer_tex);
ClearBackground(WHITE);
BeginMode2D(data->camera.cam);
for (size_t i = 0; i < tilemap.n_tiles; ++i)
@ -177,19 +178,7 @@ static void level_scene_render_func(Scene_t* scene)
EndMode2D();
EndTextureMode();
Rectangle draw_rec = data->game_rec;
draw_rec.x = 0;
draw_rec.y = 0;
draw_rec.height *= -1;
BeginDrawing();
ClearBackground( water_toggle? ColorAlpha(BLUE, 0.2) : LIGHTGRAY);
DrawTextureRec(
data->game_viewport.texture,
draw_rec,
(Vector2){data->game_rec.x, data->game_rec.y},
WHITE
);
EndDrawing();
scene->bg_colour = water_toggle ? ColorAlpha(BLUE, 0.2) : LIGHTGRAY;
}
static inline unsigned int get_tile_idx(int x, int y, const TileGrid_t* tilemap)
@ -406,18 +395,23 @@ static void player_simple_movement_system(Scene_t* scene)
int main(void)
{
InitWindow(1280, 640, "raylib");
init_engine(&engine, (Vector2){1280,640});
SetTargetFPS(60);
init_engine(&engine);
LevelScene_t scene;
scene.scene.engine = &engine;
init_scene(&scene.scene, &level_scene_render_func, &level_do_action);
init_entity_tag_map(&scene.scene.ent_manager, PLAYER_ENT_TAG, 4);
init_entity_tag_map(&scene.scene.ent_manager, DYNMEM_ENT_TAG, 16);
init_level_scene_data(
&scene.data, MAX_N_TILES, all_tiles,
(Rectangle){25, 25, VIEWABLE_MAP_WIDTH*TILE_SIZE, VIEWABLE_MAP_HEIGHT*TILE_SIZE}
);
assert(scene.data.tilemap.n_tiles <= MAX_N_TILES);
add_scene_layer(
&scene.scene, scene.data.game_rec.width, scene.data.game_rec.height,
scene.data.game_rec
);
for (size_t i = 0; i < scene.data.tilemap.width; ++i)
{
@ -441,6 +435,7 @@ int main(void)
sc_array_add(&scene.scene.systems, &toggle_block_system);
sc_array_add(&scene.scene.systems, &camera_update_system);
sc_array_add(&scene.scene.systems, &player_dir_reset_system);
sc_array_add(&scene.scene.systems, &level_scene_render_func);
sc_map_put_64(&scene.scene.action_map, KEY_R, ACTION_RESTART);
@ -474,5 +469,4 @@ int main(void)
free_scene(&scene.scene);
term_level_scene_data(&scene.data);
deinit_engine(&engine);
CloseWindow();
}