diff --git a/assets/Sounds/FX/fall.wav b/assets/Sounds/FX/fall.wav new file mode 100644 index 0000000..2c6cdb3 Binary files /dev/null and b/assets/Sounds/FX/fall.wav differ diff --git a/data/maproombuilder.lua b/data/maproombuilder.lua index 9b7baa6..5612126 100644 --- a/data/maproombuilder.lua +++ b/data/maproombuilder.lua @@ -126,6 +126,7 @@ local function repack(data) isCollider = data[5] or false, isLightSource = data[6] or false, isLevelExit = data[7] or false, + isLethal = data[8] or false } end @@ -154,6 +155,12 @@ end local function add_pits_to_room(map) + if CURRENT_LEVEL < 2 then + return + elseif not random(4) == 1 then + return + end + local pitdata = read_file("pitlayouts.dat") local cleanData = "" @@ -176,7 +183,7 @@ local function add_pits_to_room(map) end for i=0, #cleanData-1 do - local c = cleanData:sub(i+1, i+1) + local c = cleanData:sub(i, i) local col = i % 16 local row = (i - (i % 16))/16 if c == "#" then @@ -197,8 +204,8 @@ local function add_pits_to_room(map) io.write("\n") end - for i=2,12 do - for j=2,9 do + for i=2,13 do + for j=2,10 do if not tile_occupied(map, (i), (j)) and matrix[i][j] then if not matrix[i-1][j-1] and not matrix[i+1][j-1] and matrix[i-1][j] and matrix[i+1][j] and matrix[i][j-1] then add_tile(map, i, j, repack(pits.innermid)) @@ -458,7 +465,7 @@ function module.build_square_room(map, room) add_level_exit(map); end - if CURRENT_LEVEL > 2 and random(10) == 1 then + if CURRENT_LEVEL > 3 and random(10) == 1 then directions = { "LEFT", "RIGHT", "UP", "DOWN" } set_modifier(map, "WINDY", directions[random(#directions)]); end @@ -489,17 +496,17 @@ function module.load_textures(map) floor.singleright = { t_floor, -1, xo + 96, yo + 16, false } local pit_yo = (random(5) + random(3)) * (16 * 2) - pits.topleft = { t_pit0, t_pit1, 0, pit_yo, true } - pits.top = { t_pit0, t_pit1, 16, pit_yo, true } - pits.topright = { t_pit0, t_pit1, 32, pit_yo, true } - pits.left = { t_pit0, t_pit1, 0, pit_yo + 16, true } - pits.center = { t_pit0, t_pit1, 16, pit_yo + 16, true } - pits.right = { t_pit0, t_pit1, 32, pit_yo + 16, true } - pits.innerleft = { t_pit0, t_pit1, 80, pit_yo, true } - pits.innermid = { t_pit0, t_pit1, 96, pit_yo, true } - pits.innerright = { t_pit0, t_pit1, 112, pit_yo, true } - pits.topcrevice = { t_pit0, t_pit1, 64, pit_yo, true } - pits.bottomcrevice = { t_pit0, t_pit1, 64, pit_yo + 16, true } + pits.topleft = { t_pit0, t_pit1, 0, pit_yo, false, false, false, true } + pits.top = { t_pit0, t_pit1, 16, pit_yo, false, false, false, true } + pits.topright = { t_pit0, t_pit1, 32, pit_yo, false, false, false, true } + pits.left = { t_pit0, t_pit1, 0, pit_yo + 16, false, false, false, true } + pits.center = { t_pit0, t_pit1, 16, pit_yo + 16, false, false, false, true } + pits.right = { t_pit0, t_pit1, 32, pit_yo + 16, false, false, false, true } + pits.innerleft = { t_pit0, t_pit1, 80, pit_yo, false, false, false, true } + pits.innermid = { t_pit0, t_pit1, 96, pit_yo, false, false, false, true } + pits.innerright = { t_pit0, t_pit1, 112, pit_yo, false, false, false, true } + pits.topcrevice = { t_pit0, t_pit1, 64, pit_yo, false, false, false, true } + pits.bottomcrevice = { t_pit0, t_pit1, 64, pit_yo + 16, false, false, false, true } wall.topleft = { t_wall, -1, xo + 0, yo + 0, true } wall.topright = { t_wall, -1, xo + 32, yo + 0, true } diff --git a/data/pitlayouts.dat b/data/pitlayouts.dat index 9ce3c0f..ba098d0 100644 --- a/data/pitlayouts.dat +++ b/data/pitlayouts.dat @@ -1,12 +1,12 @@ ---------------- ---------------- -----##--#------- -----######------ ----######------- -----####-------- -------#--------- ------###-------- ------###-------- ----------------- +--##--------##-- +--##--####--##-- +-------##------- +-------##------- +-------##------- +-------##------- +--##--####--##-- +--##--------##-- ---------------- ---------------- diff --git a/src/main.c b/src/main.c index 411d063..5a856ba 100644 --- a/src/main.c +++ b/src/main.c @@ -480,7 +480,7 @@ run_game(void) roommatrix_update_with_player(gRoomMatrix, gPlayer); if (currentTurn == PLAYER) { - if (gPlayer->steps >= gPlayer->stats.speed) { + if (gPlayer->stat_data.steps >= gPlayer->stats.speed) { currentTurn = MONSTER; player_reset_steps(gPlayer); } diff --git a/src/map.c b/src/map.c index 5f94edf..8627fbb 100644 --- a/src/map.c +++ b/src/map.c @@ -42,7 +42,8 @@ Room* create_room(void) return room; } -Map* map_create() +Map* +map_create(void) { int i, j; @@ -64,7 +65,22 @@ Map* map_create() return map; } -void map_add_tile(Map *map, Position *tile_pos, MapTile *tile) +MapTile* +map_create_tile(void) +{ + MapTile *tile = ec_malloc(sizeof(MapTile)); + tile->textureIndex0 = -1; + tile->textureIndex1 = -1; + tile->clip = CLIP16(0, 0); + tile->collider = false; + tile->lethal = false; + tile->lightsource = false; + tile->levelExit = false; + return tile; +} + +void +map_add_tile(Map *map, Position *tile_pos, MapTile *tile) { const Position *cr = &map->currentRoom; Room *room = map->rooms[cr->x][cr->y]; diff --git a/src/map.h b/src/map.h index b0d2784..b10879a 100644 --- a/src/map.h +++ b/src/map.h @@ -37,6 +37,7 @@ typedef struct MapTile_t { int textureIndex1; SDL_Rect clip; bool collider; + bool lethal; bool lightsource; bool levelExit; } MapTile; @@ -61,6 +62,9 @@ typedef struct Map_t { Map* map_create(void); +MapTile * +map_create_tile(void); + int map_add_texture(Map*, const char *path, SDL_Renderer*); diff --git a/src/map_lua.c b/src/map_lua.c index f9cd19c..cd6084d 100644 --- a/src/map_lua.c +++ b/src/map_lua.c @@ -157,7 +157,7 @@ extract_tile_data(lua_State *L, Map *map; int tile_x, tile_y; int t_index0, t_index1, tile_clip_x, tile_clip_y; - bool collider, lightsource, levelExit; + bool collider, lightsource, levelExit, lethal; map = luaL_checkmap(L, 1); tile_x = (int) luaL_checkinteger(L, 2); @@ -175,28 +175,31 @@ extract_tile_data(lua_State *L, lua_getfield(L, 4, "isCollider"); lua_getfield(L, 4, "isLightSource"); lua_getfield(L, 4, "isLevelExit"); + lua_getfield(L, 4, "isLethal"); - t_index0 = (int) luaL_checkinteger(L, -7); - t_index1 = (int) luaL_checkinteger(L, -6); - tile_clip_x = (int) luaL_checkinteger(L, -5); - tile_clip_y = (int) luaL_checkinteger(L, -4); - collider = lua_toboolean(L, -3); - lightsource = lua_toboolean(L, -2); - levelExit = lua_toboolean(L, -1); + t_index0 = (int) luaL_checkinteger(L, -8); + t_index1 = (int) luaL_checkinteger(L, -7); + tile_clip_x = (int) luaL_checkinteger(L, -6); + tile_clip_y = (int) luaL_checkinteger(L, -5); + collider = lua_toboolean(L, -4); + lightsource = lua_toboolean(L, -3); + levelExit = lua_toboolean(L, -2); + lethal = lua_toboolean(L, -1); // Clear the stack - lua_pop(L, 7); + lua_pop(L, 8); Position tilePos = (Position) { tile_x, tile_y }; SDL_Rect clip = (SDL_Rect) { tile_clip_x, tile_clip_y, 16, 16 }; - MapTile *tile = malloc(sizeof(MapTile)); - *tile = (MapTile) { t_index0, - t_index1, - clip, collider, - lightsource, - levelExit - }; + MapTile *tile = map_create_tile(); + tile->textureIndex0 = t_index0; + tile->textureIndex1 = t_index1; + tile->clip = clip; + tile->collider = collider; + tile->lightsource = lightsource; + tile->levelExit = levelExit; + tile->lethal = lethal; f_add_tile(map, &tilePos, tile); } @@ -252,7 +255,7 @@ int l_tile_occupied(lua_State *L) tile = room->tiles[x][y]; decor = room->decorations[x][y]; - response = response || (tile && (tile->collider || tile->levelExit)); + response = response || (tile && (tile->collider || tile->levelExit || tile->lethal)); response = response || (decor && (decor->collider || decor->levelExit)); lua_pushboolean(L, response); diff --git a/src/mixer.c b/src/mixer.c index 8703591..1047a3b 100644 --- a/src/mixer.c +++ b/src/mixer.c @@ -79,6 +79,7 @@ load_effects(void) effects[PLAYER_HIT1] = load_effect("Sounds/FX/fistpunch_vocal_02.wav"); effects[PLAYER_HIT2] = load_effect("Sounds/FX/fistpunch_vocal_03.wav"); effects[DAGGER_PICKUP] = load_effect("Sounds/FX/dagger_pickup.wav"); + effects[FALL] = load_effect("Sounds/FX/fall.wav"); } void diff --git a/src/mixer.h b/src/mixer.h index ef6e9e4..ac6a1bd 100644 --- a/src/mixer.h +++ b/src/mixer.h @@ -42,6 +42,7 @@ typedef enum Fx_t { TRIPPLE_SWORD_HIT, BONK, DEATH, + FALL, COIN, BOTTLE, BUBBLE0, diff --git a/src/monster.c b/src/monster.c index 9f04c12..e7bac47 100644 --- a/src/monster.c +++ b/src/monster.c @@ -111,7 +111,7 @@ has_collided(Monster *monster, RoomMatrix *matrix) gui_log("%s missed you", monster->label); } - return space->occupied; + return space->occupied || space->lethal; } static bool @@ -220,7 +220,7 @@ monster_agressive_walk(Monster *m, RoomMatrix *rm) x_dist = abs(next.x - rm->playerRoomPos.x); y_dist = abs(next.y - rm->playerRoomPos.y); - if (rm->spaces[next.x][next.y].occupied) { + if (rm->spaces[next.x][next.y].occupied || rm->spaces[next.x][next.y].lethal) { nextScore += 50; } diff --git a/src/player.c b/src/player.c index c642681..4022e98 100644 --- a/src/player.c +++ b/src/player.c @@ -84,8 +84,8 @@ player_gain_xp(Player *player, unsigned int xp_gain) static void action_spent(Player *p) { - p->steps++; - p->total_steps++; + p->stat_data.steps++; + p->stat_data.total_steps++; for (size_t i = 0; i < PLAYER_SKILL_COUNT; ++i) { if (p->skills[i] != NULL && p->skills[i]->resetCountdown > 0) @@ -125,10 +125,10 @@ has_collided(Player *player, RoomMatrix *matrix) monster_hit(space->monster, hit); if (hit > 0) { - player->hits += 1; + player->stat_data.hits += 1; mixer_play_effect(SWORD_HIT); } else { - player->misses += 1; + player->stat_data.misses += 1; } if (hit > 0) @@ -155,6 +155,11 @@ has_collided(Player *player, RoomMatrix *matrix) } } + if (space->lethal && !collided) { + mixer_play_effect(FALL); + player->state = FALLING; + } + return collided; } @@ -318,6 +323,9 @@ check_skill_trigger(Player *player, RoomMatrix *matrix, SDL_Event *event) static void handle_player_input(Player *player, RoomMatrix *matrix, SDL_Event *event) { + if (player->state != ALIVE) + return; + if (event->type != SDL_KEYDOWN) return; @@ -352,16 +360,19 @@ player_create(class_t class, SDL_Renderer *renderer) { Player *player = malloc(sizeof(Player)); player->sprite = sprite_create(); - player->daggers = 0; - player->total_steps = 0; - player->steps = 0; - player->xp = 0; - player->hits = 0; - player->kills = 0; - player->misses = 0; - player->gold = 0; - player->potion_sips = 0; - player->class = class; + player->daggers = 0; + player->stat_data.total_steps = 0; + player->stat_data.steps = 0; + player->stat_data.hits = 0; + player->stat_data.kills = 0; + player->stat_data.misses = 0; + player->xp = 0; + player->gold = 0; + player->potion_sips = 0; + player->class = class; + player->state = ALIVE; + player->projectiles = linkedlist_create(); + player->animationTimer = timer_create(); for (size_t i = 0; i < PLAYER_SKILL_COUNT; ++i) { player->skills[i] = NULL; @@ -401,7 +412,6 @@ player_create(class_t class, SDL_Renderer *renderer) player->sprite->dim = GAME_DIMENSION; player->sprite->clip = (SDL_Rect) { 0, 0, 16, 16 }; player->handle_event = &handle_player_input; - player->projectiles = linkedlist_create(); player_load_texts(player, renderer); return player; @@ -425,8 +435,7 @@ player_monster_kill_check(Player *player, Monster *monster) if (monster->stats.hp <= 0) { unsigned int gained_xp = 5 * monster->stats.lvl; - player->kills += 1; - + player->stat_data.kills += 1; mixer_play_effect(DEATH); gui_log("You killed %s and gained %d xp", monster->lclabel, gained_xp); @@ -473,12 +482,13 @@ player_print(Player *p) { Position roomPos = position_to_matrix_coords(&p->sprite->pos); Position pos = p->sprite->pos; + PlayerStatData *data = &p->stat_data; debug("\n"); debug("--------=== <[ Player Stats ]> ===--------"); - debug("Hits: %u\tMisses:\t%u", p->hits, p->misses); - debug("Kills: %u", p->kills); - debug("Steps: %u", p->total_steps); + debug("Hits: %u\tMisses:\t%u", data->hits, data->misses); + debug("Kills: %u", data->kills); + debug("Steps: %u", data->total_steps); debug("Pos: %dx%d\tRoomPos: %dx%d", pos.x, pos.y, roomPos.x, roomPos.y); debug("------------------------------------------"); @@ -487,42 +497,53 @@ player_print(Player *p) void player_reset_steps(Player *p) { - p->steps = 0; + p->stat_data.steps = 0; player_print(p); } void player_update(UpdateData *data) { - if (!data->player->projectiles) - return; - - LinkedList *last, *current, *next; - last = NULL; - current = data->player->projectiles; - next = NULL; - - while (current) { - Projectile *p = current->data; - projectile_update(p, data); - if (!p->alive) { - if (last == NULL) - data->player->projectiles = current->next; - else - last->next = current->next; - - projectile_destroy(p); - - next = current->next; - current->data = NULL; - current->next = NULL; - linkedlist_destroy(¤t); - current = next; - action_spent(data->player); + Player *player = data->player; + if (player->state == FALLING) { + if (!timer_started(player->animationTimer)) { + timer_start(player->animationTimer); + player->sprite->clip = CLIP16(0, 0); } else { - last = current; - current = current->next; + if (timer_get_ticks(player->animationTimer) > 100) { + timer_start(player->animationTimer); + player->sprite->angle += 60; + player->sprite->dim.width -= 4; + player->sprite->dim.height -= 4; + player->sprite->pos.x += 2; + player->sprite->pos.y += 2; + player->sprite->rotationPoint = (SDL_Point) { + player->sprite->dim.width /2, + player->sprite->dim.height /2 + }; + if (player->sprite->dim.width <= 4) + player->stats.hp = 0; + } } } + + if (!player->projectiles) + return; + + LinkedList *remaining = linkedlist_create(); + + while (player->projectiles) { + Projectile *p = linkedlist_pop(&player->projectiles); + projectile_update(p, data); + if (p->alive) { + linkedlist_push(&remaining, p); + } else { + projectile_destroy(p); + action_spent(player); + } + } + + linkedlist_destroy(&player->projectiles); + player->projectiles = remaining; } void diff --git a/src/player.h b/src/player.h index 8347964..0129ca0 100644 --- a/src/player.h +++ b/src/player.h @@ -32,8 +32,16 @@ // Foward declare struct UpdateData_t; -enum PlayerClass { ENGINEER, MAGE, PALADIN, ROGUE, WARRIOR }; -typedef enum PlayerClass class_t; +typedef enum PlayerClass { ENGINEER, MAGE, PALADIN, ROGUE, WARRIOR } class_t; +typedef enum PlayerState { ALIVE, DEAD, FALLING } state_t; + +typedef struct PlayerStatData_t { + unsigned int total_steps; + unsigned int steps; + unsigned int hits; + unsigned int kills; + unsigned int misses; +} PlayerStatData; typedef struct ExperienceData_t { unsigned int previousLevel; @@ -50,15 +58,13 @@ typedef struct Player_t { unsigned int daggers; LinkedList *projectiles; unsigned int xp; - unsigned int total_steps; - unsigned int steps; - unsigned int hits; - unsigned int kills; - unsigned int misses; double gold; + PlayerStatData stat_data; unsigned int potion_sips; class_t class; + state_t state; Skill *skills[PLAYER_SKILL_COUNT]; + Timer *animationTimer; void (*handle_event)(struct Player_t*, RoomMatrix*, SDL_Event*); } Player; diff --git a/src/projectile.c b/src/projectile.c index 043fcff..1e7a91c 100644 --- a/src/projectile.c +++ b/src/projectile.c @@ -96,7 +96,7 @@ projectile_update(Projectile *p, UpdateData *data) if (dmg > 0) { gui_log("Your dagger pierced %s for %u damage", space->monster->lclabel, dmg); mixer_play_effect(SWORD_HIT); - data->player->hits += 1; + data->player->stat_data.hits += 1; } if (get_random(2) >= 1) { Item *item = item_builder_build_item(DAGGER, 1); diff --git a/src/roommatrix.c b/src/roommatrix.c index cd1e199..0ab2090 100644 --- a/src/roommatrix.c +++ b/src/roommatrix.c @@ -75,6 +75,8 @@ void roommatrix_populate_from_map(RoomMatrix *rm, Map *m) r->tiles[i][j]->collider; space->lightsource = r->tiles[i][j]->lightsource; + space->lethal = + r->tiles[i][j]->lethal; } if (r->decorations[i][j]) { space->occupied |= @@ -253,7 +255,8 @@ roommatrix_render_lightmap(RoomMatrix *matrix, Camera *cam) } } -void roommatrix_reset(RoomMatrix *m) +void +roommatrix_reset(RoomMatrix *m) { RoomSpace *space; int i, j; @@ -262,6 +265,7 @@ void roommatrix_reset(RoomMatrix *m) for (j = 0; j < MAP_ROOM_HEIGHT; ++j) { space = &m->spaces[i][j]; space->occupied = false; + space->lethal = false; space->lightsource = false; space->light = 0; space->monster = NULL; diff --git a/src/roommatrix.h b/src/roommatrix.h index 514dbf8..68e53ee 100644 --- a/src/roommatrix.h +++ b/src/roommatrix.h @@ -34,6 +34,7 @@ typedef struct Node LinkedList; typedef struct { bool occupied; + bool lethal; bool lightsource; unsigned int light; Monster *monster; diff --git a/src/skill.c b/src/skill.c index da35aec..df9724c 100644 --- a/src/skill.c +++ b/src/skill.c @@ -101,7 +101,7 @@ skill_use_flurry(Skill *skill, SkillData *data) mixer_play_effect(TRIPPLE_SWORD_HIT); } - data->player->hits += hitCount; + data->player->stat_data.hits += hitCount; } else { gui_log("You swing at thin air with a flurry of strikes"); @@ -283,7 +283,7 @@ skill_charge(Skill *skill, SkillData *data) if (dmg > 0) { gui_log("You charged %s for %u damage", monster->lclabel, dmg); mixer_play_effect(SWORD_HIT); - data->player->hits += 1; + data->player->stat_data.hits += 1; } monster_hit(monster, dmg); } diff --git a/src/sprite.c b/src/sprite.c index 6c336a9..581865c 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -30,6 +30,9 @@ sprite_create_default(void) s->destroyTextures = false; s->pos = (Position) { 0, 0 }; s->dim = DEFAULT_DIMENSION; + s->angle = 0; + s->rotationPoint = (SDL_Point) { 0, 0 }; + s->flip = SDL_FLIP_NONE; s->renderTimer = timer_create(); s->texture_index = 0; s->fixed = false; @@ -119,13 +122,20 @@ sprite_render(Sprite *s, Camera *cam) cameraPos.x, cameraPos.y, s->dim.width, s->dim.height }; - if (s->clip.w && s->clip.h) { + if ((s->clip.w && s->clip.h) || s->angle || s->flip != SDL_FLIP_NONE) { + texture_render_clip_ex(s->textures[s->texture_index], + &box, + &s->clip, + s->angle, + &s->rotationPoint, + s->flip, + cam); + } else if (s->clip.w && s->clip.h) { texture_render_clip(s->textures[s->texture_index], &box, &s->clip, cam); - } - else { + } else { texture_render(s->textures[s->texture_index], &box, cam); diff --git a/src/sprite.h b/src/sprite.h index 0dde7d1..51fee5f 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -33,6 +33,9 @@ typedef struct Sprite_t { bool destroyTextures; Position pos; Dimension dim; + double angle; + SDL_Point rotationPoint; + SDL_RendererFlip flip; Timer *renderTimer; unsigned int texture_index; bool fixed; diff --git a/src/texture.c b/src/texture.c index ca3cd55..6a68672 100644 --- a/src/texture.c +++ b/src/texture.c @@ -171,6 +171,21 @@ texture_render_clip(Texture *texture, SDL_Rect *box, SDL_Rect *clip, Camera *cam box); } +void +texture_render_clip_ex(Texture *texture, SDL_Rect *box, SDL_Rect *clip, double angle, SDL_Point *point, SDL_RendererFlip flipType, Camera *cam) +{ + if (!texture->texture) + return; + + SDL_RenderCopyEx(cam->renderer, + texture->texture, + clip, + box, + angle, + point, + flipType); +} + void texture_destroy(Texture *texture) { if (texture->texture) diff --git a/src/texture.h b/src/texture.h index 1db0546..1c94d99 100644 --- a/src/texture.h +++ b/src/texture.h @@ -65,6 +65,9 @@ texture_render(Texture*, SDL_Rect*, Camera*); void texture_render_clip(Texture*, SDL_Rect*, SDL_Rect*, Camera*); +void +texture_render_clip_ex(Texture*, SDL_Rect*, SDL_Rect*, double angle, SDL_Point*, SDL_RendererFlip, Camera*); + void texture_destroy(Texture *texture);