Implmented event subscription with a particular object. Added scene load event and configured enemy entities to use that to aquire pointers to child entities after scene is loaded

dev
Shariq Shah 6 years ago
parent ddfbbbfa2d
commit 8bebda53e5
  1. 23
      src/common/limits.h
  2. 2
      src/common/version.h
  3. 2
      src/game/console.c
  4. 16
      src/game/editor.c
  5. 46
      src/game/enemy.c
  6. 16
      src/game/entity.c
  7. 5
      src/game/entity.h
  8. 109
      src/game/event.c
  9. 38
      src/game/event.h
  10. 2
      src/game/material.c
  11. 3
      src/game/material.h
  12. 2
      src/game/player.c
  13. 8
      src/game/renderer.c
  14. 117
      src/game/scene.c
  15. 23
      src/game/scene.h
  16. 2
      src/system/file_io.h
  17. 4
      todo.txt

@ -0,0 +1,23 @@
#ifndef SYMMETRY_LIMITS_H
#define SYMMETRY_LIMITS_H
#define MAX_ENTITY_NAME_LEN 128
#define MAX_FILENAME_LEN 128
#define MAX_EVENTS 128
#define MAX_EVENT_SUBSCRIPTIONS 256
#define MAX_SCENE_ENTITIES 32
#define MAX_SCENE_LIGHTS 30
#define MAX_SCENE_CAMERAS 2
#define MAX_SCENE_STATIC_MESHES 1024
#define MAX_SCENE_SOUND_SOURCES 128
#define MAX_SCENE_ENTITY_ARCHETYPES 32
#define MAX_SCENE_ENEMIES 64
#define MAX_UNIFORM_NAME_LEN 64
#define MAX_MATERIAL_REGISTERED_STATIC_MESHES 1024
#endif

@ -4,7 +4,7 @@
/* Auto generated version file. DO NOT MODIFY */
#define SYMMETRY_VERSION_MAJOR 0
#define SYMMETRY_VERSION_MINOR 1
#define SYMMETRY_VERSION_REVISION 315
#define SYMMETRY_VERSION_REVISION 316
#define SYMMETRY_VERSION_BRANCH "dev"
#endif

@ -260,7 +260,7 @@ void console_command_entity_load(struct Console* console, const char* command)
return;
}
struct Entity* new_entity = entity_load(filename, DIRT_INSTALL);
struct Entity* new_entity = entity_load(filename, DIRT_INSTALL, true);
if(!new_entity)
{
log_error("entity_load", "Could not create entity from '%s'", filename);

@ -1692,42 +1692,42 @@ void editor_window_scene_hierarchy(struct nk_context* context, struct Editor* ed
{
if(nk_tree_push(context, NK_TREE_TAB, "Cameras", NK_MAXIMIZED))
{
for(int i = 0; i < MAX_CAMERAS; i++)
for(int i = 0; i < MAX_SCENE_CAMERAS; i++)
editor_show_entity_in_list(editor, context, scene, &scene->cameras[i]);
nk_tree_pop(context);
}
if(nk_tree_push(context, NK_TREE_TAB, "Lights", NK_MAXIMIZED))
{
for(int i = 0; i < MAX_LIGHTS; i++)
for(int i = 0; i < MAX_SCENE_LIGHTS; i++)
editor_show_entity_in_list(editor, context, scene, &scene->lights[i]);
nk_tree_pop(context);
}
if(nk_tree_push(context, NK_TREE_TAB, "Static Meshes", NK_MAXIMIZED))
{
for(int i = 0; i < MAX_STATIC_MESHES; i++)
for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++)
editor_show_entity_in_list(editor, context, scene, &scene->static_meshes[i]);
nk_tree_pop(context);
}
if(nk_tree_push(context, NK_TREE_TAB, "Sound Sources", NK_MAXIMIZED))
{
for(int i = 0; i < MAX_SOUND_SOURCES; i++)
for(int i = 0; i < MAX_SCENE_SOUND_SOURCES; i++)
editor_show_entity_in_list(editor, context, scene, &scene->sound_sources[i]);
nk_tree_pop(context);
}
if(nk_tree_push(context, NK_TREE_TAB, "Enemies", NK_MAXIMIZED))
{
for(int i = 0; i < MAX_ENEMIES; i++)
for(int i = 0; i < MAX_SCENE_ENEMIES; i++)
editor_show_entity_in_list(editor, context, scene, &scene->enemies[i]);
nk_tree_pop(context);
}
if(nk_tree_push(context, NK_TREE_TAB, "Entities", NK_MAXIMIZED))
{
for(int i = 0; i < MAX_ENTITIES; i++)
for(int i = 0; i < MAX_SCENE_ENTITIES; i++)
editor_show_entity_in_list(editor, context, scene, &scene->entities[i]);
nk_tree_pop(context);
}
@ -2431,7 +2431,7 @@ void editor_entity_dialog(struct Editor* editor, struct nk_context* context)
}
else
{
struct Entity* new_entity = entity_load(entity_filename, DIRT_INSTALL);
struct Entity* new_entity = entity_load(entity_filename, DIRT_INSTALL, true);
if(new_entity)
{
editor_entity_select(editor, new_entity);
@ -2451,7 +2451,7 @@ void editor_entity_dialog(struct Editor* editor, struct nk_context* context)
}
else
{
struct Entity* new_entity = entity_load(entity_filename, DIRT_INSTALL);
struct Entity* new_entity = entity_load(entity_filename, DIRT_INSTALL, true);
if(new_entity)
{
editor_entity_select(editor, new_entity);

@ -6,9 +6,12 @@
#include "../common/log.h"
#include "../common/hashmap.h"
#include "../common/parser.h"
#include "event.h"
#include <string.h>
static void enemy_on_scene_loaded(struct Event* event, void* enemy_ptr);
void enemy_init(struct Enemy* enemy, int type)
{
struct Game_State* game_state = game_state_get();
@ -36,8 +39,8 @@ void enemy_init(struct Enemy* enemy, int type)
enemy->Turret.turn_speed = 10.f;
enemy->health = 100;
enemy->damage = 10;
weapon_sound = scene_sound_source_create(scene, weapon_name_buffer, enemy, "sounds/bullet_1.wav", ST_WAV, false, false);
mesh = scene_static_mesh_create(scene, mesh_name_buffer, enemy, "suzanne.symbres", MAT_BLINN);
//weapon_sound = scene_sound_source_create(scene, weapon_name_buffer, enemy, "sounds/bullet_1.wav", ST_WAV, false, false);
//mesh = scene_static_mesh_create(scene, mesh_name_buffer, enemy, "suzanne.symbres", MAT_BLINN);
break;
}
default:
@ -45,16 +48,16 @@ void enemy_init(struct Enemy* enemy, int type)
break;
}
enemy->weapon_sound = weapon_sound ? weapon_sound : NULL;
if(!weapon_sound)
log_error("enemy:init", "Failed to add weapon sound for %s", enemy->base.name);
//enemy->weapon_sound = weapon_sound ? weapon_sound : NULL;
//if(!weapon_sound)
// log_error("enemy:init", "Failed to add weapon sound for %s", enemy->base.name);
enemy->mesh = mesh ? mesh : NULL;
if(!mesh)
log_error("enemy:init", "Failed to add mesh from file for %s", enemy->base.name);
//enemy->mesh = mesh ? mesh : NULL;
//if(!mesh)
// log_error("enemy:init", "Failed to add mesh from file for %s", enemy->base.name);
if(enemy->mesh) enemy->mesh->base.flags |= EF_TRANSIENT;
if(enemy->weapon_sound) enemy->weapon_sound->base.flags |= EF_TRANSIENT;
struct Event_Manager* event_manager = game_state->event_manager;
event_manager_subscribe_with_object(event_manager, EVT_SCENE_LOADED, &enemy_on_scene_loaded, (void*)enemy);
}
void enemy_weapon_sound_set(struct Enemy* enemy, const char* sound_filename, int type)
@ -98,6 +101,9 @@ void enemy_reset(struct Enemy* enemy)
enemy->type = -1;
enemy->damage = 0;
enemy->health = 0;
struct Event_Manager* event_manager = game_state_get()->event_manager;
event_manager_unsubscribe_with_object(event_manager, EVT_SCENE_LOADED, &enemy_on_scene_loaded, (void*)enemy);
}
struct Enemy* enemy_read(struct Parser_Object* object, const char* name, struct Entity* parent_entity)
@ -143,3 +149,23 @@ void enemy_write(struct Enemy* enemy, struct Hashmap* entity_data)
break;
}
}
void enemy_on_scene_loaded(struct Event* event, void* enemy_ptr)
{
struct Enemy* enemy = (struct Enemy*)enemy_ptr;
// Assign pointers to mesh and sound child entities
for(int i = 0; i < array_len(enemy->base.transform.children); i++)
{
struct Entity* child = enemy->base.transform.children[i];
if(child->type == ET_STATIC_MESH)
enemy->mesh = (struct Static_Mesh*)child;
else if(child->type == ET_SOUND_SOURCE)
enemy->weapon_sound = (struct Sound_Source*)child;
}
if(enemy->mesh) enemy->mesh->base.flags |= EF_TRANSIENT;
if(enemy->weapon_sound) enemy->weapon_sound->base.flags |= EF_TRANSIENT;
// Do other post-scene-load initialization stuff per enemy type here
}

@ -19,6 +19,7 @@
#include "game.h"
#include "texture.h"
#include "enemy.h"
#include "event.h"
#include <stdlib.h>
#include <string.h>
@ -538,7 +539,7 @@ struct Entity* entity_read(struct Parser_Object* object, struct Entity* parent_e
return new_entity;
}
struct Entity* entity_load(const char* filename, int directory_type)
struct Entity* entity_load(const char* filename, int directory_type, bool send_on_load_event)
{
char prefixed_filename[MAX_FILENAME_LEN + 16];
snprintf(prefixed_filename, MAX_FILENAME_LEN + 16, "entities/%s.symtres", filename);
@ -595,6 +596,19 @@ struct Entity* entity_load(const char* filename, int directory_type)
}
}
// Send simulated scene loaded event since this entity has been loaded while the scene has already been loaded
if(send_on_load_event)
{
struct Game_State* game_state = game_state_get();
struct Event_Manager* event_manager = game_state->event_manager;
struct Event on_scene_loaded_event =
{
.type = EVT_SCENE_LOADED,
};
strncpy(on_scene_loaded_event.scene_load.filename, game_state->scene->filename, MAX_FILENAME_LEN);
event_manager_send_event_entity(event_manager, &on_scene_loaded_event, parent_entity);
}
parser_free(parsed_file);
fclose(entity_file);
return parent_entity;

@ -7,8 +7,7 @@
#include "../system/sound.h"
#include "bounding_volumes.h"
#include "material.h"
#define MAX_ENTITY_NAME_LEN 128
#include "../common/limits.h"
struct Entity;
@ -212,7 +211,7 @@ struct Enemy
void entity_init(struct Entity* entity, const char* name, struct Entity* parent);
void entity_reset(struct Entity* entity, int id);
bool entity_save(struct Entity* entity, const char* filename, int directory_type);
struct Entity* entity_load(const char* filename, int directory_type);
struct Entity* entity_load(const char* filename, int directory_type, bool send_on_scene_load_event);
bool entity_write(struct Entity* entity, struct Parser_Object* object, bool write_transform);
struct Entity* entity_read(struct Parser_Object* object, struct Entity* parent_entity);
const char* entity_type_name_get(struct Entity* entity);

@ -10,13 +10,12 @@ void event_manager_init(struct Event_Manager* event_manager)
{
assert(event_manager);
memset(event_manager->event_subsciptions, '\0', sizeof(struct Event_Subscription) * MAX_EVENT_SUBSCRIPTIONS);
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
{
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
memset(subscription, '\0', sizeof(struct Event_Subscription));
memset(subscription, 0, sizeof(struct Event_Subscription));
subscription->event_type = EVT_NONE;
subscription->type = EST_NONE;
}
for(int i = 0; i < MAX_EVENTS; i++)
@ -38,7 +37,7 @@ void event_manager_subscribe(struct Event_Manager* event_manager, int event_type
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
{
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
if(subscription->event_type == event_type && subscription->handler == handler_func)
if(subscription->type == EST_WITHOUT_OBJECT && subscription->event_type == event_type && subscription->handler == handler_func)
{
log_message("Already subscibed to %s event", event_name_get(event_type));
subscribed = true;
@ -53,8 +52,9 @@ void event_manager_subscribe(struct Event_Manager* event_manager, int event_type
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
{
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
if(subscription->event_type == EVT_NONE)
if(subscription->type == EST_NONE)
{
subscription->type = EST_WITHOUT_OBJECT;
subscription->event_type = event_type;
subscription->handler = handler_func;
subscribed = true;
@ -69,17 +69,38 @@ void event_manager_subscribe(struct Event_Manager* event_manager, int event_type
log_error("event_manager:subscribe", "Could not subscribe to %s event", event_name_get(event_type));
}
void event_manager_unsubscribe(struct Event_Manager* event_manager, int event_type, Event_Handler subscriber)
void event_manager_unsubscribe(struct Event_Manager* event_manager, int event_type, Event_Handler handler_func)
{
assert(event_manager && event_type < EVT_MAX);
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
{
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
if(subscription->event_type == event_type && subscription->handler == subscriber)
if(subscription->type != EST_WITHOUT_OBJECT) continue;
if(subscription->event_type == event_type && subscription->handler == handler_func)
{
subscription->handler = NULL;
subscription->event_type = EVT_NONE;
subscription->type = EST_NONE;
break;
}
}
}
void event_manager_unsubscribe_with_object(struct Event_Manager* event_manager, int event_type, Event_Handler_Object handler_func, void* subscriber)
{
assert(event_manager && event_type < EVT_MAX);
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
{
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
if(subscription->type != EST_WITH_OBJECT) continue;
if(subscription->event_type == event_type && subscription->handler_with_object == handler_func && subscription->subscriber == subscriber)
{
subscription->handler_with_object = NULL;
subscription->event_type = EVT_NONE;
subscription->type = EST_NONE;
subscription->subscriber = NULL;
break;
}
}
@ -212,9 +233,20 @@ void event_manager_poll_events(struct Event_Manager* event_manager, bool* out_qu
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
{
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
if(subscription->type == EST_NONE) continue;
if(subscription->event_type == user_event->type)
{
if(subscription->handler) subscription->handler(user_event);
if(subscription->type == EST_WITHOUT_OBJECT)
{
if(subscription->handler)
subscription->handler(user_event);
}
else if(subscription->type == EST_WITH_OBJECT)
{
if(subscription->handler_with_object)
subscription->handler_with_object(user_event, subscription->subscriber);
}
}
}
@ -228,6 +260,49 @@ void event_manager_poll_events(struct Event_Manager* event_manager, bool* out_qu
}
}
void event_manager_subscribe_with_object(struct Event_Manager* event_manager, int event_type, Event_Handler_Object handler_func, void* subscriber)
{
assert(event_manager && event_type < EVT_MAX && event_type > EVT_NONE);
//Check if this handler/subscriber already exists
bool subscribed = false;
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
{
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
if(subscription->type == EST_WITH_OBJECT && subscription->event_type == event_type && subscription->handler_with_object == handler_func && subscription->subscriber != subscriber)
{
log_message("Already subscibed to %s event", event_name_get(event_type));
subscribed = true;
break;
}
}
//Now that we've established that we are not subscribed already we find an empty slot and
//create a new subscription there
if(!subscribed)
{
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
{
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
if(subscription->type == EST_NONE)
{
subscription->type = EST_WITH_OBJECT;
subscription->event_type = event_type;
subscription->handler_with_object = handler_func;
subscription->subscriber = subscriber;
subscribed = true;
break;
}
}
}
//if subscribed is still not true, it can only mean that all the existing slots are taken
//Show an error message in that case
if(!subscribed)
log_error("event_manager:subscribe_with_obejct", "Could not subscribe to %s event", event_name_get(event_type));
}
void event_manager_cleanup(struct Event_Manager* event_manager)
{
@ -248,7 +323,25 @@ const char* event_name_get(int event_type)
case EVT_MOUSEWHEEL: return "Mouse Wheel";
case EVT_WINDOW_RESIZED: return "Window Resized";
case EVT_TEXT_INPUT: return "Text Input";
case EVT_SCENE_LOADED: return "Scene Loaded";
case EVT_MAX: return "Max Number of Events";
default: return "Invalid event_type";
}
}
void event_manager_send_event_entity(struct Event_Manager* event_manager, struct Event* event, struct Entity* entity)
{
// Check if this entity has a subscription, if it does,
// call the registered callback with this entity as the parameter to simulate an event
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
{
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
if(subscription->type != EST_WITH_OBJECT) continue;
if(subscription->event_type == event->type && subscription->subscriber == entity && subscription->handler_with_object)
{
subscription->handler_with_object(event, (void*)entity);
break;
}
}
}

@ -3,11 +3,13 @@
#include "../common/linmath.h"
#include "../common/num_types.h"
#include "../common/limits.h"
struct Entity;
typedef void (*Event_Handler) (const struct Event* event);
typedef void (*Event_Handler_Object) (const struct Event* event, void* subscriber);
#define MAX_EVENTS 128
#define MAX_EVENT_SUBSCRIPTIONS 256
enum Event_Types
{
@ -20,9 +22,17 @@ enum Event_Types
EVT_MOUSEWHEEL,
EVT_WINDOW_RESIZED,
EVT_TEXT_INPUT,
EVT_SCENE_LOADED,
EVT_MAX
};
enum Event_Subscription_Type
{
EST_NONE = 0,
EST_WITHOUT_OBJECT,
EST_WITH_OBJECT
};
struct Key_Event
{
int scancode;
@ -68,6 +78,11 @@ struct Window_Resized_Event
int height;
};
struct Scene_Loaded_Event
{
char filename[MAX_FILENAME_LEN];
};
struct Event
{
int type;
@ -79,13 +94,27 @@ struct Event
struct Mousemotion_Event mousemotion;
struct Text_Input_Event text_input;
struct Window_Resized_Event window_resize;
struct Scene_Loaded_Event scene_load;
};
};
struct Event_Subscription
{
int type;
int event_type;
union
{
struct
{
Event_Handler handler;
};
struct
{
Event_Handler_Object handler_with_object;
void* subscriber;
};
};
};
struct Event_Manager
@ -96,10 +125,13 @@ struct Event_Manager
};
void event_manager_init(struct Event_Manager* event_manager);
void event_manager_subscribe(struct Event_Manager* event_manager, int event_type, Event_Handler subscriber);
void event_manager_subscribe(struct Event_Manager* event_manager, int event_type, Event_Handler event_handler_func);
void event_manager_subscribe_with_object(struct Event_Manager* event_manager, int event_type, Event_Handler_Object handler_func, void* subscriber);
void event_manager_unsubscribe(struct Event_Manager* event_manager, int event_type, Event_Handler subscriber);
void event_manager_unsubscribe_with_object(struct Event_Manager* event_manager, int event_type, Event_Handler_Object handler_func, void* subscriber);
struct Event* event_manager_create_new_event(struct Event_Manager* event_manager);
void event_manager_send_event(struct Event_Manager* event_manager, struct Event* event);
void event_manager_send_event_entity(struct Event_Manager* event_manager, struct Event* event, struct Entity* entity);
void event_manager_poll_events(struct Event_Manager* event_manager, bool* out_quit);
void event_manager_cleanup(struct Event_Manager* event_manager);
const char* event_name_get(int event_type);

@ -27,7 +27,7 @@ bool material_init(struct Material* material, int material_type)
{
material->lit = true;
char custom_defines[64];
snprintf(custom_defines, 64, "#define MAX_LIGHTS %d", MAX_LIGHTS);
snprintf(custom_defines, 64, "#define MAX_LIGHTS %d", MAX_SCENE_LIGHTS);
material->shader = shader_create("blinn_phong.vert", "blinn_phong.frag", custom_defines);
if(material->shader == -1)

@ -4,11 +4,10 @@
#include "../common/linmath.h"
#include "../common/num_types.h"
#include "../common/variant.h"
#include "../common/limits.h"
struct Static_Mesh;
#define MAX_UNIFORM_NAME_LEN 64
#define MAX_MATERIAL_REGISTERED_STATIC_MESHES 1024
struct Uniform
{

@ -267,7 +267,7 @@ void player_on_mousebutton_released(const struct Event* event)
vec3_scale(&collision_point, &collision_point, distance);
vec3_add(&collision_point, &collision_point, &bullet_ray.origin);
//struct Static_Mesh* bullet = scene_static_mesh_create(game_state_get()->scene, "bullet", NULL, "cube.symbres", MAT_UNSHADED);
struct Light* bullet = entity_load("Spot", DIRT_INSTALL);
struct Light* bullet = entity_load("Spot", DIRT_INSTALL, true);
if(bullet) transform_set_position(bullet, &collision_point);
sound_source_play(game_state->sound, player->weapon_sound);
}

@ -103,7 +103,7 @@ void renderer_render(struct Renderer* renderer, struct Scene* scene)
char uniform_name[MAX_UNIFORM_NAME_LEN];
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
int light_count = -1;
for(int j = 0; j < MAX_LIGHTS; j++)
for(int j = 0; j < MAX_SCENE_LIGHTS; j++)
{
struct Light* light = &scene->lights[j]; /* TODO: Cull lights according to camera frustum */
if(!(light->base.flags & EF_ACTIVE) || !light->valid) continue;
@ -253,7 +253,7 @@ void renderer_render(struct Renderer* renderer, struct Scene* scene)
{
static mat4 mvp;
shader_set_uniform_vec4(renderer->debug_shader, "debug_color", &renderer->settings.debug_draw_color);
for(int i = 0; i < MAX_STATIC_MESHES; i++)
for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++)
{
struct Static_Mesh* mesh = &scene->static_meshes[i];
if(!(mesh->base.flags & EF_ACTIVE)) continue;
@ -274,7 +274,7 @@ void renderer_render(struct Renderer* renderer, struct Scene* scene)
if(renderer->settings.debug_draw_physics)
{
static vec4 physics_draw_color = { 0.f, 0.f, 1.f, 1.f };
for(int i = 0; i < MAX_STATIC_MESHES; i++)
for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++)
{
struct Static_Mesh* mesh = &scene->static_meshes[i];
if(!(mesh->base.flags & EF_ACTIVE) || (!mesh->collision.collision_shape && !mesh->collision.rigidbody)) continue;
@ -361,7 +361,7 @@ void renderer_on_framebuffer_size_changed(const struct Event* event)
struct Scene* scene = game_state_get()->scene;
float aspect = (float)width / (float)height;
for(int i = 0; i < MAX_CAMERAS; i++)
for(int i = 0; i < MAX_SCENE_CAMERAS; i++)
{
struct Camera* viewer = &scene->cameras[i];
if(viewer->resizeable)

@ -19,6 +19,7 @@
#include "renderer.h"
#include "sound_source.h"
#include "enemy.h"
#include "event.h"
#include <assert.h>
#include <string.h>
@ -41,14 +42,14 @@ void scene_init(struct Scene* scene)
scene->root_entity.id = 0;
scene->root_entity.type = ET_ROOT;
for(int i = 0; i < MAX_ENTITIES; i++) entity_reset(&scene->entities[i], i);
for(int i = 0; i < MAX_LIGHTS; i++)
for(int i = 0; i < MAX_SCENE_ENTITIES; i++) entity_reset(&scene->entities[i], i);
for(int i = 0; i < MAX_SCENE_LIGHTS; i++)
{
entity_reset(&scene->lights[i], i);
scene->lights[i].type = ET_LIGHT;
}
for(int i = 0; i < MAX_STATIC_MESHES; i++)
for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++)
{
entity_reset(&scene->static_meshes[i], i);
struct Static_Mesh* mesh = &scene->static_meshes[i];
@ -59,11 +60,11 @@ void scene_init(struct Scene* scene)
mesh->model.material = NULL;
}
for(int i = 0; i < MAX_SOUND_SOURCES; i++) entity_reset(&scene->sound_sources[i], i);
for(int i = 0; i < MAX_SCENE_SOUND_SOURCES; i++) entity_reset(&scene->sound_sources[i], i);
int width = 1280, height = 720;
window_get_drawable_size(game_state->window, &width, &height);
for(int i = 0; i < MAX_CAMERAS; i++)
for(int i = 0; i < MAX_SCENE_CAMERAS; i++)
{
entity_init(&scene->cameras[i], NULL, &scene->root_entity);
camera_init(&scene->cameras[i], width, height);
@ -71,10 +72,10 @@ void scene_init(struct Scene* scene)
scene->cameras[i].base.id = i;
}
for(int i = 0; i < MAX_ENTITY_ARCHETYPES; i++)
for(int i = 0; i < MAX_SCENE_ENTITY_ARCHETYPES; i++)
memset(&scene->entity_archetypes[i][0], '\0', MAX_FILENAME_LEN);
for(int i = 0; i < MAX_ENEMIES; i++)
for(int i = 0; i < MAX_SCENE_ENEMIES; i++)
{
entity_reset(&scene->enemies[i], i);
scene->enemies->base.type = ET_ENEMY;
@ -156,7 +157,7 @@ bool scene_load(struct Scene* scene, const char* filename, int directory_type)
struct Hashmap* entity_entry_data = object->data;
if(hashmap_value_exists(object->data, "filename"))
{
struct Entity* loaded_entity = entity_load(hashmap_str_get(entity_entry_data, "filename"), DIRT_INSTALL);
struct Entity* loaded_entity = entity_load(hashmap_str_get(entity_entry_data, "filename"), DIRT_INSTALL, false);
if(loaded_entity)
{
vec3 position = { 0.f, 0.f, 0.f };
@ -208,6 +209,16 @@ bool scene_load(struct Scene* scene, const char* filename, int directory_type)
parser_free(parsed_file);
fclose(scene_file);
strncpy(scene->filename, filename, MAX_FILENAME_LEN);
if(num_objects_loaded > 0)
{
struct Event_Manager* event_manager = game_state_get()->event_manager;
struct Event* scene_loaded_event = event_manager_create_new_event(event_manager);
scene_loaded_event->type = EVT_SCENE_LOADED;
memset(scene_loaded_event->scene_load.filename, '\0', MAX_FILENAME_LEN);
strncpy(scene_loaded_event->scene_load.filename, filename, MAX_FILENAME_LEN);
event_manager_send_event(event_manager, scene_loaded_event);
}
return num_objects_loaded > 0 ? true : false;
}
@ -267,32 +278,32 @@ void scene_write_entity_list(struct Scene* scene, int entity_type, struct Parser
switch(entity_type)
{
case ET_DEFAULT:
max_length = MAX_ENTITIES;
max_length = MAX_SCENE_ENTITIES;
entity = &scene->entities[0];
stride = sizeof(struct Entity);
break;
case ET_LIGHT:
max_length = MAX_LIGHTS;
max_length = MAX_SCENE_LIGHTS;
entity = &scene->lights[0].base;
stride = sizeof(struct Light);
break;
case ET_STATIC_MESH:
max_length = MAX_STATIC_MESHES;
max_length = MAX_SCENE_STATIC_MESHES;
entity = &scene->static_meshes[0].base;
stride = sizeof(struct Static_Mesh);
break;
case ET_CAMERA:
max_length = MAX_CAMERAS;
max_length = MAX_SCENE_CAMERAS;
entity = &scene->cameras[0].base;
stride = sizeof(struct Camera);
break;
case ET_SOUND_SOURCE:
max_length = MAX_SOUND_SOURCES;
max_length = MAX_SCENE_SOUND_SOURCES;
entity = &scene->sound_sources[0].base;
stride = sizeof(struct Sound_Source);
break;
case ET_ENEMY:
max_length = MAX_ENEMIES;
max_length = MAX_SCENE_ENEMIES;
entity = &scene->enemies[0].base;
stride = sizeof(struct Enemy);
break;
@ -338,13 +349,13 @@ void scene_destroy(struct Scene* scene)
{
assert(scene);
for(int i = 0; i < MAX_ENTITIES; i++) scene_entity_base_remove(scene, &scene->entities[i]);
for(int i = 0; i < MAX_CAMERAS; i++) scene_camera_remove(scene, &scene->cameras[i]);
for(int i = 0; i < MAX_LIGHTS; i++) scene_light_remove(scene, &scene->lights[i]);
for(int i = 0; i < MAX_STATIC_MESHES; i++) scene_static_mesh_remove(scene, &scene->static_meshes[i]);
for(int i = 0; i < MAX_SOUND_SOURCES; i++) scene_sound_source_remove(scene, &scene->sound_sources[i]);
for(int i = 0; i < MAX_ENEMIES; i++) scene_enemy_remove(scene, &scene->enemies[i]);
for(int i = 0; i < MAX_ENTITY_ARCHETYPES; i++) memset(&scene->entity_archetypes[i][0], '\0', MAX_FILENAME_LEN);
for(int i = 0; i < MAX_SCENE_ENTITIES; i++) scene_entity_base_remove(scene, &scene->entities[i]);
for(int i = 0; i < MAX_SCENE_CAMERAS; i++) scene_camera_remove(scene, &scene->cameras[i]);
for(int i = 0; i < MAX_SCENE_LIGHTS; i++) scene_light_remove(scene, &scene->lights[i]);
for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++) scene_static_mesh_remove(scene, &scene->static_meshes[i]);
for(int i = 0; i < MAX_SCENE_SOUND_SOURCES; i++) scene_sound_source_remove(scene, &scene->sound_sources[i]);
for(int i = 0; i < MAX_SCENE_ENEMIES; i++) scene_enemy_remove(scene, &scene->enemies[i]);
for(int i = 0; i < MAX_SCENE_ENTITY_ARCHETYPES; i++) memset(&scene->entity_archetypes[i][0], '\0', MAX_FILENAME_LEN);
player_destroy(&scene->player);
entity_reset(&scene->root_entity, 0);
scene->root_entity.flags &= ~EF_ACTIVE;
@ -355,7 +366,7 @@ void scene_update(struct Scene* scene, float dt)
if(game_state_get()->game_mode == GAME_MODE_GAME)
{
player_update(&scene->player, scene, dt);
for(int i = 0; i < MAX_ENEMIES; i++)
for(int i = 0; i < MAX_SCENE_ENEMIES; i++)
{
if(scene->enemies[i].base.flags & EF_ACTIVE)
enemy_update(&scene->enemies[i], scene, dt);
@ -368,7 +379,7 @@ void scene_post_update(struct Scene* scene)
assert(scene);
struct Sound* sound = game_state_get()->sound;
for(int i = 0; i < MAX_ENTITIES; i++)
for(int i = 0; i < MAX_SCENE_ENTITIES; i++)
{
struct Entity* entity = &scene->entities[i];
if(!(entity->flags & EF_ACTIVE)) continue;
@ -382,7 +393,7 @@ void scene_post_update(struct Scene* scene)
if(entity->transform.is_modified) entity->transform.is_modified = false;
}
for(int i = 0; i < MAX_CAMERAS; i++)
for(int i = 0; i < MAX_SCENE_CAMERAS; i++)
{
struct Camera* camera = &scene->cameras[i];
if(!(camera->base.flags & EF_ACTIVE)) continue;
@ -400,7 +411,7 @@ void scene_post_update(struct Scene* scene)
}
}
for(int i = 0; i < MAX_SOUND_SOURCES; i++)
for(int i = 0; i < MAX_SCENE_SOUND_SOURCES; i++)
{
struct Sound_Source* sound_source = &scene->sound_sources[i];
if(!(sound_source->base.flags & EF_ACTIVE)) continue;
@ -418,7 +429,7 @@ void scene_post_update(struct Scene* scene)
}
}
for(int i = 0; i < MAX_STATIC_MESHES; i++)
for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++)
{
struct Static_Mesh* static_mesh = &scene->static_meshes[i];
if(!(static_mesh->base.flags & EF_ACTIVE)) continue;
@ -445,7 +456,7 @@ void scene_post_update(struct Scene* scene)
}
}
for(int i = 0; i < MAX_LIGHTS; i++)
for(int i = 0; i < MAX_SCENE_LIGHTS; i++)
{
struct Light* light = &scene->lights[i];
if(!(light->base.flags & EF_ACTIVE)) continue;
@ -459,7 +470,7 @@ void scene_post_update(struct Scene* scene)
if(light->base.transform.is_modified) light->base.transform.is_modified = false;
}
for(int i = 0; i < MAX_ENEMIES; i++)
for(int i = 0; i < MAX_SCENE_ENEMIES; i++)
{
struct Enemy* enemy = &scene->enemies[i];
if(!(enemy->base.flags & EF_ACTIVE)) continue;
@ -483,7 +494,7 @@ struct Entity* scene_entity_create(struct Scene* scene, const char* name, struct
assert(scene);
struct Entity* new_entity = NULL;
for(int i = 0; i < MAX_ENTITIES; i++)
for(int i = 0; i < MAX_SCENE_ENTITIES; i++)
{
struct Entity* entity = &scene->entities[i];
if(!(entity->flags & EF_ACTIVE))
@ -511,7 +522,7 @@ struct Light* scene_light_create(struct Scene* scene, const char* name, struct E
{
assert(scene);
struct Light* new_light = NULL;
for(int i = 0; i < MAX_LIGHTS; i++)
for(int i = 0; i < MAX_SCENE_LIGHTS; i++)
{
struct Light* light = &scene->lights[i];
if(!(light->base.flags & EF_ACTIVE))
@ -539,7 +550,7 @@ struct Camera* scene_camera_create(struct Scene* scene, const char* name, struct
{
assert(scene);
struct Camera* new_camera = NULL;
for(int i = 0; i < MAX_CAMERAS; i++)
for(int i = 0; i < MAX_SCENE_CAMERAS; i++)
{
struct Camera* camera = &scene->cameras[i];
if(!(camera->base.flags & EF_ACTIVE))
@ -567,7 +578,7 @@ struct Static_Mesh* scene_static_mesh_create(struct Scene* scene, const char* na
{
assert(scene);
struct Static_Mesh* new_static_mesh = NULL;
for(int i = 0; i < MAX_STATIC_MESHES; i++)
for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++)
{
struct Static_Mesh* static_mesh = &scene->static_meshes[i];
if(!(static_mesh->base.flags & EF_ACTIVE))
@ -599,7 +610,7 @@ struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char*
assert(scene && filename);
struct Sound* sound = game_state_get()->sound;
struct Sound_Source* new_sound_source = NULL;
for(int i = 0; i < MAX_SOUND_SOURCES; i++)
for(int i = 0; i < MAX_SCENE_SOUND_SOURCES; i++)
{
struct Sound_Source* sound_source = &scene->sound_sources[i];
if(!(sound_source->base.flags & EF_ACTIVE))
@ -657,7 +668,7 @@ struct Enemy* scene_enemy_create(struct Scene* scene, const char* name, struct E
{
assert(scene);
struct Enemy* new_enemy = NULL;
for(int i = 0; i < MAX_ENEMIES; i++)
for(int i = 0; i < MAX_SCENE_ENEMIES; i++)
{
struct Enemy* enemy = &scene->enemies[i];
if(!(enemy->base.flags & EF_ACTIVE))
@ -738,7 +749,7 @@ struct Entity* scene_entity_find(struct Scene* scene, const char* name)
assert(scene && name);
struct Entity* entity = NULL;
for(int i = 0; i < MAX_ENTITIES; i++)
for(int i = 0; i < MAX_SCENE_ENTITIES; i++)
{
if(strncmp(name, scene->entities[i].name, MAX_ENTITY_NAME_LEN) == 0)
{
@ -755,7 +766,7 @@ struct Light* scene_light_find(struct Scene* scene, const char* name)
assert(scene && name);
struct Light* light = NULL;
for(int i = 0; i < MAX_LIGHTS; i++)
for(int i = 0; i < MAX_SCENE_LIGHTS; i++)
{
if(strncmp(name, scene->lights[i].base.name, MAX_ENTITY_NAME_LEN) == 0)
{
@ -772,7 +783,7 @@ struct Camera* scene_camera_find(struct Scene* scene, const char* name)
assert(scene && name);
struct Camera* camera = NULL;
for(int i = 0; i < MAX_CAMERAS; i++)
for(int i = 0; i < MAX_SCENE_CAMERAS; i++)
{
if(strncmp(name, scene->cameras[i].base.name, MAX_ENTITY_NAME_LEN) == 0)
{
@ -789,7 +800,7 @@ struct Static_Mesh* scene_static_mesh_find(struct Scene* scene, const char* name
assert(scene && name);
struct Static_Mesh* static_mesh = NULL;
for(int i = 0; i < MAX_STATIC_MESHES; i++)
for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++)
{
if(strncmp(name, scene->static_meshes[i].base.name, MAX_ENTITY_NAME_LEN) == 0)
{
@ -806,7 +817,7 @@ struct Sound_Source* scene_sound_source_find(struct Scene* scene, const char* na
assert(scene && name);
struct Sound_Source* sound_source = NULL;
for(int i = 0; i < MAX_SOUND_SOURCES; i++)
for(int i = 0; i < MAX_SCENE_SOUND_SOURCES; i++)
{
if(strncmp(name, scene->sound_sources[i].base.name, MAX_ENTITY_NAME_LEN) == 0)
{
@ -823,7 +834,7 @@ struct Enemy* scene_enemy_get(struct Scene* scene, const char* name)
assert(scene && name);
struct Enemy* enemy = NULL;
for(int i = 0; i < MAX_ENEMIES; i++)
for(int i = 0; i < MAX_SCENE_ENEMIES; i++)
{
if(strncmp(name, scene->enemies[i].base.name, MAX_ENTITY_NAME_LEN) == 0)
{
@ -906,31 +917,31 @@ void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Re
{
case ET_DEFAULT:
if(!(ray_mask & ERM_DEFAULT)) continue;
max_length = MAX_ENTITIES;
max_length = MAX_SCENE_ENTITIES;
entity = &scene->entities[0];
stride = sizeof(struct Entity);
break;
case ET_LIGHT:
if(!(ray_mask & ERM_LIGHT)) continue;
max_length = MAX_LIGHTS;
max_length = MAX_SCENE_LIGHTS;
entity = &scene->lights[0].base;
stride = sizeof(struct Light);
break;
case ET_STATIC_MESH:
if(!(ray_mask & ERM_STATIC_MESH)) continue;
max_length = MAX_STATIC_MESHES;
max_length = MAX_SCENE_STATIC_MESHES;
entity = &scene->static_meshes[0].base;
stride = sizeof(struct Static_Mesh);
break;
case ET_CAMERA:
if(!(ray_mask & ERM_CAMERA)) continue;
max_length = MAX_CAMERAS;
max_length = MAX_SCENE_CAMERAS;
entity = &scene->cameras[0].base;
stride = sizeof(struct Camera);
break;
case ET_SOUND_SOURCE:
if(!(ray_mask & ERM_SOUND_SOURCE)) continue;
max_length = MAX_SOUND_SOURCES;
max_length = MAX_SCENE_SOUND_SOURCES;
entity = &scene->sound_sources[0].base;
stride = sizeof(struct Sound_Source);
break;
@ -981,31 +992,31 @@ struct Entity* scene_ray_intersect_closest(struct Scene* scene, struct Ray* ray,
{
case ET_DEFAULT:
if(!(ray_mask & ERM_DEFAULT)) continue;
max_length = MAX_ENTITIES;
max_length = MAX_SCENE_ENTITIES;
entity = &scene->entities[0];
stride = sizeof(struct Entity);
break;
case ET_LIGHT:
if(!(ray_mask & ERM_LIGHT)) continue;
max_length = MAX_LIGHTS;
max_length = MAX_SCENE_LIGHTS;
entity = &scene->lights[0].base;
stride = sizeof(struct Light);
break;
case ET_STATIC_MESH:
if(!(ray_mask & ERM_STATIC_MESH)) continue;
max_length = MAX_STATIC_MESHES;
max_length = MAX_SCENE_STATIC_MESHES;
entity = &scene->static_meshes[0].base;
stride = sizeof(struct Static_Mesh);
break;
case ET_CAMERA:
if(!(ray_mask & ERM_CAMERA)) continue;
max_length = MAX_CAMERAS;
max_length = MAX_SCENE_CAMERAS;
entity = &scene->cameras[0].base;
stride = sizeof(struct Camera);
break;
case ET_SOUND_SOURCE:
if(!(ray_mask & ERM_SOUND_SOURCE)) continue;
max_length = MAX_SOUND_SOURCES;
max_length = MAX_SCENE_SOUND_SOURCES;
entity = &scene->sound_sources[0].base;
stride = sizeof(struct Sound_Source);
break;
@ -1068,7 +1079,7 @@ int scene_entity_archetype_add(struct Scene* scene, const char* filename)
// check if we have already added this archetype, if we have, return that index
// otherwise add it and return the index
int index = -1;
for(int i = 0; i < MAX_ENTITY_ARCHETYPES; i++)
for(int i = 0; i < MAX_SCENE_ENTITY_ARCHETYPES; i++)
{
if(strncmp(filename, &scene->entity_archetypes[i][0], MAX_FILENAME_LEN) == 0)
{
@ -1079,7 +1090,7 @@ int scene_entity_archetype_add(struct Scene* scene, const char* filename)
if(index == -1)
{
for(int i = 0; i < MAX_ENTITY_ARCHETYPES; i++)
for(int i = 0; i < MAX_SCENE_ENTITY_ARCHETYPES; i++)
{
if(scene->entity_archetypes[i][0] == '\0')
{
@ -1103,7 +1114,7 @@ struct Entity* scene_entity_duplicate(struct Scene* scene, struct Entity* entity
struct Entity* new_entity = NULL;
if(entity->archetype_index != -1)
{
new_entity = entity_load(scene->entity_archetypes[entity->archetype_index], DIRT_INSTALL);
new_entity = entity_load(scene->entity_archetypes[entity->archetype_index], DIRT_INSTALL, true);
if(new_entity) scene_entity_parent_set(scene, new_entity, entity->transform.parent);
return new_entity;
}

@ -3,14 +3,7 @@
#include "entity.h"
#include "renderer.h"
#define MAX_ENTITIES 32
#define MAX_LIGHTS 30
#define MAX_CAMERAS 2
#define MAX_STATIC_MESHES 1024
#define MAX_SOUND_SOURCES 128
#define MAX_ENTITY_ARCHETYPES 32
#define MAX_ENEMIES 64
#include "../common/limits.h"
struct Ray;
struct Raycast_Result;
@ -20,13 +13,13 @@ struct Scene
char filename[MAX_FILENAME_LEN];
struct Entity root_entity;
struct Player player;
struct Entity entities[MAX_ENTITIES];
struct Static_Mesh static_meshes[MAX_STATIC_MESHES];
struct Camera cameras[MAX_CAMERAS];
struct Light lights[MAX_LIGHTS];
struct Sound_Source sound_sources[MAX_SOUND_SOURCES];
struct Enemy enemies[MAX_ENEMIES];
char entity_archetypes[MAX_ENTITY_ARCHETYPES][MAX_FILENAME_LEN];
struct Entity entities[MAX_SCENE_ENTITIES];
struct Static_Mesh static_meshes[MAX_SCENE_STATIC_MESHES];
struct Camera cameras[MAX_SCENE_CAMERAS];
struct Light lights[MAX_SCENE_LIGHTS];
struct Sound_Source sound_sources[MAX_SCENE_SOUND_SOURCES];
struct Enemy enemies[MAX_SCENE_ENEMIES];
char entity_archetypes[MAX_SCENE_ENTITY_ARCHETYPES][MAX_FILENAME_LEN];
int active_camera_index;
};

@ -4,7 +4,7 @@
#include <stdbool.h>
#include <stdio.h>
#define MAX_FILENAME_LEN 128
#include "../common/limits.h"
enum Directory_Type
{

@ -1,5 +1,4 @@
Todo:
- Imlement reading/writing enemy mesh and weapon sound to file and resetting it in code
- Enemy ray casting and shooting
- Player shooting
- Player jump cooldown, don't allow jump until a certian time interval has passed, even if we're grounded
@ -34,6 +33,7 @@ Todo:
- Command to reload entities only
- Serialize player, camera properties to file
- Change mouse behaviour to lock cursor when looking around so as not to interfere with gui elements when in editor mode
- Resource manager that loads/unloads/reloads all types of assets and caches them when required so that we don't end up constantly loading files from disk
- Folder management api to create/delete folders when none exist. Dirent would suffice for our simple needs?
? Entity creator window to create new types of entities and write them
to disk
@ -402,3 +402,5 @@ Done:
* Screen mouse coordinates to world-coordinates for aiming
* Sound source entity functions that automatically track if handles are valid and create/update as necessary
* Apply sound source properties to source instance whenever a new instance is created
* Imlemented reading/writing enemy mesh and weapon sound to file and resetting it in code
* Implemented on_load and on_update callbacks for enemies. Different enemy types have different callbacks that are assigned when they are created.
Loading…
Cancel
Save