|
/* LDB: Ludum Dare Boilerplate */ |
|
/* Written by KPCFTSZ for LD48 */ |
|
#ifndef _ldb_h_ |
|
#define _ldb_h_ |
|
|
|
#ifdef __cplusplus |
|
extern "C" |
|
{ |
|
#endif |
|
|
|
typedef unsigned char uint8; |
|
typedef signed char int8; |
|
typedef unsigned short uint16; |
|
typedef signed short int16; |
|
typedef unsigned int uint32; |
|
typedef signed int int32; |
|
typedef unsigned long long uint64; |
|
typedef signed long long int64; |
|
|
|
typedef uint8 uchar; |
|
typedef uint16 ushort; |
|
typedef uint32 uint; |
|
typedef uint64 ulong; |
|
|
|
typedef uint8 byte; |
|
|
|
#undef TRUE |
|
#undef FALSE |
|
|
|
typedef enum { FALSE, TRUE } boolean; |
|
|
|
/* - GRAPHICS - */ |
|
|
|
struct ldb_bitmap |
|
{ |
|
uint width; |
|
uint height; |
|
uint data[]; |
|
}; |
|
|
|
extern struct ldb_bitmap *ldb_bitmap_create(uint width, uint height); |
|
extern struct ldb_bitmap *ldb_bitmap_load(const char *path); |
|
extern void ldb_bitmap_delete(struct ldb_bitmap *bitmap); |
|
|
|
// |
|
|
|
extern void ldb_draw(struct ldb_bitmap *dest, const struct ldb_bitmap *src, float x, float y); |
|
extern void ldb_draw_s(struct ldb_bitmap *dest, const struct ldb_bitmap *src, float x, float y, float width, float height); |
|
extern void ldb_draw_crop(struct ldb_bitmap *dest, const struct ldb_bitmap *src, uint crop_x, uint crop_y, uint crop_width, uint crop_height, float x, float y); |
|
extern void ldb_draw_crop_s(struct ldb_bitmap *dest, const struct ldb_bitmap *src, uint crop_x, uint crop_y, uint crop_width, uint crop_height, float x, float y, float width, float height); |
|
extern void ldb_draw_line(struct ldb_bitmap *dest, float x_start, float y_start, float x_end, float y_end, uint color); |
|
extern void ldb_clear(struct ldb_bitmap *dest, uint color); |
|
|
|
/* - MATH - */ |
|
|
|
#define LDB_PI 3.141593f |
|
#define LDB_E 2.718281f |
|
|
|
#define MIN(a, b) ((a) < (b) ? (a) : (b)) |
|
#define MAX(a, b) ((a) > (b) ? (a) : (b)) |
|
|
|
extern float ldb_to_radians(float degrees); |
|
extern float ldb_to_degrees(float radians); |
|
extern float ldb_fast_sqrt(float value); |
|
extern uint ldb_random(void); |
|
extern void ldb_seed(uint seed); |
|
extern uint ldb_blend(uint color, uint other); |
|
|
|
// |
|
|
|
struct ldb_vec2 |
|
{ |
|
float x, y; |
|
}; |
|
|
|
extern float ldb_vec2_length(const struct ldb_vec2 *vec2); |
|
extern float ldb_vec2_dot(const struct ldb_vec2 *vec2, const struct ldb_vec2 *other); |
|
extern float ldb_vec2_cross(const struct ldb_vec2 *vec2, const struct ldb_vec2 *other); |
|
extern boolean ldb_vec2_equals(const struct ldb_vec2 *vec2, const struct ldb_vec2 *other); |
|
extern struct ldb_vec2 ldb_vec2_rotate(const struct ldb_vec2 *vec2, float degrees); |
|
|
|
#define VEC(v) (v.x), (v.y) |
|
|
|
/* - INPUT - */ |
|
|
|
enum ldb_key |
|
{ |
|
LDB_KEY_UNKNOWN = 0, |
|
/* Alphabet/Numbers */ |
|
LDB_KEY_A = 4, LDB_KEY_B = 5, LDB_KEY_C = 6, LDB_KEY_D = 7, LDB_KEY_E = 8, LDB_KEY_F = 9, |
|
LDB_KEY_G = 10, LDB_KEY_H = 11, LDB_KEY_I = 12, LDB_KEY_J = 13, LDB_KEY_K = 14, LDB_KEY_L = 15, |
|
LDB_KEY_M = 16, LDB_KEY_N = 17, LDB_KEY_O = 18, LDB_KEY_P = 19, LDB_KEY_Q = 20, LDB_KEY_R = 21, |
|
LDB_KEY_S = 22, LDB_KEY_T = 23, LDB_KEY_U = 24, LDB_KEY_V = 25, LDB_KEY_W = 26, LDB_KEY_X = 27, |
|
LDB_KEY_Y = 28, LDB_KEY_Z = 29, LDB_KEY_1 = 30, LDB_KEY_2 = 31, LDB_KEY_3 = 32, LDB_KEY_4 = 33, |
|
LDB_KEY_5 = 34, LDB_KEY_6 = 35, LDB_KEY_7 = 36, LDB_KEY_8 = 37, LDB_KEY_9 = 38, LDB_KEY_0 = 39, |
|
/* Formatting */ |
|
LDB_KEY_RETURN = 40, LDB_KEY_ESCAPE = 41, LDB_KEY_BACKSPACE = 42, LDB_KEY_TAB = 43, LDB_KEY_SPACE = 44, LDB_KEY_MINUS = 45, |
|
LDB_KEY_EQUALS = 46, LDB_KEY_LEFTBRACKET = 47, LDB_KEY_RIGHTBRACKET = 48, LDB_KEY_BACKSLASH = 49, LDB_KEY_NONUSHASH = 50, LDB_KEY_SEMICOLON = 51, |
|
LDB_KEY_APOSTROPHE = 52, LDB_KEY_GRAVE = 53, LDB_KEY_COMMA = 54, LDB_KEY_PERIOD = 55, LDB_KEY_SLASH = 56, LDB_KEY_CAPSLOCK = 57, |
|
/* Function */ |
|
LDB_KEY_F1 = 58, LDB_KEY_F2 = 59, LDB_KEY_F3 = 60, LDB_KEY_F4 = 61, LDB_KEY_F5 = 62, LDB_KEY_F6 = 63, |
|
LDB_KEY_F7 = 64, LDB_KEY_F8 = 65, LDB_KEY_F9 = 66, LDB_KEY_F10 = 67, LDB_KEY_F11 = 68, LDB_KEY_F12 = 69, |
|
/* Arrow block */ |
|
LDB_KEY_INSERT = 73, DB_KEY_HOME = 74, LDB_KEY_PAGEUP = 75, LDB_KEY_DELETE = 76, LDB_KEY_END = 77, LDB_KEY_PAGEDOWN = 78, |
|
LDB_KEY_RIGHT = 79, LDB_KEY_LEFT = 80, LDB_KEY_DOWN = 81, LDB_KEY_UP = 82, |
|
/* Tenkey */ |
|
LDB_KEY_KP_DIVIDE = 84, LDB_KEY_KP_MULTIPLY = 85, LDB_KEY_KP_MINUS = 86, LDB_KEY_KP_PLUS = 87, LDB_KEY_KP_ENTER = 88, LDB_KEY_KP_1 = 89, |
|
LDB_KEY_KP_2 = 90, LDB_KEY_KP_3 = 91, LDB_KEY_KP_4 = 92, LDB_KEY_KP_5 = 93, LDB_KEY_KP_6 = 94, LDB_KEY_KP_7 = 95, |
|
LDB_KEY_KP_8 = 96, LDB_KEY_KP_9 = 97, LDB_KEY_KP_0 = 98, LDB_KEY_KP_PERIOD = 99, LDB_KEY_KP_EQUALS = 103, |
|
LDB_KEY_KP_COMMA = 133, LDB_KEY_KP_EQUALSAS400 = 134, |
|
/* Modifiers */ |
|
LDB_KEY_LCTRL = 224, LDB_KEY_LSHIFT = 225, LDB_KEY_LALT = 226, LDB_KEY_LGUI = 227, LDB_KEY_RCTRL = 228, LDB_KEY_RSHIFT = 229, |
|
LDB_KEY_RALT = 230, LDB_KEY_RGUI = 231, |
|
/* For use in arrays */ |
|
LDB_NUM_KEYS = 256 |
|
}; |
|
|
|
enum ldb_button |
|
{ |
|
LDB_BUTTON_UNKNOWN = 0, |
|
/* No fancy gamer mice here, God said 3 buttons */ |
|
LDB_BUTTON_LEFT = 1, |
|
LDB_BUTTON_MIDDLE = 2, |
|
LDB_BUTTON_RIGHT = 3, |
|
/* For use in arrays */ |
|
LDB_NUM_BUTTONS = 8 |
|
}; |
|
|
|
extern boolean ldb_key_down(enum ldb_key key); |
|
extern void ldb_key_reset(enum ldb_key key); |
|
extern boolean ldb_button_down(enum ldb_button button); |
|
extern void ldb_button_reset(enum ldb_button button); |
|
extern boolean ldb_key_grouped(uint min_keys, uint num_keys, ...); |
|
|
|
// |
|
|
|
extern struct ldb_vec2 ldb_cursor_pos(void); |
|
|
|
/* - SETUP - */ |
|
|
|
struct ldb_game |
|
{ |
|
void (*func_init)(void); |
|
void (*func_update)(void); |
|
void (*func_render)(void); |
|
void (*func_destroy)(void); |
|
}; |
|
|
|
extern int ldb_exec(struct ldb_game *game, uint window_width, uint window_height, boolean fullscreen); |
|
extern void ldb_set_screen(struct ldb_bitmap *screen); |
|
extern void ldb_quit(void); |
|
|
|
#ifdef __cplusplus |
|
} |
|
#endif |
|
|
|
#endif /* _ldb_h_ */ |
|
|
|
/* - IMPLEMENTATION - */ |
|
|
|
#ifdef USE_LDB |
|
|
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <stddef.h> |
|
#include <string.h> |
|
#include <math.h> |
|
#include <stdarg.h> |
|
|
|
#ifndef STB_IMAGE_IMPLEMENTATION |
|
#define STB_IMAGE_IMPLEMENTATION |
|
#endif |
|
|
|
#include <stb_image.h> |
|
|
|
#include <SDL2/SDL.h> |
|
|
|
#ifdef __CYGWIN__ |
|
#undef main |
|
#endif |
|
|
|
/********************************/ |
|
|
|
static SDL_Window *ldb__sdl_window; |
|
static SDL_Renderer *ldb__sdl_renderer; |
|
static SDL_Texture *ldb__sdl_framebuffer; |
|
|
|
static boolean ldb__key_state[LDB_NUM_KEYS]; |
|
static boolean ldb__button_state[LDB_NUM_BUTTONS]; |
|
|
|
static struct ldb_game *ldb__user_game; |
|
static struct ldb_bitmap *ldb__user_screen; |
|
|
|
static int ldb__cursor_x; |
|
static int ldb__cursor_y; |
|
|
|
static uint ldb__seed; |
|
|
|
static boolean ldb__running = FALSE; |
|
|
|
/********************************/ |
|
|
|
struct ldb_bitmap *ldb_bitmap_create(uint width, uint height) |
|
{ |
|
struct ldb_bitmap *bitmap = malloc(sizeof *bitmap + sizeof(uint) * width * height); |
|
bitmap->width = width; |
|
bitmap->height = height; |
|
|
|
return bitmap; |
|
} |
|
|
|
struct ldb_bitmap *ldb_bitmap_load(const char *path) |
|
{ |
|
int width = 0, height = 0; |
|
byte *data = stbi_load(path, &width, &height, NULL, 4); |
|
|
|
struct ldb_bitmap *bitmap = ldb_bitmap_create((uint) width, (uint) height); |
|
for (size_t i = 0; i < bitmap->width * bitmap->height; i++) |
|
{ |
|
byte c[4]; |
|
for (size_t j = 0; j < 4; j++) |
|
c[j] = data[i * 4 + j]; |
|
|
|
bitmap->data[i] = c[3] << 24 | c[0] << 16 | c[1] << 8 | c[2]; |
|
} |
|
|
|
stbi_image_free(data); |
|
|
|
return bitmap; |
|
} |
|
|
|
void ldb_bitmap_delete(struct ldb_bitmap *bitmap) |
|
{ |
|
free(bitmap); |
|
bitmap = NULL; |
|
} |
|
|
|
/********************************/ |
|
|
|
void ldb_draw(struct ldb_bitmap *dest, const struct ldb_bitmap *src, float x, float y) |
|
{ |
|
for (size_t i = 0; i < src->width; i++) |
|
{ |
|
int xp = i + x; |
|
if (xp < 0 || xp >= dest->width) continue; |
|
|
|
for (size_t j = 0; j < src->height; j++) |
|
{ |
|
int yp = j + y; |
|
if (yp < 0 || yp >= dest->height) continue; |
|
|
|
uint *dest_data = &dest->data[xp + yp * dest->width]; |
|
*dest_data = ldb_blend(*dest_data, src->data[i + j * src->width]); |
|
} |
|
} |
|
} |
|
|
|
void ldb_draw_s(struct ldb_bitmap *dest, const struct ldb_bitmap *src, float x, float y, float width, float height) |
|
{ |
|
for (size_t i = 0; i < width; i++) |
|
{ |
|
int xp = i + x; |
|
if (xp < 0 || xp >= dest->width) continue; |
|
|
|
int xf = i / (width / src->width); |
|
|
|
for (size_t j = 0; j < height; j++) |
|
{ |
|
int yp = j + y; |
|
if (yp < 0 || yp >= dest->height) continue; |
|
|
|
int yf = j / (height / src->height); |
|
|
|
uint *dest_data = &dest->data[xp + yp * dest->width]; |
|
*dest_data = ldb_blend(*dest_data, src->data[xf + yf * src->width]); |
|
} |
|
} |
|
} |
|
|
|
void ldb_draw_crop(struct ldb_bitmap *dest, const struct ldb_bitmap *src, uint crop_x, uint crop_y, uint crop_width, uint crop_height, float x, float y) |
|
{ |
|
for (size_t i = 0; i < crop_width; i++) |
|
{ |
|
int xp = i + x; |
|
if (xp < 0 || xp >= dest->width) continue; |
|
|
|
for (size_t j = 0; j < crop_height; j++) |
|
{ |
|
int yp = j + y; |
|
if (yp < 0 || yp >= dest->height) continue; |
|
|
|
uint *dest_data = &dest->data[xp + yp * dest->width]; |
|
*dest_data = ldb_blend(*dest_data, src->data[i + crop_x + (j + crop_y) * src->width]); |
|
} |
|
} |
|
} |
|
|
|
void ldb_draw_crop_s(struct ldb_bitmap *dest, const struct ldb_bitmap *src, uint crop_x, uint crop_y, uint crop_width, uint crop_height, float x, float y, float width, float height) |
|
{ |
|
for (size_t i = 0; i < width; i++) |
|
{ |
|
int xp = i + x; |
|
if (xp < 0 || xp >= dest->width) continue; |
|
|
|
int xf = i / (width / crop_width); |
|
|
|
for (size_t j = 0; j < height; j++) |
|
{ |
|
int yp = j + y; |
|
if (yp < 0 || yp >= dest->height) continue; |
|
|
|
int yf = j / (height / crop_height); |
|
|
|
uint *dest_data = &dest->data[xp + yp * dest->width]; |
|
*dest_data = ldb_blend(*dest_data, src->data[xf + crop_x + (yf + crop_y) * src->width]); |
|
} |
|
} |
|
} |
|
|
|
void ldb_draw_line(struct ldb_bitmap *dest, float x_start, float y_start, float x_end, float y_end, uint color) |
|
{ |
|
int x_start_i = (int) x_start, x_end_i = (int) x_end; |
|
int y_start_i = (int) y_start, y_end_i = (int) y_end; |
|
|
|
int x_dist = abs(x_end_i - x_start_i), x_dir = x_start_i < x_end_i ? 1 : -1; |
|
int y_dist = abs(y_end_i - y_start_i), y_dir = y_start_i < y_end_i ? 1 : -1; |
|
|
|
int err = (x_dist > y_dist ? x_dist : -y_dist) / 2, e = 0; |
|
|
|
for (;;) |
|
{ |
|
uint *dest_data = &dest->data[x_start_i + y_start_i * dest->width]; |
|
|
|
if (x_start_i >= 0 && x_start_i < dest->width && y_start_i >= 0 && y_start_i < dest->height) |
|
*dest_data = ldb_blend(*dest_data, color); |
|
|
|
if (x_start_i == x_end_i && y_start_i == y_end_i) |
|
break; |
|
|
|
e = err; |
|
if (e > -x_dist) err -= y_dist, x_start_i += x_dir; |
|
if (e < y_dist) err += x_dist, y_start_i += y_dir; |
|
} |
|
} |
|
|
|
void ldb_clear(struct ldb_bitmap *dest, uint color) |
|
{ |
|
for (int i = 0; i < dest->width * dest->height; i++) |
|
dest->data[i] = color; |
|
} |
|
|
|
|
|
/********************************/ |
|
|
|
float ldb_vec2_length(const struct ldb_vec2 *vec2) |
|
{ |
|
return sqrtf(vec2->x * vec2->x + vec2->y * vec2->y); |
|
} |
|
|
|
float ldb_vec2_dot(const struct ldb_vec2 *vec2, const struct ldb_vec2 *other) |
|
{ |
|
return vec2->x * other->x + vec2->y * other->y; |
|
} |
|
|
|
float ldb_vec2_cross(const struct ldb_vec2 *vec2, const struct ldb_vec2 *other) |
|
{ |
|
return vec2->x * other->y - vec2->y * other->x; |
|
} |
|
|
|
boolean ldb_vec2_equals(const struct ldb_vec2 *vec2, const struct ldb_vec2 *other) |
|
{ |
|
return vec2->x == other->x && vec2->y == other->y; |
|
} |
|
|
|
struct ldb_vec2 ldb_vec2_rotate(const struct ldb_vec2 *vec2, float degrees) |
|
{ |
|
float in_radians = ldb_to_radians(degrees); |
|
float cosine = cosf(in_radians); |
|
float sine = sinf(in_radians); |
|
|
|
struct ldb_vec2 rotated = |
|
{ |
|
vec2->x * cosine - vec2->y * sine, |
|
vec2->x * sine + vec2->y * cosine |
|
}; |
|
|
|
return rotated; |
|
} |
|
|
|
/********************************/ |
|
|
|
float ldb_to_radians(float degrees) |
|
{ |
|
return degrees * LDB_PI / 180.0f; |
|
} |
|
|
|
float ldb_to_degrees(float radians) |
|
{ |
|
return radians * 180.0f / LDB_PI; |
|
} |
|
|
|
float ldb_fast_sqrt(float value) |
|
{ |
|
uint i = *(uint*) &value; |
|
i += 127 << 23; |
|
i >>= 1; |
|
|
|
return *(float*) &i; |
|
} |
|
|
|
uint ldb_random(void) |
|
{ |
|
ldb__seed = 0x015A4E35 * ldb__seed + 1; |
|
|
|
return (ldb__seed >> 16) & 0x7FFF; |
|
} |
|
|
|
void ldb_seed(uint seed) |
|
{ |
|
ldb__seed = seed; |
|
} |
|
|
|
uint ldb_blend(uint color, uint other) |
|
{ |
|
uint masks[4] = |
|
{ |
|
0xFF000000, |
|
0x00FF00FF, |
|
0xFF00FF00, |
|
0x0000FF00 |
|
}; |
|
|
|
uint a = (other & masks[0]) >> 24; |
|
uint na = 0xFF - a; |
|
uint rb = ((na * (color & masks[1])) + (a * (other & masks[1]))) >> 8; |
|
uint ag = (na * (color & masks[2]) >> 8) + (a * (1 << 24 | ((other & masks[3]) >> 8))); |
|
|
|
return (rb & masks[1]) | (ag & masks[2]); |
|
} |
|
|
|
/********************************/ |
|
|
|
boolean ldb_key_down(enum ldb_key key) |
|
{ |
|
return ldb__key_state[key]; |
|
} |
|
|
|
void ldb_key_reset(enum ldb_key key) |
|
{ |
|
ldb__key_state[key] = FALSE; |
|
} |
|
|
|
boolean ldb_button_down(enum ldb_button button) |
|
{ |
|
return ldb__button_state[button]; |
|
} |
|
|
|
void ldb_button_reset(enum ldb_button button) |
|
{ |
|
ldb__button_state[button] = FALSE; |
|
} |
|
|
|
boolean ldb_key_grouped(uint min_keys, uint num_keys, ...) |
|
{ |
|
va_list args; |
|
uint grouped = 0; |
|
|
|
va_start(args, num_keys); |
|
for (size_t i = 0; i < num_keys; i++) |
|
if (ldb_key_down(va_arg(args, enum ldb_key))) |
|
grouped++; |
|
va_end(args); |
|
|
|
return grouped >= min_keys; |
|
} |
|
|
|
struct ldb_vec2 ldb_cursor_pos(void) |
|
{ |
|
struct ldb_vec2 cursor = |
|
{ |
|
(float) ldb__cursor_x, |
|
(float) ldb__cursor_y |
|
}; |
|
|
|
if (ldb__user_screen) |
|
{ |
|
int width = 0, height = 0; |
|
|
|
SDL_GetWindowSize(ldb__sdl_window, &width, &height); |
|
|
|
cursor.x /= width / (float) ldb__user_screen->width; |
|
cursor.y /= height / (float) ldb__user_screen->height; |
|
} |
|
|
|
return cursor; |
|
} |
|
|
|
/********************************/ |
|
|
|
int ldb_exec(struct ldb_game *game, uint window_width, uint window_height, boolean fullscreen) |
|
{ |
|
ldb__running = TRUE; |
|
|
|
if (SDL_Init(SDL_INIT_EVERYTHING)) |
|
{ |
|
fprintf(stderr, "SDL initialization failed: %s\n", SDL_GetError()); |
|
return 1; |
|
} |
|
|
|
ldb__sdl_window = SDL_CreateWindow( |
|
"Game", |
|
SDL_WINDOWPOS_CENTERED, |
|
SDL_WINDOWPOS_CENTERED, |
|
window_width, |
|
window_height, |
|
fullscreen |
|
); |
|
|
|
if (!ldb__sdl_window) |
|
{ |
|
fprintf(stderr, "SDL window creation failed: %s\n", SDL_GetError()); |
|
ldb_quit(); |
|
|
|
return 1; |
|
} |
|
|
|
ldb__sdl_renderer = SDL_CreateRenderer(ldb__sdl_window, -1, SDL_RENDERER_ACCELERATED); |
|
|
|
if (!ldb__sdl_renderer) |
|
{ |
|
fprintf(stderr, "SDL renderer creation failed: %s\n", SDL_GetError()); |
|
ldb_quit(); |
|
|
|
return 1; |
|
} |
|
|
|
ldb__user_game = game; |
|
ldb__user_game->func_init(); |
|
|
|
ldb__sdl_framebuffer = SDL_CreateTexture( |
|
ldb__sdl_renderer, |
|
SDL_PIXELFORMAT_ARGB8888, |
|
SDL_TEXTUREACCESS_STREAMING, |
|
ldb__user_screen ? ldb__user_screen->width : window_width, |
|
ldb__user_screen ? ldb__user_screen->height : window_height |
|
); |
|
|
|
if (!ldb__sdl_framebuffer) |
|
{ |
|
fprintf(stderr, "SDL framebuffer creation failed: %s\n", SDL_GetError()); |
|
ldb_quit(); |
|
|
|
return 1; |
|
} |
|
|
|
double time_delta = 1.0 / 60.0; |
|
double time_accumulator = 0.0; |
|
|
|
while (ldb__running) |
|
{ |
|
double time_iteration = 0.0; |
|
double time_present = SDL_GetTicks() / 1000.0; |
|
|
|
SDL_Event e; |
|
while (SDL_PollEvent(&e)) |
|
{ |
|
switch (e.type) |
|
{ |
|
case SDL_QUIT: |
|
ldb__running = FALSE; |
|
break; |
|
|
|
case SDL_MOUSEBUTTONDOWN: |
|
ldb__button_state[e.button.button] = TRUE; |
|
break; |
|
|
|
case SDL_MOUSEBUTTONUP: |
|
ldb__button_state[e.button.button] = FALSE; |
|
break; |
|
|
|
case SDL_KEYDOWN: |
|
if (e.key.repeat == 0) |
|
ldb__key_state[e.key.keysym.scancode] = TRUE; |
|
break; |
|
|
|
case SDL_KEYUP: |
|
ldb__key_state[e.key.keysym.scancode] = FALSE; |
|
break; |
|
|
|
} |
|
} |
|
|
|
SDL_GetMouseState(&ldb__cursor_x, &ldb__cursor_y); |
|
|
|
while (time_accumulator >= time_delta) |
|
{ |
|
game->func_update(); |
|
|
|
time_accumulator -= time_delta; |
|
time_iteration += time_delta; |
|
} |
|
|
|
game->func_render(); |
|
|
|
if (ldb__user_screen) |
|
SDL_UpdateTexture(ldb__sdl_framebuffer, NULL, &ldb__user_screen->data[0], ldb__user_screen->width * 4); |
|
|
|
SDL_RenderCopy(ldb__sdl_renderer, ldb__sdl_framebuffer, NULL, NULL); |
|
SDL_RenderPresent(ldb__sdl_renderer); |
|
|
|
time_accumulator += SDL_GetTicks() / 1000.0 - time_present; |
|
} |
|
|
|
ldb__running = FALSE; |
|
|
|
ldb_quit(); |
|
|
|
return 0; |
|
} |
|
|
|
void ldb_set_screen(struct ldb_bitmap *screen) |
|
{ |
|
ldb__user_screen = screen; |
|
} |
|
|
|
void ldb_quit(void) |
|
{ |
|
if (ldb__running) |
|
{ |
|
ldb__running = FALSE; |
|
} |
|
else |
|
{ |
|
if (ldb__user_game) |
|
ldb__user_game->func_destroy(); |
|
|
|
if (ldb__sdl_framebuffer) |
|
SDL_DestroyTexture(ldb__sdl_framebuffer); |
|
|
|
if (ldb__sdl_renderer) |
|
SDL_DestroyRenderer(ldb__sdl_renderer); |
|
|
|
if (ldb__sdl_window) |
|
SDL_DestroyWindow(ldb__sdl_window); |
|
|
|
SDL_Quit(); |
|
} |
|
} |
|
|
|
#endif /* USE_LDB */ |