-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathfish.hpp
More file actions
186 lines (143 loc) · 5.52 KB
/
fish.hpp
File metadata and controls
186 lines (143 loc) · 5.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
//
// fish.hpp
// CompSci78
//
// Created by Elaine Demetrion on 10/30/20.
// Copyright © 2020 Elaine Demetrion. All rights reserved.
//
#ifndef fish_hpp
#define fish_hpp
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <vector>
#include "vector3.hpp"
#include "agent.hpp"
using namespace std;
class fish : public agent {
public:
//variables for boid movement
float cohesion=0.1, separation=0.1, alignment=0.2, avoidance=0.1;
//how fast the fish actually move
float speed = 20;
bool inBubbleNet;
//constructor. Assigns vision, framerate, etc.
fish(vector3 pos, vector3 vel, int _framerate, int _vision = 10) : agent(pos, vel, _framerate), vision(_vision) {
inBubbleNet = false;
}
void updateFish(vector<fish> &allFish, vector<vector3> &allWhalePos);
fish &operator=(const fish &f);
private:
const float fishboundary = 100;
float vision;
void fixOffScreen();
//The functions to calculate each of the velocities that contribute to boid movement. Require knowledge of where all the fish are
vector3 vSeparation(vector<fish> &allFish);
vector3 vAlignment(vector<fish> &allFish);
vector3 vCohesion(vector<fish> &allFish);
vector3 vAvoidWhales(vector<vector3> &allWhalePos);
//function to update velocity
void updateVelocity(vector<fish> &allFish, vector<vector3> &allWhalePos);
//function to update position based on current velocity
void updatePosition();
};
///Way to set one fish's movement values to those of another fish (I think)
fish &fish::operator=(const fish &f) {
cohesion=f.cohesion;
separation=f.separation;
alignment=f.alignment;
vision = f.vision;
framerate = f.framerate;
speed = f.speed;
return *this;
}
//Calls all functions necessary to this one fish
void fish::updateFish(vector<fish> &allFish, vector<vector3> &allWhalePos) {
updateVelocity(allFish, allWhalePos);
fixOffScreen();
updatePosition();
}
//If fish are offscreen, this function fixes it. You can uncomment the portion with the behavior you want
void fish::fixOffScreen() {
//if fish is off screen, move it to the opposite side and let it continue. Defines boundary to be cube starting at (0, 0, 0) and ending at (fishBoundary, fishBoundary, fishBoundary)
position %= fishboundary;
}
//updates the velocity variable
void fish::updateVelocity(vector<fish> &allFish, vector<vector3> &allWhalePos) {
velocity = speed * (avoidance * vAvoidWhales(allWhalePos) + separation*vSeparation(allFish) + alignment*vAlignment(allFish) + cohesion*vCohesion(allFish)).normalized();
if(inBubbleNet) {
velocity = vector3(0, 0, 0);
}
}
//updates the position variable. Call after updateVelocity
void fish::updatePosition() {
position += velocity / framerate;
}
/* ************BOID MOVEMENT FUNCTIONS***********************/
vector3 fish::vAvoidWhales(vector<vector3> &allWhalePos) {
vector3 finalV;
float r = vision * 2;
for(int ii = 0; ii < allWhalePos.size(); ii ++) {
float dist = position.distance(allWhalePos[ii]);
if(dist < r) {
finalV += (position - allWhalePos[ii]) / (dist*dist);
}
}
return finalV;
}
//Velocity for RULE: fish should move away from close fish
vector3 fish::vSeparation(vector<fish> &allFish) {
vector3 finalV; //will become the returned vector3
//radius of personal "space bubble"
float r = vision*0.99;
//Evaluate each fish in the array
for (int ii = 0; ii < allFish.size(); ii ++) {
//check that the fish isn't me
if(allFish[ii].id != id) {
float dist = position.distance(allFish[ii].position);
if (dist < r) {
//adjust finalV by: vector3 of movement away from fish, but move less for farther away fish
finalV += (position - allFish[ii].position) / (dist*dist);
}
}
}
return finalV;
}
//Velocity for RULE: fish should move in the same direction as nearby fish
vector3 fish::vAlignment(vector<fish> &allFish) {
vector3 finalV;//vector3 that will get returned
//sum all other fish velocities (if fish can be seen), but add less for farther away velocities
for(int ii = 0; ii < allFish.size(); ii++) {
//make sure that this fish isn't me (and has a different id)
if(allFish[ii].id != id) {
double dist = position.distance(allFish[ii].position);
if (dist < vision) {
finalV += allFish[ii].velocity / (dist*dist);
}
}
}
return finalV;
}
//Velocity for RULE: fish should swim to the center of their local flock
vector3 fish::vCohesion(vector<fish> &allFish) {
vector3 avgPos;
int fishConsidering = 0; //how many fish are within my range of vision
//goes through each fish and adds the positions of all local fish to avgPos
for (int ii = 0; ii < allFish.size(); ii++) {
//make sure this fish isn't me and has a different id
if(allFish[ii].id != id) {
float dist = position.distance(allFish[ii].position);
if (dist < vision) {
fishConsidering++;
avgPos += allFish[ii].position;
}
}
}
//check that fishConsidering isn't 0, b/c we're dividing avgPos by it
if(fishConsidering > 0) {
avgPos /= fishConsidering; //turns avgPos to the actual average position
avgPos -= position;//find vector from current position to average position
}
return avgPos; //returns vector from current position to average position
}
#endif /* fish_hpp */