From 9b332a09a9d4b7f4edef23726afa7a472404c2a8 Mon Sep 17 00:00:00 2001 From: Sara Date: Thu, 5 Jun 2025 22:44:46 +0200 Subject: [PATCH] feat: world generation and initial work for enemy spawning --- resources/critte.png | Bin 0 -> 216 bytes resources/player.png | Bin 0 -> 296 bytes resources/wall.png | Bin 386 -> 383 bytes resources/wizard.png | Bin 1392 -> 380 bytes src/core/character.h | 6 +- src/core/renderer.cpp | 9 ++- src/core/renderer.h | 3 +- src/core/roguedefs.h | 14 +++-- src/core/world.cpp | 140 ++++++++++++++++++++++++++++-------------- src/core/world.h | 14 +++-- src/enemies.cpp | 48 +++++++++++++++ src/enemies.h | 13 ++++ src/main.cpp | 37 +++++++---- 13 files changed, 211 insertions(+), 73 deletions(-) create mode 100644 resources/critte.png create mode 100644 resources/player.png create mode 100644 src/enemies.cpp create mode 100644 src/enemies.h diff --git a/resources/critte.png b/resources/critte.png new file mode 100644 index 0000000000000000000000000000000000000000..ab1a661380c1de5c81b7f1ca210621f438bef405 GIT binary patch literal 216 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!I0Jk_T!HkDA3rv1*s%KC78f9g zxg^Lh`2YX^zfL?l1LRhFx;TbJw7#9Zo3BAZfaT`z|NUVF%I#s>LsYC;FP&+bzE(21 z$8b5r17po!f{m#`dbP0l+XkK%IHsa literal 0 HcmV?d00001 diff --git a/resources/player.png b/resources/player.png new file mode 100644 index 0000000000000000000000000000000000000000..408275fa94ed75e71d7dd64f94ac5d870ddca04f GIT binary patch literal 296 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!I0Jk_T!HkDA3rv1*s%KC78f9g zxg^Lh`2YX^zfL?l1LU6eba4!cXni})TCBlr%(CG4#yWIPdN&TM{qNN0grgenKiis=rFc3Yh_4g_zpf0+`^7|S!y zu|$O_f;;0$0P}*)e`A=eCg@c+%4h7EJa=K?x^M=kvd?E7SrtMZOahsuKBz0qul&<1 qy4{%h$z3scir(0G3_WZ=nZ{b%>2!K$qUe!+flMRAnmM6((0)hjOB!5XsL_t(oh0Rw%4#OY}a}lrh1M<;*WQT4okkBT;)LClPg=KHn}gsI`QR(SkMTRIv~2~pm+rrNX{$+-Zag~>03xyzOh9@Bo}fNH za}oSEfp>2PBjAw=HbI+i7wvg){NrsB5CH82-yx?dtj3y`$bYAax?P8$+EXpsxUfRo zXwk38#F6u$8^K)$HQ-_~4b5di1aoT`i-5)|r-6m9;FU9tF9GVxWT?qda1+LjoI5LA z6wh3H@v2+FTh&H2VrXN>#WYvi&Ow(~CW%hzAH)>YLWS-P#e>V@>gnCj1J9g(mJ# z3-}W{8i8gu2_na23i>PW1PDkf7n7Cx*Yuxn$0A;f?G1r>Ng2g!VF~~M002ovPDHLk FV1fgNro8|F diff --git a/resources/wizard.png b/resources/wizard.png index 4083189ae342840992ab0e0cc44d24663bdbe9d1..75b923aa9e05fd21c0e9ccf71725228686e9ca6b 100644 GIT binary patch delta 354 zcmV-o0iFKv3j6|)BYyx1P)t-s0002^`1r7}u&d6rL;wH)19VbOQ~&?}`pDwU0003W zNklkh*p2!#vp|Iq8?BD%Hqz|v*O_|=%6Pi~6a_O~01s`@IRPWS+zNFe?) zfcVz|yS_r$OV|K3)N)Z+|GRy#nJmiMDd4Fg9>wm3%2)cRiGLrBz3NN(bKH7Bp35!D z(fbg?Qr;2KGy#{?6YH|$ht9n85hq+I0b1qa0;-?WhXJS#@D}zJ956IN7GQ}4J3`Mz z@F3xU11JNKvl#Ax3_ve~MnF@*9YFm?0s&kEkO8O!$T=_q7}vk|0MXn1Y;8~g$XUol zFasdH%_5BJplB%mK!S8$XY^N@8eP0Agd?uBNSlUdlWc;Jc*e+$~9zq zEhePz5de>qu)BE>^iTxz8!yv|!Ik9m=5P1e1GbR_h)$*;TL1t607*qoM6N<$g5+JO AKmY&$ literal 1392 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+yeRz|0Wf6XFWwGBPqUF)=YSGqbR; zu(GnUv9YnUvvY88aB^~TadB~TbMx@<@bdEV@$vEV^9u+F2nq@c2?+@c3yX+|h>D7e ziHV7ei%UpINJ>gdNl8gdOUuZ}$jZvf$;rvf%PS}-C@Lx{DJdx{E32resH&=}si~=} zt7~XzXliO|X=!O|YwPIf=<4d~>FMd~>l+vt7#bQH85tQH8=IJzn3|fJnVFfJn_E~| zSXx?ISy@?ITie*!*xK6K+1c6K+dDWoI668yIXO8yJG;2JxVpN!xw*N!yL)(eczSwz zd3kwzd;9qK`1<<#`T6<#`v(LB1O^5M1qB5M2Zw}&gocKOg@uKOhet$2L`FtNMMXtN zN5{m(#Ky+P#l^+P$0sBtBqk;%B_$;%C#R&Oq^72(rKP2(r)OkjWM*b&Wo2b&XXoVP zlq)=NA+d6c!d16%`d17nhWjl$Ms3m6es3mseC&R9042RaI42SJ%|k)YjJ4 z)z#J4*EcjYG&VLiH8nLiH@CF3w6?akwY9akw|8`Obar-jb#--jclY%4^!E1l_4W1l z_fMEGVdBJzlO|1?JbChzDO09SojPsWwCU5Q&zLb|=FFM1X3d&Cd-j|;bLP&SJ8#~+ z`Sa&5Sg>H>!i9?#En2*I@scG=mM&eoY}vBq%a^ZMv0~-Qm8({*TD^Mpnl)?Iu3fus z-MaPb*KgRcVdKV)n>KCQym|AMEnBv3-MVetw(Z-u@7S?p=gytGcJ11|d-t9_d-m?# zyKmpV{rmSHIB?+L!Gnhm9XfpY@R1`&jvhUF?AWp6$B&;lapL63lc!FdI(_=|nKNh3 zo;`c++`04T&tJH3;o`-Mmo8npeEIT~D_5>wy?X81wd>cf-?(w(=FOY8Zr!?l`}UnX zckbT3d+*-8`}glZc<|ui!-tO^J$n53@slS{o<4p0?Af#D&!4||@#5vnm#<#Edj0zK zn>TOXzJ2@d-Mjbi-+%b<;p4}TpFVy1{Q2{jFJHcX{rc_Ox9{J-|M>Ca=g*(Ne*OCW z`}dzefBydc`|sbs|Ns9#+7Md{%mNH0L4LtN?uZ6;Utg>MhK0PRi(^Pc>)UCbe1{cy zT#Nr-{!tNUc9glzO!5A@pwLy}f~V>$Shl^*HV<{44*hU>rGRYw&^K!zNvKxu>rG5-4mhReg2(r{_DqHrPy$p0fD6V%yR^ z%8N3Y^j4~0OFhm%xALX(gi!V^r$WCJ|1w~>&Uo+8z9!~2wG&J_6BFED#IW!S@mVw& zGt4|%z?Q;LC1Juei|G}^J9QzB1xgLP2UH!-H3~ZH__vq6}Dp1G)3WqJPlvU z#4~wzdMeF*{`vJ6h70ev-dUQ|yGHfM*E(A->6EW;YFn6cs{5JPH>evzopr0IPi% AQvd(} diff --git a/src/core/character.h b/src/core/character.h index ef3b955..e60c7db 100644 --- a/src/core/character.h +++ b/src/core/character.h @@ -26,17 +26,19 @@ struct CharacterData { }; struct Character { + Character() = default; Character(Tile location, CharacterLogic *logic, CharacterData stats); void act(); void draw(); bool deal_damage(int damage); - CharacterData const data; - std::shared_ptr logic{nullptr}; + CharacterData data{}; int health{1}; Tile location{0, 0}; World *world{nullptr}; +private: + std::shared_ptr logic{nullptr}; }; struct NullCharacterLogic : public CharacterLogic { diff --git a/src/core/renderer.cpp b/src/core/renderer.cpp index d8c800d..e8a92f8 100644 --- a/src/core/renderer.cpp +++ b/src/core/renderer.cpp @@ -77,14 +77,15 @@ void Render::provide_render_data(RenderData &data) { Render::data = &data; } -void Render::clear(Tile camera_center) { +void Render::clear(Tile camera_center, unsigned fov) { assert_render_initialized(); + Render::camera_width = fov; SDL_SetRenderDrawColor(Render::data->renderer, 0u, 0u, 0u, 255u); SDL_RenderClear(Render::data->renderer); int width, height; SDL_GetWindowSize(Render::data->window, &width, &height); - Render::tile_screen_width = int(width / camera_width); + Render::tile_screen_width = int(width / Render::camera_width); Render::half_tile_screen_width = Render::tile_screen_width >> 1; Render::camera_center = camera_center; @@ -94,6 +95,10 @@ void Render::clear(Tile camera_center) { void Render::draw(Tile world_space_tile, Sprite sprite) { assert_render_initialized(); + if(abs(world_space_tile.x - Render::camera_center.x) > Render::camera_width / 2 + || abs(world_space_tile.y - Render::camera_center.y) > Render::camera_width / 2) { + return; + } SDL_Rect const rect{ .x = (world_space_tile.x * Render::tile_screen_width) - Render::half_tile_screen_width + Render::camera_offset.x, .y = (world_space_tile.y * Render::tile_screen_width) - Render::half_tile_screen_width + Render::camera_offset.y, diff --git a/src/core/renderer.h b/src/core/renderer.h index e2e287b..0c7a1e8 100644 --- a/src/core/renderer.h +++ b/src/core/renderer.h @@ -29,7 +29,7 @@ private: public: static void provide_render_data(RenderData &data); - static void clear(Tile camera_center); + static void clear(Tile camera_center, unsigned fov = 10); static void draw(Tile world_space_tile, Sprite sprite); static void present(); private: @@ -51,6 +51,7 @@ public: RenderDataSetup &with_sprite(std::filesystem::path sprite_path); RenderData build(); private: + unsigned fov{10}; std::optional resource_base_path; SDL_Window *window{nullptr}; SDL_Renderer *renderer{nullptr}; diff --git a/src/core/roguedefs.h b/src/core/roguedefs.h index 257798a..336df9e 100644 --- a/src/core/roguedefs.h +++ b/src/core/roguedefs.h @@ -3,12 +3,14 @@ #include "SDL2/SDL_rect.h" -enum Directions : unsigned short { - NORTH = 0x1, - EAST = 0x2, - SOUTH = 0x4, - WEST = 0x8, -}; + +typedef unsigned short Directions; +#define NORTH 0x1u +#define EAST (0x1u << 1) +#define SOUTH (0x1u << 2) +#define WEST (0x1u << 3) + +#define WRAP(M_x, M_min, M_max) (((M_x - M_min) % (M_max - M_min)) + M_min) #define casel(M_switch, M_case)\ case M_case:\ diff --git a/src/core/world.cpp b/src/core/world.cpp index c9e598f..0d26d46 100644 --- a/src/core/world.cpp +++ b/src/core/world.cpp @@ -3,6 +3,7 @@ #include "core/renderer.h" #include "core/roguedefs.h" #include +#include #include #include #include @@ -30,10 +31,10 @@ bool Room::tile_is_wall(Tile local_tile) const { || local_tile.y >= this->rect.y + this->rect.h-1}; int chunk_size2 = chunk_size/2; bool const is_outside_hallways{ - ((this->hallway_paths & Directions::NORTH) == 0 || local_tile.x != chunk_size / 2 || local_tile.y > chunk_size2) - && ((this->hallway_paths & Directions::SOUTH) == 0 || local_tile.x != chunk_size / 2 || local_tile.y < chunk_size2) - && ((this->hallway_paths & Directions::WEST) == 0 || local_tile.y != chunk_size / 2 || local_tile.x < chunk_size2) - && ((this->hallway_paths & Directions::EAST) == 0 || local_tile.y != chunk_size / 2 || local_tile.x > chunk_size2) + ((this->hallway_paths & NORTH) == 0 || local_tile.x != chunk_size / 2 || local_tile.y > chunk_size2) + && ((this->hallway_paths & SOUTH) == 0 || local_tile.x != chunk_size / 2 || local_tile.y < chunk_size2) + && ((this->hallway_paths & WEST) == 0 || local_tile.y != chunk_size / 2 || local_tile.x > chunk_size2) + && ((this->hallway_paths & EAST) == 0 || local_tile.y != chunk_size / 2 || local_tile.x < chunk_size2) }; return is_outside_room && is_outside_hallways; } @@ -47,13 +48,14 @@ World::World() } {} void World::act() { + player.act(); for(Character &character : this->characters) { character.act(); } } void World::render() { - Render::clear(this->player->location); + Render::clear(this->player.location, 15); for(size_t i{0}; i < this->rooms.size(); ++i) { this->rooms[i].draw({ .x = int(i % this->shear * this->chunk_size), @@ -63,20 +65,33 @@ void World::render() { for(Character &character : this->characters) { character.draw(); } + player.draw(); } Room &World::get_room(Chunk chunk) { return rooms[chunk.x + chunk.y * this->shear]; } +Character *World::get_player() { + return &this->player; +} + +Chunk World::get_chunk(Tile tile) { + return {tile.x / this->chunk_size, tile.y / this->chunk_size}; +} + TileData World::query_tile(Tile tile) { Room &room{this->get_room({tile.x / this->chunk_size, tile.y / this->chunk_size})}; TileData out{ .character = nullptr, .is_wall = room.tile_is_wall({tile.x % this->chunk_size, tile.y % this->chunk_size}) }; + if(player.location == tile) { + out.character = &player; + return out; + } for(Character &character : this->characters) { - if(character.location == tile) { + if(character.location == tile && character.health > 0) { out.character = &character; return out; } @@ -118,6 +133,16 @@ WorldGenerator &WorldGenerator::with_player(Character character) { return *this; } +WorldGenerator &WorldGenerator::with_enemy(std::function spawner, int inv_frequency) { + this->enemy_spawners.push_back({spawner, inv_frequency}); + return *this; +} + +WorldGenerator &WorldGenerator::with_connecting_chance(unsigned num) { + this->connecting_chance = num; + return *this; +} + std::unique_ptr WorldGenerator::generate() { assert(this->chunk_side_length > 0 && "Chunk size is required to generate world"); assert(this->min_room_size > 0 && "Room size is required to generate world"); @@ -126,28 +151,12 @@ std::unique_ptr WorldGenerator::generate() { assert(this->player.has_value() && "World cannot be generated without a player"); std::unique_ptr world{new World()}; - Chunk start_room{this->select_start()}; + Chunk start_room{this->world_side_length / 2, this->world_side_length / 2}; this->setup_player(world, start_room); + this->generate_world(world, start_room); return world; } -Chunk WorldGenerator::select_start() const { - Chunk start{0, 0}; - switch(std::rand() % 4) { - case 0: - start.y = this->world_side_length - 1; - case 1: - start.x = std::rand() % this->world_side_length; - break; - case 2: - start.x = this->world_side_length - 1; - case 3: - start.y = std::rand() % this->world_side_length; - break; - } - return start; -} - void WorldGenerator::generate_world(std::unique_ptr &world, Chunk start) { world->chunk_size = this->chunk_side_length; world->shear = this->world_side_length; @@ -157,48 +166,85 @@ void WorldGenerator::generate_world(std::unique_ptr &world, Chunk start) .hallway_paths = Directions(0x0), .chunk_size = this->chunk_side_length, .rect = { - (this->chunk_side_length - this->max_room_size) / 2, - (this->chunk_side_length - this->max_room_size) / 2, - this->max_room_size, - this->max_room_size + 0, + 0, + this->chunk_side_length, + this->chunk_side_length } }; } + world->get_room(start).rect = SDL_Rect { + .x = this->chunk_side_length/2-2, + .y = this->chunk_side_length/2-2, + .w = 5, + .h = 5 + }; world->get_room(start).initialized = true; this->generate_room(world, start); } -void WorldGenerator::generate_room(std::unique_ptr &world, Chunk last) { - static const Chunk options[]{ +void WorldGenerator::generate_room(std::unique_ptr &world, Chunk const &last) { + Room &last_room{world->get_room(last)}; + last_room.initialized = true; + // generate a room that encloses center tile of this chunk + last_room.rect.w = WRAP(std::rand(), this->min_room_size, this->max_room_size); + last_room.rect.x = WRAP(std::rand(), + std::max(this->chunk_side_length/2 - last_room.rect.w + 2, 0), + 1 + std::min(this->chunk_side_length - last_room.rect.w - 1, this->chunk_side_length/2)); + last_room.rect.h = WRAP(std::rand(), this->min_room_size, this->max_room_size); + last_room.rect.y = WRAP(std::rand(), + std::max(this->chunk_side_length/2 - last_room.rect.h + 2, 0), + 1 + std::min(this->chunk_side_length - last_room.rect.h - 1, this->chunk_side_length/2)); + const Chunk options[]{ {last.x + 1, last.y}, {last.x - 1, last.y}, {last.x, last.y + 1}, {last.x, last.y - 1} }; - static const Directions directions[]{ - EAST, WEST, SOUTH, NORTH - }; + this->add_enemies(world, last, last_room); + static const Directions directions[]{EAST, WEST, SOUTH, NORTH}; + static const Directions inv_directions[] {WEST, EAST, NORTH, SOUTH}; + int const rand_offset{std::rand() % 4}; for(size_t i{0}; i < 4; ++i) { - Chunk next{options[i]}; - Room &option{world->get_room(next)}; - if(options[i].x < 0 || options[i].x >= this->world_side_length - || options[i].y < 0 || options[i].y >= this->world_side_length) { - continue; - } else if(option.initialized) { + size_t const true_offset{(i + rand_offset) % 4}; + Chunk const &next{options[true_offset]}; + if(next.x < 0 || next.x >= this->world_side_length + || next.y < 0 || next.y >= this->world_side_length) { continue; } - // register hallway with the last chunk - option.hallway_paths = Directions(option.hallway_paths | directions[i]); - // generate random rect that encloses center of chunk - // add hallway to the new chunk + Room &option{world->get_room(next)}; + if(this->connecting_chance > 0 && !option.initialized || WRAP(std::rand(), 0, this->connecting_chance) == 0) { + // register hallway with the last chunk + last_room.hallway_paths |= directions[true_offset]; + // add returning hallway from the new chunk + option.hallway_paths |= inv_directions[true_offset]; + } + if(option.initialized) { + continue; + } + // generate surrounding rooms + this->generate_room(world, next); + } +} + +void WorldGenerator::add_enemies(std::unique_ptr &world, Chunk const &chunk, Room &room) { + for(std::pair, int> const &pair : this->enemy_spawners) { + if(WRAP(std::rand(), 0, pair.second) == 0) { + Tile offset{ + WRAP(std::rand(), 1, room.rect.w - 2) + (chunk.x * this->chunk_side_length), + WRAP(std::rand(), 1, room.rect.h - 2) + (chunk.y * this->chunk_side_length) + }; + Character character{pair.first(offset)}; + character.world = world.get(); + world->characters.push_back(character); + } } } void WorldGenerator::setup_player(std::unique_ptr &world, Chunk spawn_chunk) { - world->characters.push_back(player.value()); - world->player = &world->characters[0]; - world->player->world = world.get(); - world->player->location = { + world->player = this->player.value(); + world->player.world = world.get(); + world->player.location = { (spawn_chunk.x * this->chunk_side_length) + (this->chunk_side_length / 2), (spawn_chunk.y * this->chunk_side_length) + (this->chunk_side_length / 2), }; diff --git a/src/core/world.h b/src/core/world.h index 1245131..a213722 100644 --- a/src/core/world.h +++ b/src/core/world.h @@ -2,6 +2,7 @@ #define ROGUE_WORLD_H #include +#include #include #include #include "character.h" @@ -34,16 +35,17 @@ struct World { void act(); void render(); Room &get_room(Chunk chunk); + Character *get_player(); + Chunk get_chunk(Tile tile); TileData query_tile(Tile tile); void on_input(bool); private: int chunk_size{1}; unsigned shear{0}; - Character *player{nullptr}; + Character player{}; std::vector rooms{}; std::vector characters{}; KeyEventHandler direction_pressed; -private: }; class WorldGenerator { @@ -53,16 +55,20 @@ public: WorldGenerator &with_world_size(unsigned side_length); WorldGenerator &with_room_size(unsigned min_side_length, unsigned max_side_length); WorldGenerator &with_player(Character character); + WorldGenerator &with_enemy(std::function spawner, int inv_frequency); + WorldGenerator &with_connecting_chance(unsigned num); std::unique_ptr generate(); private: - Chunk select_start() const; void generate_world(std::unique_ptr &world, Chunk start); - void generate_room(std::unique_ptr &world, Chunk last); + void generate_room(std::unique_ptr &world, Chunk const &last); + void add_enemies(std::unique_ptr &world, Chunk const &chunk, Room &room); void setup_player(std::unique_ptr &world, Chunk spawn_chunk); private: std::optional player; + std::vector, int>> enemy_spawners{}; int chunk_side_length{0}, world_side_length{0}; int max_room_size{0}, min_room_size{0}; + unsigned connecting_chance{1}; }; } diff --git a/src/enemies.cpp b/src/enemies.cpp new file mode 100644 index 0000000..1339e4e --- /dev/null +++ b/src/enemies.cpp @@ -0,0 +1,48 @@ +#include "enemies.h" +#include "core/roguedefs.h" +#include "core/world.h" +#include + +namespace rogue { +Tile CritteLogic::move() { + Tile location{this->character->location}; + Character *player{this->character->world->get_player()}; + if(this->is_aware_of_player) { + // cache query_tile call for repeated use + std::function query_tile{std::bind(&World::query_tile, this->character->world, std::placeholders::_1)}; + Tile difference{ + player->location.x - location.x, + player->location.y - location.y + }; + Tile abs{std::abs(difference.x), std::abs(difference.y)}; + Tile direction{ + difference.x == 0 ? 0 : difference.x / std::abs(difference.x), + difference.y == 0 ? 0 : difference.y / std::abs(difference.y) + }; + Tile x_motion{location.x + direction.x, location.y}; + Tile y_motion{location.x, location.y + direction.y}; + if(abs.x > abs.y) { + if(!query_tile(x_motion).is_wall) + return x_motion; + else if(!query_tile(y_motion).is_wall) { + return y_motion; + } + } else { + if(!query_tile(y_motion).is_wall) { + return y_motion; + } else if(!query_tile(x_motion).is_wall) { + return x_motion; + } + } + } else { + // cache get_chunk call for easier reading + std::function get_chunk{std::bind(&World::get_chunk, this->character->world, std::placeholders::_1)}; + this->is_aware_of_player |= get_chunk(player->location) != get_chunk(location); + } + // fallback return value, for if there is no desirable tile to move to + return { + .x = location.x, + .y = location.y + }; +} +} diff --git a/src/enemies.h b/src/enemies.h new file mode 100644 index 0000000..7e97d96 --- /dev/null +++ b/src/enemies.h @@ -0,0 +1,13 @@ +#ifndef ENEMIES_H +#define ENEMIES_H + +#include "core/character.h" + +namespace rogue { +class CritteLogic : public CharacterLogic { + virtual Tile move() override; + bool is_aware_of_player{false}; +}; +} + +#endif // !ENEMIES_H diff --git a/src/main.cpp b/src/main.cpp index dd5a620..c6137aa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,23 +4,36 @@ #include "core/input.h" #include "core/renderer.h" #include "core/world.h" +#include "enemies.h" #include "player_logic.h" using namespace rogue; +CharacterData const player_data{ + .health = 20, + .damage = 2, + .sprite = 3 +}; + +CharacterData const critte_data{ + .health = 5, + .damage = 1, + .sprite = 2 +}; + +template +Character create_character(CharacterData const &stats, Tile tile) { + return Character(tile, new TLogicType, stats); +} + int main(int argc, char *argv[]) { std::unique_ptr world{WorldGenerator() - .with_world_size(5) - .with_chunk_size(9) - .with_room_size(2, 5) - .with_player(Character({9/2, 9/2}, - new PlayerCharacterLogic(), - CharacterData { - .health = 1, - .damage = 1, - .sprite = 0 - } - )) + .with_world_size(20) + .with_chunk_size(10) + .with_room_size(6, 10) + .with_connecting_chance(5) + .with_player(Character({0,0}, new PlayerCharacterLogic(), player_data)) + .with_enemy(std::bind(&create_character, critte_data, std::placeholders::_1), 2) .generate() }; RenderData data{RenderDataSetup() @@ -29,6 +42,8 @@ int main(int argc, char *argv[]) { .with_resource_path("resources/") .with_sprite("wizard.png") .with_sprite("wall.png") + .with_sprite("critte.png") + .with_sprite("player.png") .build() }; Render::provide_render_data(data);