From 6007976d2313d150f2544f0cd59d9f4981dc0c05 Mon Sep 17 00:00:00 2001 From: Linus Probert Date: Sun, 17 Dec 2017 13:43:41 +0100 Subject: [PATCH] Roaming monsters. --- .vimrc | 4 +- CMakeLists.txt | 1 + TODO.txt | 10 +++-- bhack_raw.out | 59 +++++++++++++++++++++++++++++ data/monstergen.lua | 9 +++++ src/actiontext.c | 2 +- src/main.c | 11 ++++++ src/map.c | 23 ++++++++++-- src/map.h | 6 ++- src/monster.c | 91 ++++++++++++++++++++++++++++++++++++++++++++- src/monster.h | 2 + src/player.c | 66 ++++++++++++++++++++++++++------ src/player.h | 5 +++ src/position.c | 6 +++ src/position.h | 2 + src/random.c | 10 +++++ src/random.h | 7 ++++ src/roommatrix.c | 12 ++++-- src/stats.c | 8 ++-- src/stats.h | 1 + 20 files changed, 302 insertions(+), 33 deletions(-) create mode 100644 bhack_raw.out create mode 100644 src/random.c create mode 100644 src/random.h diff --git a/.vimrc b/.vimrc index b80e862..ed5989c 100644 --- a/.vimrc +++ b/.vimrc @@ -1,3 +1,3 @@ -nnoremap :Make -C build --no-print-directory -l -set makeprg=make\ -C\ build\ --no-print-directory\ -l +nnoremap :Make +au FileType c setl makeprg=ninja\ -C\ build let g:syntastic_c_include_dirs = [ 'linkedlist', 'hashtable' ] diff --git a/CMakeLists.txt b/CMakeLists.txt index 9de0c9c..80750a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ add_executable(breakhack src/monster src/stats src/actiontext + src/random ) target_link_libraries(breakhack diff --git a/TODO.txt b/TODO.txt index c884a07..d1b144d 100644 --- a/TODO.txt +++ b/TODO.txt @@ -6,10 +6,14 @@ x Add enemies (generated through lua) x Making some better generation and randomeness x Move "clip" from texture to sprite x Hitting enemies -- Nicer enemy hits (Text textures, healthbars?) -- Moving enemies +x Nicer enemy hits (Text textures, healthbars?) + - This could need some love later on. (Misses seem to be broken) (Add hits to stats) +x Moving enemies + x Stupid roaming enemies + - Smart agressive enemies + - Fleeing enemies - Lower levels -- XP +o XP - gui - Items - More gui diff --git a/bhack_raw.out b/bhack_raw.out new file mode 100644 index 0000000..3a28a6c --- /dev/null +++ b/bhack_raw.out @@ -0,0 +1,59 @@ +==32279== Memcheck, a memory error detector +==32279== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. +==32279== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info +==32279== Command: ./build/breakhack +==32279== Parent PID: 16002 +==32279== +==32279== Invalid write of size 1 +==32279== at 0x10E8B7: monster_move (monster.c:112) +==32279== by 0x10C634: map_move_monsters (map.c:122) +==32279== by 0x10AF7C: run (main.c:155) +==32279== by 0x10B0CF: main (main.c:195) +==32279== Address 0x104ae5b0 is 2,992 bytes inside an unallocated block of size 11,760 in arena "client" +==32279== +==32279== Invalid write of size 1 +==32279== at 0x10E9AB: monster_move (monster.c:127) +==32279== by 0x10C634: map_move_monsters (map.c:122) +==32279== by 0x10AF7C: run (main.c:155) +==32279== by 0x10B0CF: main (main.c:195) +==32279== Address 0x104ac1b0 is 240 bytes inside a block of size 704 free'd +==32279== at 0x4C2E14B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) +==32279== by 0x70D07B3: ??? (in /usr/lib/libfreetype.so.6.15.0) +==32279== by 0x70D0C99: ??? (in /usr/lib/libfreetype.so.6.15.0) +==32279== by 0x70D1378: ??? (in /usr/lib/libfreetype.so.6.15.0) +==32279== by 0x7080C4A: FT_Load_Glyph (in /usr/lib/libfreetype.so.6.15.0) +==32279== by 0x59E134D: ??? (in /usr/lib/libSDL2_ttf-2.0.so.0.14.0) +==32279== by 0x59E24A4: TTF_SizeUTF8 (in /usr/lib/libSDL2_ttf-2.0.so.0.14.0) +==32279== by 0x59E28A0: TTF_RenderUTF8_Solid (in /usr/lib/libSDL2_ttf-2.0.so.0.14.0) +==32279== by 0x59E2CB9: TTF_RenderText_Solid (in /usr/lib/libSDL2_ttf-2.0.so.0.14.0) +==32279== by 0x10B2CA: texture_load_from_text (texture.c:69) +==32279== by 0x10EC23: actiontext_set_text (actiontext.c:25) +==32279== by 0x10E4D8: monster_load_texts (monster.c:20) +==32279== Block was alloc'd at +==32279== at 0x4C2EF35: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) +==32279== by 0x7DD3D50: hb_set_create (in /usr/lib/libharfbuzz.so.0.10702.0) +==32279== by 0x70D04BE: ??? (in /usr/lib/libfreetype.so.6.15.0) +==32279== by 0x70D0C99: ??? (in /usr/lib/libfreetype.so.6.15.0) +==32279== by 0x70D1378: ??? (in /usr/lib/libfreetype.so.6.15.0) +==32279== by 0x7080C4A: FT_Load_Glyph (in /usr/lib/libfreetype.so.6.15.0) +==32279== by 0x59E134D: ??? (in /usr/lib/libSDL2_ttf-2.0.so.0.14.0) +==32279== by 0x59E24A4: TTF_SizeUTF8 (in /usr/lib/libSDL2_ttf-2.0.so.0.14.0) +==32279== by 0x59E28A0: TTF_RenderUTF8_Solid (in /usr/lib/libSDL2_ttf-2.0.so.0.14.0) +==32279== by 0x59E2CB9: TTF_RenderText_Solid (in /usr/lib/libSDL2_ttf-2.0.so.0.14.0) +==32279== by 0x10B2CA: texture_load_from_text (texture.c:69) +==32279== by 0x10EC23: actiontext_set_text (actiontext.c:25) +==32279== +==32279== +==32279== HEAP SUMMARY: +==32279== in use at exit: 23,660,148 bytes in 6,478 blocks +==32279== total heap usage: 145,650 allocs, 139,172 frees, 128,822,768 bytes allocated +==32279== +==32279== LEAK SUMMARY: +==32279== definitely lost: 0 bytes in 0 blocks +==32279== indirectly lost: 0 bytes in 0 blocks +==32279== possibly lost: 0 bytes in 0 blocks +==32279== still reachable: 0 bytes in 0 blocks +==32279== suppressed: 23,660,148 bytes in 6,478 blocks +==32279== +==32279== For counts of detected and suppressed errors, rerun with: -v +==32279== ERROR SUMMARY: 359 errors from 2 contexts (suppressed: 59281051 from 1900) diff --git a/data/monstergen.lua b/data/monstergen.lua index 74f8e07..ac17c68 100644 --- a/data/monstergen.lua +++ b/data/monstergen.lua @@ -83,6 +83,15 @@ local enemies = { { texturePaths.pest0, texturePaths.pest1, 16, 112 }, { texturePaths.pest0, texturePaths.pest1, 32, 112 }, { texturePaths.pest0, texturePaths.pest1, 48, 112 }, + + { texturePaths.undead0, texturePaths.undead1, 0, 32 }; + { texturePaths.undead0, texturePaths.undead1, 16, 32 }; + { texturePaths.undead0, texturePaths.undead1, 32, 32 }; + { texturePaths.undead0, texturePaths.undead1, 48, 32 }; + { texturePaths.undead0, texturePaths.undead1, 64, 32 }; + { texturePaths.undead0, texturePaths.undead1, 80, 32 }; + { texturePaths.undead0, texturePaths.undead1, 96, 32 }; + { texturePaths.undead0, texturePaths.undead1, 112, 32 }; } local function repack(data) diff --git a/src/actiontext.c b/src/actiontext.c index 5ed4655..e5210f4 100644 --- a/src/actiontext.c +++ b/src/actiontext.c @@ -35,7 +35,7 @@ actiontext_render(ActionText *t, Camera *cam) timer_start(t->timer); Position cameraPos = camera_to_camera_position(cam, &t->pos); - if (timer_get_ticks(t->timer) < 100) { + if (timer_get_ticks(t->timer) < 300) { texture_render(t->texture, &cameraPos, cam); } else { timer_stop(t->timer); diff --git a/src/main.c b/src/main.c index 87f29e5..d71b841 100644 --- a/src/main.c +++ b/src/main.c @@ -104,6 +104,7 @@ bool init() gCamera.renderer = gRenderer; gRoomMatrix = roommatrix_create(); } + return result; } @@ -150,6 +151,16 @@ void run() &gPlayer->sprite->pos); roommatrix_build_lightmap(gRoomMatrix); + if (gPlayer->steps == gPlayer->stats.speed) { + player_print(gPlayer); + gPlayer->steps = 0; + Position rp = + position_to_matrix_coords(&gPlayer->sprite->pos); + gRoomMatrix->spaces[rp.x][rp.y].occupied = true; + gRoomMatrix->spaces[rp.x][rp.y].player = gPlayer; + map_move_monsters(gMap, gRoomMatrix); + } + SDL_RenderClear(gRenderer); map_render(gMap, &gCamera); diff --git a/src/map.c b/src/map.c index 5f22657..f677544 100644 --- a/src/map.c +++ b/src/map.c @@ -110,6 +110,19 @@ map_add_monster(Map *map, Monster *m) linkedlist_append(&map->monsters, m); } +void +map_move_monsters(Map *map, RoomMatrix *rm) +{ + LinkedList *m = map->monsters; + while (m) { + Monster *monster = m->data; + m = m->next; + if (!position_in_room(&monster->sprite->pos, &map->currentRoom)) + continue; + monster_move(monster, rm); + } +} + int map_add_texture(Map *map, const char *path, SDL_Renderer *renderer) { Texture *t = texture_create(); @@ -156,7 +169,8 @@ void map_tile_render(Map *map, MapTile *tile, Position *pos, Camera *cam) void map_render(Map *map, Camera *cam) { - unsigned int i, j, monster_count; + unsigned int i, j; + LinkedList *monsterItem; Room *room; if (!timer_started(map->renderTimer)) { @@ -184,9 +198,10 @@ void map_render(Map *map, Camera *cam) } } - monster_count = linkedlist_size(map->monsters); - for (i = 0; i < monster_count; ++i) { - Monster *monster = linkedlist_get(&map->monsters, i); + monsterItem = map->monsters; + while (monsterItem) { + Monster *monster = monsterItem->data; + monsterItem = monsterItem->next; monster_render(monster, cam); } } diff --git a/src/map.h b/src/map.h index 14c80f5..2906c2e 100644 --- a/src/map.h +++ b/src/map.h @@ -48,10 +48,12 @@ void map_add_decoration(Map *map, Position *tile_pos, MapTile*); Texture* map_add_monster_texture(Map*, const char *path, SDL_Renderer*); -void map_clear_dead_monsters(Map*); - void map_add_monster(Map*, Monster*); +void map_move_monsters(Map*, RoomMatrix*); + +void map_clear_dead_monsters(Map*); + void map_render(Map*, Camera*); void map_set_current_room(Map*, Position*); diff --git a/src/monster.c b/src/monster.c index be4fe66..3bf99f8 100644 --- a/src/monster.c +++ b/src/monster.c @@ -1,7 +1,9 @@ +#include #include "monster.h" #include "util.h" #include "player.h" #include "monster.h" +#include "random.h" static void monster_load_texts(Monster *m, SDL_Renderer *renderer) @@ -27,7 +29,7 @@ monster_create(SDL_Renderer *renderer) Monster *m = ec_malloc(sizeof(Monster)); m->sprite = sprite_create(); m->sprite->clip = (SDL_Rect) { 0, 0, 16, 16 }; - m->stats = (Stats) { 11, 1, 0, 0, 1 }; + m->stats = (Stats) { 11, 1, 0, 0, 1, 1 }; monster_load_texts(m, renderer); @@ -45,6 +47,93 @@ monster_update_pos(Monster *m, Position pos) m->missText->pos = textPos; } +static bool +has_collided(Monster *monster, RoomMatrix *matrix) +{ + if (!position_in_room(&monster->sprite->pos, &matrix->roomPos)) + return true; + + Position roomPos = position_to_matrix_coords(&monster->sprite->pos); + RoomSpace *space = &matrix->spaces[roomPos.x][roomPos.y]; + return space->occupied; +} + +static bool +move_left(Monster *m, RoomMatrix *rm) +{ + m->sprite->pos.x -= TILE_DIMENSION; + if (has_collided(m, rm)) { + m->sprite->pos.x += TILE_DIMENSION; + return false; + } + return true; +} + +static bool +move_right(Monster *m, RoomMatrix *rm) +{ + m->sprite->pos.x += TILE_DIMENSION; + if (has_collided(m, rm)) { + m->sprite->pos.x -= TILE_DIMENSION; + return false; + } + return true; +} + +static bool +move_up(Monster *m, RoomMatrix *rm) +{ + m->sprite->pos.y -= TILE_DIMENSION; + if (has_collided(m, rm)) { + m->sprite->pos.y += TILE_DIMENSION; + return false; + } + return true; +} + +static bool +move_down(Monster *m, RoomMatrix *rm) +{ + m->sprite->pos.y += TILE_DIMENSION; + if (has_collided(m, rm)) { + m->sprite->pos.y -= TILE_DIMENSION; + return false; + } + return true; +} + +void +monster_move(Monster *m, RoomMatrix *rm) +{ + unsigned int i, maxMoveAttempts = 6; + Position monsterRoomPos; + + if (get_random(4) == 0) + return; + + monsterRoomPos = position_to_matrix_coords(&m->sprite->pos); + rm->spaces[monsterRoomPos.x][monsterRoomPos.y].occupied = false; + rm->spaces[monsterRoomPos.x][monsterRoomPos.y].monster = NULL; + + for (i = 0; i < maxMoveAttempts; ++i) { + int move = get_random(3); + if (move == 0 && move_left(m, rm)) + break; + else if (move == 1 && move_right(m, rm)) + break; + else if (move == 2 && move_up(m, rm)) + break; + else if (move == 3 && move_down(m, rm)) + break; + } + + monster_update_pos(m, m->sprite->pos); + + monsterRoomPos = position_to_matrix_coords(&m->sprite->pos); + rm->spaces[monsterRoomPos.x][monsterRoomPos.y].occupied = true; + rm->spaces[monsterRoomPos.x][monsterRoomPos.y].monster = m; +} + void monster_render(Monster *m, Camera *cam) { diff --git a/src/monster.h b/src/monster.h index ce72af7..25a1166 100644 --- a/src/monster.h +++ b/src/monster.h @@ -17,6 +17,8 @@ Monster* monster_create(SDL_Renderer*); void monster_update_pos(Monster*, Position); +void monster_move(Monster*, RoomMatrix*); + void monster_render(Monster*, Camera*); void monster_destroy(Monster*); diff --git a/src/player.c b/src/player.c index 5081aa3..0f761ff 100644 --- a/src/player.c +++ b/src/player.c @@ -3,11 +3,11 @@ #include "monster.h" static Stats classStats[] = { - (Stats) { 11, 5, 7, 2, 1 }, /* ENGINEER */ - (Stats) { 11, 5, 7, 2, 1 }, /* MAGE */ - (Stats) { 11, 5, 7, 2, 1 }, /* PALADIN */ - (Stats) { 11, 5, 7, 2, 2 }, /* ROGUE */ - (Stats) { 11, 5, 7, 2, 1 }, /* WARRIOR */ + (Stats) { 11, 5, 7, 2, 1, 1 }, /* ENGINEER */ + (Stats) { 11, 5, 7, 2, 1, 1 }, /* MAGE */ + (Stats) { 11, 5, 7, 2, 1, 1 }, /* PALADIN */ + (Stats) { 11, 5, 7, 2, 2, 1 }, /* ROGUE */ + (Stats) { 11, 5, 7, 2, 1, 1 }, /* WARRIOR */ }; static bool @@ -27,22 +27,42 @@ has_collided(Player *player, RoomMatrix *matrix) if (space->monster != NULL) { unsigned int hit = stats_fight(&player->stats, &space->monster->stats); - if (hit > 0) + if (hit > 0) { space->monster->hitText->active = true; - else + space->monster->missText->active = false; + } else { + // TODO(Linus): The misses seem to be missing space->monster->missText->active = true; + space->monster->hitText->active = false; + } + + if (space->monster->stats.hp <= 0) { + // TODO(Linus): This needs some love later on. + player->xp += 10; + } } return collided; } +static void +player_step(Player *p, RoomMatrix* m) +{ + Position pos = position_to_matrix_coords(&p->sprite->pos); + m->spaces[pos.x][pos.y].occupied = true; + p->total_steps++; + p->steps++; +} + static void move_left(Player *player, RoomMatrix *matrix) { player->sprite->clip.y = 16; player->sprite->pos.x -= TILE_DIMENSION; - if (has_collided(player, matrix)) + if (has_collided(player, matrix)) { player->sprite->pos.x += TILE_DIMENSION; + } + player_step(player, matrix); } static @@ -50,8 +70,10 @@ void move_right(Player *player, RoomMatrix *matrix) { player->sprite->clip.y = 32; player->sprite->pos.x += TILE_DIMENSION; - if (has_collided(player, matrix)) + if (has_collided(player, matrix)) { player->sprite->pos.x -= TILE_DIMENSION; + } + player_step(player, matrix); } static @@ -59,8 +81,10 @@ void move_up(Player *player, RoomMatrix *matrix) { player->sprite->clip.y = 48; player->sprite->pos.y -= TILE_DIMENSION; - if (has_collided(player, matrix)) + if (has_collided(player, matrix)) { player->sprite->pos.y += TILE_DIMENSION; + } + player_step(player, matrix); } static @@ -68,8 +92,10 @@ void move_down(Player *player, RoomMatrix *matrix) { player->sprite->clip.y = 0; player->sprite->pos.y += TILE_DIMENSION; - if (has_collided(player, matrix)) + if (has_collided(player, matrix)) { player->sprite->pos.y -= TILE_DIMENSION; + } + player_step(player, matrix); } static @@ -109,6 +135,9 @@ player_create(class_t class, SDL_Renderer *renderer) { Player *player = malloc(sizeof(Player)); player->sprite = sprite_create(); + player->total_steps = 0; + player->steps = 0; + player->xp = 0; char asset[100]; switch (class) { @@ -144,6 +173,21 @@ player_create(class_t class, SDL_Renderer *renderer) return player; } +void +player_print(Player *p) +{ + Position roomPos = position_to_matrix_coords(&p->sprite->pos); + Position pos = p->sprite->pos; + + printf("\n"); + printf("--------=== <[ Player Stats ]> ===--------\n"); + printf("HP: %u\n", p->stats.hp); + printf("Level: %u XP: %u\n", p->stats.lvl, p->xp); + printf("Pos: %dx%d RoomPos: %dx%d\n", pos.x, pos.y, roomPos.x, roomPos.y); + printf("Steps: %u\n", p->total_steps); + printf("------------------------------------------\n"); +} + void player_destroy(Player *player) { diff --git a/src/player.h b/src/player.h index 066a434..6fed0b2 100644 --- a/src/player.h +++ b/src/player.h @@ -11,11 +11,16 @@ typedef enum PlayerClass class_t; typedef struct Player_t { Sprite *sprite; Stats stats; + unsigned int xp; + unsigned int total_steps; + unsigned int steps; void (*handle_event)(struct Player_t*, RoomMatrix*, SDL_Event*); } Player; Player* player_create(class_t, SDL_Renderer*); +void player_print(Player*); + void player_destroy(Player*); #endif // PLAYER_H_ diff --git a/src/position.c b/src/position.c index d5ee729..554ba8c 100644 --- a/src/position.c +++ b/src/position.c @@ -29,6 +29,12 @@ Position position_to_room_coords(Position *src) return pos; } +bool +position_equals(const Position *p1, const Position *p2) +{ + return p1->x == p2->x && p1->y == p2->y; +} + bool position_in_room(Position *pos, Position *roomPos) { unsigned int room_px_width, room_px_height, room_x_px, room_y_px; diff --git a/src/position.h b/src/position.h index 2aa1468..bfd52f8 100644 --- a/src/position.h +++ b/src/position.h @@ -14,4 +14,6 @@ Position position_to_room_coords(Position*); bool position_in_room(Position *pos, Position *roomPos); +bool position_equals(const Position*, const Position*); + #endif // POSITION_H_ diff --git a/src/random.c b/src/random.c new file mode 100644 index 0000000..08c5569 --- /dev/null +++ b/src/random.c @@ -0,0 +1,10 @@ +#include +#include +#include + +unsigned int +get_random(unsigned int max) +{ + srand(time(NULL)); + return rand() % (max + 1); +} diff --git a/src/random.h b/src/random.h new file mode 100644 index 0000000..a69ce47 --- /dev/null +++ b/src/random.h @@ -0,0 +1,7 @@ +#ifndef RANDOM_H_ +#define RANDOM_H_ + +unsigned int +get_random(unsigned int max); + +#endif // RANDOM_H_ diff --git a/src/roommatrix.c b/src/roommatrix.c index d01622d..c5b222c 100644 --- a/src/roommatrix.c +++ b/src/roommatrix.c @@ -12,10 +12,11 @@ RoomMatrix* roommatrix_create() void roommatrix_populate_from_map(RoomMatrix *rm, Map *m) { - int i, j, monster_count; + int i, j; Position monster_matrix_pos; Room *r; Monster *monster; + LinkedList *monsterItem; roommatrix_reset(rm); @@ -41,11 +42,14 @@ void roommatrix_populate_from_map(RoomMatrix *rm, Map *m) } } - monster_count = linkedlist_size(m->monsters); - for (i = 0; i < monster_count; ++i) { - monster = linkedlist_get(&m->monsters, i); + monsterItem = m->monsters; + while (monsterItem) { + monster = monsterItem->data; + monsterItem = monsterItem->next; + if (!position_in_room(&monster->sprite->pos, &m->currentRoom)) continue; + monster_matrix_pos = position_to_matrix_coords(&monster->sprite->pos); diff --git a/src/stats.c b/src/stats.c index e36c92f..3f02574 100644 --- a/src/stats.c +++ b/src/stats.c @@ -1,10 +1,9 @@ #include -#include -#include #include #include #include "stats.h" +#include "random.h" unsigned int stats_fight(Stats *attacker, Stats *defender) @@ -12,12 +11,11 @@ stats_fight(Stats *attacker, Stats *defender) unsigned int atkRoll, defRoll, dmgRoll; bool critical = false; - srand(time(NULL)); - atkRoll = (rand() % 20); + atkRoll = get_random(19) + 1; if (atkRoll == 20) critical = true; atkRoll += attacker->atk; - defRoll = (rand() % 20) + defender->def; + defRoll = (get_random(19) + 1) + defender->def; dmgRoll = 0; //printf("Attacking: %u, Defending: %u\n", atkRoll, defRoll); diff --git a/src/stats.h b/src/stats.h index ccac3c3..d846721 100644 --- a/src/stats.h +++ b/src/stats.h @@ -7,6 +7,7 @@ typedef struct { int atk; /* Attack rating */ int def; /* Defence rating */ int speed; /* Speed */ + int lvl; /* Level */ } Stats; unsigned int