diff --git a/include/ant.hpp b/include/ant.hpp index 89b5ed03..857f4a86 100644 --- a/include/ant.hpp +++ b/include/ant.hpp @@ -11,157 +11,157 @@ struct Ant { - Ant() = default; - - Ant(float x, float y, float angle, uint32_t id_) - : position(x, y) - , direction(angle) - , last_direction_update(getRandUnder(100.0f) * 0.01f * direction_update_period) - , last_marker(getRandUnder(100.0f) * 0.01f * marker_period) - , phase(Marker::Type::ToFood) - , reserve(0.0f) - , id(id_) - { - reserve = max_reserve; - } - - void update(const float dt, World& world) - { - updatePosition(dt); - if (phase == Marker::ToFood) { - checkFood(world); - } - - last_direction_update += dt; - if (last_direction_update > direction_update_period) { - findMarker(world); - direction += getRandRange(direction_noise_range); - last_direction_update = 0.0f; - } - - last_marker += dt; - if (last_marker >= marker_period) { - addMarker(world); - } - - direction.update(dt); - } - - void updatePosition(const float dt) - { - position += (dt * move_speed) * direction.getVec(); - - position.x = position.x < 0.0f ? Conf::WIN_WIDTH : position.x; - position.y = position.y < 0.0f ? Conf::WIN_HEIGHT : position.y; - - position.x = position.x > Conf::WIN_WIDTH ? 0.0f : position.x; - position.y = position.y > Conf::WIN_HEIGHT ? 0.0f : position.y; - } - - void checkFood(World& world) - { - const std::list food_spots = world.grid_food.getAllAt(position); - for (Food* fp : food_spots) { - if (getLength(position - fp->position) < fp->radius) { - phase = Marker::ToHome; - direction.addNow(PI); - reserve = max_reserve; - fp->pick(); - return; - } - } - } - - void checkColony(const sf::Vector2f colony_position) - { - if (getLength(position - colony_position) < colony_size) { - if (phase == Marker::ToHome) { - phase = Marker::ToFood; - direction.addNow(PI); - } - reserve = max_reserve; - } - } - - void findMarker(World& world) - { - std::list markers = world.getGrid(phase).getAllAt(position); - - float total_intensity = 0.0f; - sf::Vector2f point(0.0f, 0.0f); - - const sf::Vector2f dir_vec = direction.getVec(); - - for (Marker* mp : markers) { - const Marker& m = *mp; - const sf::Vector2f to_marker = m.position - position; - const float length = getLength(to_marker); - - if (length < marker_detection_max_dist) { - if (dot(to_marker, dir_vec) > 0.0f) { - total_intensity += m.intensity; - point += m.intensity * m.position; - } - } - } - - if (total_intensity) { - direction = getAngle(point / total_intensity - position); - } - } - - void addMarker(World& world) - { - if (reserve > 1.0f) { - world.addMarker(Marker(position, phase == Marker::ToFood ? Marker::ToHome : Marker::ToFood, reserve * marker_reserve_consumption)); - reserve *= 1.0f - marker_reserve_consumption; - } - - last_marker = 0.0f; - } - - void render_food(sf::RenderTarget& target, const sf::RenderStates& states) const - { - if (phase == Marker::ToHome) { - const float radius = 2.0f; - sf::CircleShape circle(radius); - circle.setOrigin(radius, radius); - circle.setPosition(position + length * 0.5f * direction.getVec()); - circle.setFillColor(Conf::FOOD_COLOR); - target.draw(circle, states); - } - } - - void render_in(sf::VertexArray& va, const uint32_t index) const - { - const sf::Vector2f dir_vec(direction.getVec()); - const sf::Vector2f nrm_vec(-dir_vec.y, dir_vec.x); - - va[index + 0].position = position - width * nrm_vec + length * dir_vec; - va[index + 1].position = position + width * nrm_vec + length * dir_vec; - va[index + 2].position = position + width * nrm_vec - length * dir_vec; - va[index + 3].position = position - width * nrm_vec - length * dir_vec; - } - - sf::Vector2f position; - - Direction direction; - - float last_direction_update; - float last_marker; - Marker::Type phase; - float reserve; - const uint32_t id; - - // Parameters - const float width = 2.0f; - const float length = 3.5f; - const float move_speed = 50.0f; - const float marker_detection_max_dist = 40.0f; - const float direction_update_period = 0.125f; - const float marker_period = 0.25f; - const float max_reserve = 2000.0f; - const float direction_noise_range = PI * 0.1f; - const float marker_reserve_consumption = 0.02f; - const float colony_size = 20.0f; + Ant() = default; + + Ant(float x, float y, float angle, uint32_t id_) + : position(x, y) + , direction(angle) + , last_direction_update(getRandUnder(100.0f) * 0.01f * direction_update_period) + , last_marker(getRandUnder(100.0f) * 0.01f * marker_period) + , phase(Marker::Type::ToFood) + , reserve(0.0f) + , id(id_) + { + reserve = max_reserve; + } + + void update(const float dt, World& world) + { + updatePosition(dt); + if (phase == Marker::ToFood) { + checkFood(world); + } + + last_direction_update += dt; + if (last_direction_update > direction_update_period) { + findMarker(world); + direction += getRandRange(direction_noise_range); + last_direction_update = 0.0f; + } + + last_marker += dt; + if (last_marker >= marker_period) { + addMarker(world); + } + + direction.update(dt); + } + + void updatePosition(const float dt) + { + position += (dt * move_speed) * direction.getVec(); + + position.x = position.x < 0.0f ? Conf::WIN_WIDTH : position.x; + position.y = position.y < 0.0f ? Conf::WIN_HEIGHT : position.y; + + position.x = position.x > Conf::WIN_WIDTH ? 0.0f : position.x; + position.y = position.y > Conf::WIN_HEIGHT ? 0.0f : position.y; + } + + void checkFood(World& world) + { + const std::list food_spots = world.grid_food.getAllAt(position); + for (Food* fp : food_spots) { + if (getLength(position - fp->position) < fp->radius) { + phase = Marker::ToHome; + direction.addNow(PI); + reserve = max_reserve; + fp->pick(); + return; + } + } + } + + void checkColony(const sf::Vector2f colony_position) + { + if (getLength(position - colony_position) < colony_size) { + if (phase == Marker::ToHome) { + phase = Marker::ToFood; + direction.addNow(PI); + } + reserve = max_reserve; + } + } + + void findMarker(World& world) + { + std::list markers = world.getGrid(phase).getAllAt(position); + + float total_intensity = 0.0f; + sf::Vector2f point(0.0f, 0.0f); + + const sf::Vector2f dir_vec = direction.getVec(); + + for (Marker* mp : markers) { + const Marker& m = *mp; + const sf::Vector2f to_marker = m.position - position; + const float length = getLength(to_marker); + + if (length < marker_detection_max_dist) { + if (dot(to_marker, dir_vec) > 0.0f) { + total_intensity += m.intensity; + point += m.intensity * m.position; + } + } + } + + if (total_intensity) { + direction = getAngle(point / total_intensity - position); + } + } + + void addMarker(World& world) + { + if (reserve > 1.0f) { + world.addMarker(Marker(position, phase == Marker::ToFood ? Marker::ToHome : Marker::ToFood, reserve * marker_reserve_consumption)); + reserve *= 1.0f - marker_reserve_consumption; + } + + last_marker = 0.0f; + } + + void render_food(sf::RenderTarget& target, const sf::RenderStates& states) const + { + if (phase == Marker::ToHome) { + const float radius = 2.0f; + sf::CircleShape circle(radius); + circle.setOrigin(radius, radius); + circle.setPosition(position + length * 0.5f * direction.getVec()); + circle.setFillColor(Conf::FOOD_COLOR); + target.draw(circle, states); + } + } + + void render_in(sf::VertexArray& va, const uint32_t index) const + { + const sf::Vector2f dir_vec(direction.getVec()); + const sf::Vector2f nrm_vec(-dir_vec.y, dir_vec.x); + + va[index + 0].position = position - width * nrm_vec + length * dir_vec; + va[index + 1].position = position + width * nrm_vec + length * dir_vec; + va[index + 2].position = position + width * nrm_vec - length * dir_vec; + va[index + 3].position = position - width * nrm_vec - length * dir_vec; + } + + sf::Vector2f position; + + Direction direction; + + float last_direction_update; + float last_marker; + Marker::Type phase; + float reserve; + const uint32_t id; + + // Parameters + const float width = 2.0f; + const float length = 3.5f; + const float move_speed = 50.0f; + const float marker_detection_max_dist = 40.0f; + const float direction_update_period = 0.125f; + const float marker_period = 0.25f; + const float max_reserve = 2000.0f; + const float direction_noise_range = PI * 0.1f; + const float marker_reserve_consumption = 0.02f; + const float colony_size = 20.0f; }; diff --git a/include/colony.hpp b/include/colony.hpp index 2526d335..a1148dca 100644 --- a/include/colony.hpp +++ b/include/colony.hpp @@ -9,68 +9,68 @@ struct Colony { - Colony(float x, float y, uint32_t n) - : position(x, y) - , last_direction_update(0.0f) - , ants_va(sf::Quads, 4 * n) - { - for (uint32_t i(n); i--;) { - ants.emplace_back(x, y, getRandRange(2.0f * PI), n - i - 1); - } + Colony(float x, float y, uint32_t n) + : position(x, y) + , last_direction_update(0.0f) + , ants_va(sf::Quads, 4 * n) + { + for (uint32_t i(n); i--;) { + ants.emplace_back(x, y, getRandRange(2.0f * PI), n - i - 1); + } - for (uint64_t i(0); i < n; ++i) { - const uint64_t index = 4 * i; - ants_va[index + 0].color = Conf::ANT_COLOR; - ants_va[index + 1].color = Conf::ANT_COLOR; - ants_va[index + 2].color = Conf::ANT_COLOR; - ants_va[index + 3].color = Conf::ANT_COLOR; + for (uint64_t i(0); i < n; ++i) { + const uint64_t index = 4 * i; + ants_va[index + 0].color = Conf::ANT_COLOR; + ants_va[index + 1].color = Conf::ANT_COLOR; + ants_va[index + 2].color = Conf::ANT_COLOR; + ants_va[index + 3].color = Conf::ANT_COLOR; - ants_va[index + 0].texCoords = sf::Vector2f(0.0f, 0.0f); - ants_va[index + 1].texCoords = sf::Vector2f(73.0f, 0.0f); - ants_va[index + 2].texCoords = sf::Vector2f(73.0f, 107.0f); - ants_va[index + 3].texCoords = sf::Vector2f(0.0f, 107.0f); - } - } + ants_va[index + 0].texCoords = sf::Vector2f(0.0f, 0.0f); + ants_va[index + 1].texCoords = sf::Vector2f(73.0f, 0.0f); + ants_va[index + 2].texCoords = sf::Vector2f(73.0f, 107.0f); + ants_va[index + 3].texCoords = sf::Vector2f(0.0f, 107.0f); + } + } - void update(const float dt, World& world) - { - for (Ant& ant : ants) { - ant.update(dt, world); - } + void update(const float dt, World& world) + { + for (Ant& ant : ants) { + ant.update(dt, world); + } - for (Ant& ant : ants) { - ant.checkColony(position); - } - } + for (Ant& ant : ants) { + ant.checkColony(position); + } + } - void render(sf::RenderTarget& target, const sf::RenderStates& states) const - { - for (const Ant& a : ants) { - a.render_food(target, states); - } + void render(sf::RenderTarget& target, const sf::RenderStates& states) const + { + for (const Ant& a : ants) { + a.render_food(target, states); + } - uint32_t index = 0; - for (const Ant& a : ants) { - a.render_in(ants_va, 4 * (index++)); - } + uint32_t index = 0; + for (const Ant& a : ants) { + a.render_in(ants_va, 4 * (index++)); + } - sf::RenderStates rs = states; - rs.texture = &(*Conf::ANT_TEXTURE); - target.draw(ants_va, rs); + sf::RenderStates rs = states; + rs.texture = &(*Conf::ANT_TEXTURE); + target.draw(ants_va, rs); - sf::CircleShape circle(size); - circle.setOrigin(size, size); - circle.setPosition(position); - circle.setFillColor(Conf::COLONY_COLOR); - target.draw(circle, states); - } + sf::CircleShape circle(size); + circle.setOrigin(size, size); + circle.setPosition(position); + circle.setFillColor(Conf::COLONY_COLOR); + target.draw(circle, states); + } - const sf::Vector2f position; - std::vector ants; - mutable sf::VertexArray ants_va; - const float size = 20.0f; + const sf::Vector2f position; + std::vector ants; + mutable sf::VertexArray ants_va; + const float size = 20.0f; - float last_direction_update; - const float direction_update_period = 0.25f; + float last_direction_update; + const float direction_update_period = 0.25f; }; diff --git a/include/config.hpp b/include/config.hpp index 1d2057aa..abaf6a47 100644 --- a/include/config.hpp +++ b/include/config.hpp @@ -6,32 +6,32 @@ struct Conf { - const static sf::Color ANT_COLOR; - const static sf::Color FOOD_COLOR; - const static sf::Color TO_FOOD_COLOR; - const static sf::Color TO_HOME_COLOR; - const static sf::Color COLONY_COLOR; - const static uint32_t MAX_MARKERS_PER_CELL; - static uint32_t WIN_WIDTH; - static uint32_t WIN_HEIGHT; - static uint32_t ANTS_COUNT; - static std::shared_ptr ANT_TEXTURE; - static std::shared_ptr MARKER_TEXTURE; + const static sf::Color ANT_COLOR; + const static sf::Color FOOD_COLOR; + const static sf::Color TO_FOOD_COLOR; + const static sf::Color TO_HOME_COLOR; + const static sf::Color COLONY_COLOR; + const static uint32_t MAX_MARKERS_PER_CELL; + static uint32_t WIN_WIDTH; + static uint32_t WIN_HEIGHT; + static uint32_t ANTS_COUNT; + static std::shared_ptr ANT_TEXTURE; + static std::shared_ptr MARKER_TEXTURE; - static void loadTextures() - { - Conf::ANT_TEXTURE = std::make_shared(); - Conf::ANT_TEXTURE->loadFromFile("res/ant_2.png"); - Conf::ANT_TEXTURE->setSmooth(true); + static void loadTextures() + { + Conf::ANT_TEXTURE = std::make_shared(); + Conf::ANT_TEXTURE->loadFromFile("res/ant_2.png"); + Conf::ANT_TEXTURE->setSmooth(true); - Conf::MARKER_TEXTURE = std::make_shared(); - Conf::MARKER_TEXTURE->loadFromFile("res/marker.png"); - Conf::MARKER_TEXTURE->setSmooth(true); - } + Conf::MARKER_TEXTURE = std::make_shared(); + Conf::MARKER_TEXTURE->loadFromFile("res/marker.png"); + Conf::MARKER_TEXTURE->setSmooth(true); + } - static void freeTextures() - { - Conf::ANT_TEXTURE = nullptr; - Conf::MARKER_TEXTURE = nullptr; - } + static void freeTextures() + { + Conf::ANT_TEXTURE = nullptr; + Conf::MARKER_TEXTURE = nullptr; + } }; diff --git a/include/direction.hpp b/include/direction.hpp index 85b33dba..1e0e34e0 100644 --- a/include/direction.hpp +++ b/include/direction.hpp @@ -6,66 +6,66 @@ struct Direction { public: - Direction(float angle, float rotation_speed = 10.0f) - : m_angle(angle) - , m_target_angle(angle) - , m_rotation_speed(rotation_speed) - { - updateVec(); - m_target_vec = m_vec; - } + Direction(float angle, float rotation_speed = 10.0f) + : m_angle(angle) + , m_target_angle(angle) + , m_rotation_speed(rotation_speed) + { + updateVec(); + m_target_vec = m_vec; + } - void update(float dt) - { - updateVec(); + void update(float dt) + { + updateVec(); - const sf::Vector2f dir_nrm(-m_vec.y, m_vec.x); + const sf::Vector2f dir_nrm(-m_vec.y, m_vec.x); - const float dir_delta = dot(m_target_vec, dir_nrm); - const float rotation_speed = 10.0f; - m_angle += rotation_speed * dir_delta * dt; - } + const float dir_delta = dot(m_target_vec, dir_nrm); + const float rotation_speed = 10.0f; + m_angle += rotation_speed * dir_delta * dt; + } - sf::Vector2f getVec() const - { - return m_vec; - } + sf::Vector2f getVec() const + { + return m_vec; + } - void operator+=(float a) - { - m_target_angle += a; - updateTargetVec(); - } + void operator+=(float a) + { + m_target_angle += a; + updateTargetVec(); + } - void operator=(float a) - { - m_target_angle = a; - updateTargetVec(); - } + void operator=(float a) + { + m_target_angle = a; + updateTargetVec(); + } - void addNow(float a) - { - this->operator+=(a); - m_angle = m_target_angle; - updateVec(); - } + void addNow(float a) + { + this->operator+=(a); + m_angle = m_target_angle; + updateVec(); + } private: - sf::Vector2f m_vec; - sf::Vector2f m_target_vec; - float m_angle; - float m_target_angle; - float m_rotation_speed; + sf::Vector2f m_vec; + sf::Vector2f m_target_vec; + float m_angle; + float m_target_angle; + float m_rotation_speed; - void updateVec() - { - m_vec.x = cos(m_angle); - m_vec.y = sin(m_angle); - } + void updateVec() + { + m_vec.x = cos(m_angle); + m_vec.y = sin(m_angle); + } - void updateTargetVec() - { - m_target_vec.x = cos(m_target_angle); - m_target_vec.y = sin(m_target_angle); - } + void updateTargetVec() + { + m_target_vec.x = cos(m_target_angle); + m_target_vec.y = sin(m_target_angle); + } }; diff --git a/include/display_manager.hpp b/include/display_manager.hpp index 48880e86..8a531f3a 100644 --- a/include/display_manager.hpp +++ b/include/display_manager.hpp @@ -11,53 +11,73 @@ class DisplayManager DisplayManager(sf::RenderTarget& target, sf::RenderWindow& window, World& world, Colony& colony); //offset mutators - void setOffset(float x, float y) {m_offsetX=x; m_offsetY=y;}; - void setOffset(const sf::Vector2f& off) {m_offsetX=off.x; m_offsetY=off.y;}; - - void addOffset(float x, float y) {m_offsetX-=x/m_zoom; m_offsetY-=y/m_zoom;}; - void addOffset(const sf::Vector2f& off) {m_offsetX-=off.x/m_zoom; m_offsetY-=off.y/m_zoom;}; + void setOffset(float x, float y) { + m_offsetX=x; + m_offsetY=y; + }; + void setOffset(const sf::Vector2f& off) { + m_offsetX=off.x; + m_offsetY=off.y; + }; + + void addOffset(float x, float y) { + m_offsetX-=x/m_zoom; + m_offsetY-=y/m_zoom; + }; + void addOffset(const sf::Vector2f& off) { + m_offsetX-=off.x/m_zoom; + m_offsetY-=off.y/m_zoom; + }; // set the absolute zoom - void setZoom(float zoom) {m_zoom = zoom;}; + void setZoom(float zoom) { + m_zoom = zoom; + }; // zoom - void zoom(float zoomFactor) {m_zoom *= zoomFactor;}; + void zoom(float zoomFactor) { + m_zoom *= zoomFactor; + }; // draw the current world void draw(); - void processEvents(); + void processEvents(); // getters - sf::Vector2f getOffset() const {return sf::Vector2f(m_offsetX, m_offsetY);}; - float getZoom() const {return m_zoom;}; - sf::Vector2f worldCoordToDisplayCoord(const sf::Vector2f&); - sf::Vector2f displayCoordToWorldCoord(const sf::Vector2f&); - - bool clic; - bool pause; - bool draw_markers; - bool update; - float render_time; - bool speed_mode; - bool debug_mode; - - sf::Vector2f getClicPosition() const - { - return sf::Vector2f(to(m_clic_position.x), to(m_clic_position.y)); - } + sf::Vector2f getOffset() const { + return sf::Vector2f(m_offsetX, m_offsetY); + }; + float getZoom() const { + return m_zoom; + }; + sf::Vector2f worldCoordToDisplayCoord(const sf::Vector2f&); + sf::Vector2f displayCoordToWorldCoord(const sf::Vector2f&); + + bool clic; + bool pause; + bool draw_markers; + bool update; + float render_time; + bool speed_mode; + bool debug_mode; + + sf::Vector2f getClicPosition() const + { + return sf::Vector2f(to(m_clic_position.x), to(m_clic_position.y)); + } private: - sf::RenderTarget& m_target; - sf::RenderWindow& m_window; + sf::RenderTarget& m_target; + sf::RenderWindow& m_window; sf::Texture m_texture; - sf::VertexArray m_va; + sf::VertexArray m_va; - World& m_world; - Colony& m_colony; + World& m_world; + Colony& m_colony; - bool m_mouse_button_pressed; - sf::Vector2i m_drag_clic_position, m_clic_position; + bool m_mouse_button_pressed; + sf::Vector2i m_drag_clic_position, m_clic_position; float m_zoom, m_offsetX, m_offsetY, m_windowOffsetX, m_windowOffsetY; }; diff --git a/include/food.hpp b/include/food.hpp index 25f3238e..6f434e72 100644 --- a/include/food.hpp +++ b/include/food.hpp @@ -5,43 +5,43 @@ struct Food { - Food() = default; - - Food(float x, float y, float r, float quantity_, Marker* maker_ptr = nullptr) - : position(x, y) - , radius(r) - , quantity(quantity_) - , marker(maker_ptr) - {} - - void pick() - { - quantity -= 1.0f; - if (isDone()) { - if (marker) { - marker->intensity = 10.0f; - marker->permanent = false; - } - } - } - - bool isDone() const - { - return quantity <= 0.0f; - } - - void render(sf::RenderTarget& target, const sf::RenderStates& states) const - { - sf::CircleShape circle(radius); - circle.setOrigin(radius, radius); - circle.setPosition(position); - circle.setFillColor(Conf::FOOD_COLOR); - - target.draw(circle, states); - } - - sf::Vector2f position; - float radius; - float quantity; - Marker* marker; + Food() = default; + + Food(float x, float y, float r, float quantity_, Marker* maker_ptr = nullptr) + : position(x, y) + , radius(r) + , quantity(quantity_) + , marker(maker_ptr) + {} + + void pick() + { + quantity -= 1.0f; + if (isDone()) { + if (marker) { + marker->intensity = 10.0f; + marker->permanent = false; + } + } + } + + bool isDone() const + { + return quantity <= 0.0f; + } + + void render(sf::RenderTarget& target, const sf::RenderStates& states) const + { + sf::CircleShape circle(radius); + circle.setOrigin(radius, radius); + circle.setPosition(position); + circle.setFillColor(Conf::FOOD_COLOR); + + target.draw(circle, states); + } + + sf::Vector2f position; + float radius; + float quantity; + Marker* marker; }; diff --git a/include/marker.hpp b/include/marker.hpp index 2d23a3d9..c074fb61 100644 --- a/include/marker.hpp +++ b/include/marker.hpp @@ -5,64 +5,64 @@ struct Marker { - enum Type { - ToHome, - ToFood - }; + enum Type { + ToHome, + ToFood + }; - Marker() = default; - Marker(const sf::Vector2f& pos, Type type_, float intensity_, bool permanent_ = false) - : position(pos) - , intensity(intensity_) - , type(type_) - , permanent(permanent_) - {} + Marker() = default; + Marker(const sf::Vector2f& pos, Type type_, float intensity_, bool permanent_ = false) + : position(pos) + , intensity(intensity_) + , type(type_) + , permanent(permanent_) + {} - void update(const float dt) - { - if (!permanent) { - intensity -= 1.0f * dt; - } - } + void update(const float dt) + { + if (!permanent) { + intensity -= 1.0f * dt; + } + } - void destroy() - { - intensity = -1.0f; - } + void destroy() + { + intensity = -1.0f; + } - bool isDone() const - { - return intensity < 0.0f; - } + bool isDone() const + { + return intensity < 0.0f; + } - void render_in(sf::VertexArray& va, const uint32_t index) const - { - if (!permanent) { - const float radius = intensity * 0.15f; - - sf::Color color = (type == ToHome) ? Conf::TO_HOME_COLOR : Conf::TO_FOOD_COLOR; + void render_in(sf::VertexArray& va, const uint32_t index) const + { + if (!permanent) { + const float radius = intensity * 0.15f; - va[index + 0].position = position + sf::Vector2f(radius, 0.0f); - va[index + 1].position = position + sf::Vector2f(0.0f, radius); - va[index + 2].position = position + sf::Vector2f(-radius, 0.0f); - va[index + 3].position = position + sf::Vector2f(0.0f, -radius); + sf::Color color = (type == ToHome) ? Conf::TO_HOME_COLOR : Conf::TO_FOOD_COLOR; - va[index + 0].color = color; - va[index + 1].color = color; - va[index + 2].color = color; - va[index + 3].color = color; + va[index + 0].position = position + sf::Vector2f(radius, 0.0f); + va[index + 1].position = position + sf::Vector2f(0.0f, radius); + va[index + 2].position = position + sf::Vector2f(-radius, 0.0f); + va[index + 3].position = position + sf::Vector2f(0.0f, -radius); - constexpr float tex_size = 100.0f; - va[index + 0].texCoords = sf::Vector2f(0.0f, 0.0f); - va[index + 1].texCoords = sf::Vector2f(tex_size, 0.0f); - va[index + 2].texCoords = sf::Vector2f(tex_size, tex_size); - va[index + 3].texCoords = sf::Vector2f(0.0f, tex_size); - } - } + va[index + 0].color = color; + va[index + 1].color = color; + va[index + 2].color = color; + va[index + 3].color = color; - sf::Vector2f position; - Type type; + constexpr float tex_size = 100.0f; + va[index + 0].texCoords = sf::Vector2f(0.0f, 0.0f); + va[index + 1].texCoords = sf::Vector2f(tex_size, 0.0f); + va[index + 2].texCoords = sf::Vector2f(tex_size, tex_size); + va[index + 3].texCoords = sf::Vector2f(0.0f, tex_size); + } + } - float intensity; - bool permanent; + sf::Vector2f position; + Type type; + + float intensity; + bool permanent; }; diff --git a/include/utils.hpp b/include/utils.hpp index d040d46f..cf2b97c4 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -15,14 +15,14 @@ float getRandUnder(float width); template float getLength(const sf::Vector2& v) { - return sqrt(v.x * v.x + v.y * v.y); + return sqrt(v.x * v.x + v.y * v.y); } template T to(const U& u) { - return static_cast(u); + return static_cast(u); } diff --git a/include/world.hpp b/include/world.hpp index 5d6065d4..cc023ef6 100644 --- a/include/world.hpp +++ b/include/world.hpp @@ -11,199 +11,205 @@ template struct Grid { - Grid(int32_t width_, int32_t height_, uint32_t cell_size_) - : cell_size(cell_size_) - , width(width_ / cell_size_) - , height(height_ / cell_size_) - { - cells.resize(width * height); - } - - T* add(const T& obj) - { - return add(getCellCoords(obj.position), obj); - } - - std::list* getAt(const sf::Vector2f& position) - { - const sf::Vector2i cell_coords = getCellCoords(position); - - if (checkCell(cell_coords)) { - return &cells[getIndexFromCoords(cell_coords)]; - } - - return nullptr; - } - - std::list getAllAt(const sf::Vector2f& position) - { - std::list result(0); - const sf::Vector2i cell_coords = getCellCoords(position); - - for (int32_t x(-1); x < 2; ++x) { - for (int32_t y(-1); y < 2; ++y) { - const sf::Vector2i coords = cell_coords + sf::Vector2i(x, y); - if (checkCell(coords)) { - const uint64_t index = getIndexFromCoords(coords); - for (T& m : cells[index]) { - result.push_back(&m); - } - } - } - } - - return result; - } - - T* add(const sf::Vector2i& cell_coords, const T& obj) - { - if (checkCell(cell_coords)) { - std::list& l = cells[getIndexFromCoords(cell_coords)]; - if (Conf::MAX_MARKERS_PER_CELL > l.size()) { - l.emplace_back(obj); - return &l.back(); - } - } - return nullptr; - } - - bool checkCell(const sf::Vector2i& cell_coords) - { - return cell_coords.x > -1 && cell_coords.x < width && cell_coords.y > -1 && cell_coords.y < height; - } - - uint64_t getIndexFromCoords(const sf::Vector2i& cell_coords) - { - return cell_coords.x + cell_coords.y * width; - } - - sf::Vector2i getCellCoords(const sf::Vector2f& position) - { - const int32_t x_cell = to(position.x / cell_size); - const int32_t y_cell = to(position.y / cell_size); - - return sf::Vector2i(x_cell, y_cell); - } - - std::vector> cells; - - const int32_t width, height, cell_size; + Grid(int32_t width_, int32_t height_, uint32_t cell_size_) + : cell_size(cell_size_) + , width(width_ / cell_size_) + , height(height_ / cell_size_) + { + cells.resize(width * height); + } + + T* add(const T& obj) + { + return add(getCellCoords(obj.position), obj); + } + + std::list* getAt(const sf::Vector2f& position) + { + const sf::Vector2i cell_coords = getCellCoords(position); + + if (checkCell(cell_coords)) { + return &cells[getIndexFromCoords(cell_coords)]; + } + + return nullptr; + } + + std::list getAllAt(const sf::Vector2f& position) + { + std::list result(0); + const sf::Vector2i cell_coords = getCellCoords(position); + + for (int32_t x(-1); x < 2; ++x) { + for (int32_t y(-1); y < 2; ++y) { + const sf::Vector2i coords = cell_coords + sf::Vector2i(x, y); + if (checkCell(coords)) { + const uint64_t index = getIndexFromCoords(coords); + for (T& m : cells[index]) { + result.push_back(&m); + } + } + } + } + + return result; + } + + T* add(const sf::Vector2i& cell_coords, const T& obj) + { + if (checkCell(cell_coords)) { + std::list& l = cells[getIndexFromCoords(cell_coords)]; + if (Conf::MAX_MARKERS_PER_CELL > l.size()) { + l.emplace_back(obj); + return &l.back(); + } + } + return nullptr; + } + + bool checkCell(const sf::Vector2i& cell_coords) + { + return cell_coords.x > -1 && cell_coords.x < width && cell_coords.y > -1 && cell_coords.y < height; + } + + uint64_t getIndexFromCoords(const sf::Vector2i& cell_coords) + { + return cell_coords.x + cell_coords.y * width; + } + + sf::Vector2i getCellCoords(const sf::Vector2f& position) + { + const int32_t x_cell = to(position.x / cell_size); + const int32_t y_cell = to(position.y / cell_size); + + return sf::Vector2i(x_cell, y_cell); + } + + std::vector> cells; + + const int32_t width, height, cell_size; }; struct World { - World(uint32_t width, uint32_t height) - : grid_markers_home(width, height, 45) - , grid_markers_food(width, height, 45) - , grid_food(width, height, 5) - , size(to(width), to(height)) - , va(sf::Quads) - {} - - void removeExpiredMarkers() - { - // Home - for (std::list& l : grid_markers_home.cells) { - l.remove_if([&](const Marker& m) {return m.isDone(); }); - } - // Food - for (std::list& l : grid_markers_food.cells) { - l.remove_if([&](const Marker& m) {return m.isDone(); }); - } - } - - void removeExpiredFood() - { - for (std::list& l : grid_food.cells) { - l.remove_if([&](const Food& m) {return m.isDone(); }); - } - } - - void update(const float dt) - { - removeExpiredMarkers(); - removeExpiredFood(); - - markers_count = 0u; - for (std::list& l : grid_markers_home.cells) { - for (Marker& m : l) { - markers_count += m.permanent ? 0 : 1; - m.update(dt); - } - } - - for (std::list& l : grid_markers_food.cells) { - for (Marker& m : l) { - markers_count += m.permanent ? 0 : 1; - m.update(dt); - } - } - } - - Marker* addMarker(const Marker& marker) - { - return getGrid(marker.type).add(marker); - } - - void render(sf::RenderTarget& target, const sf::RenderStates& states, bool draw_markers = true) const - { - if (draw_markers) { - va.resize(4 * markers_count); - generateMarkersVertexArray(va); - sf::RenderStates rs = states; - rs.texture = &(*Conf::MARKER_TEXTURE); - target.draw(va, rs); - } - - for (const std::list& l : grid_food.cells) { - for (const Food& f : l) { - f.render(target, states); - } - } - } - - void generateMarkersVertexArray(sf::VertexArray& va) const - { - uint32_t current_index = 0; - for (const std::list& l : grid_markers_home.cells) { - for (const Marker& m : l) { - if (!m.permanent) { - m.render_in(va, 4 * (current_index++)); - } - } - } - - for (const std::list& l : grid_markers_food.cells) { - for (const Marker& m : l) { - if (!m.permanent) { - m.render_in(va, 4 * (current_index++)); - } - } - } - } - - void addFoodAt(float x, float y, float quantity) - { - Marker* marker = addMarker(Marker(sf::Vector2f(x, y), Marker::ToFood, 100000000.0f, true)); - if (marker) { - grid_food.add(Food(x, y, 4.0f, quantity, marker)); - } - } - - Grid& getGrid(Marker::Type type) - { - if (type == Marker::ToFood) { - return grid_markers_food; - } - return grid_markers_home; - } - - sf::Vector2f size; - mutable sf::VertexArray va; - Grid grid_markers_home; - Grid grid_markers_food; - Grid grid_food; - - uint64_t markers_count; + World(uint32_t width, uint32_t height) + : grid_markers_home(width, height, 45) + , grid_markers_food(width, height, 45) + , grid_food(width, height, 5) + , size(to(width), to(height)) + , va(sf::Quads) + {} + + void removeExpiredMarkers() + { + // Home + for (std::list& l : grid_markers_home.cells) { + l.remove_if([&](const Marker& m) { + return m.isDone(); + }); + } + // Food + for (std::list& l : grid_markers_food.cells) { + l.remove_if([&](const Marker& m) { + return m.isDone(); + }); + } + } + + void removeExpiredFood() + { + for (std::list& l : grid_food.cells) { + l.remove_if([&](const Food& m) { + return m.isDone(); + }); + } + } + + void update(const float dt) + { + removeExpiredMarkers(); + removeExpiredFood(); + + markers_count = 0u; + for (std::list& l : grid_markers_home.cells) { + for (Marker& m : l) { + markers_count += m.permanent ? 0 : 1; + m.update(dt); + } + } + + for (std::list& l : grid_markers_food.cells) { + for (Marker& m : l) { + markers_count += m.permanent ? 0 : 1; + m.update(dt); + } + } + } + + Marker* addMarker(const Marker& marker) + { + return getGrid(marker.type).add(marker); + } + + void render(sf::RenderTarget& target, const sf::RenderStates& states, bool draw_markers = true) const + { + if (draw_markers) { + va.resize(4 * markers_count); + generateMarkersVertexArray(va); + sf::RenderStates rs = states; + rs.texture = &(*Conf::MARKER_TEXTURE); + target.draw(va, rs); + } + + for (const std::list& l : grid_food.cells) { + for (const Food& f : l) { + f.render(target, states); + } + } + } + + void generateMarkersVertexArray(sf::VertexArray& va) const + { + uint32_t current_index = 0; + for (const std::list& l : grid_markers_home.cells) { + for (const Marker& m : l) { + if (!m.permanent) { + m.render_in(va, 4 * (current_index++)); + } + } + } + + for (const std::list& l : grid_markers_food.cells) { + for (const Marker& m : l) { + if (!m.permanent) { + m.render_in(va, 4 * (current_index++)); + } + } + } + } + + void addFoodAt(float x, float y, float quantity) + { + Marker* marker = addMarker(Marker(sf::Vector2f(x, y), Marker::ToFood, 100000000.0f, true)); + if (marker) { + grid_food.add(Food(x, y, 4.0f, quantity, marker)); + } + } + + Grid& getGrid(Marker::Type type) + { + if (type == Marker::ToFood) { + return grid_markers_food; + } + return grid_markers_home; + } + + sf::Vector2f size; + mutable sf::VertexArray va; + Grid grid_markers_home; + Grid grid_markers_food; + Grid grid_food; + + uint64_t markers_count; }; diff --git a/src/display_manager.cpp b/src/display_manager.cpp index 700fd908..f7280eed 100644 --- a/src/display_manager.cpp +++ b/src/display_manager.cpp @@ -2,27 +2,27 @@ DisplayManager::DisplayManager(sf::RenderTarget& target, sf::RenderWindow& window, World& world, Colony& colony) - : m_window(window) - , m_target(target) - , m_zoom(1.0f) - , m_offsetX(0.0f) - , m_offsetY(0.0f) - , speed_mode(false) - , m_va(sf::Quads, 0) - , update(true) - , debug_mode(false) - , m_world(world) - , m_colony(colony) - , clic(false) - , m_mouse_button_pressed(false) - , pause(false) - , draw_markers(true) + : m_window(window) + , m_target(target) + , m_zoom(1.0f) + , m_offsetX(0.0f) + , m_offsetY(0.0f) + , speed_mode(false) + , m_va(sf::Quads, 0) + , update(true) + , debug_mode(false) + , m_world(world) + , m_colony(colony) + , clic(false) + , m_mouse_button_pressed(false) + , pause(false) + , draw_markers(true) { - m_windowOffsetX = m_window.getSize().x * 0.5f; + m_windowOffsetX = m_window.getSize().x * 0.5f; m_windowOffsetY = m_window.getSize().y * 0.5f; - m_offsetX = m_windowOffsetX; - m_offsetY = m_windowOffsetY; + m_offsetX = m_windowOffsetX; + m_offsetY = m_windowOffsetY; m_texture.loadFromFile("res/circle.png"); } @@ -51,98 +51,98 @@ sf::Vector2f DisplayManager::displayCoordToWorldCoord(const sf::Vector2f& viewCo void DisplayManager::draw() { - sf::Clock clock; + sf::Clock clock; // draw the world's ground as a big black square sf::RectangleShape ground(sf::Vector2f(m_world.size.x, m_world.size.y)); ground.setFillColor(sf::Color::Black); - sf::RenderStates rs_ground; - rs_ground.transform.translate(m_windowOffsetX, m_windowOffsetY); - rs_ground.transform.scale(m_zoom, m_zoom); - rs_ground.transform.translate(-m_offsetX, -m_offsetY); + sf::RenderStates rs_ground; + rs_ground.transform.translate(m_windowOffsetX, m_windowOffsetY); + rs_ground.transform.scale(m_zoom, m_zoom); + rs_ground.transform.translate(-m_offsetX, -m_offsetY); m_target.draw(ground, rs_ground); - sf::RenderStates rs; - //rs.texture = &m_texture; - rs.transform.translate(m_windowOffsetX, m_windowOffsetY); - rs.transform.scale(m_zoom, m_zoom); - rs.transform.translate(-m_offsetX, -m_offsetY); + sf::RenderStates rs; + //rs.texture = &m_texture; + rs.transform.translate(m_windowOffsetX, m_windowOffsetY); + rs.transform.scale(m_zoom, m_zoom); + rs.transform.translate(-m_offsetX, -m_offsetY); - m_world.render(m_target, rs, draw_markers); - m_colony.render(m_target, rs); + m_world.render(m_target, rs, draw_markers); + m_colony.render(m_target, rs); - render_time = clock.getElapsedTime().asMicroseconds() * 0.001f; + render_time = clock.getElapsedTime().asMicroseconds() * 0.001f; } void DisplayManager::processEvents() { - sf::Vector2i mousePosition = sf::Mouse::getPosition(m_window); - - sf::Event event; - while (m_window.pollEvent(event)) - { - switch (event.type) - { - case sf::Event::Closed: - m_window.close(); - break; - case sf::Event::KeyPressed: - if (event.key.code == sf::Keyboard::Escape) m_window.close(); - else if ((event.key.code == sf::Keyboard::Subtract)) zoom(0.8f); - else if ((event.key.code == sf::Keyboard::Add)) zoom(1.2f); - else if ((event.key.code == sf::Keyboard::Space)) update = !update; - else if ((event.key.code == sf::Keyboard::E)) pause = !pause; - else if ((event.key.code == sf::Keyboard::A)) draw_markers = !draw_markers; - else if ((event.key.code == sf::Keyboard::D)) debug_mode = !debug_mode; - else if ((event.key.code == sf::Keyboard::R)) - { - m_offsetX = 0.0f; - m_offsetY = 0.0f; - m_zoom = 1.0f; - } - else if ((event.key.code == sf::Keyboard::S)) - { - speed_mode = !speed_mode; - m_window.setFramerateLimit(speed_mode ? 0 : 60); - } - break; - case sf::Event::MouseWheelMoved: - // this is an amazing zoom - zoom(1 + event.mouseWheel.delta * 0.2f); - break; - case sf::Event::MouseButtonPressed: - if (event.mouseButton.button == sf::Mouse::Left) - { - m_mouse_button_pressed = true; - m_drag_clic_position = mousePosition; - m_clic_position = mousePosition; - } - else if (event.mouseButton.button == sf::Mouse::Right) - { - clic = true; - } - break; - case sf::Event::MouseButtonReleased: - m_mouse_button_pressed = false; - if (event.mouseButton.button == sf::Mouse::Right) - { - clic = false; - } - break; - case sf::Event::MouseMoved: - if (m_mouse_button_pressed) // in this case we are dragging - { - // updating displayManager offset - const float vx = float(mousePosition.x - m_drag_clic_position.x); - const float vy = float(mousePosition.y - m_drag_clic_position.y); - addOffset(vx, vy); - m_drag_clic_position = mousePosition; - } - break; - default: - break; - } - } + sf::Vector2i mousePosition = sf::Mouse::getPosition(m_window); + + sf::Event event; + while (m_window.pollEvent(event)) + { + switch (event.type) + { + case sf::Event::Closed: + m_window.close(); + break; + case sf::Event::KeyPressed: + if (event.key.code == sf::Keyboard::Escape) m_window.close(); + else if ((event.key.code == sf::Keyboard::Subtract)) zoom(0.8f); + else if ((event.key.code == sf::Keyboard::Add)) zoom(1.2f); + else if ((event.key.code == sf::Keyboard::Space)) update = !update; + else if ((event.key.code == sf::Keyboard::E)) pause = !pause; + else if ((event.key.code == sf::Keyboard::A)) draw_markers = !draw_markers; + else if ((event.key.code == sf::Keyboard::D)) debug_mode = !debug_mode; + else if ((event.key.code == sf::Keyboard::R)) + { + m_offsetX = 0.0f; + m_offsetY = 0.0f; + m_zoom = 1.0f; + } + else if ((event.key.code == sf::Keyboard::S)) + { + speed_mode = !speed_mode; + m_window.setFramerateLimit(speed_mode ? 0 : 60); + } + break; + case sf::Event::MouseWheelMoved: + // this is an amazing zoom + zoom(1 + event.mouseWheel.delta * 0.2f); + break; + case sf::Event::MouseButtonPressed: + if (event.mouseButton.button == sf::Mouse::Left) + { + m_mouse_button_pressed = true; + m_drag_clic_position = mousePosition; + m_clic_position = mousePosition; + } + else if (event.mouseButton.button == sf::Mouse::Right) + { + clic = true; + } + break; + case sf::Event::MouseButtonReleased: + m_mouse_button_pressed = false; + if (event.mouseButton.button == sf::Mouse::Right) + { + clic = false; + } + break; + case sf::Event::MouseMoved: + if (m_mouse_button_pressed) // in this case we are dragging + { + // updating displayManager offset + const float vx = float(mousePosition.x - m_drag_clic_position.x); + const float vy = float(mousePosition.y - m_drag_clic_position.y); + addOffset(vx, vy); + m_drag_clic_position = mousePosition; + } + break; + default: + break; + } + } } diff --git a/src/main.cpp b/src/main.cpp index c639df01..61853777 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,67 +10,67 @@ void loadUserConf() { - std::ifstream conf_file("conf.txt"); - if (conf_file) { - conf_file >> Conf::WIN_WIDTH; - conf_file >> Conf::WIN_HEIGHT; - conf_file >> Conf::ANTS_COUNT; - } - else { - std::cout << "Couldn't find 'conf.txt', loading default" << std::endl; - } + std::ifstream conf_file("conf.txt"); + if (conf_file) { + conf_file >> Conf::WIN_WIDTH; + conf_file >> Conf::WIN_HEIGHT; + conf_file >> Conf::ANTS_COUNT; + } + else { + std::cout << "Couldn't find 'conf.txt', loading default" << std::endl; + } } int main() { - Conf::loadTextures(); - loadUserConf(); - - sf::ContextSettings settings; - settings.antialiasingLevel = 8; - sf::RenderWindow window(sf::VideoMode(Conf::WIN_WIDTH, Conf::WIN_HEIGHT), "AntSim", sf::Style::Default, settings); - window.setFramerateLimit(60); - - World world(Conf::WIN_WIDTH, Conf::WIN_HEIGHT); - Colony colony(Conf::WIN_WIDTH * 0.5f, Conf::WIN_HEIGHT * 0.5f, Conf::ANTS_COUNT); - world.addMarker(Marker(colony.position, Marker::ToHome, 10.0f, true)); - - DisplayManager display_manager(window, window, world, colony); - - sf::Vector2f last_clic; - - while (window.isOpen()) - { - display_manager.processEvents(); - - // Add food on clic - if (display_manager.clic) { - const sf::Vector2i mouse_position = sf::Mouse::getPosition(window); - const sf::Vector2f world_position = display_manager.displayCoordToWorldCoord(sf::Vector2f(to(mouse_position.x), to(mouse_position.y))); - const float clic_min_dist = 2.0f; - if (getLength(world_position - last_clic) > clic_min_dist) { - world.addFoodAt(world_position.x, world_position.y, 5.0f); - last_clic = world_position; - } - } - - const float dt = 0.016f; - - if (!display_manager.pause) { - colony.update(dt, world); - world.update(dt); - } - - window.clear(sf::Color(94, 87, 87)); - - display_manager.draw(); - - window.display(); - } - - // Free textures - Conf::freeTextures(); - - return 0; + Conf::loadTextures(); + loadUserConf(); + + sf::ContextSettings settings; + settings.antialiasingLevel = 8; + sf::RenderWindow window(sf::VideoMode(Conf::WIN_WIDTH, Conf::WIN_HEIGHT), "AntSim", sf::Style::Default, settings); + window.setFramerateLimit(60); + + World world(Conf::WIN_WIDTH, Conf::WIN_HEIGHT); + Colony colony(Conf::WIN_WIDTH * 0.5f, Conf::WIN_HEIGHT * 0.5f, Conf::ANTS_COUNT); + world.addMarker(Marker(colony.position, Marker::ToHome, 10.0f, true)); + + DisplayManager display_manager(window, window, world, colony); + + sf::Vector2f last_clic; + + while (window.isOpen()) + { + display_manager.processEvents(); + + // Add food on clic + if (display_manager.clic) { + const sf::Vector2i mouse_position = sf::Mouse::getPosition(window); + const sf::Vector2f world_position = display_manager.displayCoordToWorldCoord(sf::Vector2f(to(mouse_position.x), to(mouse_position.y))); + const float clic_min_dist = 2.0f; + if (getLength(world_position - last_clic) > clic_min_dist) { + world.addFoodAt(world_position.x, world_position.y, 5.0f); + last_clic = world_position; + } + } + + const float dt = 0.016f; + + if (!display_manager.pause) { + colony.update(dt, world); + world.update(dt); + } + + window.clear(sf::Color(94, 87, 87)); + + display_manager.draw(); + + window.display(); + } + + // Free textures + Conf::freeTextures(); + + return 0; } \ No newline at end of file diff --git a/src/utils.cpp b/src/utils.cpp index e6688289..17e72ec4 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -6,29 +6,29 @@ std::mt19937 gen(0); float getRandRange(float width) { - std::uniform_real_distribution distr(-width, width); - return distr(gen); + std::uniform_real_distribution distr(-width, width); + return distr(gen); } float getRandUnder(float width) { - std::uniform_real_distribution distr(0.0f, width); - return distr(gen); + std::uniform_real_distribution distr(0.0f, width); + return distr(gen); } float getAngle(const sf::Vector2f & v) { - const float a = acos(v.x / getLength(v)); - return v.y > 0.0f ? a : -a; + const float a = acos(v.x / getLength(v)); + return v.y > 0.0f ? a : -a; } float dot(const sf::Vector2f & v1, const sf::Vector2f & v2) { - return v1.x * v2.x + v1.y * v2.y; + return v1.x * v2.x + v1.y * v2.y; } float sign(const float f) { - return f < 0.0f ? -1.0f : 1.0f; + return f < 0.0f ? -1.0f : 1.0f; }