world-format #14
|
@ -18,7 +18,7 @@ static resource_t* insert_asset(const resource_t* resource) {
|
|||
return inserted;
|
||||
}
|
||||
|
||||
void add_arbitrary_asset(void* memory, deleter_t deleter) {
|
||||
void add_arbitrary_asset(void* memory, deleter_fn deleter) {
|
||||
char name_buf[99];
|
||||
// generate the name of the arbitrary block based on adresses
|
||||
sprintf(name_buf, "%p%p", memory, deleter);
|
||||
|
|
|
@ -17,7 +17,7 @@ typedef enum resourcetype_t {
|
|||
RESOURCETYPE_MAX
|
||||
} resourcetype_t;
|
||||
|
||||
typedef void(*deleter_t)(void* target);
|
||||
typedef void(*deleter_fn)(void* target);
|
||||
|
||||
typedef struct resource_t {
|
||||
resourcetype_t type;
|
||||
|
@ -31,13 +31,13 @@ typedef struct resource_t {
|
|||
} font;
|
||||
struct {
|
||||
void* memory;
|
||||
deleter_t deleter;
|
||||
deleter_fn deleter;
|
||||
} arbitrary_type;
|
||||
};
|
||||
} resource_t;
|
||||
|
||||
extern void add_arbitrary_asset(void* memory, deleter_t deleter);
|
||||
extern void add_arbitrary_asset_by_name(void* memory, deleter_t deleter, const char* name);
|
||||
extern void add_arbitrary_asset(void* memory, deleter_fn deleter);
|
||||
extern void add_arbitrary_asset_by_name(void* memory, deleter_fn deleter, const char* name);
|
||||
extern SDL_Texture* load_texture(const char* file);
|
||||
extern TTF_Font* load_font(const char* file, int size);
|
||||
extern SDL_Texture* get_texture(const char* file);
|
||||
|
|
|
@ -6,6 +6,34 @@
|
|||
#include "SDL2/SDL_render.h"
|
||||
#include <SDL2/SDL_events.h>
|
||||
|
||||
enum INPUT_LISTENER_TYPE_T {
|
||||
INPUT_LISTENER_MOUSE,
|
||||
INPUT_LISTENER_AXIS,
|
||||
INPUT_LISTENER_SCROLL,
|
||||
INPUT_LISTENER_BUTTON,
|
||||
};
|
||||
|
||||
typedef struct input_listener_t {
|
||||
enum INPUT_LISTENER_TYPE_T type;
|
||||
union {
|
||||
struct {
|
||||
input_axis_fn delegate;
|
||||
SDL_Scancode positive, negative;
|
||||
int last_positive, last_negative;
|
||||
} axis;
|
||||
struct {
|
||||
input_mouse_fn delegate;
|
||||
} mouse;
|
||||
struct {
|
||||
input_button_fn delegate;
|
||||
uint32_t button;
|
||||
int last;
|
||||
} button;
|
||||
struct {
|
||||
input_scroll_fn delegate;
|
||||
} scroll;
|
||||
};
|
||||
} input_listener_t;
|
||||
|
||||
const Uint8* g_key_states = NULL;
|
||||
input_listener_t g_key_listeners[24];
|
||||
|
@ -17,7 +45,7 @@ static uint32_t _mouse_left_seconds = 0;
|
|||
static float _scroll_delta = 0;
|
||||
|
||||
void add_key_listener(SDL_Scancode negative, SDL_Scancode positive,
|
||||
input_axis_delegate_t delegate) {
|
||||
input_axis_fn delegate) {
|
||||
memset(g_key_listeners_endptr, 0x0, sizeof(input_listener_t));
|
||||
g_key_listeners_endptr->type = INPUT_LISTENER_AXIS;
|
||||
g_key_listeners_endptr->axis.delegate = delegate;
|
||||
|
@ -28,14 +56,14 @@ void add_key_listener(SDL_Scancode negative, SDL_Scancode positive,
|
|||
++g_key_listeners_endptr;
|
||||
}
|
||||
|
||||
void add_mouse_listener(input_mouse_delegate_t delegate) {
|
||||
void add_mouse_listener(input_mouse_fn delegate) {
|
||||
memset(g_key_listeners_endptr, 0x0, sizeof(input_listener_t));
|
||||
g_key_listeners_endptr->type = INPUT_LISTENER_MOUSE;
|
||||
g_key_listeners_endptr->mouse.delegate = delegate;
|
||||
++g_key_listeners_endptr;
|
||||
}
|
||||
|
||||
void add_mouse_button_listener(uint32_t button, input_button_delegate_t delegate) {
|
||||
void add_mouse_button_listener(uint32_t button, input_button_fn delegate) {
|
||||
memset(g_key_listeners_endptr, 0x0, sizeof(input_listener_t));
|
||||
g_key_listeners_endptr->type = INPUT_LISTENER_BUTTON;
|
||||
g_key_listeners_endptr->button.delegate = delegate;
|
||||
|
@ -44,7 +72,7 @@ void add_mouse_button_listener(uint32_t button, input_button_delegate_t delegate
|
|||
++g_key_listeners_endptr;
|
||||
}
|
||||
|
||||
void add_scroll_listener(input_scroll_delegate_t delegate) {
|
||||
void add_scroll_listener(input_scroll_fn delegate) {
|
||||
memset(g_key_listeners_endptr, 0x0, sizeof(input_listener_t));
|
||||
g_key_listeners_endptr->type = INPUT_LISTENER_SCROLL;
|
||||
g_key_listeners_endptr->scroll.delegate = delegate;
|
||||
|
|
|
@ -7,56 +7,28 @@ extern "C" {
|
|||
|
||||
#include "SDL2/SDL.h"
|
||||
|
||||
typedef void(*input_axis_delegate_t)(int value);
|
||||
typedef void(*input_mouse_delegate_t)(float dx, float dy);
|
||||
typedef void(*input_button_delegate_t)(int down);
|
||||
typedef void(*input_scroll_delegate_t)(float delta);
|
||||
|
||||
enum INPUT_LISTENER_TYPE_T {
|
||||
INPUT_LISTENER_MOUSE,
|
||||
INPUT_LISTENER_AXIS,
|
||||
INPUT_LISTENER_SCROLL,
|
||||
INPUT_LISTENER_BUTTON,
|
||||
};
|
||||
|
||||
typedef struct input_listener_t {
|
||||
enum INPUT_LISTENER_TYPE_T type;
|
||||
union {
|
||||
struct {
|
||||
input_axis_delegate_t delegate;
|
||||
SDL_Scancode positive, negative;
|
||||
int last_positive, last_negative;
|
||||
} axis;
|
||||
struct {
|
||||
input_mouse_delegate_t delegate;
|
||||
} mouse;
|
||||
struct {
|
||||
input_button_delegate_t delegate;
|
||||
uint32_t button;
|
||||
int last;
|
||||
} button;
|
||||
struct {
|
||||
input_scroll_delegate_t delegate;
|
||||
} scroll;
|
||||
};
|
||||
} input_listener_t;
|
||||
typedef void(*input_axis_fn)(int value);
|
||||
typedef void(*input_mouse_fn)(float dx, float dy);
|
||||
typedef void(*input_button_fn)(int down);
|
||||
typedef void(*input_scroll_fn)(float delta);
|
||||
|
||||
extern const Uint8* g_key_states;
|
||||
|
||||
extern void add_key_listener(SDL_Scancode negative, SDL_Scancode positive,
|
||||
input_axis_delegate_t delegate);
|
||||
extern void add_mouse_listener(input_mouse_delegate_t delegate);
|
||||
extern void add_mouse_button_listener(uint32_t button, input_button_delegate_t delegate);
|
||||
extern void add_scroll_listener(input_scroll_delegate_t delegate);
|
||||
extern void remove_listener_at(size_t index);
|
||||
input_axis_fn delegate);
|
||||
extern void add_mouse_listener(input_mouse_fn delegate);
|
||||
extern void add_mouse_button_listener(uint32_t button, input_button_fn delegate);
|
||||
extern void add_scroll_listener(input_scroll_fn delegate);
|
||||
|
||||
extern void mouse_screen_position(float* ox, float* oy);
|
||||
extern void mouse_world_position(float* ox, float* oy);
|
||||
|
||||
extern int input_get_keydown(SDL_Scancode scancode);
|
||||
extern int input_get_mousedown(int mousebtn);
|
||||
|
||||
extern void input_init();
|
||||
extern void update_input();
|
||||
extern void input_notify_event(SDL_Event event);
|
||||
extern int input_get_keydown(SDL_Scancode scancode);
|
||||
extern int input_get_mousedown(int mousebtn);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
object_t object_default() {
|
||||
return (object_t){
|
||||
.active = 1,
|
||||
.enabled = 1,
|
||||
.physics = physics_default(),
|
||||
.evt_draw = &object_draw_sprite,
|
||||
.evt_update = NULL,
|
||||
|
|
|
@ -11,8 +11,8 @@ typedef void(*draw_fn)(struct object_t*);
|
|||
|
||||
struct object_t {
|
||||
sprite_t sprite;
|
||||
int active; // 1 if this object is in use and should not be overriden.
|
||||
int enabled; // 1 if this object's events should be triggered.
|
||||
int active; // 1 if this object's events should be triggered by the game world update.
|
||||
int wants_to_be_deleted;
|
||||
physics_t physics; // the collider to use for this object's physics interaction.
|
||||
|
||||
uintptr_t timer; // free to use for whatever
|
||||
|
@ -26,7 +26,7 @@ object_t object_default();
|
|||
void object_draw_sprite(object_t* object);
|
||||
static inline
|
||||
int object_is_valid(const object_t* object) {
|
||||
return object != NULL && object->active != 0;
|
||||
return object != NULL && object->wants_to_be_deleted == 0;
|
||||
}
|
||||
|
||||
#endif /* _object_h */
|
||||
|
|
|
@ -24,7 +24,7 @@ void object_broadcast_collision(object_t* this, object_t* other) {
|
|||
}
|
||||
}
|
||||
short can_collide(const object_t* this) {
|
||||
return object_is_valid(this) && this->enabled;
|
||||
return object_is_valid(this);
|
||||
}
|
||||
|
||||
static inline
|
||||
|
|
|
@ -34,15 +34,9 @@ typedef struct physics_t {
|
|||
} physics_t;
|
||||
|
||||
extern physics_t physics_default();
|
||||
|
||||
extern void object_broadcast_evt_collision(object_t* this, object_t* other);
|
||||
|
||||
extern void physics_update();
|
||||
|
||||
extern void physics_move(object_t* this, float delta_time);
|
||||
|
||||
extern short can_collide(const object_t* this);
|
||||
|
||||
extern void solve_collision_slide(object_t* left, object_t* right);
|
||||
extern float get_solve_force(const object_t* this, const object_t* other, float* solve_x, float* solve_y);
|
||||
|
||||
|
|
|
@ -104,7 +104,6 @@ extern sprite_t make_sprite(const char* file, float x, float y);
|
|||
extern sprite_t sprite_from_spritesheet(spritesheet_t* sheet, int index);
|
||||
extern text_style_t make_text_style(const char* font, SDL_Color color, int dpi, float size);
|
||||
extern SDL_Rect get_srcrect_from(spritesheet_t* sheet, int index);
|
||||
extern void set_active_view(const view_t* view);
|
||||
|
||||
#define no_sprite (sprite_t){NULL, 0.0, 0.0, {0.0, 0.0}, 0.0, 0.0, 0.0, 0, {0, 0, 0, 0}}
|
||||
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
#include "scene.h"
|
||||
|
||||
#include "ctype.h"
|
||||
#include "stdint.h"
|
||||
#include "stddef.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "hash.h"
|
||||
#include "malloc.h"
|
||||
#include "math.h"
|
||||
#include "world.h"
|
||||
|
||||
static
|
||||
struct type_handler_t {
|
||||
uintptr_t hash;
|
||||
char* type;
|
||||
type_handler_fn handler;
|
||||
} _type_handlers[99];
|
||||
|
||||
static
|
||||
int _type_handler_num = 0;
|
||||
|
||||
static
|
||||
struct type_handler_t* _find_handler_for(const char* type) {
|
||||
uintptr_t hash = hashstr(type);
|
||||
for(int i = 0; i < 99; ++i) {
|
||||
if(_type_handlers[i].hash == hash && strcmp(type, _type_handlers[i].type) == 0) {
|
||||
return _type_handlers + i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
struct type_handler_t* _new_handler_for(const char* type) {
|
||||
_type_handlers[_type_handler_num].type = malloc(strlen(type) * sizeof(char));
|
||||
strcpy(_type_handlers[_type_handler_num].type, type);
|
||||
_type_handlers[_type_handler_num].hash = hashstr(type);
|
||||
struct type_handler_t* ptr = _type_handlers + _type_handler_num;
|
||||
++_type_handler_num;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void set_type_handler(const char* type, type_handler_fn handler) {
|
||||
struct type_handler_t* ptr = _find_handler_for(type);
|
||||
if(ptr == NULL) {
|
||||
ptr = _new_handler_for(type);
|
||||
}
|
||||
ptr->handler = handler;
|
||||
}
|
||||
|
||||
static
|
||||
int fpeekc(FILE* file) {
|
||||
int c = fgetc(file);
|
||||
ungetc(c, file);
|
||||
return c;
|
||||
}
|
||||
|
||||
static
|
||||
void freadto(FILE* file, char c) {
|
||||
char read;
|
||||
do {
|
||||
read = fgetc(file);
|
||||
} while(read != c);
|
||||
}
|
||||
|
||||
static
|
||||
int nextnw(FILE* file) {
|
||||
int next;
|
||||
char c;
|
||||
do {
|
||||
next = fgetc(file);
|
||||
c = (char)next;
|
||||
} while(isspace(c));
|
||||
return next;
|
||||
}
|
||||
|
||||
static
|
||||
void _parse_key(FILE* file, char* out) {
|
||||
char c;
|
||||
do {
|
||||
c = fgetc(file);
|
||||
if(c == ':') {
|
||||
*out = '\0';
|
||||
} else if(c == '#') {
|
||||
freadto(file, '\n');
|
||||
} else if(!isspace(c)) {
|
||||
*out = c;
|
||||
++out;
|
||||
}
|
||||
} while(c != ':');
|
||||
}
|
||||
|
||||
static
|
||||
void _parse_value(FILE* file, char* out, int* _argc, char** argv) {
|
||||
char c;
|
||||
int argc = 0;
|
||||
argv[argc] = out;
|
||||
++argc;
|
||||
do {
|
||||
c = fgetc(file);
|
||||
switch(c) {
|
||||
case '#':
|
||||
freadto(file, '\n');
|
||||
// fall through
|
||||
case '\n':
|
||||
ungetc(nextnw(file), file);
|
||||
break;
|
||||
case ';':
|
||||
*out = '\0';
|
||||
break;
|
||||
case ',':
|
||||
*out = '\0';
|
||||
++out;
|
||||
argv[argc] = out;
|
||||
++argc;
|
||||
ungetc(nextnw(file), file);
|
||||
break;
|
||||
default:
|
||||
*out = c;
|
||||
++out;
|
||||
break;
|
||||
}
|
||||
} while(c != ';');
|
||||
*_argc = argc;
|
||||
}
|
||||
|
||||
static
|
||||
void _parse_config(FILE* file) {
|
||||
char key[24];
|
||||
char value[128];
|
||||
int argc = 0;
|
||||
char* argv[24];
|
||||
|
||||
char begin = nextnw(file);
|
||||
ungetc(begin, file);
|
||||
|
||||
_parse_key(file, key);
|
||||
ungetc(nextnw(file), file);
|
||||
_parse_value(file, value, &argc, argv);
|
||||
|
||||
struct type_handler_t* handler = _find_handler_for(key);
|
||||
|
||||
if(handler != NULL) {
|
||||
printf("found handler\n");
|
||||
if(begin == '!') {
|
||||
handler->handler(NULL, argc, argv);
|
||||
} else {
|
||||
handler->handler(make_object(), argc, argv);
|
||||
}
|
||||
}
|
||||
if(fpeekc(file) == EOF) return;
|
||||
}
|
||||
|
||||
static
|
||||
void _parse_scene(FILE* file) {
|
||||
int next;
|
||||
do {
|
||||
_parse_config(file);
|
||||
next = nextnw(file);
|
||||
ungetc(next, file);
|
||||
} while(next != EOF);
|
||||
}
|
||||
|
||||
static
|
||||
int _validate_config(FILE* file) {
|
||||
char c;
|
||||
int colon_count = 0;
|
||||
do {
|
||||
c = nextnw(file);
|
||||
switch(c) {
|
||||
default: break;
|
||||
case ':':
|
||||
colon_count++;
|
||||
break;
|
||||
}
|
||||
} while(c != ';');
|
||||
|
||||
return colon_count == 1;
|
||||
}
|
||||
|
||||
static
|
||||
int _validate_scene(FILE* file) {
|
||||
if(file == NULL) return 0;
|
||||
|
||||
int next;
|
||||
int validated;
|
||||
do {
|
||||
validated = _validate_config(file);
|
||||
next = nextnw(file);
|
||||
ungetc(next, file);
|
||||
} while(validated == 1 && next != EOF);
|
||||
|
||||
rewind(file);
|
||||
|
||||
return validated;
|
||||
}
|
||||
|
||||
void load_scene(const char* filename) {
|
||||
FILE* file = fopen(filename, "r");
|
||||
if(_validate_scene(file)) {
|
||||
world_clear();
|
||||
_parse_scene(file);
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
void load_scene_additive(const char* filename) {
|
||||
FILE* file = fopen(filename, "r");
|
||||
if(_validate_scene(file)) {
|
||||
_parse_scene(file);
|
||||
fclose(file);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef _corelib_scene_h
|
||||
#define _corelib_scene_h
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
typedef struct object_t object_t;
|
||||
|
||||
typedef void(*type_handler_fn)(object_t* this, int argc, char** argv);
|
||||
|
||||
// Add or replace the type handler for [Object] entries of a given key.
|
||||
// Will delete the handler entry if handler == NULL.
|
||||
void set_type_handler(const char* type, type_handler_fn handler);
|
||||
|
||||
// Load a scene exclusively. Clears the current scene before parsing file.
|
||||
void load_scene(const char* file);
|
||||
|
||||
// Load a scene additively.
|
||||
// Will not clear the currently active objects before parsing file.
|
||||
void load_scene_additive(const char* file);
|
||||
|
||||
#endif /* _corelib_scene_h */
|
||||
|
|
@ -47,23 +47,36 @@ size_t _find_free_object() {
|
|||
}
|
||||
|
||||
void world_clear() {
|
||||
// free all allocated objects
|
||||
for(int i = 0; i < _world_objects.num; ++i) {
|
||||
_world_objects.objects[i]->active = 0;
|
||||
_world_objects.objects[i]->enabled = 0;
|
||||
object_t* object = _world_objects.objects[i];
|
||||
if(object != NULL) {
|
||||
free(object);
|
||||
}
|
||||
}
|
||||
// free world array
|
||||
free(_world_objects.objects);
|
||||
// reset world objects struct
|
||||
_world_objects.objects = NULL;
|
||||
_world_objects.num = 0;
|
||||
}
|
||||
|
||||
object_t* make_object() {
|
||||
// acquire pointer to empty slot
|
||||
size_t index = _find_free_object();
|
||||
// allocate new object
|
||||
if(_world_objects.objects[index] == NULL) {
|
||||
_world_objects.objects[index] = malloc(sizeof(object_t));
|
||||
}
|
||||
// initialize object to default
|
||||
object_t* o = _world_objects.objects[index];
|
||||
*o = object_default();
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
object_t* instantiate_object(const object_t *original) {
|
||||
// create new object with default settings
|
||||
object_t* obj = make_object();
|
||||
*obj = *original;
|
||||
obj->active = 1;
|
||||
|
|
33
src/game.c
33
src/game.c
|
@ -4,38 +4,9 @@
|
|||
#include "corelib/render.h"
|
||||
#include "corelib/assets.h"
|
||||
#include "corelib/layers.h"
|
||||
#include "SDL2/SDL_mouse.h"
|
||||
#include "SDL2/SDL_scancode.h"
|
||||
|
||||
void on_quit_key(int down) {
|
||||
// Q is pressed or released
|
||||
if(down) {
|
||||
// stop running when Q is pressed
|
||||
g_context.running = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void on_horizontal(int axis) {
|
||||
// when A or D is pressed or released
|
||||
}
|
||||
|
||||
void on_vertical(int axis) {
|
||||
// W or S is pressed or released
|
||||
}
|
||||
|
||||
void on_click(int down) {
|
||||
// when the left mouse button is pressed down
|
||||
// float mouse_x, mouse_y;
|
||||
// mouse_world_position(&mouse_x, &mouse_y);
|
||||
}
|
||||
|
||||
void start_game() {
|
||||
// called when the game is done initializing the backend and ready to start
|
||||
g_active_view.width = 21;
|
||||
add_key_listener(SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_Q, &on_quit_key);
|
||||
add_key_listener(SDL_SCANCODE_S, SDL_SCANCODE_W, &on_horizontal);
|
||||
add_key_listener(SDL_SCANCODE_A, SDL_SCANCODE_D, &on_vertical);
|
||||
add_mouse_button_listener(SDL_BUTTON_LMASK, &on_click);
|
||||
}
|
||||
|
||||
void update_game() {
|
||||
|
@ -48,4 +19,6 @@ void update_ui() {
|
|||
// render calls made in this function will be in *screen* space
|
||||
}
|
||||
|
||||
void game_exit() {}
|
||||
void game_exit() {
|
||||
// called when the game shuts down
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue