update, implement polymorphism
This commit is contained in:
188
src/ant.cpp
188
src/ant.cpp
@ -3,136 +3,124 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <numbers>
|
#include <numbers>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
Ant::Ant(Pheromones &pheromones, const Colony &colony, double x, double y)
|
Ant::Ant(Pheromones& pheromones, double x, double y)
|
||||||
: x(x), y(y), pheromones(pheromones), colony(colony) {
|
: WorldObject(x, y, 2, sf::Color::Black), pheromones(pheromones) {
|
||||||
std::random_device rd; // obtain a random number from hardware
|
std::random_device rd; // obtain a random number from hardware
|
||||||
std::mt19937 gen(rd()); // seed the generator
|
std::mt19937 gen(rd()); // seed the generator
|
||||||
|
|
||||||
std::uniform_real_distribution<> degree_distribution(0, 2 * std::numbers::pi);
|
std::uniform_real_distribution<> degree_distribution(0, 2 * std::numbers::pi);
|
||||||
direction = degree_distribution(gen);
|
direction = degree_distribution(gen);
|
||||||
|
|
||||||
setAppearance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ant::Ant(Pheromones &pheromones, const Colony &colony, unsigned short direction)
|
Ant::Ant(Pheromones& pheromones, unsigned short direction)
|
||||||
: direction(direction), pheromones(pheromones), colony(colony) {
|
: WorldObject(0, 0, 2, sf::Color::Black), direction(direction),
|
||||||
std::random_device device; // obtain a random number from hardware
|
pheromones(pheromones) {
|
||||||
std::mt19937 generator(device()); // seed the generator
|
std::random_device device; // obtain a random number from hardware
|
||||||
|
std::mt19937 generator(device()); // seed the generator
|
||||||
|
|
||||||
std::uniform_int_distribution<> width_distribution(0, WIDTH);
|
std::uniform_int_distribution<> width_distribution(0, WIDTH);
|
||||||
x = width_distribution(generator);
|
x = width_distribution(generator);
|
||||||
|
|
||||||
std::uniform_int_distribution<> height_distribution(0, HEIGHT);
|
std::uniform_int_distribution<> height_distribution(0, HEIGHT);
|
||||||
y = height_distribution(generator);
|
y = height_distribution(generator);
|
||||||
|
|
||||||
setAppearance();
|
updateAppearance();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ant::Ant(Pheromones &pheromones, const Colony &colony)
|
Ant::Ant(Pheromones& pheromones)
|
||||||
: pheromones(pheromones), colony(colony) {
|
: WorldObject(0, 0, 2, sf::Color::Black), pheromones(pheromones) {
|
||||||
std::random_device device; // obtain a random number from hardware
|
std::random_device device; // obtain a random number from hardware
|
||||||
std::mt19937 generator(device()); // seed the generator
|
std::mt19937 generator(device()); // seed the generator
|
||||||
|
|
||||||
std::uniform_int_distribution<> width_distribution(0, WIDTH);
|
std::uniform_int_distribution<> width_distribution(0, WIDTH);
|
||||||
x = width_distribution(generator);
|
x = width_distribution(generator);
|
||||||
|
|
||||||
std::uniform_int_distribution<> height_distribution(0, HEIGHT);
|
std::uniform_int_distribution<> height_distribution(0, HEIGHT);
|
||||||
y = height_distribution(generator);
|
y = height_distribution(generator);
|
||||||
|
|
||||||
std::uniform_real_distribution<> degree_distribution(0, 2 * std::numbers::pi);
|
std::uniform_real_distribution<> degree_distribution(0, 2 * std::numbers::pi);
|
||||||
direction = degree_distribution(generator);
|
direction = degree_distribution(generator);
|
||||||
|
|
||||||
setAppearance();
|
updateAppearance();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ant::setAppearance() {
|
void Ant::addToUmwelt(std::shared_ptr<WorldObject> object) {
|
||||||
appearance = sf::CircleShape(2);
|
umwelt.push_back(object);
|
||||||
appearance.setFillColor(sf::Color::Black);
|
|
||||||
appearance.setPosition(x - appearance.getRadius(), y - appearance.getRadius());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ant::update() {
|
void Ant::update() {
|
||||||
// TODO: save the generator for each ant
|
move();
|
||||||
std::random_device device; // obtain a random number from hardware
|
|
||||||
std::mt19937 generator(device()); // seed the generator
|
|
||||||
|
|
||||||
// Move
|
// Respect borders
|
||||||
std::uniform_real_distribution<> degree_distribution(-std::numbers::pi,
|
if (isOffScreen()) {
|
||||||
std::numbers::pi);
|
direction += std::numbers::pi / 2;
|
||||||
|
|
||||||
direction += degree_distribution(generator) * (1 / determination);
|
x += std::cos(direction) * speed;
|
||||||
if (direction > 2 * std::numbers::pi) {
|
y += std::sin(direction) * speed;
|
||||||
direction -= 2 * std::numbers::pi;
|
|
||||||
}
|
|
||||||
|
|
||||||
x += std::cos(direction) * speed;
|
return;
|
||||||
y += std::sin(direction) * speed;
|
}
|
||||||
|
|
||||||
// Update appearance
|
updateAppearance();
|
||||||
appearance.setPosition(x - appearance.getRadius(), y - appearance.getRadius());
|
updatePheromones();
|
||||||
if (was_home) {
|
updateUmwelt();
|
||||||
appearance.setFillColor(sf::Color::Red);
|
}
|
||||||
}
|
|
||||||
if (has_food) {
|
|
||||||
appearance.setFillColor(sf::Color::Green);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Respect borders
|
void Ant::move() {
|
||||||
if (isOffScreen()) {
|
// TODO: Leftoff, add ant-vision lol
|
||||||
direction += std::numbers::pi / 2;
|
for (int i = x; i < WIDTH * HEIGHT; ++i) {
|
||||||
|
if (true) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::random_device device; // obtain a random number from hardware
|
||||||
|
std::mt19937 generator(device()); // seed the generator
|
||||||
|
|
||||||
|
// Move
|
||||||
|
std::uniform_real_distribution<> degree_distribution(-std::numbers::pi,
|
||||||
|
std::numbers::pi);
|
||||||
|
|
||||||
|
direction += degree_distribution(generator) * (1 / determination);
|
||||||
|
if (direction > 2 * std::numbers::pi) {
|
||||||
|
direction -= 2 * std::numbers::pi;
|
||||||
|
}
|
||||||
|
|
||||||
x += std::cos(direction) * speed;
|
x += std::cos(direction) * speed;
|
||||||
y += std::sin(direction) * speed;
|
y += std::sin(direction) * speed;
|
||||||
|
|
||||||
appearance.setPosition(x - appearance.getRadius(), y - appearance.getRadius());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Visited Home?
|
|
||||||
if (!was_home && colony.antIsHome(*this)) {
|
|
||||||
was_home = true;
|
|
||||||
std::cout << "Ant has come home!" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pheromones
|
|
||||||
if (was_home && next_pheromone_home_drop == 0) {
|
|
||||||
dropHomePheromone();
|
|
||||||
next_pheromone_home_drop = pheromone_home_interval + 1;
|
|
||||||
}
|
|
||||||
next_pheromone_home_drop = std::max(0, next_pheromone_home_drop - 1);
|
|
||||||
|
|
||||||
if (has_food && next_pheromone_food_drop == 0) {
|
|
||||||
dropFoodPheromone();
|
|
||||||
next_pheromone_food_drop = pheromone_food_interval + 1;
|
|
||||||
}
|
|
||||||
next_pheromone_food_drop = std::max(0, next_pheromone_food_drop - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ant::isOffScreen() const {
|
void Ant::updateAppearance() {
|
||||||
return x < 0 || x > WIDTH || y < 0 || y > HEIGHT;
|
appearance.setPosition(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ant::dropHomePheromone() {
|
void Ant::updatePheromones() {
|
||||||
if (isOffScreen()) {
|
if (next_pheromone_drop == 0) {
|
||||||
std::cout << "Ant can't drop Pheromones offscreen!" << std::endl;
|
dropPheromone();
|
||||||
return;
|
next_pheromone_drop = pheromone_interval + 1;
|
||||||
}
|
}
|
||||||
|
next_pheromone_drop = std::max(0, next_pheromone_drop - 1);
|
||||||
// TODO: Replace this with null-safe funtion
|
|
||||||
pheromones.map[((short)y) * WIDTH + ((short)x)].color = sf::Color::Red;
|
|
||||||
// pheromones.map[((short)y - 1) * WIDTH + ((short)x)].color = sf::Color::Red;
|
|
||||||
// pheromones.map[((short)y + 1) * WIDTH + ((short)x)].color = sf::Color::Red;
|
|
||||||
// pheromones.map[((short)y) * WIDTH + ((short)x - 1)].color = sf::Color::Red;
|
|
||||||
// pheromones.map[((short)y) * WIDTH + ((short)x + 1)].color = sf::Color::Red;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ant::dropFoodPheromone() {
|
sf::Color Ant::getPheromoneType() const {
|
||||||
if (isOffScreen()) {
|
return sf::Color::Transparent;
|
||||||
std::cout << "Ant can't drop Pheromones offscreen!" << std::endl;
|
}
|
||||||
return;
|
|
||||||
}
|
void Ant::dropPheromone() {
|
||||||
|
if (isOffScreen()) {
|
||||||
pheromones.map[((short)y) * WIDTH + ((short)x)].color = sf::Color::Green;
|
std::cout << "Ant can't drop Pheromones offscreen!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pheromones.place(x, y, pheromone_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ant::updateUmwelt() {
|
||||||
|
for (std::shared_ptr<WorldObject> const& obj: umwelt) {
|
||||||
|
if (obj->collides(*this)) {
|
||||||
|
pheromone_type = obj->getPheromoneType();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
56
src/ant.hpp
56
src/ant.hpp
@ -2,51 +2,47 @@
|
|||||||
#define H_ANT
|
#define H_ANT
|
||||||
|
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
#include <random>
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "food.hpp"
|
#include "world_object.hpp"
|
||||||
#include "colony.hpp"
|
|
||||||
#include "pheromones.hpp"
|
#include "pheromones.hpp"
|
||||||
|
#include "colony.hpp"
|
||||||
extern const unsigned short WIDTH;
|
#include "food.hpp"
|
||||||
extern const unsigned short HEIGHT;
|
|
||||||
|
|
||||||
const double speed = 1;
|
const double speed = 1;
|
||||||
const double determination = 25; // straightness of the path, (0, 1]
|
const double determination = 25; // straightness of the path, (0, 1]
|
||||||
const unsigned short pheromone_home_interval = 10; // updates between pheromone-drops
|
const unsigned short pheromone_interval = 5; // updates between drops
|
||||||
const unsigned short pheromone_food_interval = 5;
|
|
||||||
|
|
||||||
const unsigned short view_angle = 45; // angle degrees to each side
|
const unsigned short view_angle = 45; // angle degrees to each side
|
||||||
const unsigned short view_distance = 25;
|
const unsigned short view_distance = 25;
|
||||||
|
|
||||||
class Ant {
|
class Ant : public WorldObject
|
||||||
double x, y;
|
{
|
||||||
double direction; // in radians
|
double direction; // in radians
|
||||||
|
|
||||||
Pheromones &pheromones;
|
Pheromones& pheromones;
|
||||||
const Colony &colony;
|
unsigned short next_pheromone_drop = 0;
|
||||||
|
sf::Color pheromone_type = sf::Color::Transparent; // ANT, HOME, FOOD
|
||||||
bool was_home = false; // TODO: Timer-based
|
|
||||||
bool has_food = false;
|
|
||||||
unsigned short next_pheromone_home_drop = 0;
|
|
||||||
unsigned short next_pheromone_food_drop = 0;
|
|
||||||
|
|
||||||
friend class Colony;
|
|
||||||
friend class Food;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sf::CircleShape appearance;
|
std::vector<std::shared_ptr<WorldObject>> umwelt;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ant(Pheromones &pheromones, const Colony &colony, double x, double y);
|
Ant(Pheromones& pheromones, double x, double y);
|
||||||
Ant(Pheromones &pheromones, const Colony &colony, unsigned short direction);
|
Ant(Pheromones& pheromones, unsigned short direction);
|
||||||
Ant(Pheromones &pheromones, const Colony &colony);
|
explicit Ant(Pheromones& pheromones);
|
||||||
void setAppearance();
|
|
||||||
|
|
||||||
void update();
|
void addToUmwelt(std::shared_ptr<WorldObject> object);
|
||||||
bool isOffScreen() const;
|
|
||||||
void dropHomePheromone(); // red
|
void update() override;
|
||||||
void dropFoodPheromone(); // green
|
sf::Color getPheromoneType() const override;
|
||||||
|
|
||||||
|
void move();
|
||||||
|
void updateAppearance();
|
||||||
|
void updatePheromones();
|
||||||
|
void dropPheromone(); // red
|
||||||
|
void updateUmwelt();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,15 +1,9 @@
|
|||||||
#include "colony.hpp"
|
#include "colony.hpp"
|
||||||
#include "ant.hpp"
|
|
||||||
|
|
||||||
Colony::Colony(double x, double y)
|
Colony::Colony(double x, double y) : WorldObject(x, y, 25, sf::Color::Red) {}
|
||||||
: x(x), y(y) {
|
|
||||||
appearance = sf::CircleShape(25);
|
|
||||||
appearance.setFillColor(sf::Color::Red);
|
|
||||||
appearance.setPosition(x - appearance.getRadius(), y - appearance.getRadius());
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: don't use appearance for this, add radius field
|
void Colony::update() {}
|
||||||
bool Colony::antIsHome(const Ant& ant) const {
|
|
||||||
return ant.x > x - appearance.getRadius() && ant.x < x + appearance.getRadius()
|
sf::Color Colony::getPheromoneType() const {
|
||||||
&& ant.y > y - appearance.getRadius() && ant.y < y + appearance.getRadius();
|
return sf::Color::Red;
|
||||||
}
|
}
|
||||||
|
@ -2,19 +2,17 @@
|
|||||||
#define __COLONY_H_
|
#define __COLONY_H_
|
||||||
|
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include "world_object.hpp"
|
||||||
|
|
||||||
class Ant; // Colony and Ant can't include eachother so forward-declare
|
class Colony : public WorldObject
|
||||||
|
{
|
||||||
class Colony {
|
|
||||||
double x, y;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sf::CircleShape appearance;
|
Colony(double x, double y);
|
||||||
|
|
||||||
public:
|
void update() override;
|
||||||
Colony(double x, double y);
|
|
||||||
|
|
||||||
bool antIsHome(const Ant& ant) const;
|
sf::Color getPheromoneType() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __COLONY_H_
|
#endif // __COLONY_H_
|
||||||
|
15
src/food.cpp
15
src/food.cpp
@ -1,14 +1,9 @@
|
|||||||
#include "food.hpp"
|
#include "food.hpp"
|
||||||
#include "ant.hpp"
|
|
||||||
|
|
||||||
Food::Food(double x, double y)
|
Food::Food(double x, double y) : WorldObject(x, y, 15, sf::Color::Green) {}
|
||||||
: x(x), y(y) {
|
|
||||||
appearance = sf::CircleShape(15);
|
|
||||||
appearance.setFillColor(sf::Color::Green);
|
|
||||||
appearance.setPosition(x - appearance.getRadius(), y - appearance.getRadius());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Food::antHasFood(const Ant &ant) const {
|
void Food::update() {}
|
||||||
return ant.x > x - appearance.getRadius() && ant.x < x + appearance.getRadius()
|
|
||||||
&& ant.y > y - appearance.getRadius() && ant.y < y + appearance.getRadius();
|
sf::Color Food::getPheromoneType() const {
|
||||||
|
return sf::Color::Green;
|
||||||
}
|
}
|
||||||
|
14
src/food.hpp
14
src/food.hpp
@ -2,19 +2,17 @@
|
|||||||
#define __FOOD_H_
|
#define __FOOD_H_
|
||||||
|
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include "world_object.hpp"
|
||||||
|
|
||||||
class Ant;
|
class Food : public WorldObject
|
||||||
|
{
|
||||||
class Food {
|
|
||||||
double x, y;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sf::CircleShape appearance;
|
Food(double x, double y);
|
||||||
|
|
||||||
public:
|
void update() override;
|
||||||
Food(double x, double y);
|
|
||||||
|
|
||||||
bool antHasFood(const Ant& ant) const;
|
sf::Color getPheromoneType() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __FOOD_H_
|
#endif // __FOOD_H_
|
||||||
|
37
src/main.cpp
37
src/main.cpp
@ -5,18 +5,21 @@
|
|||||||
|
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
|
#include "pheromones.hpp"
|
||||||
|
#include "world_object.hpp"
|
||||||
#include "ant.hpp"
|
#include "ant.hpp"
|
||||||
#include "colony.hpp"
|
#include "colony.hpp"
|
||||||
|
#include "food.hpp"
|
||||||
|
|
||||||
const unsigned short HEIGHT = 500;
|
const unsigned short HEIGHT = 500;
|
||||||
const unsigned short WIDTH = 500;
|
const unsigned short WIDTH = 500;
|
||||||
const unsigned short FPS = 60;
|
const unsigned short FPS = 60;
|
||||||
|
|
||||||
const unsigned short ANTCOUNT = 50;
|
const unsigned short ANTCOUNT = 500;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
sf::ContextSettings settings;
|
sf::ContextSettings settings;
|
||||||
settings.antialiasingLevel = 8;
|
// settings.antialiasingLevel = 8;
|
||||||
|
|
||||||
sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "Ants", sf::Style::Close, settings);
|
sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "Ants", sf::Style::Close, settings);
|
||||||
window.setFramerateLimit(FPS); // Limit FPS
|
window.setFramerateLimit(FPS); // Limit FPS
|
||||||
@ -24,14 +27,19 @@ int main(int argc, char *argv[]) {
|
|||||||
float t = 0.0; // Verstrichene Zeit in ms
|
float t = 0.0; // Verstrichene Zeit in ms
|
||||||
float dt = 1.0 / FPS; // Schrittweite in ms
|
float dt = 1.0 / FPS; // Schrittweite in ms
|
||||||
|
|
||||||
Pheromones pheromones = Pheromones();
|
Pheromones pheromones;
|
||||||
const Colony colony = Colony(WIDTH / 2, HEIGHT / 2);
|
std::vector<std::unique_ptr<Ant>> ants; // Use pointer bc we can't instatiate abstract classes
|
||||||
const Food foodA = Food(50, 50);
|
|
||||||
|
|
||||||
std::vector<Ant> ants;
|
|
||||||
ants.reserve(ANTCOUNT);
|
ants.reserve(ANTCOUNT);
|
||||||
|
|
||||||
|
std::shared_ptr<Colony> colony = std::make_shared<Colony>(WIDTH / 2, HEIGHT / 2);
|
||||||
|
std::shared_ptr<Food> foodA = std::make_shared<Food>(50, 50);
|
||||||
|
|
||||||
for (int i = 0; i < ANTCOUNT; ++i) {
|
for (int i = 0; i < ANTCOUNT; ++i) {
|
||||||
ants.push_back(Ant(pheromones, colony));
|
ants.push_back(std::make_unique<Ant>(pheromones));
|
||||||
|
}
|
||||||
|
for (std::unique_ptr<Ant> const& ant : ants) {
|
||||||
|
ant->addToUmwelt(colony);
|
||||||
|
ant->addToUmwelt(foodA);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (window.isOpen()) {
|
while (window.isOpen()) {
|
||||||
@ -45,18 +53,19 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
// Update
|
// Update
|
||||||
t += dt;
|
t += dt;
|
||||||
for (unsigned long i = 0; i < ants.size(); ++i) {
|
for (std::unique_ptr<Ant> const& obj: ants) {
|
||||||
ants[i].update();
|
obj->update();
|
||||||
}
|
}
|
||||||
pheromones.update();
|
pheromones.update();
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
window.clear(sf::Color::White);
|
window.clear(sf::Color::White);
|
||||||
window.draw(pheromones.map);
|
window.draw(pheromones.map);
|
||||||
for (Ant const& ant: ants) {
|
for (std::unique_ptr<Ant> const& obj: ants) {
|
||||||
window.draw(ant.appearance);
|
window.draw(obj->appearance);
|
||||||
}
|
}
|
||||||
window.draw(colony.appearance);
|
window.draw(colony->appearance);
|
||||||
|
window.draw(foodA->appearance);
|
||||||
window.display();
|
window.display();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
#ifndef __OBJECT_H_
|
|
||||||
#define __OBJECT_H_
|
|
||||||
|
|
||||||
#include <SFML/Graphics.hpp>
|
|
||||||
|
|
||||||
class Object {
|
|
||||||
protected:
|
|
||||||
double x, y;
|
|
||||||
const unsigned short radius;
|
|
||||||
|
|
||||||
sf::CircleShape appearance;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Object(double x, double y, unsigned short radius);
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual bool collide(const Object& other);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __OBJECT_H_
|
|
@ -4,19 +4,31 @@ extern const unsigned short WIDTH;
|
|||||||
extern const unsigned short HEIGHT;
|
extern const unsigned short HEIGHT;
|
||||||
|
|
||||||
Pheromones::Pheromones() {
|
Pheromones::Pheromones() {
|
||||||
for (unsigned short y = 0; y < HEIGHT; ++y) {
|
for (unsigned short y = 0; y < HEIGHT; ++y) {
|
||||||
for (unsigned short x = 0; x < WIDTH; ++x) {
|
for (unsigned short x = 0; x < WIDTH; ++x) {
|
||||||
map[y * WIDTH + x].position.x = x;
|
map[y * WIDTH + x].position.x = x;
|
||||||
map[y * WIDTH + x].position.y = y;
|
map[y * WIDTH + x].position.y = y;
|
||||||
map[y * WIDTH + x].color = sf::Color(0, 0, 0, 0);
|
map[y * WIDTH + x].color = sf::Color(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pheromones::place(unsigned short x, unsigned short y, sf::Color col) {
|
||||||
|
map[y * WIDTH + x].color = col;
|
||||||
|
map[(y + 1) * WIDTH + x].color = col;
|
||||||
|
map[(y - 1) * WIDTH + x].color = col;
|
||||||
|
map[y * WIDTH + (x + 1)].color = col;
|
||||||
|
map[y * WIDTH + (x - 1)].color = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pheromones::update() {
|
void Pheromones::update() {
|
||||||
for (int i = 0; i < WIDTH * HEIGHT; ++i) {
|
for (int i = 0; i < WIDTH * HEIGHT; ++i) {
|
||||||
// if (map[i].color != sf::Color::White) {
|
map[i].color -= sf::Color(decay, decay, decay, decay);
|
||||||
map[i].color -= sf::Color(decay, decay, decay, decay);
|
}
|
||||||
// }
|
for (int x = 0; x < WIDTH; ++x) {
|
||||||
}
|
map[(HEIGHT / 2) * WIDTH + x].color = sf::Color::Black;
|
||||||
|
}
|
||||||
|
for (int y = 0; y < HEIGHT; ++y) {
|
||||||
|
map[y * WIDTH + (WIDTH / 2)].color = sf::Color::Black;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,17 @@ extern const unsigned short HEIGHT;
|
|||||||
|
|
||||||
const unsigned short decay = 1;
|
const unsigned short decay = 1;
|
||||||
|
|
||||||
class Pheromones {
|
class Pheromones
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
sf::VertexArray map = sf::VertexArray(sf::PrimitiveType::Points, WIDTH * HEIGHT);
|
sf::VertexArray map = sf::VertexArray(sf::PrimitiveType::Points, WIDTH * HEIGHT);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Pheromones();
|
Pheromones();
|
||||||
|
|
||||||
void update();
|
void place(unsigned short x, unsigned short y, sf::Color col);
|
||||||
|
|
||||||
|
void update();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
#ifndef __UMWELT_H_
|
|
||||||
#define __UMWELT_H_
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "object.hpp"
|
|
||||||
|
|
||||||
struct Umwelt {
|
|
||||||
std::vector<Object> objects;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __UMWELT_H_
|
|
28
src/world_object.cpp
Normal file
28
src/world_object.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "world_object.hpp"
|
||||||
|
|
||||||
|
WorldObject::WorldObject(double x, double y, unsigned short radius, sf::Color color)
|
||||||
|
: x(x), y(y), radius(radius) {
|
||||||
|
appearance = sf::CircleShape(radius);
|
||||||
|
appearance.setFillColor(color);
|
||||||
|
appearance.setPosition(x, y);
|
||||||
|
appearance.setOrigin(radius, radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WorldObject::isOffScreen() const {
|
||||||
|
return x < 0 || x > WIDTH || y < 0 || y > HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WorldObject::collides(const WorldObject& other) const {
|
||||||
|
return distance(other) < radius + other.radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
double WorldObject::distance(const WorldObject& other) const {
|
||||||
|
const double dx = std::abs(x - other.x);
|
||||||
|
const double dy = std::abs(y - other.y);
|
||||||
|
return std::sqrt(dx * dx + dy * dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
double WorldObject::angle(const WorldObject& other) const {
|
||||||
|
const double dy = std::abs(y - other.y);
|
||||||
|
return std::asin(dy / distance(other));
|
||||||
|
}
|
34
src/world_object.hpp
Normal file
34
src/world_object.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef __OBJECT_H_
|
||||||
|
#define __OBJECT_H_
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
|
extern const unsigned short WIDTH;
|
||||||
|
extern const unsigned short HEIGHT;
|
||||||
|
|
||||||
|
class WorldObject
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
double x, y;
|
||||||
|
const unsigned short radius;
|
||||||
|
|
||||||
|
public:
|
||||||
|
sf::CircleShape appearance;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
WorldObject(double x, double y, unsigned short radius, sf::Color color);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool isOffScreen() const; // virtual: late-binding, no static linkage
|
||||||
|
bool collides(const WorldObject& other) const;
|
||||||
|
|
||||||
|
double distance(const WorldObject& other) const;
|
||||||
|
|
||||||
|
double angle(const WorldObject& other) const;
|
||||||
|
|
||||||
|
virtual void update() = 0; // pure virtual: has to be overridden
|
||||||
|
virtual sf::Color getPheromoneType() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __OBJECT_H_
|
Reference in New Issue
Block a user