Adds room objects and FIRE rooms.
This commit is contained in:
parent
0b58e535ec
commit
6633db7aa4
|
@ -176,6 +176,7 @@ add_executable(breakhack
|
||||||
src/artifact
|
src/artifact
|
||||||
src/screen
|
src/screen
|
||||||
src/hiscore
|
src/hiscore
|
||||||
|
src/object
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sqlite has some warnings that I we don't need to see
|
# Sqlite has some warnings that I we don't need to see
|
||||||
|
|
|
@ -431,10 +431,13 @@ local function build_normal_room(room)
|
||||||
add_level_exit(room)
|
add_level_exit(room)
|
||||||
end
|
end
|
||||||
|
|
||||||
if CURRENT_LEVEL > 3 and random(10) == 1 then
|
if CURRENT_LEVEL > 3 and random(8) == 1 then
|
||||||
directions = { "LEFT", "RIGHT", "UP", "DOWN" }
|
directions = { "LEFT", "RIGHT", "UP", "DOWN" }
|
||||||
room.modifier.type = "WINDY"
|
room.modifier.type = "WINDY"
|
||||||
room.modifier.arg = directions[random(#directions)]
|
room.modifier.arg = directions[random(#directions)]
|
||||||
|
elseif CURRENT_LEVEL > 5 and random(8) == 1 then
|
||||||
|
room.modifier.type = "FIRE"
|
||||||
|
room.modifier.arg = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
return room
|
return room
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#ifndef DEFINES_H_
|
#ifndef DEFINES_H_
|
||||||
#define DEFINES_H_
|
#define DEFINES_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
/* Room/Map dimensions */
|
/* Room/Map dimensions */
|
||||||
|
@ -76,6 +77,13 @@
|
||||||
#define min(a, b) (a < b ? a : b)
|
#define min(a, b) (a < b ? a : b)
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
typedef int8_t Sint8;
|
||||||
|
typedef uint8_t Uint8;
|
||||||
|
typedef int16_t Sint16;
|
||||||
|
typedef uint16_t Uint16;
|
||||||
|
typedef int32_t Sint32;
|
||||||
|
typedef uint32_t Uint32;
|
||||||
|
|
||||||
typedef enum Direction_t {
|
typedef enum Direction_t {
|
||||||
UP, DOWN, LEFT, RIGHT
|
UP, DOWN, LEFT, RIGHT
|
||||||
} Direction;
|
} Direction;
|
||||||
|
|
|
@ -523,16 +523,13 @@ run_game_update(void)
|
||||||
if (gGameState == IN_GAME_MENU)
|
if (gGameState == IN_GAME_MENU)
|
||||||
menu_update(inGameMenu, &input);
|
menu_update(inGameMenu, &input);
|
||||||
|
|
||||||
map_clear_dead_monsters(gMap, gPlayer);
|
|
||||||
map_clear_collected_items(gMap);
|
|
||||||
map_clear_collected_artifacts(gMap);
|
|
||||||
|
|
||||||
populateUpdateData(&updateData, deltaTime);
|
populateUpdateData(&updateData, deltaTime);
|
||||||
if (playerLevel != gPlayer->stats.lvl) {
|
if (playerLevel != gPlayer->stats.lvl) {
|
||||||
playerLevel = gPlayer->stats.lvl;
|
playerLevel = gPlayer->stats.lvl;
|
||||||
skillbar_check_skill_activation(gSkillBar, gPlayer);
|
skillbar_check_skill_activation(gSkillBar, gPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map_clear_expired_entities(gMap, gPlayer);
|
||||||
if (gGameState == PLAYING && currentTurn == PLAYER)
|
if (gGameState == PLAYING && currentTurn == PLAYER)
|
||||||
player_update(&updateData);
|
player_update(&updateData);
|
||||||
|
|
||||||
|
@ -550,6 +547,7 @@ run_game_update(void)
|
||||||
if (player_turn_over(gPlayer)) {
|
if (player_turn_over(gPlayer)) {
|
||||||
currentTurn = MONSTER;
|
currentTurn = MONSTER;
|
||||||
player_reset_steps(gPlayer);
|
player_reset_steps(gPlayer);
|
||||||
|
map_on_new_turn(gMap);
|
||||||
repopulate_roommatrix();
|
repopulate_roommatrix();
|
||||||
}
|
}
|
||||||
} else if (currentTurn == MONSTER) {
|
} else if (currentTurn == MONSTER) {
|
||||||
|
|
56
src/map.c
56
src/map.c
|
@ -55,6 +55,7 @@ map_create(void)
|
||||||
map->monsters = linkedlist_create();
|
map->monsters = linkedlist_create();
|
||||||
map->items = linkedlist_create();
|
map->items = linkedlist_create();
|
||||||
map->artifacts = linkedlist_create();
|
map->artifacts = linkedlist_create();
|
||||||
|
map->objects = linkedlist_create();
|
||||||
map->currentRoom = (Position) { 0, 0 };
|
map->currentRoom = (Position) { 0, 0 };
|
||||||
map->renderTimer = timer_create();
|
map->renderTimer = timer_create();
|
||||||
map->monsterMoveTimer = timer_create();
|
map->monsterMoveTimer = timer_create();
|
||||||
|
@ -128,9 +129,9 @@ map_add_trap(Map *map, Position *pos, Trap *trap)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
map_clear_dead_monsters(Map *map, Player *player)
|
map_clear_expired_entities(Map *map, Player *player)
|
||||||
{
|
{
|
||||||
LinkedList *cleared = linkedlist_create();
|
LinkedList *filtered = linkedlist_create();
|
||||||
|
|
||||||
while (map->monsters) {
|
while (map->monsters) {
|
||||||
Monster *monster = linkedlist_pop(&map->monsters);
|
Monster *monster = linkedlist_pop(&map->monsters);
|
||||||
|
@ -138,17 +139,12 @@ map_clear_dead_monsters(Map *map, Player *player)
|
||||||
monster_drop_loot(monster, map, player);
|
monster_drop_loot(monster, map, player);
|
||||||
monster_destroy(monster);
|
monster_destroy(monster);
|
||||||
} else {
|
} else {
|
||||||
linkedlist_append(&cleared, monster);
|
linkedlist_append(&filtered, monster);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
map->monsters = cleared;
|
map->monsters = filtered;
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
map_clear_collected_items(Map *map)
|
|
||||||
{
|
|
||||||
LinkedList *filtered = linkedlist_create();
|
|
||||||
|
|
||||||
|
filtered = linkedlist_create();
|
||||||
while (map->items) {
|
while (map->items) {
|
||||||
Item *item = linkedlist_pop(&map->items);
|
Item *item = linkedlist_pop(&map->items);
|
||||||
if (item->collected)
|
if (item->collected)
|
||||||
|
@ -157,12 +153,8 @@ map_clear_collected_items(Map *map)
|
||||||
linkedlist_append(&filtered, item);
|
linkedlist_append(&filtered, item);
|
||||||
}
|
}
|
||||||
map->items = filtered;
|
map->items = filtered;
|
||||||
}
|
|
||||||
|
|
||||||
void
|
filtered = linkedlist_create();
|
||||||
map_clear_collected_artifacts(Map *map)
|
|
||||||
{
|
|
||||||
LinkedList *filtered = linkedlist_create();
|
|
||||||
while (map->artifacts) {
|
while (map->artifacts) {
|
||||||
Artifact *a = linkedlist_pop(&map->artifacts);
|
Artifact *a = linkedlist_pop(&map->artifacts);
|
||||||
if (!a->collected)
|
if (!a->collected)
|
||||||
|
@ -171,6 +163,16 @@ map_clear_collected_artifacts(Map *map)
|
||||||
artifact_destroy(a);
|
artifact_destroy(a);
|
||||||
}
|
}
|
||||||
map->artifacts = filtered;
|
map->artifacts = filtered;
|
||||||
|
|
||||||
|
filtered = linkedlist_create();
|
||||||
|
while (map->objects) {
|
||||||
|
Object *o = linkedlist_pop(&map->objects);
|
||||||
|
if (o->dead)
|
||||||
|
object_destroy(o);
|
||||||
|
else
|
||||||
|
linkedlist_append(&filtered, o);
|
||||||
|
}
|
||||||
|
map->objects = filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -204,7 +206,7 @@ map_move_monsters(Map *map, RoomMatrix *rm)
|
||||||
&& position_proximity(1, &rm->playerRoomPos, &pos))
|
&& position_proximity(1, &rm->playerRoomPos, &pos))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
allDone = allDone && monster_move(monster, rm);
|
allDone = allDone && monster_move(monster, rm, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allDone)
|
if (allDone)
|
||||||
|
@ -259,6 +261,17 @@ void map_tile_render(Map *map, MapTile *tile, Position *pos, Camera *cam)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
map_on_new_turn(Map *map)
|
||||||
|
{
|
||||||
|
LinkedList *objects = map->objects;
|
||||||
|
while (objects) {
|
||||||
|
Object *o = objects->data;
|
||||||
|
objects = objects->next;
|
||||||
|
object_step(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
map_update(UpdateData *data)
|
map_update(UpdateData *data)
|
||||||
{
|
{
|
||||||
|
@ -304,6 +317,8 @@ void map_render(Map *map, Camera *cam)
|
||||||
}
|
}
|
||||||
if (room->modifier.type == RMOD_TYPE_WINDY) {
|
if (room->modifier.type == RMOD_TYPE_WINDY) {
|
||||||
particle_engine_wind(room->modifier.data.wind.direction);
|
particle_engine_wind(room->modifier.data.wind.direction);
|
||||||
|
} else if (room->modifier.type == RMOD_TYPE_FIRE) {
|
||||||
|
particle_engine_heat();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -317,6 +332,12 @@ map_render_mid_layer(Map *map, Camera *cam)
|
||||||
items = items->next;
|
items = items->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LinkedList *objects = map->objects;
|
||||||
|
while (objects != NULL) {
|
||||||
|
object_render(objects->data, cam);
|
||||||
|
objects = objects->next;
|
||||||
|
}
|
||||||
|
|
||||||
LinkedList *artifacts = map->artifacts;
|
LinkedList *artifacts = map->artifacts;
|
||||||
while (artifacts != NULL) {
|
while (artifacts != NULL) {
|
||||||
artifact_render(artifacts->data, cam);
|
artifact_render(artifacts->data, cam);
|
||||||
|
@ -410,6 +431,9 @@ void map_destroy(Map *map)
|
||||||
while (map->artifacts != NULL)
|
while (map->artifacts != NULL)
|
||||||
artifact_destroy(linkedlist_pop(&map->artifacts));
|
artifact_destroy(linkedlist_pop(&map->artifacts));
|
||||||
|
|
||||||
|
while (map->objects != NULL)
|
||||||
|
artifact_destroy(linkedlist_pop(&map->objects));
|
||||||
|
|
||||||
timer_destroy(map->renderTimer);
|
timer_destroy(map->renderTimer);
|
||||||
timer_destroy(map->monsterMoveTimer);
|
timer_destroy(map->monsterMoveTimer);
|
||||||
free(map);
|
free(map);
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "monster.h"
|
#include "monster.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "map_room_modifiers.h"
|
#include "map_room_modifiers.h"
|
||||||
|
#include "object.h"
|
||||||
|
|
||||||
typedef struct UpdateData UpdateData;
|
typedef struct UpdateData UpdateData;
|
||||||
typedef struct Trap Trap;
|
typedef struct Trap Trap;
|
||||||
|
@ -58,6 +59,7 @@ typedef struct Map_t {
|
||||||
LinkedList *monsters;
|
LinkedList *monsters;
|
||||||
LinkedList *items;
|
LinkedList *items;
|
||||||
LinkedList *artifacts;
|
LinkedList *artifacts;
|
||||||
|
LinkedList *objects;
|
||||||
Position currentRoom;
|
Position currentRoom;
|
||||||
Timer *renderTimer;
|
Timer *renderTimer;
|
||||||
Timer *monsterMoveTimer;
|
Timer *monsterMoveTimer;
|
||||||
|
@ -89,13 +91,10 @@ bool
|
||||||
map_move_monsters(Map*, RoomMatrix*);
|
map_move_monsters(Map*, RoomMatrix*);
|
||||||
|
|
||||||
void
|
void
|
||||||
map_clear_dead_monsters(Map*, Player*);
|
map_clear_expired_entities(Map*, Player*);
|
||||||
|
|
||||||
void
|
void
|
||||||
map_clear_collected_items(Map*);
|
map_on_new_turn(Map*);
|
||||||
|
|
||||||
void
|
|
||||||
map_clear_collected_artifacts(Map*);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
map_update(UpdateData*);
|
map_update(UpdateData*);
|
||||||
|
|
|
@ -116,6 +116,9 @@ l_map_set_current_room_modifier(lua_State *L)
|
||||||
Room *room = map->rooms[map->currentRoom.x][map->currentRoom.y];
|
Room *room = map->rooms[map->currentRoom.x][map->currentRoom.y];
|
||||||
room->modifier.type = RMOD_TYPE_WINDY;
|
room->modifier.type = RMOD_TYPE_WINDY;
|
||||||
room->modifier.data.wind.direction = dir;
|
room->modifier.data.wind.direction = dir;
|
||||||
|
} else if (strcmp(modifier, "FIRE") == 0) {
|
||||||
|
Room *room = map->rooms[map->currentRoom.x][map->currentRoom.y];
|
||||||
|
room->modifier.type = RMOD_TYPE_FIRE;
|
||||||
} else {
|
} else {
|
||||||
luaL_error(L, "Unknown room modifier: %s", modifier);
|
luaL_error(L, "Unknown room modifier: %s", modifier);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -27,10 +27,11 @@ typedef struct RoomMatrix_t RoomMatrix;
|
||||||
|
|
||||||
typedef enum RoomModifierType_e {
|
typedef enum RoomModifierType_e {
|
||||||
RMOD_TYPE_NONE,
|
RMOD_TYPE_NONE,
|
||||||
RMOD_TYPE_WINDY
|
RMOD_TYPE_WINDY,
|
||||||
|
RMOD_TYPE_FIRE
|
||||||
} RoomModifierType;
|
} RoomModifierType;
|
||||||
|
|
||||||
typedef struct WindData_t {
|
typedef struct WindData {
|
||||||
Vector2d direction;
|
Vector2d direction;
|
||||||
} WindData;
|
} WindData;
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ typedef union RoomModifierDataContainer_t {
|
||||||
WindData wind;
|
WindData wind;
|
||||||
} RoomModifierDataContainer;
|
} RoomModifierDataContainer;
|
||||||
|
|
||||||
typedef struct RoomModifierData_t {
|
typedef struct RoomModifierData {
|
||||||
RoomModifierType type;
|
RoomModifierType type;
|
||||||
RoomModifierDataContainer data;
|
RoomModifierDataContainer data;
|
||||||
} RoomModifierData;
|
} RoomModifierData;
|
||||||
|
|
|
@ -236,7 +236,7 @@ has_collided(Monster *monster, RoomMatrix *matrix, Vector2d direction)
|
||||||
monster_behaviour_check_post_attack(monster);
|
monster_behaviour_check_post_attack(monster);
|
||||||
}
|
}
|
||||||
|
|
||||||
return space->occupied || space->lethal || space->trap;
|
return space->occupied || space->lethal || space->trap || space->damaging;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -376,7 +376,7 @@ monster_coward_walk(Monster *m, RoomMatrix *rm)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
monster_move(Monster *m, RoomMatrix *rm)
|
monster_move(Monster *m, RoomMatrix *rm, Map *map)
|
||||||
{
|
{
|
||||||
if (m->state.forceCount) {
|
if (m->state.forceCount) {
|
||||||
if (m->state.stepsSinceChange >= m->state.forceCount) {
|
if (m->state.stepsSinceChange >= m->state.forceCount) {
|
||||||
|
@ -392,10 +392,11 @@ monster_move(Monster *m, RoomMatrix *rm)
|
||||||
|
|
||||||
monster_behaviour_check(m, rm);
|
monster_behaviour_check(m, rm);
|
||||||
|
|
||||||
Position originalPosition =
|
Position origPos = m->sprite->pos;
|
||||||
|
Position originalMPos =
|
||||||
position_to_matrix_coords(&m->sprite->pos);
|
position_to_matrix_coords(&m->sprite->pos);
|
||||||
rm->spaces[originalPosition.x][originalPosition.y].occupied = false;
|
rm->spaces[originalMPos.x][originalMPos.y].occupied = false;
|
||||||
rm->spaces[originalPosition.x][originalPosition.y].monster = NULL;
|
rm->spaces[originalMPos.x][originalMPos.y].monster = NULL;
|
||||||
|
|
||||||
switch (m->state.current) {
|
switch (m->state.current) {
|
||||||
case PASSIVE:
|
case PASSIVE:
|
||||||
|
@ -420,7 +421,7 @@ monster_move(Monster *m, RoomMatrix *rm)
|
||||||
rm->spaces[newPos.x][newPos.y].occupied = true;
|
rm->spaces[newPos.x][newPos.y].occupied = true;
|
||||||
rm->spaces[newPos.x][newPos.y].monster = m;
|
rm->spaces[newPos.x][newPos.y].monster = m;
|
||||||
|
|
||||||
if (!position_equals(&originalPosition, &newPos)) {
|
if (!position_equals(&originalMPos, &newPos)) {
|
||||||
Player *p = rm->spaces[rm->playerRoomPos.x][rm->playerRoomPos.y].player;
|
Player *p = rm->spaces[rm->playerRoomPos.x][rm->playerRoomPos.y].player;
|
||||||
if (p) {
|
if (p) {
|
||||||
Uint32 range = 3 + player_has_artifact(p, IMPROVED_HEARING) * 2;
|
Uint32 range = 3 + player_has_artifact(p, IMPROVED_HEARING) * 2;
|
||||||
|
@ -434,6 +435,14 @@ monster_move(Monster *m, RoomMatrix *rm)
|
||||||
actiontextbuilder_create_text("!", C_WHITE, &m->sprite->pos);
|
actiontextbuilder_create_text("!", C_WHITE, &m->sprite->pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!position_equals(&origPos, &m->sprite->pos) && rm->modifier->type == RMOD_TYPE_FIRE) {
|
||||||
|
Object *o = object_create_fire();
|
||||||
|
o->sprite->pos = origPos;
|
||||||
|
o->damage *= m->stats.lvl;
|
||||||
|
linkedlist_push(&map->objects, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
m->steps++;
|
m->steps++;
|
||||||
|
@ -576,6 +585,9 @@ monster_render(Monster *m, Camera *cam)
|
||||||
void
|
void
|
||||||
monster_render_top_layer(Monster *m, Camera *cam)
|
monster_render_top_layer(Monster *m, Camera *cam)
|
||||||
{
|
{
|
||||||
|
if (m->stats.hp <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (m->stateIndicator.displayCount != 0)
|
if (m->stateIndicator.displayCount != 0)
|
||||||
sprite_render(m->stateIndicator.sprite, cam);
|
sprite_render(m->stateIndicator.sprite, cam);
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ void
|
||||||
monster_update_pos(Monster*, Position);
|
monster_update_pos(Monster*, Position);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
monster_move(Monster*, RoomMatrix*);
|
monster_move(Monster*, RoomMatrix*, Map*);
|
||||||
|
|
||||||
void
|
void
|
||||||
monster_render(Monster*, Camera*);
|
monster_render(Monster*, Camera*);
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* 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 "object.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "mixer.h"
|
||||||
|
#include "random.h"
|
||||||
|
#include "texturecache.h"
|
||||||
|
|
||||||
|
Object *
|
||||||
|
object_create(void)
|
||||||
|
{
|
||||||
|
Object *o = ec_malloc(sizeof(Object));
|
||||||
|
o->sprite = sprite_create();
|
||||||
|
o->blocking = false;
|
||||||
|
o->damage = 0;
|
||||||
|
o->timeout = -1;
|
||||||
|
o->dead = false;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object *
|
||||||
|
object_create_fire()
|
||||||
|
{
|
||||||
|
Object *o = object_create();
|
||||||
|
Texture *t0 = texturecache_add("Objects/Effect0.png");
|
||||||
|
Texture *t1 = texturecache_add("Objects/Effect1.png");
|
||||||
|
sprite_set_texture(o->sprite, t0, 0);
|
||||||
|
sprite_set_texture(o->sprite, t1, 1);
|
||||||
|
o->sprite->dim = GAME_DIMENSION;
|
||||||
|
o->sprite->clip = CLIP16(16, 21*16);
|
||||||
|
o->damage = 3;
|
||||||
|
o->timeout = 5;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
object_render(Object *o, Camera *cam)
|
||||||
|
{
|
||||||
|
sprite_render(o->sprite, cam);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
object_step(Object *o)
|
||||||
|
{
|
||||||
|
if (o->timeout < 0)
|
||||||
|
return;
|
||||||
|
o->timeout--;
|
||||||
|
if (o->timeout <= 0)
|
||||||
|
o->dead = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
object_damage(Object *o, Player *p)
|
||||||
|
{
|
||||||
|
if (!o->damage)
|
||||||
|
return;
|
||||||
|
p->stats.hp -= o->damage;
|
||||||
|
player_hit(p, o->damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
object_destroy(Object *o)
|
||||||
|
{
|
||||||
|
sprite_destroy(o->sprite);
|
||||||
|
free(o);
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "camera.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "sprite.h"
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
|
typedef struct Object {
|
||||||
|
Sprite *sprite;
|
||||||
|
bool blocking;
|
||||||
|
Uint32 damage;
|
||||||
|
Sint32 timeout;
|
||||||
|
bool dead;
|
||||||
|
} Object;
|
||||||
|
|
||||||
|
Object *
|
||||||
|
object_create(void);
|
||||||
|
|
||||||
|
Object *
|
||||||
|
object_create_fire(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
object_render(Object*, Camera*);
|
||||||
|
|
||||||
|
void
|
||||||
|
object_damage(Object*, Player*);
|
||||||
|
|
||||||
|
void
|
||||||
|
object_step(Object*);
|
||||||
|
|
||||||
|
void
|
||||||
|
object_destroy(Object*);
|
|
@ -294,6 +294,49 @@ particle_engine_wind(Vector2d direction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_engine_heat()
|
||||||
|
{
|
||||||
|
unsigned int count = 5;
|
||||||
|
|
||||||
|
Position pos = { 0, 0 };
|
||||||
|
Dimension dim = { GAME_VIEW_WIDTH, GAME_VIEW_HEIGHT };
|
||||||
|
|
||||||
|
if (dim.width == 0 || dim.height == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < count; ++i) {
|
||||||
|
int x, y;
|
||||||
|
int w, h;
|
||||||
|
unsigned int lt;
|
||||||
|
Particle *p;
|
||||||
|
int yvel, xvel;
|
||||||
|
|
||||||
|
x = get_random(dim.width) + pos.x;
|
||||||
|
y = get_random(dim.height) + pos.y;
|
||||||
|
w = get_random(2) + 2;
|
||||||
|
h = get_random(2) + 2;
|
||||||
|
|
||||||
|
yvel = get_random(50) - 200;
|
||||||
|
xvel = get_random(100) * -get_random(1);
|
||||||
|
|
||||||
|
lt = get_random(500);
|
||||||
|
|
||||||
|
p = create_rect_particle();
|
||||||
|
p->particle.rect.pos = (Position) { x, y };
|
||||||
|
p->particle.rect.dim = (Dimension) { w, h };
|
||||||
|
p->velocity = (Vector2d) { (float) xvel, (float) yvel };
|
||||||
|
p->movetime = lt;
|
||||||
|
p->lifetime = lt;
|
||||||
|
if (get_random(1) == 0)
|
||||||
|
p->color = C_YELLOW;
|
||||||
|
else
|
||||||
|
p->color = C_RED;
|
||||||
|
p->fixed = true;
|
||||||
|
linkedlist_append(&engine->game_particles, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
move_particle(Particle *particle, float deltaTime)
|
move_particle(Particle *particle, float deltaTime)
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,6 +46,9 @@ particle_engine_sparkle(Position, Dimension, SDL_Color, bool global);
|
||||||
void
|
void
|
||||||
particle_engine_wind(Vector2d direction);
|
particle_engine_wind(Vector2d direction);
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_engine_heat(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
particle_engine_update(float deltatime);
|
particle_engine_update(float deltatime);
|
||||||
|
|
||||||
|
|
17
src/player.c
17
src/player.c
|
@ -194,6 +194,14 @@ has_collided(Player *player, RoomMatrix *matrix, Vector2d direction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (space->objects && !collided) {
|
||||||
|
LinkedList *objects = space->objects;
|
||||||
|
while (objects) {
|
||||||
|
object_damage(objects->data, player);
|
||||||
|
objects = objects->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (space->lethal && !collided) {
|
if (space->lethal && !collided) {
|
||||||
mixer_play_effect(FALL0 + get_random(2) - 1);
|
mixer_play_effect(FALL0 + get_random(2) - 1);
|
||||||
player->state = FALLING;
|
player->state = FALLING;
|
||||||
|
@ -294,6 +302,7 @@ handle_next_move(UpdateData *data)
|
||||||
static unsigned int step = 1;
|
static unsigned int step = 1;
|
||||||
|
|
||||||
Player *player = data->player;
|
Player *player = data->player;
|
||||||
|
Position originPos = player->sprite->pos;
|
||||||
|
|
||||||
// Don't move when projectiles are still moving
|
// Don't move when projectiles are still moving
|
||||||
if (linkedlist_size(player->projectiles) > 0)
|
if (linkedlist_size(player->projectiles) > 0)
|
||||||
|
@ -304,6 +313,14 @@ handle_next_move(UpdateData *data)
|
||||||
if (!vector2d_equals(nextDir, VECTOR2D_NODIR))
|
if (!vector2d_equals(nextDir, VECTOR2D_NODIR))
|
||||||
move(player, matrix, nextDir);
|
move(player, matrix, nextDir);
|
||||||
|
|
||||||
|
if (!position_equals(&originPos, &player->sprite->pos)
|
||||||
|
&& matrix->modifier->type == RMOD_TYPE_FIRE) {
|
||||||
|
Object *o = object_create_fire();
|
||||||
|
o->damage *= player->stats.lvl;
|
||||||
|
o->sprite->pos = originPos;
|
||||||
|
linkedlist_append(&data->map->objects, o);
|
||||||
|
}
|
||||||
|
|
||||||
map_room_modifier_player_effect(player, matrix, &nextDir, move);
|
map_room_modifier_player_effect(player, matrix, &nextDir, move);
|
||||||
|
|
||||||
if (!vector2d_equals(VECTOR2D_NODIR, nextDir)) {
|
if (!vector2d_equals(VECTOR2D_NODIR, nextDir)) {
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "update_data.h"
|
#include "update_data.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "trap.h"
|
#include "trap.h"
|
||||||
|
#include "object.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
roommatrix_reset(RoomMatrix *m)
|
roommatrix_reset(RoomMatrix *m)
|
||||||
|
@ -39,6 +40,7 @@ roommatrix_reset(RoomMatrix *m)
|
||||||
space = &m->spaces[i][j];
|
space = &m->spaces[i][j];
|
||||||
space->occupied = false;
|
space->occupied = false;
|
||||||
space->lethal = false;
|
space->lethal = false;
|
||||||
|
space->damaging = false;
|
||||||
space->lightsource = false;
|
space->lightsource = false;
|
||||||
space->light = 0;
|
space->light = 0;
|
||||||
space->monster = NULL;
|
space->monster = NULL;
|
||||||
|
@ -48,6 +50,8 @@ roommatrix_reset(RoomMatrix *m)
|
||||||
linkedlist_pop(&space->items);
|
linkedlist_pop(&space->items);
|
||||||
while (space->artifacts != NULL)
|
while (space->artifacts != NULL)
|
||||||
linkedlist_pop(&space->artifacts);
|
linkedlist_pop(&space->artifacts);
|
||||||
|
while (space->objects != NULL)
|
||||||
|
linkedlist_pop(&space->objects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m->roomPos = (Position) { 0, 0 };
|
m->roomPos = (Position) { 0, 0 };
|
||||||
|
@ -62,6 +66,7 @@ RoomMatrix* roommatrix_create(void)
|
||||||
for (j = 0; j < MAP_ROOM_HEIGHT; ++j) {
|
for (j = 0; j < MAP_ROOM_HEIGHT; ++j) {
|
||||||
m->spaces[i][j].items = linkedlist_create();;
|
m->spaces[i][j].items = linkedlist_create();;
|
||||||
m->spaces[i][j].artifacts = linkedlist_create();;
|
m->spaces[i][j].artifacts = linkedlist_create();;
|
||||||
|
m->spaces[i][j].objects = linkedlist_create();;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
roommatrix_reset(m);
|
roommatrix_reset(m);
|
||||||
|
@ -168,6 +173,21 @@ void roommatrix_populate_from_map(RoomMatrix *rm, Map *m)
|
||||||
position = position_to_matrix_coords(&a->sprite->pos);
|
position = position_to_matrix_coords(&a->sprite->pos);
|
||||||
linkedlist_push(&rm->spaces[position.x][position.y].artifacts, a);
|
linkedlist_push(&rm->spaces[position.x][position.y].artifacts, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LinkedList *objects = m->objects;
|
||||||
|
while (objects) {
|
||||||
|
Object *o = objects->data;
|
||||||
|
objects = objects->next;
|
||||||
|
|
||||||
|
if (!position_in_room(&o->sprite->pos, &m->currentRoom))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
position = position_to_matrix_coords(&o->sprite->pos);
|
||||||
|
RoomSpace *space = &rm->spaces[position.x][position.y];
|
||||||
|
linkedlist_push(&space->objects, o);
|
||||||
|
space->occupied = space->occupied || o->blocking;
|
||||||
|
space->damaging = o->damage > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -275,6 +295,8 @@ void roommatrix_destroy(RoomMatrix *m)
|
||||||
linkedlist_pop(&space->items);
|
linkedlist_pop(&space->items);
|
||||||
while (space->artifacts)
|
while (space->artifacts)
|
||||||
linkedlist_pop(&space->artifacts);
|
linkedlist_pop(&space->artifacts);
|
||||||
|
while (space->objects)
|
||||||
|
linkedlist_pop(&space->objects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,19 +33,22 @@ typedef struct Player Player;
|
||||||
typedef struct Item_t Item;
|
typedef struct Item_t Item;
|
||||||
typedef struct Node LinkedList;
|
typedef struct Node LinkedList;
|
||||||
typedef struct Trap Trap;
|
typedef struct Trap Trap;
|
||||||
|
typedef struct Object Object;
|
||||||
|
|
||||||
struct UpdateData;
|
struct UpdateData;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct RoomSpace {
|
||||||
bool occupied;
|
bool occupied;
|
||||||
bool lethal;
|
bool lethal;
|
||||||
bool lightsource;
|
bool lightsource;
|
||||||
|
bool damaging;
|
||||||
int light;
|
int light;
|
||||||
Monster *monster;
|
Monster *monster;
|
||||||
Player *player;
|
Player *player;
|
||||||
Trap *trap;
|
Trap *trap;
|
||||||
LinkedList *items;
|
LinkedList *items;
|
||||||
LinkedList *artifacts;
|
LinkedList *artifacts;
|
||||||
|
LinkedList *objects;
|
||||||
} RoomSpace;
|
} RoomSpace;
|
||||||
|
|
||||||
typedef struct RoomMatrix_t {
|
typedef struct RoomMatrix_t {
|
||||||
|
|
Loading…
Reference in New Issue