update, implement polymorphism
This commit is contained in:
188
src/ant.cpp
188
src/ant.cpp
@ -3,136 +3,124 @@
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <numbers>
|
||||
#include <random>
|
||||
|
||||
Ant::Ant(Pheromones &pheromones, const Colony &colony, double x, double y)
|
||||
: x(x), y(y), pheromones(pheromones), colony(colony) {
|
||||
std::random_device rd; // obtain a random number from hardware
|
||||
std::mt19937 gen(rd()); // seed the generator
|
||||
Ant::Ant(Pheromones& pheromones, double x, double y)
|
||||
: WorldObject(x, y, 2, sf::Color::Black), pheromones(pheromones) {
|
||||
std::random_device rd; // obtain a random number from hardware
|
||||
std::mt19937 gen(rd()); // seed the generator
|
||||
|
||||
std::uniform_real_distribution<> degree_distribution(0, 2 * std::numbers::pi);
|
||||
direction = degree_distribution(gen);
|
||||
|
||||
setAppearance();
|
||||
std::uniform_real_distribution<> degree_distribution(0, 2 * std::numbers::pi);
|
||||
direction = degree_distribution(gen);
|
||||
}
|
||||
|
||||
Ant::Ant(Pheromones &pheromones, const Colony &colony, unsigned short direction)
|
||||
: direction(direction), pheromones(pheromones), colony(colony) {
|
||||
std::random_device device; // obtain a random number from hardware
|
||||
std::mt19937 generator(device()); // seed the generator
|
||||
Ant::Ant(Pheromones& pheromones, unsigned short direction)
|
||||
: WorldObject(0, 0, 2, sf::Color::Black), direction(direction),
|
||||
pheromones(pheromones) {
|
||||
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);
|
||||
x = width_distribution(generator);
|
||||
std::uniform_int_distribution<> width_distribution(0, WIDTH);
|
||||
x = width_distribution(generator);
|
||||
|
||||
std::uniform_int_distribution<> height_distribution(0, HEIGHT);
|
||||
y = height_distribution(generator);
|
||||
std::uniform_int_distribution<> height_distribution(0, HEIGHT);
|
||||
y = height_distribution(generator);
|
||||
|
||||
setAppearance();
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
Ant::Ant(Pheromones &pheromones, const Colony &colony)
|
||||
: pheromones(pheromones), colony(colony) {
|
||||
std::random_device device; // obtain a random number from hardware
|
||||
std::mt19937 generator(device()); // seed the generator
|
||||
Ant::Ant(Pheromones& pheromones)
|
||||
: WorldObject(0, 0, 2, sf::Color::Black), pheromones(pheromones) {
|
||||
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);
|
||||
x = width_distribution(generator);
|
||||
std::uniform_int_distribution<> width_distribution(0, WIDTH);
|
||||
x = width_distribution(generator);
|
||||
|
||||
std::uniform_int_distribution<> height_distribution(0, HEIGHT);
|
||||
y = height_distribution(generator);
|
||||
std::uniform_int_distribution<> height_distribution(0, HEIGHT);
|
||||
y = height_distribution(generator);
|
||||
|
||||
std::uniform_real_distribution<> degree_distribution(0, 2 * std::numbers::pi);
|
||||
direction = degree_distribution(generator);
|
||||
std::uniform_real_distribution<> degree_distribution(0, 2 * std::numbers::pi);
|
||||
direction = degree_distribution(generator);
|
||||
|
||||
setAppearance();
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
void Ant::setAppearance() {
|
||||
appearance = sf::CircleShape(2);
|
||||
appearance.setFillColor(sf::Color::Black);
|
||||
appearance.setPosition(x - appearance.getRadius(), y - appearance.getRadius());
|
||||
void Ant::addToUmwelt(std::shared_ptr<WorldObject> object) {
|
||||
umwelt.push_back(object);
|
||||
}
|
||||
|
||||
void Ant::update() {
|
||||
// TODO: save the generator for each ant
|
||||
std::random_device device; // obtain a random number from hardware
|
||||
std::mt19937 generator(device()); // seed the generator
|
||||
move();
|
||||
|
||||
// Move
|
||||
std::uniform_real_distribution<> degree_distribution(-std::numbers::pi,
|
||||
std::numbers::pi);
|
||||
// Respect borders
|
||||
if (isOffScreen()) {
|
||||
direction += std::numbers::pi / 2;
|
||||
|
||||
direction += degree_distribution(generator) * (1 / determination);
|
||||
if (direction > 2 * std::numbers::pi) {
|
||||
direction -= 2 * std::numbers::pi;
|
||||
}
|
||||
x += std::cos(direction) * speed;
|
||||
y += std::sin(direction) * speed;
|
||||
|
||||
x += std::cos(direction) * speed;
|
||||
y += std::sin(direction) * speed;
|
||||
return;
|
||||
}
|
||||
|
||||
// Update appearance
|
||||
appearance.setPosition(x - appearance.getRadius(), y - appearance.getRadius());
|
||||
if (was_home) {
|
||||
appearance.setFillColor(sf::Color::Red);
|
||||
}
|
||||
if (has_food) {
|
||||
appearance.setFillColor(sf::Color::Green);
|
||||
}
|
||||
updateAppearance();
|
||||
updatePheromones();
|
||||
updateUmwelt();
|
||||
}
|
||||
|
||||
// Respect borders
|
||||
if (isOffScreen()) {
|
||||
direction += std::numbers::pi / 2;
|
||||
void Ant::move() {
|
||||
// TODO: Leftoff, add ant-vision lol
|
||||
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;
|
||||
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 {
|
||||
return x < 0 || x > WIDTH || y < 0 || y > HEIGHT;
|
||||
void Ant::updateAppearance() {
|
||||
appearance.setPosition(x, y);
|
||||
}
|
||||
|
||||
void Ant::dropHomePheromone() {
|
||||
if (isOffScreen()) {
|
||||
std::cout << "Ant can't drop Pheromones offscreen!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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::updatePheromones() {
|
||||
if (next_pheromone_drop == 0) {
|
||||
dropPheromone();
|
||||
next_pheromone_drop = pheromone_interval + 1;
|
||||
}
|
||||
next_pheromone_drop = std::max(0, next_pheromone_drop - 1);
|
||||
}
|
||||
|
||||
void Ant::dropFoodPheromone() {
|
||||
if (isOffScreen()) {
|
||||
std::cout << "Ant can't drop Pheromones offscreen!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
pheromones.map[((short)y) * WIDTH + ((short)x)].color = sf::Color::Green;
|
||||
sf::Color Ant::getPheromoneType() const {
|
||||
return sf::Color::Transparent;
|
||||
}
|
||||
|
||||
void Ant::dropPheromone() {
|
||||
if (isOffScreen()) {
|
||||
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
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "food.hpp"
|
||||
#include "colony.hpp"
|
||||
#include "world_object.hpp"
|
||||
#include "pheromones.hpp"
|
||||
|
||||
extern const unsigned short WIDTH;
|
||||
extern const unsigned short HEIGHT;
|
||||
#include "colony.hpp"
|
||||
#include "food.hpp"
|
||||
|
||||
const double speed = 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_food_interval = 5;
|
||||
const unsigned short pheromone_interval = 5; // updates between drops
|
||||
|
||||
const unsigned short view_angle = 45; // angle degrees to each side
|
||||
const unsigned short view_distance = 25;
|
||||
|
||||
class Ant {
|
||||
double x, y;
|
||||
double direction; // in radians
|
||||
class Ant : public WorldObject
|
||||
{
|
||||
double direction; // in radians
|
||||
|
||||
Pheromones &pheromones;
|
||||
const Colony &colony;
|
||||
|
||||
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;
|
||||
Pheromones& pheromones;
|
||||
unsigned short next_pheromone_drop = 0;
|
||||
sf::Color pheromone_type = sf::Color::Transparent; // ANT, HOME, FOOD
|
||||
|
||||
public:
|
||||
sf::CircleShape appearance;
|
||||
std::vector<std::shared_ptr<WorldObject>> umwelt;
|
||||
|
||||
public:
|
||||
Ant(Pheromones &pheromones, const Colony &colony, double x, double y);
|
||||
Ant(Pheromones &pheromones, const Colony &colony, unsigned short direction);
|
||||
Ant(Pheromones &pheromones, const Colony &colony);
|
||||
void setAppearance();
|
||||
Ant(Pheromones& pheromones, double x, double y);
|
||||
Ant(Pheromones& pheromones, unsigned short direction);
|
||||
explicit Ant(Pheromones& pheromones);
|
||||
|
||||
void update();
|
||||
bool isOffScreen() const;
|
||||
void dropHomePheromone(); // red
|
||||
void dropFoodPheromone(); // green
|
||||
void addToUmwelt(std::shared_ptr<WorldObject> object);
|
||||
|
||||
void update() override;
|
||||
sf::Color getPheromoneType() const override;
|
||||
|
||||
void move();
|
||||
void updateAppearance();
|
||||
void updatePheromones();
|
||||
void dropPheromone(); // red
|
||||
void updateUmwelt();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,15 +1,9 @@
|
||||
#include "colony.hpp"
|
||||
#include "ant.hpp"
|
||||
|
||||
Colony::Colony(double x, double y)
|
||||
: x(x), y(y) {
|
||||
appearance = sf::CircleShape(25);
|
||||
appearance.setFillColor(sf::Color::Red);
|
||||
appearance.setPosition(x - appearance.getRadius(), y - appearance.getRadius());
|
||||
}
|
||||
Colony::Colony(double x, double y) : WorldObject(x, y, 25, sf::Color::Red) {}
|
||||
|
||||
// TODO: don't use appearance for this, add radius field
|
||||
bool Colony::antIsHome(const Ant& ant) const {
|
||||
return ant.x > x - appearance.getRadius() && ant.x < x + appearance.getRadius()
|
||||
&& ant.y > y - appearance.getRadius() && ant.y < y + appearance.getRadius();
|
||||
void Colony::update() {}
|
||||
|
||||
sf::Color Colony::getPheromoneType() const {
|
||||
return sf::Color::Red;
|
||||
}
|
||||
|
@ -2,19 +2,17 @@
|
||||
#define __COLONY_H_
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "world_object.hpp"
|
||||
|
||||
class Ant; // Colony and Ant can't include eachother so forward-declare
|
||||
|
||||
class Colony {
|
||||
double x, y;
|
||||
class Colony : public WorldObject
|
||||
{
|
||||
|
||||
public:
|
||||
sf::CircleShape appearance;
|
||||
Colony(double x, double y);
|
||||
|
||||
public:
|
||||
Colony(double x, double y);
|
||||
void update() override;
|
||||
|
||||
bool antIsHome(const Ant& ant) const;
|
||||
sf::Color getPheromoneType() const override;
|
||||
};
|
||||
|
||||
#endif // __COLONY_H_
|
||||
|
15
src/food.cpp
15
src/food.cpp
@ -1,14 +1,9 @@
|
||||
#include "food.hpp"
|
||||
#include "ant.hpp"
|
||||
|
||||
Food::Food(double x, double y)
|
||||
: x(x), y(y) {
|
||||
appearance = sf::CircleShape(15);
|
||||
appearance.setFillColor(sf::Color::Green);
|
||||
appearance.setPosition(x - appearance.getRadius(), y - appearance.getRadius());
|
||||
}
|
||||
Food::Food(double x, double y) : WorldObject(x, y, 15, sf::Color::Green) {}
|
||||
|
||||
bool Food::antHasFood(const Ant &ant) const {
|
||||
return ant.x > x - appearance.getRadius() && ant.x < x + appearance.getRadius()
|
||||
&& ant.y > y - appearance.getRadius() && ant.y < y + appearance.getRadius();
|
||||
void Food::update() {}
|
||||
|
||||
sf::Color Food::getPheromoneType() const {
|
||||
return sf::Color::Green;
|
||||
}
|
||||
|
14
src/food.hpp
14
src/food.hpp
@ -2,19 +2,17 @@
|
||||
#define __FOOD_H_
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "world_object.hpp"
|
||||
|
||||
class Ant;
|
||||
|
||||
class Food {
|
||||
double x, y;
|
||||
class Food : public WorldObject
|
||||
{
|
||||
|
||||
public:
|
||||
sf::CircleShape appearance;
|
||||
Food(double x, double y);
|
||||
|
||||
public:
|
||||
Food(double x, double y);
|
||||
void update() override;
|
||||
|
||||
bool antHasFood(const Ant& ant) const;
|
||||
sf::Color getPheromoneType() const override;
|
||||
};
|
||||
|
||||
#endif // __FOOD_H_
|
||||
|
37
src/main.cpp
37
src/main.cpp
@ -5,18 +5,21 @@
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
#include "pheromones.hpp"
|
||||
#include "world_object.hpp"
|
||||
#include "ant.hpp"
|
||||
#include "colony.hpp"
|
||||
#include "food.hpp"
|
||||
|
||||
const unsigned short HEIGHT = 500;
|
||||
const unsigned short WIDTH = 500;
|
||||
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;
|
||||
settings.antialiasingLevel = 8;
|
||||
// settings.antialiasingLevel = 8;
|
||||
|
||||
sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "Ants", sf::Style::Close, settings);
|
||||
window.setFramerateLimit(FPS); // Limit FPS
|
||||
@ -24,14 +27,19 @@ int main(int argc, char *argv[]) {
|
||||
float t = 0.0; // Verstrichene Zeit in ms
|
||||
float dt = 1.0 / FPS; // Schrittweite in ms
|
||||
|
||||
Pheromones pheromones = Pheromones();
|
||||
const Colony colony = Colony(WIDTH / 2, HEIGHT / 2);
|
||||
const Food foodA = Food(50, 50);
|
||||
|
||||
std::vector<Ant> ants;
|
||||
Pheromones pheromones;
|
||||
std::vector<std::unique_ptr<Ant>> ants; // Use pointer bc we can't instatiate abstract classes
|
||||
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) {
|
||||
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()) {
|
||||
@ -45,18 +53,19 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// Update
|
||||
t += dt;
|
||||
for (unsigned long i = 0; i < ants.size(); ++i) {
|
||||
ants[i].update();
|
||||
for (std::unique_ptr<Ant> const& obj: ants) {
|
||||
obj->update();
|
||||
}
|
||||
pheromones.update();
|
||||
|
||||
// Render
|
||||
window.clear(sf::Color::White);
|
||||
window.draw(pheromones.map);
|
||||
for (Ant const& ant: ants) {
|
||||
window.draw(ant.appearance);
|
||||
for (std::unique_ptr<Ant> const& obj: ants) {
|
||||
window.draw(obj->appearance);
|
||||
}
|
||||
window.draw(colony.appearance);
|
||||
window.draw(colony->appearance);
|
||||
window.draw(foodA->appearance);
|
||||
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;
|
||||
|
||||
Pheromones::Pheromones() {
|
||||
for (unsigned short y = 0; y < HEIGHT; ++y) {
|
||||
for (unsigned short x = 0; x < WIDTH; ++x) {
|
||||
map[y * WIDTH + x].position.x = x;
|
||||
map[y * WIDTH + x].position.y = y;
|
||||
map[y * WIDTH + x].color = sf::Color(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
for (unsigned short y = 0; y < HEIGHT; ++y) {
|
||||
for (unsigned short x = 0; x < WIDTH; ++x) {
|
||||
map[y * WIDTH + x].position.x = x;
|
||||
map[y * WIDTH + x].position.y = y;
|
||||
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() {
|
||||
for (int i = 0; i < WIDTH * HEIGHT; ++i) {
|
||||
// if (map[i].color != sf::Color::White) {
|
||||
map[i].color -= sf::Color(decay, decay, decay, decay);
|
||||
// }
|
||||
}
|
||||
for (int i = 0; i < WIDTH * HEIGHT; ++i) {
|
||||
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;
|
||||
|
||||
class Pheromones {
|
||||
class Pheromones
|
||||
{
|
||||
public:
|
||||
sf::VertexArray map = sf::VertexArray(sf::PrimitiveType::Points, WIDTH * HEIGHT);
|
||||
sf::VertexArray map = sf::VertexArray(sf::PrimitiveType::Points, WIDTH * HEIGHT);
|
||||
|
||||
public:
|
||||
Pheromones();
|
||||
Pheromones();
|
||||
|
||||
void update();
|
||||
void place(unsigned short x, unsigned short y, sf::Color col);
|
||||
|
||||
void update();
|
||||
};
|
||||
|
||||
#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