Memory usage improvements

Adds a texturecache to prevent multiple loads of the same texture. Texture
dimension is now only intended for the actual texture dimension. Sprite
should hold the "rendering dimension". Music songs now load and unload
when switching songs. Standardized a lot of dimensions.
This commit is contained in:
Linus Probert 2018-02-23 23:53:52 +01:00
parent 052b03189e
commit 131c0caa4e
23 changed files with 222 additions and 159 deletions

View File

@ -94,6 +94,7 @@ add_executable(breakhack
src/io_util
src/physfsrwops
src/skillbar
src/texturecache
)
target_link_libraries(breakhack

View File

@ -54,8 +54,9 @@ actiontext_render(ActionText *t, Camera *cam)
timer_start(t->timer);
Position cameraPos = camera_to_camera_position(cam, &t->pos);
SDL_Rect box = { cameraPos.x, cameraPos.y, t->texture->dim.width, t->texture->dim.height };
if (timer_get_ticks(t->timer) < 300) {
texture_render(t->texture, &cameraPos, cam);
texture_render(t->texture, &box, cam);
} else {
timer_stop(t->timer);
t->active = false;

View File

@ -47,6 +47,9 @@
#define SCREEN_WIDTH (GAME_VIEW_WIDTH + RIGHT_GUI_WIDTH)
#define SCREEN_HEIGHT (RIGHT_GUI_HEIGHT + BOTTOM_GUI_HEIGHT)
#define DEFAULT_DIMENSION (Dimension) { 16, 16 }
#define GAME_DIMENSION (Dimension) { TILE_DIMENSION, TILE_DIMENSION }
/* Windows and compile crap */
#ifdef _WIN32
#define strdup _strdup

View File

@ -25,6 +25,7 @@
#include "gui.h"
#include "util.h"
#include "map.h"
#include "texturecache.h"
#define DEFAULT_LOG { NULL, 50, 0, 200 }
@ -35,11 +36,11 @@ static SDL_Rect frame_top_left = { 16, 160, 16, 16 };
static SDL_Rect frame_top_right = { 48, 160, 16, 16 };
static SDL_Rect frame_bottom_left = { 16, 192, 16, 16 };
static SDL_Rect frame_bottom_right = { 48, 192, 16, 16 };
static SDL_Rect frame_top = { 32, 160, 16, 16 };
static SDL_Rect frame_top = { 32, 160, 16, 16 };
static SDL_Rect frame_bottom = { 32, 192, 16, 16 };
static SDL_Rect frame_center = { 32, 176, 16, 16 };
static SDL_Rect frame_left = { 16, 176, 16, 16 };
static SDL_Rect frame_right = { 48, 176, 16, 16 };
static SDL_Rect frame_left = { 16, 176, 16, 16 };
static SDL_Rect frame_right = { 48, 176, 16, 16 };
static struct LogData_t {
char **log;
@ -48,19 +49,6 @@ static struct LogData_t {
unsigned int strlen;
} log_data = DEFAULT_LOG;
static Texture*
add_texture(Gui *gui, const char *path, SDL_Renderer *renderer)
{
Texture *t = ht_get(gui->textures, path);
if (t == NULL) {
t = texture_create();
texture_load_from_file(t, path, renderer);
t->dim = (Dimension) { 16, 16 };
ht_set(gui->textures, path, t);
}
return t;
}
static void
gui_malloc_log(void)
{
@ -101,7 +89,7 @@ init_sprites(Gui *gui, SDL_Renderer *renderer)
Texture *t;
unsigned int i;
t = add_texture(gui, "GUI/GUI0.png", renderer);
t = texturecache_add("GUI/GUI0.png");
/*
* Add XP bar decoration
@ -138,7 +126,7 @@ init_sprites(Gui *gui, SDL_Renderer *renderer)
}
Sprite *s;
t = add_texture(gui, "Items/Potion.png", renderer);
t = texturecache_add("Items/Potion.png");
s = sprite_create();
s->fixed = true;
sprite_set_texture(s, t, 0);
@ -146,7 +134,7 @@ init_sprites(Gui *gui, SDL_Renderer *renderer)
s->pos = (Position) { 16, POS_Y_COLLECTABLES };
linkedlist_append(&gui->sprites, s);
t = add_texture(gui, "Items/Money.png", renderer);
t = texturecache_add("Items/Money.png");
s = sprite_create();
s->fixed = true;
sprite_set_texture(s, t, 0);
@ -165,7 +153,6 @@ gui_create(SDL_Renderer *renderer)
gui->sprites = linkedlist_create();
gui->health = linkedlist_create();
gui->xp_bar = linkedlist_create();
gui->textures = ht_create(5);
for (i = 0; i < LOG_LINES_COUNT; ++i) {
t = texture_create();
@ -201,8 +188,8 @@ set_max_health(Gui *gui, int max, SDL_Renderer *renderer)
while (gui->health != NULL)
sprite_destroy(linkedlist_pop(&gui->health));
texture0 = add_texture(gui, "GUI/GUI0.png", renderer);
texture1 = add_texture(gui, "GUI/GUI1.png", renderer);
texture0 = texturecache_add("GUI/GUI0.png");
texture1 = texturecache_add("GUI/GUI1.png");
for (i = 0; i < max/3; ++i) {
Sprite *sprite = sprite_create();
@ -313,30 +300,35 @@ gui_update_player_stats(Gui *gui, Player *player, Map *map, SDL_Renderer *render
if (dungeon_level != (unsigned int) map->level) {
m_sprintf(buffer, 200, "Dungeon level: %d", map->level);
texture_load_from_text(gui->labels[DUNGEON_LEVEL_LABEL]->textures[0], buffer, color, renderer);
gui->labels[DUNGEON_LEVEL_LABEL]->dim = gui->labels[DUNGEON_LEVEL_LABEL]->textures[0]->dim;
dungeon_level = (unsigned int) map->level;
}
if (current_potion_sips != (int) player->potion_sips) {
m_sprintf(buffer, 200, "x %u", (unsigned int) player->potion_sips);
texture_load_from_text(gui->labels[HEALTH_POTION_LABEL]->textures[0], buffer, color, renderer);
gui->labels[HEALTH_POTION_LABEL]->dim = gui->labels[HEALTH_POTION_LABEL]->textures[0]->dim;
current_potion_sips = player->potion_sips;
}
if (last_gold != player->gold) {
m_sprintf(buffer, 200, "x %.2f", player->gold);
texture_load_from_text(gui->labels[GOLD_LABEL]->textures[0], buffer, color, renderer);
gui->labels[GOLD_LABEL]->dim = gui->labels[GOLD_LABEL]->textures[0]->dim;
last_gold = player->gold;
}
if (last_xp != (int) data.current) {
m_sprintf(buffer, 200, "XP: %u / %u", data.current, data.nextLevel);
texture_load_from_text(gui->labels[CURRENT_XP_LABEL]->textures[0], buffer, color, renderer);
gui->labels[CURRENT_XP_LABEL]->dim = gui->labels[CURRENT_XP_LABEL]->textures[0]->dim;
last_xp = data.current;
}
if (last_level != data.level) {
m_sprintf(buffer, 200, "Level: %u", data.level);
texture_load_from_text(gui->labels[LEVEL_LABEL]->textures[0], buffer, color, renderer);
gui->labels[LEVEL_LABEL]->dim = gui->labels[LEVEL_LABEL]->textures[0]->dim;
last_level = data.level;
}
}
@ -344,33 +336,34 @@ gui_update_player_stats(Gui *gui, Player *player, Map *map, SDL_Renderer *render
static void
gui_render_frame(Gui *gui, unsigned int width, unsigned int height, Camera *cam)
{
Texture *texture = ht_get(gui->textures, "GUI/GUI0.png");
Position pos = { 0, 0 };
Texture *texture = texturecache_get("GUI/GUI0.png");
unsigned int i, j;
SDL_Rect box = { 0, 0, 16, 16 };
for (i = 0; i < width; ++i) {
for (j = 0; j < height; ++j) {
pos.x = i * 16;
pos.y = j * 16;
box.x = i * 16;
box.y = j * 16;
if (i == 0 && j == 0) {
texture_render_clip(texture, &pos, &frame_top_left, cam);
texture_render_clip(texture, &box, &frame_top_left, cam);
} else if (i == (width - 1) && j == 0) {
texture_render_clip(texture, &pos, &frame_top_right, cam);
texture_render_clip(texture, &box, &frame_top_right, cam);
} else if (i == 0 && j == (height - 1)) {
texture_render_clip(texture, &pos, &frame_bottom_left, cam);
texture_render_clip(texture, &box, &frame_bottom_left, cam);
} else if (i == (width - 1) && j == (height - 1)) {
texture_render_clip(texture, &pos, &frame_bottom_right, cam);
texture_render_clip(texture, &box, &frame_bottom_right, cam);
} else if (i == 0) {
texture_render_clip(texture, &pos, &frame_left, cam);
texture_render_clip(texture, &box, &frame_left, cam);
} else if (i == (width - 1)) {
texture_render_clip(texture, &pos, &frame_right, cam);
texture_render_clip(texture, &box, &frame_right, cam);
} else if (j == 0) {
texture_render_clip(texture, &pos, &frame_top, cam);
texture_render_clip(texture, &box, &frame_top, cam);
} else if (j == (height - 1)) {
texture_render_clip(texture, &pos, &frame_bottom, cam);
texture_render_clip(texture, &box, &frame_bottom, cam);
} else {
texture_render_clip(texture, &pos, &frame_center, cam);
texture_render_clip(texture, &box, &frame_center, cam);
}
}
}
@ -445,19 +438,20 @@ gui_render_log(Gui *gui, unsigned int width, unsigned int height, Camera *cam)
unsigned int i;
unsigned int render_count;
Position p;
SDL_Rect box = { 16, 0, 16, 16 };
render_count = LOG_LINES_COUNT > log_data.count ? log_data.count : LOG_LINES_COUNT;
p = (Position) { 16, 0 };
gui_render_frame(gui, width/16, height/16, cam);
for (i = 0; i < render_count; ++i) {
Texture *t;
p.y = 16 + ((LOG_FONT_SIZE+5) * i);
box.y = 16 + ((LOG_FONT_SIZE+5) * i);
t = gui->log_lines[i];
texture_load_from_text(t, log_data.log[i], color, cam->renderer);
texture_render(t, &p, cam);
box.w = t->dim.width;
box.h = t->dim.height;
texture_render(t, &box, cam);
}
}
@ -493,6 +487,5 @@ gui_destroy(Gui *gui)
for (int i = 0; i < LABEL_COUNT; ++i)
sprite_destroy(gui->labels[i]);
ht_destroy_custom(gui->textures, (void (*)(void*)) &texture_destroy);
free(gui);
}

View File

@ -24,7 +24,6 @@
#define LABEL_FONT_SIZE 8
#include "linkedlist.h"
#include "hashtable.h"
#include "sprite.h"
#include "camera.h"
#include "player.h"
@ -42,7 +41,6 @@ typedef struct {
LinkedList *sprites;
LinkedList *health;
LinkedList *xp_bar;
Hashtable *textures;
Sprite *labels[LABEL_COUNT];
Texture *log_lines[LOG_LINES_COUNT];
} Gui;

View File

@ -25,6 +25,7 @@
#include "gui.h"
#include "mixer.h"
#include "random.h"
#include"texturecache.h"
static ItemBuilder *builder = NULL;
@ -32,7 +33,6 @@ void
item_builder_init(SDL_Renderer *renderer)
{
builder = ec_malloc(sizeof(ItemBuilder));
builder->textures = ht_create(20);
builder->renderer = renderer;
}
@ -43,19 +43,6 @@ check_builder(void)
fatal("item_builder_init() not run");
}
static Texture *
load_texture(const char *path)
{
Texture *t = ht_get(builder->textures, path);
if (!t) {
t = texture_create();
texture_load_from_file(t, path, builder->renderer);
t->dim = (Dimension) { 32, 32 };
ht_set(builder->textures, path, t);
}
return t;
}
static void
eat_flesh(Item *item, Player *player)
{
@ -85,10 +72,11 @@ create_item(const char *path, SDL_Rect clip, void (*cb)(Item*, Player*))
Item *item;
item = item_create();
t = load_texture(path);
t = texturecache_add(path);
item->sprite = sprite_create();
sprite_set_texture(item->sprite, t, 0);
item->sprite->dim = GAME_DIMENSION;
item->sprite->clip = clip;
item->effect = cb;
@ -203,6 +191,5 @@ item_builder_build_sack(void)
void
item_builder_close(void)
{
ht_destroy_custom(builder->textures, (void (*)(void*)) texture_destroy);
free(builder);
}

View File

@ -20,10 +20,8 @@
#define ITEMBUILDER_H_
#include "item.h"
#include "hashtable.h"
typedef struct {
Hashtable *textures;
SDL_Renderer *renderer;
} ItemBuilder;

View File

@ -44,6 +44,7 @@
#include "mixer.h"
#include "random.h"
#include "skillbar.h"
#include "texturecache.h"
typedef enum Turn_t {
PLAYER,
@ -180,6 +181,7 @@ static bool
initGame(void)
{
initViewports();
texturecache_init(gRenderer);
gCamera.renderer = gRenderer;
gRoomMatrix = roommatrix_create();
gGui = gui_create(gRenderer);
@ -253,6 +255,7 @@ createMenu(Menu **menu, struct MENU_ITEM menu_items[], unsigned int size)
hcenter = (SCREEN_WIDTH/2) - (s1->textures[0]->dim.width/2);
s1->pos = (Position) { (int) hcenter, (int) 200 + (i*50) };
s1->dim = s1->textures[0]->dim;
s1->fixed = true;
Sprite *s2 = sprite_create();
@ -261,6 +264,7 @@ createMenu(Menu **menu, struct MENU_ITEM menu_items[], unsigned int size)
C_MENU_HOVER, gRenderer);
s2->pos = (Position) { (int) hcenter, (int) 200 + (i*50) };
s2->dim = s2->textures[0]->dim;
s2->fixed = true;
menu_item_add(*menu, s1, s2, menu_items[i].callback);
@ -610,8 +614,9 @@ void close(void)
item_builder_close();
particle_engine_close();
timer_destroy(menuTimer);
mixer_close();
texturecache_close();
SDL_DestroyRenderer(gRenderer);
SDL_DestroyWindow(gWindow);
gWindow = NULL;

View File

@ -46,7 +46,6 @@ Map* map_create()
Map *map = ec_malloc(sizeof(Map));
map->textures = linkedlist_create();
map->monsterTextures = ht_create(30);
map->monsters = linkedlist_create();
map->items = linkedlist_create();
map->currentRoom = (Position) { 0, 0 };
@ -95,21 +94,6 @@ void map_add_decoration(Map *map, Position *tile_pos, MapTile *tile)
*oldTile = tile;
}
Texture*
map_add_monster_texture(Map *map, const char *path, SDL_Renderer *renderer)
{
Texture *t;
t = ht_get(map->monsterTextures, path);
if (!t) {
t = texture_create();
texture_load_from_file(t, path, renderer);
ht_set(map->monsterTextures, path, t);
}
return t;
}
void
map_clear_dead_monsters(Map *map)
{
@ -357,7 +341,6 @@ void map_destroy(Map *map)
while (map->items != NULL)
item_destroy(linkedlist_pop(&map->items));
ht_destroy_custom(map->monsterTextures, (void (*)(void*)) texture_destroy);
timer_destroy(map->renderTimer);
free(map);
}

View File

@ -22,7 +22,6 @@
#include <SDL.h>
#include <stdbool.h>
#include "hashtable.h"
#include "linkedlist.h"
#include "sprite.h"
#include "camera.h"
@ -48,7 +47,6 @@ typedef struct Room_t {
typedef struct Map_t {
Room* rooms[MAP_H_ROOM_COUNT][MAP_V_ROOM_COUNT];
LinkedList *textures;
Hashtable *monsterTextures;
LinkedList *monsters;
LinkedList *items;
Position currentRoom;
@ -69,9 +67,6 @@ map_add_tile(Map *map, Position *tile_pos, MapTile*);
void
map_add_decoration(Map *map, Position *tile_pos, MapTile*);
Texture*
map_add_monster_texture(Map*, const char *path, SDL_Renderer*);
void
map_add_monster(Map*, Monster*);

View File

@ -28,6 +28,8 @@
#include "map_lua.h"
#include "util.h"
#include "stats.h"
#include "io_util.h"
#include "texturecache.h"
static
lua_State* load_lua_state(void)
@ -278,13 +280,13 @@ l_add_monster(lua_State *L)
nstate = (int) luaL_checkinteger(L, -2);
cstate = (int) luaL_checkinteger(L, -1);
texture1 = map_add_monster_texture(map, texture_path_1, renderer);
texture2 = map_add_monster_texture(map, texture_path_2, renderer);
texture1 = texturecache_add(texture_path_1);
texture2 = texturecache_add(texture_path_2);
label = strdup(tmp_label);
texture1->dim = (Dimension) { TILE_DIMENSION, TILE_DIMENSION };
texture2->dim = (Dimension) { TILE_DIMENSION, TILE_DIMENSION };
texture1->dim = GAME_DIMENSION;
texture2->dim = GAME_DIMENSION;
lua_pop(L, 8);

View File

@ -21,8 +21,16 @@
#include "util.h"
#include "io_util.h"
static Mix_Music *music[LAST_MUSIC];
static Mix_Chunk *effects[LAST_EFFECT];
static Mix_Music *current_song = NULL;
static Music loaded_song = LAST_MUSIC;
static char *music[LAST_MUSIC] = {
"Sounds/Music/fantasy-game-background-looping.ogg", // GAME_MUSIC0
"Sounds/Music/bog-creatures-on-the-move-looping.ogg", // GAME_MUSIC1
"Sounds/Music/fantascape-looping.ogg", // GAME_MUSIC2
"Sounds/Music/fantasy-forest-battle.ogg" // MENU_MUSIC
};
static bool sound_enabled = true;
static bool music_enabled = true;
@ -36,16 +44,6 @@ load_song(char *path)
return m;
}
static void
load_music(void)
{
music[GAME_MUSIC0] = load_song("Sounds/Music/fantasy-game-background-looping.ogg");
music[GAME_MUSIC1] = load_song("Sounds/Music/bog-creatures-on-the-move-looping.ogg");
music[GAME_MUSIC2] = load_song("Sounds/Music/fantascape-looping.ogg");
music[MENU_MUSIC] = load_song("Sounds/Music/fantasy-forest-battle.ogg");
}
static Mix_Chunk*
load_effect(char *path)
{
@ -85,8 +83,8 @@ mixer_init(void)
if (Mix_OpenAudio( 44100, MIX_DEFAULT_FORMAT, 2, 2048 ) == -1) {
fatal("Failed to load sound: %s", Mix_GetError());
}
load_effects();
load_music();
}
bool
@ -125,10 +123,17 @@ mixer_play_music(Music mus)
if (!music_enabled)
return;
if (mus != loaded_song) {
if (current_song)
Mix_FreeMusic(current_song);
current_song = load_song(music[mus]);
loaded_song = mus;
}
if (Mix_PlayingMusic())
mixer_stop_music();
if (Mix_PlayMusic(music[mus], -1) == -1)
if (Mix_PlayMusic(current_song, -1) == -1)
fatal("Failed to play music");
}
@ -144,7 +149,8 @@ mixer_close(void)
{
for (size_t i = 0; i < LAST_EFFECT; ++i)
Mix_FreeChunk(effects[i]);
for (size_t i = 0; i < LAST_MUSIC; ++i)
Mix_FreeMusic(music[i]);
if (current_song)
Mix_FreeMusic(current_song);
Mix_CloseAudio();
}

View File

@ -53,6 +53,7 @@ monster_create(SDL_Renderer *renderer)
{
Monster *m = ec_malloc(sizeof(Monster));
m->sprite = sprite_create();
m->sprite->dim = GAME_DIMENSION;
m->sprite->clip = (SDL_Rect) { 0, 0, 16, 16 };
m->stats = (Stats) {

View File

@ -316,9 +316,8 @@ player_create(class_t class, SDL_Renderer *renderer)
sprite_load_texture(player->sprite, asset, 0, renderer);
player->sprite->pos = (Position) { TILE_DIMENSION, TILE_DIMENSION };
player->sprite->dim = GAME_DIMENSION;
player->sprite->clip = (SDL_Rect) { 0, 0, 16, 16 };
player->sprite->textures[0]->dim = (Dimension) {
TILE_DIMENSION, TILE_DIMENSION };
player->handle_event = &handle_player_input;
player_load_texts(player, renderer);

View File

@ -32,8 +32,7 @@ pointer_create(SDL_Renderer *renderer)
sprite_load_texture(p->sprite, "Items/MedWep.png", 0, renderer);
p->sprite->fixed = true;
p->sprite->clip = (SDL_Rect) { 0, 0, 16, 16 };
p->sprite->textures[0]->dim = (Dimension) {
TILE_DIMENSION, TILE_DIMENSION };
p->sprite->dim = GAME_DIMENSION;
return p;
}

View File

@ -22,22 +22,22 @@
#include "util.h"
#include "sprite.h"
#include "keyboard.h"
#include "texturecache.h"
static void
load_texture(SkillBar *bar, const char *path, SDL_Renderer *renderer)
{
static SDL_Color c_yellow = { 255, 255, 0, 255 };
Texture *t = texture_create();
texture_load_from_file(t, path, renderer);
Texture *t = texturecache_add(path);
t->dim.width = 16;
t->dim.height = 16;
ht_set(bar->textures, path, t);
for (unsigned int i = 0; i < 4; ++i) {
char buffer[4];
Sprite *s = sprite_create();
s->pos = (Position) { i * 32 + 20, 20 };
s->dim = (Dimension) { 8, 8 };
s->fixed = true;
sprite_load_text_texture(s, "GUI/SDS_8x8.ttf", 0, 8);
m_sprintf(buffer, 4, "%u", i+1);
@ -50,7 +50,6 @@ SkillBar *
skillbar_create(SDL_Renderer *renderer)
{
SkillBar *bar = ec_malloc(sizeof(SkillBar));
bar->textures = ht_create(10);
bar->sprites = linkedlist_create();
bar->activationTimer = timer_create();
bar->lastActivation = 0;
@ -66,21 +65,21 @@ render_frame(SkillBar *bar, Camera *cam)
static SDL_Rect c_bottom_left = { 1*16, 12*16, 16, 16 };
static SDL_Rect c_bottom_right = { 3*16, 12*16, 16, 16 };
Texture *t = ht_get(bar->textures, "GUI/GUI0.png");
Position p = { 0, 0 };
Texture *t = texturecache_get("GUI/GUI0.png");
SDL_Rect box = { 0, 0, 16, 16 };
for (unsigned int i = 0; i < MAP_ROOM_WIDTH; ++i) {
p.x = i*32;
p.y = 0;
texture_render_clip(t, &p, &c_top_left, cam);
p.y = 16;
texture_render_clip(t, &p, &c_bottom_left, cam);
box.x = i*32;
box.y = 0;
texture_render_clip(t, &box, &c_top_left, cam);
box.y = 16;
texture_render_clip(t, &box, &c_bottom_left, cam);
p.x = i*32 + 16;
p.y = 0;
texture_render_clip(t, &p, &c_top_right, cam);
p.y = 16;
texture_render_clip(t, &p, &c_bottom_right, cam);
box.x = i*32 + 16;
box.y = 0;
texture_render_clip(t, &box, &c_top_right, cam);
box.y = 16;
texture_render_clip(t, &box, &c_bottom_right, cam);
}
}
@ -146,7 +145,6 @@ skillbar_handle_event(SkillBar *bar, SDL_Event *event)
void
skillbar_destroy(SkillBar *bar)
{
ht_destroy_custom(bar->textures, (void (*)(void *)) texture_destroy);
while (bar->sprites)
sprite_destroy(linkedlist_pop(&bar->sprites));
free(bar);

View File

@ -20,13 +20,11 @@
#define SKILLBAR_H_
#include <SDL.h>
#include "hashtable.h"
#include "linkedlist.h"
#include "camera.h"
#include "timer.h"
typedef struct SkillBar_t {
Hashtable *textures;
LinkedList *sprites;
Timer *activationTimer;
unsigned int lastActivation;

View File

@ -29,6 +29,7 @@ sprite_create_default(void)
s->clip = (SDL_Rect) { 0, 0, 0, 0 };
s->destroyTextures = false;
s->pos = (Position) { 0, 0 };
s->dim = DEFAULT_DIMENSION;
s->renderTimer = timer_create();
s->texture_index = 0;
s->fixed = false;
@ -39,7 +40,7 @@ sprite_create_default(void)
}
Sprite*
sprite_create()
sprite_create(void)
{
return sprite_create_default();
}
@ -111,15 +112,19 @@ void sprite_render(Sprite *s, Camera *cam)
else
cameraPos = s->pos;
SDL_Rect box = {
cameraPos.x, cameraPos.y, s->dim.width, s->dim.height
};
if (s->clip.w && s->clip.h) {
texture_render_clip(s->textures[s->texture_index],
&cameraPos,
&box,
&s->clip,
cam);
}
else {
texture_render(s->textures[s->texture_index],
&cameraPos,
&box,
cam);
}
}

View File

@ -32,6 +32,7 @@ typedef struct Sprite_t {
SDL_Rect clip;
bool destroyTextures;
Position pos;
Dimension dim;
Timer *renderTimer;
unsigned int texture_index;
bool fixed;

View File

@ -117,38 +117,24 @@ texture_load_from_text(Texture *t,
}
void
texture_render(Texture *texture, Position *p, Camera *cam)
texture_render(Texture *texture, SDL_Rect *box, Camera *cam)
{
if (!texture->texture)
return;
SDL_Rect draw_box = (SDL_Rect) {
p->x,
p->y,
texture->dim.width,
texture->dim.height
};
SDL_RenderCopy(cam->renderer,
texture->texture,
NULL,
&draw_box);
texture_render_clip(texture, box, NULL, cam);
}
void
texture_render_clip(Texture *texture, Position *p, SDL_Rect *clip, Camera *cam)
texture_render_clip(Texture *texture, SDL_Rect *box, SDL_Rect *clip, Camera *cam)
{
SDL_Rect draw_box = (SDL_Rect) {
p->x,
p->y,
texture->dim.width,
texture->dim.height
};
if (!texture->texture)
return;
SDL_RenderCopy(cam->renderer,
texture->texture,
clip,
&draw_box);
box);
}
void texture_destroy(Texture *texture)

View File

@ -31,21 +31,28 @@ typedef struct {
Dimension dim;
} Texture;
Texture* texture_create(void);
Texture*
texture_create(void);
void texture_load_from_file(Texture*, const char *path, SDL_Renderer*);
void
texture_load_from_file(Texture*, const char *path, SDL_Renderer*);
void texture_load_font(Texture*, const char *path, unsigned int size);
void
texture_load_font(Texture*, const char *path, unsigned int size);
void texture_load_from_text(Texture*,
const char *text,
SDL_Color,
SDL_Renderer*);
void
texture_load_from_text(Texture*,
const char *text,
SDL_Color,
SDL_Renderer*);
void texture_render(Texture*, Position*, Camera*);
void
texture_render(Texture*, SDL_Rect*, Camera*);
void texture_render_clip(Texture*, Position*, SDL_Rect*, Camera*);
void
texture_render_clip(Texture*, SDL_Rect*, SDL_Rect*, Camera*);
void texture_destroy(Texture *texture);
void
texture_destroy(Texture *texture);
#endif // TEXTURE_H_

60
src/texturecache.c Normal file
View File

@ -0,0 +1,60 @@
/*
* BreakHack - A dungeone crawler RPG
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "texturecache.h"
#include "hashtable.h"
#include "util.h"
static Hashtable *textures = NULL;
static SDL_Renderer *renderer;
void
texturecache_init(SDL_Renderer *rend)
{
textures = ht_create(50);
renderer = rend;
}
Texture*
texturecache_add(const char *path)
{
Texture *t = ht_get(textures, path);
if (!t) {
t = texture_create();
texture_load_from_file(t, path, renderer);
ht_set(textures, path, t);
debug("Cached texture: %s", path);
}
return t;
}
Texture*
texturecache_get(const char *path)
{
Texture *t = ht_get(textures, path);
if (!t)
fatal("Texture not loaded: %s", path);
return t;
}
void
texturecache_close(void)
{
ht_destroy_custom(textures, (void(*)(void*)) texture_destroy);
}

37
src/texturecache.h Normal file
View File

@ -0,0 +1,37 @@
/*
* BreakHack - A dungeone crawler RPG
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TEXTURECACHE_H_
#define TEXTURECACHE_H_
#include <SDL.h>
#include "texture.h"
void
texturecache_init(SDL_Renderer*);
Texture*
texturecache_add(const char *path);
Texture*
texturecache_get(const char *path);
void
texturecache_close(void);
#endif // TEXTURECACHE_H_