From d0be87d32929c42502fb842aa2b0ab0233313b93 Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Tue, 7 Nov 2017 13:50:52 +0100 Subject: Refactoring, introduce text.cpp, closer to an actual game. --- Makefile | 1 + src/common.hpp | 19 +++++++++- src/game.cpp | 110 +++++++++++++++++++++++++++++++++++++----------------- src/interface.cpp | 4 ++ src/main.cpp | 3 +- src/render.cpp | 47 ++++++++++------------- src/text.cpp | 14 +++++++ src/world.cpp | 7 +++- 8 files changed, 140 insertions(+), 65 deletions(-) create mode 100644 src/text.cpp diff --git a/Makefile b/Makefile index 2f10e98..74c2486 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ SRC := src/assets.cpp \ src/path_finder.cpp \ src/procgen.cpp \ src/render.cpp \ + src/text.cpp \ src/world.cpp OBJ := $(SRC:src/%.cpp=obj/%.o) diff --git a/src/common.hpp b/src/common.hpp index ecdb549..043323a 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -128,9 +128,12 @@ namespace world { size_t cookie = 0; public: + int type; cmodel_t cmodel; rectf_t render_bounds; + entity_t(int type_); + void link(world_t *world); void unlink(); @@ -169,7 +172,11 @@ namespace world { namespace game { bool load_assets(void); + class unit_t; + class state_t { + std::unordered_set selected_units; + public: world::world_t world; @@ -203,7 +210,7 @@ namespace interface { public: state_t(sf::RenderWindow *window_, game::state_t *game); void tick(void); - void render(void); + void render_to(render::state_t *render); }; } @@ -247,7 +254,6 @@ namespace render { sf::RenderWindow *window; double now; - void drender_rect(rectf_t rect, sf::Color color); void drender_text(rectf_t rect, std::string str); void drender_entity(world::entity_t *ent); public: @@ -259,6 +265,8 @@ namespace render { void render(animated_texture_t *anim, rectf_t bounds, bool mirror = false); void render(oriented_sprite_t *sprite, rectf_t bounds, float angle); + void render_hlrect(rectf_t rect, sf::Color color); + void debug_path(std::list *path); }; } @@ -276,6 +284,13 @@ namespace assets { void load(void); }; +namespace text { + extern std::string unit_no_path; + extern std::string unit_blocked; + + void load_strings(std::string lang); +} + // Divide and round to minus infinity. template T divide_rmi(T x, T y, T *rem) diff --git a/src/game.cpp b/src/game.cpp index f5341d1..48047a4 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2,6 +2,12 @@ namespace game { +static size_t selection_cookie = 1; + +enum { + ET_UNIT +}; + class unit_t : public world::entity_t { world::world_t *world; @@ -26,6 +32,11 @@ public: v2f_t x; rectf_t size, render_size; world::cflags_t cflags; + size_t selected = 0; + + unit_t() : entity_t(ET_UNIT) + { + } struct { bool moving = false; @@ -33,8 +44,18 @@ public: float angle = 0.0f; std::list path; + + bool blocked; + size_t attempts_left; + float next_attempt; } move; + void say(std::string str) + { + //TODO + std::cout << (void*)this << ": " << str << "\n"; + } + void place(world::world_t *world_, v2f_t x_) { world = world_; @@ -48,14 +69,17 @@ public: link(world); } - void keep_moving(void) + void keep_moving(double now) { float time; if (!move.moving) return; - time = 0.15; + if (move.blocked && now < move.next_attempt) + return; + + time = 0.15; // FIXME while (time > 0.0f) { v2f_t delta, next, x_new; @@ -80,13 +104,22 @@ public: } cmodel_next = make_cmodel(x_new); - if (world->test_rect(&cmodel_next, this)) { - move.moving = false; - break; + if (!world->test_rect(&cmodel_next, this)) { + x = x_new; + cmodel = cmodel_next; + continue; } - x = x_new; - cmodel = cmodel_next; + if (move.attempts_left) { + move.blocked = true; + move.attempts_left--; + move.next_attempt = now + 0.5f; + } else { + if ((x - move.dst).len() > 1.5f) + say(text::unit_blocked); + move.moving = false; + } + break; } @@ -105,12 +138,19 @@ public: move.dst = dst_; move.path.clear(); - if (world->find_path(x, move.dst, &cmodel, this, &move.path)) - move.moving = true; - else + if (!world->find_path(x, move.dst, &cmodel, this, &move.path)) { + say(text::unit_no_path); move.moving = false; + return false; + } + + move.moving = true; + + move.blocked = false; + move.attempts_left = 10; + move.next_attempt = -INFINITY; - return move.moving; + return true; } }; @@ -120,7 +160,14 @@ public: void render_to(render::state_t *render) { - render->render((move.moving ? &assets::human.legs_walking : + bool moving; + + if (selected == selection_cookie) + render->render_hlrect(render_bounds, sf::Color::Blue); + + moving = move.moving && !move.blocked; + + render->render((moving ? &assets::human.legs_walking : &assets::human.legs_idle), render_bounds, move.angle); render->render(&assets::human.body_idle, render_bounds, move.angle); render->render(&assets::human.head_idle, render_bounds, move.angle); @@ -145,40 +192,35 @@ void state_t::start(void) human2.render_size[0] = v2f_t(-0.5f, -1.0f); human2.render_size[1] = v2f_t(+0.5f, +0.5f); human2.place(&world, v2f_t(3.5f, 0.5f)); - } void state_t::select(rectf_t x) { - + selection_cookie++; + selected_units.clear(); + + for (world::entity_t *ent : world.get_render_entities(x, -1)) { + unit_t *unit; + + if (ent->type != ET_UNIT) + continue; + + unit = (unit_t*)ent; + unit->selected = selection_cookie; + selected_units.insert(unit); + } } void state_t::command(v2f_t x) { - + for (unit_t *unit : selected_units) + unit->start_moving(x); } void state_t::tick(double now) { - if ((human2.x - human.x).len() > 3) { - if (now > human2.last_follow + 0.5) { - for (size_t i = 0; i < 8; i++) { - float angle; - v2f_t offset; - - angle = (float)i / 8 * 2 * M_PI; - offset[0] = cos(angle); - offset[1] = sin(angle); - - if (human2.start_moving(human.x + offset)) - break; - } - human2.last_follow = now; - } - } - - human.keep_moving(); - human2.keep_moving(); + human.keep_moving(now); + human2.keep_moving(now); } } //namespace game diff --git a/src/interface.cpp b/src/interface.cpp index d6137fd..11e297e 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -59,6 +59,10 @@ void state_t::tick(void) select.rect[1] = wmouse; break; + case sf::Mouse::Button::Right: + game->command(wmouse); + break; + case sf::Mouse::Button::Middle: camera.panning = true; camera.pan_ref = wmouse; diff --git a/src/main.cpp b/src/main.cpp index 01c1df4..8b3eef7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,6 +23,7 @@ int main() window.setVerticalSyncEnabled(true); + text::load_strings("en"); assets::load(); game.start(); @@ -38,7 +39,7 @@ int main() window.clear(); render.begin_frame(now); render.render(&game); - interface.render(); + interface.render_to(&render); render.end_frame(); } diff --git a/src/render.cpp b/src/render.cpp index 41bcd4b..80ed2b6 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -23,7 +23,7 @@ static void draw_tile(sf::RenderWindow *window, v2f_t x, world::tile_t *tile, break; } - wot_rect.setTexture(texture); + wot_rect.setTexture(texture, true); wot_rect.setSize(sf::Vector2f(1.0f, 1.0f)); wot_rect.setPosition(x); wot_rect.setFillColor(sf::Color::White); @@ -50,16 +50,10 @@ static void draw_sector(sf::RenderWindow *window, world::sector_t *sector) world::tile_index_t(x, y)); } -void interface::state_t::render() +void interface::state_t::render_to(render::state_t *render) { - if (select.selecting) { - wot_rect.setSize(select.rect.dims()); - wot_rect.setPosition(select.rect[0]); - wot_rect.setFillColor(sf::Color(200, 100, 50, 100)); - wot_rect.setOutlineThickness(0.02f); - wot_rect.setOutlineColor(sf::Color(200, 100, 50, 255)); - window->draw(wot_rect); - } + if (select.selecting) + render->render_hlrect(select.rect, sf::Color(200, 100, 50)); } namespace render { @@ -82,21 +76,6 @@ void state_t::end_frame(void) window->display(); } -void state_t::drender_rect(rectf_t rect, sf::Color color) -{ - sf::Color fill; - - - fill = sf::Color(color.r, color.g, color.b, 50); - - wot_rect.setSize(rect.dims()); - wot_rect.setPosition(rect[0]); - wot_rect.setFillColor(fill); - wot_rect.setOutlineThickness(0.01); - wot_rect.setOutlineColor(color); - window->draw(wot_rect); -} - void state_t::drender_text(rectf_t rect, std::string str) { sf::Text text(str, font, 20); @@ -121,8 +100,8 @@ void state_t::drender_entity(world::entity_t *ent) { std::stringstream ss; - drender_rect(ent->render_bounds, sf::Color::Red); - drender_rect(ent->cmodel.bounds, sf::Color::Yellow); + render_hlrect(ent->render_bounds, sf::Color::Red); + render_hlrect(ent->cmodel.bounds, sf::Color::Yellow); ss << (void*)ent << "\n"; ss << "CF=" << ent->cmodel.cflags; @@ -202,6 +181,20 @@ void state_t::render(oriented_sprite_t *sprite, rectf_t bounds, float angle) render(sprite->textures + index, bounds, mirror); } +void state_t::render_hlrect(rectf_t rect, sf::Color color) +{ + sf::Color fill; + + fill = sf::Color(color.r, color.g, color.b, 50); + wot_rect.setSize(rect.dims()); + wot_rect.setPosition(rect[0]); + wot_rect.setFillColor(fill); + wot_rect.setOutlineThickness(0.01); + wot_rect.setOutlineColor(color); + window->draw(wot_rect); + wot_rect.setOutlineColor(sf::Color::Transparent); +} + void state_t::debug_path(std::list *path) { bool first = true; diff --git a/src/text.cpp b/src/text.cpp new file mode 100644 index 0000000..baeabcd --- /dev/null +++ b/src/text.cpp @@ -0,0 +1,14 @@ +#include "common.hpp" + +namespace text { + +std::string unit_no_path; +std::string unit_blocked; + +void load_strings(std::string lang) +{ + unit_no_path = "Cannot find a path."; + unit_blocked = "The path is blocked."; +} + +} diff --git a/src/world.cpp b/src/world.cpp index 004f03f..ef056db 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -113,7 +113,7 @@ bool world_t::find_path(v2f_t src, v2f_t dst, cmodel_t *cmodel, entity_t *ignore if (ent != ignore) finder.eliminate_nodes(ent->cmodel.bounds); - if (finder.find()) + if (!finder.find()) return false; finder.export_path(path); @@ -270,6 +270,11 @@ void world_t::debug_point(sf::Vector2f point) printf("sector (%zd, %zd)\n", index[0], index[1]); } +entity_t::entity_t(int type_) +{ + type = type_; +} + void entity_t::link_to_sector(sector_t *sector) { parents.push_back(sector); -- cgit