-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
272 additions
and
230 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
#include "Boids.h" | ||
#include <cmath> | ||
|
||
#define PI 3.14159265 | ||
|
||
int ReturnIntRandom(int lower, int upper) | ||
{ | ||
return (rand() % (upper - lower + 1)) + lower; | ||
} | ||
|
||
float ReturnFloatRandom(float lower, float upper) | ||
{ | ||
float r3 = lower + static_cast<float>(rand()) / (static_cast<float>(RAND_MAX / (upper - lower))); | ||
} | ||
|
||
Boids::Boids() | ||
{ | ||
texture.loadFromFile("arrow.png"); | ||
sprite.setTexture(texture); | ||
sprite.setOrigin(sf::Vector2f(texture.getSize().x/2,texture.getSize().y/2)); | ||
|
||
sprite.setScale(0.02f, 0.02f); | ||
position = Vector2f(ReturnIntRandom(0, 800), ReturnIntRandom(0, 500)); | ||
sprite.setPosition(position.ConverttoSF()); | ||
auto pi = 4.0 * atan(1.0); | ||
auto phi = rand() / (double)(RAND_MAX); | ||
phi *= 2.0 * pi; | ||
velocity = Vector2f(sin(phi), cos(phi)); | ||
|
||
velocity = velocity.setMag(ReturnIntRandom(2, 4)); | ||
acceleration = Vector2f(0.0f, 0.0f); | ||
maxForce = 1.5f; | ||
maxSpeed = 5.0f; | ||
} | ||
|
||
|
||
void Boids::AvoidEdges(const int& HEIGHT, const int& WIDTH) | ||
{ | ||
if (position.x > WIDTH) | ||
{ | ||
position.x = 0; | ||
} | ||
else if (position.x < 0) | ||
{ | ||
position.x = WIDTH; | ||
} | ||
if (position.y > HEIGHT) | ||
{ | ||
position.y = 0; | ||
} | ||
else if (position.y < 0) | ||
{ | ||
position.y = HEIGHT; | ||
} | ||
} | ||
|
||
template <typename std::size_t S> | ||
Vector2f Boids::align(Boids (&otherBoids)[S], int alignmentRadius) | ||
{ | ||
int perceptionRadius = alignmentRadius; | ||
Vector2f steering = Vector2f(0.f, 0.f); | ||
int total = 0; | ||
|
||
for (int i = 0; i < sizeof(otherBoids) / sizeof(otherBoids[0]); i++) | ||
{ | ||
auto distance = position.dist(otherBoids[i].position); | ||
if (*this != otherBoids[i] && distance < perceptionRadius) | ||
{ | ||
steering = steering.add(otherBoids[i].velocity); | ||
total++; | ||
} | ||
} | ||
if (total > 0) | ||
{ | ||
steering = steering.divide(total); | ||
steering = steering.setMag(maxSpeed); | ||
steering = steering.sub(velocity); | ||
steering = steering.limit(maxForce); | ||
} | ||
return steering; | ||
} | ||
|
||
|
||
template <typename std::size_t S> | ||
Vector2f Boids::separation(Boids (&otherBoids)[S], int separationRadius) | ||
{ | ||
int perceptionRadius = separationRadius; | ||
Vector2f steering = Vector2f(0.f, 0.f); | ||
|
||
int total = 0; | ||
for (int i = 0; i < sizeof(otherBoids) / sizeof(otherBoids[0]); i++) | ||
{ | ||
float distance = position.dist(otherBoids[i].position); | ||
if ((*this != otherBoids[i]) && (distance < perceptionRadius) && (distance > 0.0f)) | ||
{ | ||
|
||
Vector2f diff = position.sub(otherBoids[i].position); | ||
if (distance < 1.0f) | ||
diff = diff.mult(1 / (distance * distance)); | ||
steering = steering.add(diff); | ||
total++; | ||
} | ||
} | ||
if (total > 0) | ||
{ | ||
steering = steering.divide(total); | ||
steering = steering.setMag(maxSpeed); | ||
steering = steering.sub(velocity); | ||
steering = steering.limit(maxForce); | ||
} | ||
return steering; | ||
} | ||
|
||
Vector2f Boids::collision(std::vector<sf::CircleShape> &shape) | ||
{ | ||
int perceptionRadius = 50; | ||
Vector2f steering = Vector2f(0.f, 0.f); | ||
|
||
int total = 0; | ||
for (int i = 0; i < shape.size(); i++) | ||
{ | ||
float distance = position.dist(Vector2f(shape[i].getPosition().x, shape[i].getPosition().y)); | ||
if ((distance < perceptionRadius) && (distance > 0.0f)) | ||
{ | ||
|
||
Vector2f diff = position.sub(Vector2f(shape[i].getPosition().x, shape[i].getPosition().y)); | ||
if (distance < 1.0f) | ||
diff = diff.mult(1 / (distance * distance)); | ||
steering = steering.add(diff); | ||
total++; | ||
} | ||
} | ||
if (total > 0) | ||
{ | ||
steering = steering.divide(total); | ||
steering = steering.setMag(maxSpeed); | ||
steering = steering.sub(velocity); | ||
steering = steering.limit(maxForce); | ||
} | ||
return steering; | ||
} | ||
|
||
template <typename std::size_t S> | ||
Vector2f Boids::cohesion(Boids (&otherBoids)[S], int cohesionRadius) | ||
{ | ||
int perceptionRadius = cohesionRadius; | ||
Vector2f steering = Vector2f(0.f, 0.f); | ||
int total = 0; | ||
for (int i = 0; i < sizeof(otherBoids) / sizeof(otherBoids[0]); i++) | ||
{ | ||
auto distance = position.dist(otherBoids[i].position); | ||
if (*this != otherBoids[i] && distance < perceptionRadius) | ||
{ | ||
steering = steering.add(otherBoids[i].position); | ||
total++; | ||
} | ||
} | ||
if (total > 0) | ||
{ | ||
steering = steering.divide(total); | ||
steering = steering.sub(position); | ||
steering = steering.setMag(maxSpeed); | ||
steering = steering.sub(velocity); | ||
steering = steering.limit(maxForce); | ||
} | ||
return steering; | ||
} | ||
|
||
template < std::size_t S> | ||
void Boids::flock(Boids (&otherBoids)[S], std::vector<sf::CircleShape> &shape, int alignmentRadius, int cohesionRadius, int separationRadius) | ||
{ | ||
Vector2f alignment = align(otherBoids, alignmentRadius); | ||
Vector2f cohes = cohesion(otherBoids, cohesionRadius); | ||
Vector2f sep = separation(otherBoids, separationRadius); | ||
Vector2f col = collision(shape); | ||
|
||
acceleration = acceleration.add(alignment); | ||
acceleration = acceleration.add(cohes); | ||
acceleration = acceleration.add(sep); | ||
acceleration = acceleration.add(col); | ||
} | ||
|
||
void Boids::update() | ||
{ | ||
position = position.add(velocity); | ||
velocity = velocity.add(acceleration); | ||
velocity = velocity.limit(maxSpeed); | ||
acceleration = acceleration.mult(0); | ||
|
||
float angle = atan2(velocity.y, velocity.x); | ||
angle = angle * (180 / PI) - 90; | ||
angle = (velocity.x < 0.0f || velocity.y < 0.0f) ? angle - 180 : angle + 180; | ||
|
||
sprite.setRotation(angle); | ||
sprite.setPosition(position.ConverttoSF()); | ||
} | ||
|
||
void Boids::draw(sf::RenderWindow &window) | ||
{ | ||
window.draw(sprite); | ||
} | ||
|
||
|
||
|
||
bool operator==(const Boids &a, const Boids &b) | ||
{ | ||
return (a.position.x == b.position.x) && (a.position.y == b.position.y) && (a.velocity.x == b.velocity.x) && (a.velocity.y == b.velocity.y) && (a.acceleration.x == b.acceleration.x) && (a.acceleration.y == b.acceleration.y); | ||
} | ||
|
||
bool operator!=(const Boids &a, const Boids &b) | ||
{ | ||
return !(a == b); | ||
} | ||
|
||
template void Boids::flock(Boids (&otherBoids)[200], std::vector<sf::CircleShape> &shape, int alignmentRadius, int cohesionRadius, int separationRadius); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#ifndef BOIDS_H | ||
#define BOIDS_H | ||
#include "Vector2.h" | ||
|
||
class Boids | ||
{ | ||
Vector2f position; | ||
Vector2f velocity; | ||
Vector2f acceleration; | ||
float maxSpeed, maxForce; | ||
sf::Texture texture; | ||
sf::Sprite sprite; | ||
|
||
public: | ||
Boids(); | ||
void AvoidEdges(const int& HEIGHT, const int& WIDTH); | ||
|
||
template < std::size_t S> | ||
Vector2f align(Boids (&otherBoids)[S], int alignmentRadius); | ||
|
||
template < std::size_t S> | ||
Vector2f separation(Boids (&otherBoids)[S], int separationRadius); | ||
|
||
template < std::size_t S> | ||
Vector2f cohesion(Boids (&otherBoids)[S], int cohesionRadius); | ||
|
||
Vector2f collision(std::vector<sf::CircleShape>& shape); | ||
|
||
template <std::size_t S> | ||
void flock(Boids (&otherBoids)[S], std::vector<sf::CircleShape> &shape, int alignmentRadius, int aohesionRadius, int separationRadius); | ||
|
||
void update(); | ||
void draw(sf::RenderWindow& window); | ||
|
||
friend bool operator==(const Boids &a, const Boids &b); | ||
friend bool operator!=(const Boids &a, const Boids &b); | ||
}; | ||
|
||
#endif //BOIDS_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,17 @@ | ||
all: sfml-app | ||
./sfml-app | ||
|
||
sfml-app: $(F2) Vector2.o | ||
g++ -std=c++17 $(F2) Vector2.o -o sfml-app -ltgui -lsfml-graphics -lsfml-window -lsfml-audio -lsfml-system | ||
sfml-app: $(F2) Vector2.o Boids.o | ||
g++ -std=c++17 $(F2) Vector2.o Boids.o -o sfml-app -ltgui -lsfml-graphics -lsfml-window -lsfml-audio -lsfml-system | ||
|
||
Vector2.o : Vector2.cpp Vector2.h; | ||
g++ -std=c++17 -c Vector2.cpp | ||
|
||
$(F2) : Vector2.h $(F1) | ||
g++ -c $(F1) | ||
Boids.o : Boids.cpp Boids.h | ||
g++ -std=c++17 -c Boids.cpp | ||
|
||
$(F2) : Vector2.h $(F1) Boids.h | ||
g++ -std=c++17 -c $(F1) | ||
|
||
clean: | ||
rm -rf *o sfml-app |
Oops, something went wrong.