Added items, so far only health that always drops.

This commit is contained in:
Linus Probert 2018-01-24 21:14:34 +01:00
parent 2d05f10a44
commit 417cb78f31
12 changed files with 262 additions and 13 deletions

View File

@ -59,6 +59,8 @@ add_executable(breakhack
src/linkedlist src/linkedlist
src/hashtable src/hashtable
src/gui src/gui
src/item
src/item_builder
) )
target_link_libraries(breakhack target_link_libraries(breakhack

View File

@ -35,8 +35,8 @@ hash(Hashtable *table, const char *key)
// TODO(Linus): This isn't very good, // TODO(Linus): This isn't very good,
// bad distribution on similar strings // bad distribution on similar strings
while (hashval < ULONG_MAX && i < strlen(key)) { while (hashval < ULONG_MAX && i < strlen(key)) {
hashval = hashval << 8;
hashval += key[i++]; hashval += key[i++];
hashval = hashval << 8;
} }
return hashval % table->size; return hashval % table->size;

25
src/item.c Normal file
View File

@ -0,0 +1,25 @@
#include "item.h"
#include "util.h"
Item *
item_create(void)
{
Item *item = ec_malloc(sizeof(Item));
item->sprite = NULL;
item->collected = false;
item->effect = NULL;
return item;
}
void item_render(Item *item, Camera *cam)
{
sprite_render(item->sprite, cam);
}
void
item_destroy(Item *item)
{
if (item->sprite)
sprite_destroy(item->sprite);
free(item);
}

26
src/item.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef ITEM_H_
#define ITEM_H_
#include <stdbool.h>
#include "sprite.h"
#include "position.h"
#include "player.h"
#include "camera.h"
typedef struct Item_t {
Sprite *sprite;
bool collected;
void (*effect)(struct Item_t *, Player *);
} Item;
Item *
item_create(void);
void
item_render(Item*, Camera*);
void
item_destroy(Item*);
#endif // ITEM_H_

88
src/item_builder.c Normal file
View File

@ -0,0 +1,88 @@
#include <SDL2/SDL.h>
#include "item_builder.h"
#include "texture.h"
#include "util.h"
#include "gui.h"
static ItemBuilder *builder = NULL;
void
item_builder_init(SDL_Renderer *renderer)
{
builder = ec_malloc(sizeof(ItemBuilder));
builder->textures = ht_create(20);
builder->renderer = renderer;
}
static void
check_builder()
{
if (!builder)
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 };
}
return t;
}
static void
add_health(Item *item, Player *player)
{
int original_hp = player->stats.hp;
player->stats.hp += 2;
if (player->stats.hp > player->stats.maxhp)
player->stats.hp = player->stats.maxhp;
gui_log("You gained %d health", player->stats.hp - original_hp);
}
static Item *
create_health()
{
Texture *t;
Item *item;
item = item_create();
t = load_texture("assets/Items/Potion.png");
item->sprite = sprite_create();
sprite_set_texture(item->sprite, t, 0);
item->sprite->clip = (SDL_Rect) { 0, 0, 16, 16 };
item->effect = &add_health;
return item;
}
Item *
item_builder_build_item(ItemKey key)
{
check_builder();
Item *item = NULL;
switch (key) {
case HEALTH:
item = create_health(builder);
break;
default:
fatal("in item_builder_build() : Unhandled item key %d", key);
break;
}
return item;
}
void
item_builder_close()
{
ht_destroy_custom(builder->textures, (void (*)(void*)) &texture_destroy);
free(builder);
}

25
src/item_builder.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef ITEMBUILDER_H_
#define ITEMBUILDER_H_
#include "item.h"
#include "hashtable.h"
typedef struct {
Hashtable *textures;
SDL_Renderer *renderer;
} ItemBuilder;
typedef enum {
HEALTH
} ItemKey;
void
item_builder_init(SDL_Renderer *);
Item *
item_builder_build_item(ItemKey key);
void
item_builder_close();
#endif // ITEMBUILDER_H_

View File

@ -15,6 +15,7 @@
#include "gamestate.h" #include "gamestate.h"
#include "gui.h" #include "gui.h"
#include "util.h" #include "util.h"
#include "item_builder.h"
static SDL_Window *gWindow = NULL; static SDL_Window *gWindow = NULL;
static SDL_Renderer *gRenderer = NULL; static SDL_Renderer *gRenderer = NULL;
@ -36,7 +37,6 @@ bool initSDL(void)
{ {
int imgFlags = IMG_INIT_PNG; int imgFlags = IMG_INIT_PNG;
Dimension dim = getScreenDimensions(); Dimension dim = getScreenDimensions();
//Dimension dim = (Dimension) { 1920, 1080 };
if (dim.height > 1080) { if (dim.height > 1080) {
info("Hi resolution screen detected (%u x %u)", dim.width, dim.height); info("Hi resolution screen detected (%u x %u)", dim.width, dim.height);
@ -131,6 +131,7 @@ bool init(void)
gCamera.renderer = gRenderer; gCamera.renderer = gRenderer;
gRoomMatrix = roommatrix_create(); gRoomMatrix = roommatrix_create();
gGui = gui_create(); gGui = gui_create();
item_builder_init(gRenderer);
} }
gGameState = PLAYING; gGameState = PLAYING;
@ -188,6 +189,7 @@ static void
run_game(void) run_game(void)
{ {
map_clear_dead_monsters(gMap); map_clear_dead_monsters(gMap);
map_clear_collected_items(gMap);
roommatrix_populate_from_map(gRoomMatrix, gMap); roommatrix_populate_from_map(gRoomMatrix, gMap);
roommatrix_add_lightsource(gRoomMatrix, roommatrix_add_lightsource(gRoomMatrix,
&gPlayer->sprite->pos); &gPlayer->sprite->pos);
@ -266,6 +268,7 @@ void close(void)
map_destroy(gMap); map_destroy(gMap);
roommatrix_destroy(gRoomMatrix); roommatrix_destroy(gRoomMatrix);
gui_destroy(gGui); gui_destroy(gGui);
item_builder_close();
SDL_DestroyRenderer(gRenderer); SDL_DestroyRenderer(gRenderer);
SDL_DestroyWindow(gWindow); SDL_DestroyWindow(gWindow);
gWindow = NULL; gWindow = NULL;

View File

@ -2,6 +2,9 @@
#include "map.h" #include "map.h"
#include "map_lua.h" #include "map_lua.h"
#include "util.h" #include "util.h"
#include "item.h"
#include "item_builder.h"
#include "gui.h"
static static
Room* create_room(void) Room* create_room(void)
@ -27,6 +30,7 @@ Map* map_create()
map->textures = linkedlist_create(); map->textures = linkedlist_create();
map->monsterTextures = ht_create(30); map->monsterTextures = ht_create(30);
map->monsters = linkedlist_create(); map->monsters = linkedlist_create();
map->items = linkedlist_create();
map->currentRoom = (Position) { 0, 0 }; map->currentRoom = (Position) { 0, 0 };
map->renderTimer = timer_create(); map->renderTimer = timer_create();
map->level = 1; map->level = 1;
@ -102,7 +106,43 @@ map_clear_dead_monsters(Map *map)
else else
last->next = current->next; last->next = current->next;
monster_destroy(current->data); // TODO(Linus): We should really move this code somewhere else, perhaps to monster.c?
// Create a health drop
Monster *monster = current->data;
Item *item = item_builder_build_item(HEALTH);
item->sprite->pos = monster->sprite->pos;
linkedlist_append(&map->items, item);
gui_log("%s dropped a health potion", monster->label);
monster_destroy(monster);
current->data = NULL;
next = current->next;
current->next = NULL;
linkedlist_destroy(&current);
current = next;
continue;
}
last = current;
current = current->next;
}
}
void
map_clear_collected_items(Map *map)
{
LinkedList *last, *current, *next;
last = NULL;
current = map->items;
while (current != NULL) {
if (((Item*) current->data)->collected) {
if (last == NULL)
map->items = current->next;
else
last->next = current->next;
item_destroy(current->data);
current->data = NULL; current->data = NULL;
next = current->next; next = current->next;
current->next = NULL; current->next = NULL;
@ -182,6 +222,7 @@ void map_render(Map *map, Camera *cam)
{ {
unsigned int i, j; unsigned int i, j;
LinkedList *monsterItem; LinkedList *monsterItem;
LinkedList *items;
Room *room; Room *room;
if (!timer_started(map->renderTimer)) { if (!timer_started(map->renderTimer)) {
@ -215,6 +256,13 @@ void map_render(Map *map, Camera *cam)
monsterItem = monsterItem->next; monsterItem = monsterItem->next;
monster_render(monster, cam); monster_render(monster, cam);
} }
items = map->items;
while (items != NULL) {
Item *item = items->data;
items = items->next;
item_render(item, cam);
}
} }
void map_set_current_room(Map *map, Position *pos) void map_set_current_room(Map *map, Position *pos)
@ -269,12 +317,16 @@ void map_destroy(Map *map)
map_room_destroy(map->rooms[i][j]); map_room_destroy(map->rooms[i][j]);
} }
} }
while (map->textures != NULL) {
while (map->textures != NULL)
texture_destroy(linkedlist_pop(&map->textures)); texture_destroy(linkedlist_pop(&map->textures));
}
while (map->monsters != NULL) { while (map->monsters != NULL)
monster_destroy(linkedlist_pop(&map->monsters)); monster_destroy(linkedlist_pop(&map->monsters));
}
while (map->items != NULL)
item_destroy(linkedlist_pop(&map->items));
ht_destroy_custom(map->monsterTextures, (void (*)(void*)) texture_destroy); ht_destroy_custom(map->monsterTextures, (void (*)(void*)) texture_destroy);
timer_destroy(map->renderTimer); timer_destroy(map->renderTimer);
free(map); free(map);

View File

@ -33,6 +33,7 @@ typedef struct Map_t {
LinkedList *textures; LinkedList *textures;
Hashtable *monsterTextures; Hashtable *monsterTextures;
LinkedList *monsters; LinkedList *monsters;
LinkedList *items;
Position currentRoom; Position currentRoom;
Timer *renderTimer; Timer *renderTimer;
int level; int level;
@ -54,6 +55,8 @@ void map_move_monsters(Map*, RoomMatrix*);
void map_clear_dead_monsters(Map*); void map_clear_dead_monsters(Map*);
void map_clear_collected_items(Map*);
void map_render(Map*, Camera*); void map_render(Map*, Camera*);
void map_set_current_room(Map*, Position*); void map_set_current_room(Map*, Position*);

View File

@ -6,6 +6,7 @@
#include "monster.h" #include "monster.h"
#include "util.h" #include "util.h"
#include "gui.h" #include "gui.h"
#include "item.h"
#define ENGINEER_STATS { 12, 12, 5, 7, 2, 1, 1 } #define ENGINEER_STATS { 12, 12, 5, 7, 2, 1, 1 }
#define MAGE_STATS { 12, 12, 5, 7, 2, 1, 1 } #define MAGE_STATS { 12, 12, 5, 7, 2, 1, 1 }
@ -53,6 +54,12 @@ has_collided(Player *player, RoomMatrix *matrix)
gui_log("Ouch! There is something in the way"); gui_log("Ouch! There is something in the way");
} }
if (space->item != NULL) {
if (space->item->effect)
space->item->effect(space->item, player);
space->item->collected = true;
}
return collided; return collided;
} }

View File

@ -4,6 +4,7 @@
#include "util.h" #include "util.h"
#include "map.h" #include "map.h"
#include "player.h" #include "player.h"
#include "item.h"
RoomMatrix* roommatrix_create() RoomMatrix* roommatrix_create()
{ {
@ -15,10 +16,12 @@ RoomMatrix* roommatrix_create()
void roommatrix_populate_from_map(RoomMatrix *rm, Map *m) void roommatrix_populate_from_map(RoomMatrix *rm, Map *m)
{ {
int i, j; int i, j;
Position monster_matrix_pos; Position position;
Room *r; Room *r;
Monster *monster; Monster *monster;
LinkedList *monsterItem; LinkedList *monsterItem;
Item *item;
LinkedList *items;
roommatrix_reset(rm); roommatrix_reset(rm);
@ -51,14 +54,26 @@ void roommatrix_populate_from_map(RoomMatrix *rm, Map *m)
if (!position_in_room(&monster->sprite->pos, &m->currentRoom)) if (!position_in_room(&monster->sprite->pos, &m->currentRoom))
continue; continue;
monster_matrix_pos = position =
position_to_matrix_coords(&monster->sprite->pos); position_to_matrix_coords(&monster->sprite->pos);
rm->spaces[monster_matrix_pos.x][monster_matrix_pos.y] rm->spaces[position.x][position.y]
.occupied = true; .occupied = true;
rm->spaces[monster_matrix_pos.x][monster_matrix_pos.y] rm->spaces[position.x][position.y]
.monster = monster; .monster = monster;
} }
items = m->items;
while (items) {
item = items->data;
items = items->next;
if (!position_in_room(&item->sprite->pos, &m->currentRoom))
continue;
position = position_to_matrix_coords(&item->sprite->pos);
rm->spaces[position.x][position.y].item = item;
}
} }
// TODO(Linus): These should probably be macros // TODO(Linus): These should probably be macros
@ -172,6 +187,7 @@ void roommatrix_reset(RoomMatrix *m)
m->spaces[i][j].lightsource = false; m->spaces[i][j].lightsource = false;
m->spaces[i][j].light = 0; m->spaces[i][j].light = 0;
m->spaces[i][j].monster = NULL; m->spaces[i][j].monster = NULL;
m->spaces[i][j].item = NULL;
m->spaces[i][j].player = NULL; m->spaces[i][j].player = NULL;
} }
} }

View File

@ -10,6 +10,7 @@ typedef struct Sprite_t Sprite;
typedef struct Map_t Map; typedef struct Map_t Map;
typedef struct Monster_t Monster; typedef struct Monster_t Monster;
typedef struct Player_t Player; typedef struct Player_t Player;
typedef struct Item_t Item;
typedef struct { typedef struct {
bool occupied; bool occupied;
@ -17,6 +18,7 @@ typedef struct {
unsigned int light; unsigned int light;
Monster *monster; Monster *monster;
Player *player; Player *player;
Item *item;
} RoomSpace; } RoomSpace;
typedef struct { typedef struct {