#include "ofApp.h"
//--------------------------------------------------------------
Actor::Actor(vector<glm::vec3>& location_list, vector<vector<int>>& next_index_list, vector<int>& destination_list) {
this->select_index = ofRandom(location_list.size());
while (true) {
auto itr = find(destination_list.begin(), destination_list.end(), this->select_index);
if (itr == destination_list.end()) {
destination_list.push_back(this->select_index);
break;
}
this->select_index = (this->select_index + 1) % location_list.size();
}
this->next_index = this->select_index;
}
//--------------------------------------------------------------
void Actor::update(const int& frame_span, vector<glm::vec3>& location_list, vector<vector<int>>& next_index_list, vector<int>& destination_list) {
if (ofGetFrameNum() % frame_span == 0) {
auto tmp_index = this->select_index;
this->select_index = this->next_index;
int retry = next_index_list[this->select_index].size() + 1;
this->next_index = next_index_list[this->select_index][(int)ofRandom(next_index_list[this->select_index].size())];
while (--retry > 0) {
auto destination_itr = find(destination_list.begin(), destination_list.end(), this->next_index);
if (destination_itr == destination_list.end()) {
if (tmp_index != this->next_index) {
destination_list.push_back(this->next_index);
break;
}
}
this->next_index = next_index_list[this->select_index][(this->next_index + 1) % next_index_list[this->select_index].size()];
}
if (retry <= 0) {
destination_list.push_back(this->select_index);
this->next_index = this->select_index;
}
}
auto param = ofGetFrameNum() % frame_span;
auto distance = location_list[this->next_index] - location_list[this->select_index];
if (this->next_index != this->select_index) {
this->prev_location = location;
}
this->location = location_list[this->select_index] + distance / frame_span * param;
}
//--------------------------------------------------------------
glm::vec3 Actor::get_location() {
return this->location;
}
//--------------------------------------------------------------
glm::vec3 Actor::get_prev_location() {
return this->prev_location;
}
//--------------------------------------------------------------
void ofApp::setup() {
ofSetFrameRate(60);
ofSetWindowTitle("openFrameworks");
ofBackground(255);
ofEnableDepthTest();
ofSetLineWidth(2);
auto span = 25;
for (int x = -200; x <= 200; x += span) {
for (int y = -200; y <= 200; y += span) {
this->location_list.push_back(glm::vec3(x, y, 0));
}
}
for (auto& location : this->location_list) {
vector<int> next_index = vector<int>();
int index = -1;
for (auto& other : this->location_list) {
index++;
if (location == other) { continue; }
float distance = glm::distance(location, other);
if (distance <= span + 1) {
next_index.push_back(index);
}
}
this->next_index_list.push_back(next_index);
}
for (int i = 0; i < 255; i++) {
this->actor_list.push_back(make_unique<Actor>(this->location_list, this->next_index_list, this->destination_list));
}
}
//--------------------------------------------------------------
void ofApp::update() {
int frame_span = 15;
int prev_index_size = 0;
if (ofGetFrameNum() % frame_span == 0) {
prev_index_size = this->destination_list.size();
}
for (auto& actor : this->actor_list) {
actor->update(frame_span, this->location_list, this->next_index_list, this->destination_list);
}
if (prev_index_size != 0) {
this->destination_list.erase(this->destination_list.begin(), this->destination_list.begin() + prev_index_size);
}
}
//--------------------------------------------------------------
void ofApp::draw() {
this->cam.begin();
int count = 0;
ofColor color;
for (auto& actor : this->actor_list) {
color.setHsb(count++, 130, 255);
this->draw_arrow(actor->get_prev_location(), actor->get_location(), 10, color);
}
this->cam.end();
}
//--------------------------------------------------------------
void ofApp::draw_arrow(glm::vec2 location, glm::vec2 next_location, float size, ofColor color) {
auto angle = std::atan2(next_location.y - location.y, next_location.x - location.x);
ofSetColor(color);
ofFill();
ofBeginShape();
ofVertex(location + glm::vec2(size * cos(angle), size * sin(angle)));
ofVertex(location + glm::vec2(size * 0.5 * cos(angle + PI * 0.5), size * 0.5 * sin(angle + PI * 0.5)));
ofVertex(location + glm::vec2(size * 0.5 * cos(angle - PI * 0.5), size * 0.5 * sin(angle - PI * 0.5)));
ofEndShape();
ofBeginShape();
ofVertex(location + glm::vec2(size * 0.5 * cos(angle + PI * 0.5), size * 0.5 * sin(angle + PI * 0.5)) * 0.25);
ofVertex(location + glm::vec2(size * 0.5 * cos(angle + PI * 0.5), size * 0.5 * sin(angle + PI * 0.5)) * 0.25 - glm::vec2(size * cos(angle), size * sin(angle)) * 0.5);
ofVertex(location + glm::vec2(size * 0.5 * cos(angle - PI * 0.5), size * 0.5 * sin(angle - PI * 0.5)) * 0.25 - glm::vec2(size * cos(angle), size * sin(angle)) * 0.5);
ofVertex(location + glm::vec2(size * 0.5 * cos(angle - PI * 0.5), size * 0.5 * sin(angle - PI * 0.5)) * 0.25);
ofEndShape();
ofSetColor(255);
ofNoFill();
ofBeginShape();
ofVertex(location + glm::vec2(size * cos(angle), size * sin(angle)));
ofVertex(location + glm::vec2(size * 0.5 * cos(angle + PI * 0.5), size * 0.5 * sin(angle + PI * 0.5)));
ofVertex(location + glm::vec2(size * 0.5 * cos(angle - PI * 0.5), size * 0.5 * sin(angle - PI * 0.5)));
ofEndShape(true);
ofBeginShape();
ofVertex(location + glm::vec2(size * 0.5 * cos(angle + PI * 0.5), size * 0.5 * sin(angle + PI * 0.5)) * 0.25);
ofVertex(location + glm::vec2(size * 0.5 * cos(angle + PI * 0.5), size * 0.5 * sin(angle + PI * 0.5)) * 0.25 - glm::vec2(size * cos(angle), size * sin(angle)) * 0.5);
ofVertex(location + glm::vec2(size * 0.5 * cos(angle - PI * 0.5), size * 0.5 * sin(angle - PI * 0.5)) * 0.25 - glm::vec2(size * cos(angle), size * sin(angle)) * 0.5);
ofVertex(location + glm::vec2(size * 0.5 * cos(angle - PI * 0.5), size * 0.5 * sin(angle - PI * 0.5)) * 0.25);
ofEndShape();
}
//--------------------------------------------------------------
int main() {
ofSetupOpenGL(720, 720, OF_WINDOW);
ofRunApp(new ofApp());
}