Adds falling into pits

Monsters also avoid pits. Still need more pit layouts and
prevent monsters from "spawning"  in pits.
This commit is contained in:
Linus Probert 2018-03-25 23:30:26 +02:00
parent 1206ec8a2d
commit 0a21a2d915
20 changed files with 202 additions and 107 deletions

BIN
assets/Sounds/FX/fall.wav Normal file

Binary file not shown.

View File

@ -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 }

View File

@ -1,12 +1,12 @@
----------------
----------------
----##--#-------
----######------
---######-------
----####--------
------#---------
-----###--------
-----###--------
----------------
--##--------##--
--##--####--##--
-------##-------
-------##-------
-------##-------
-------##-------
--##--####--##--
--##--------##--
----------------
----------------

View File

@ -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);
}

View File

@ -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];

View File

@ -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*);

View File

@ -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);

View File

@ -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

View File

@ -42,6 +42,7 @@ typedef enum Fx_t {
TRIPPLE_SWORD_HIT,
BONK,
DEATH,
FALL,
COIN,
BOTTLE,
BUBBLE0,

View File

@ -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;
}

View File

@ -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(&current);
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

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -34,6 +34,7 @@ typedef struct Node LinkedList;
typedef struct {
bool occupied;
bool lethal;
bool lightsource;
unsigned int light;
Monster *monster;

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -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);