Version 1
This commit is contained in:
parent
0ebd216c99
commit
94725bf255
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include "Field.hpp"
|
||||
|
||||
class Agent
|
||||
{
|
||||
public:
|
||||
Agent(float fl_x, float fl_y, float fl_w, float fl_h, float direction, float fl_pheromone_strength, float fl_random_influence, float fl_lookahead_distance);
|
||||
~Agent();
|
||||
|
||||
void tick(Field* field);
|
||||
|
||||
private:
|
||||
float fl_x, fl_y, fl_w, fl_h, fl_direction, fl_pheromone_strength, fl_random_influence, fl_lookahead_distance;
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include <math.h>
|
||||
|
||||
class Field
|
||||
{
|
||||
public:
|
||||
Field(int i_width, int i_height, float fl_pheromone_max);
|
||||
~Field();
|
||||
|
||||
void tick();
|
||||
|
||||
void add_pheromone(float fl_x, float fl_y, float fl_strength);
|
||||
|
||||
float get_pheromone_strength(float fl_x, float fl_y);
|
||||
float get_pheromone_strength(int i_x, int i_y);
|
||||
|
||||
float get_pheromone_max();
|
||||
|
||||
private:
|
||||
int i_width, i_height;
|
||||
|
||||
float** fl_ground;
|
||||
|
||||
float fl_pheromone_max;
|
||||
};
|
|
@ -0,0 +1,89 @@
|
|||
#include "Agent.hpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
Agent::Agent(float fl_x, float fl_y, float fl_w, float fl_h, float fl_direction, float fl_pheromone_strength, float fl_random_influence, float fl_lookahead_distance)
|
||||
{
|
||||
this->fl_x = fl_x;
|
||||
this->fl_y = fl_y;
|
||||
this->fl_w = fl_w;
|
||||
this->fl_h = fl_h;
|
||||
this->fl_direction = fl_direction;
|
||||
this->fl_pheromone_strength = fl_pheromone_strength;
|
||||
this->fl_random_influence = 100.0f*fl_random_influence;
|
||||
this->fl_lookahead_distance = fl_lookahead_distance;
|
||||
}
|
||||
|
||||
Agent::~Agent()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Agent::tick(Field* field)
|
||||
{
|
||||
///Update direction
|
||||
float fl_xd, fl_yd;
|
||||
|
||||
if ((float)(rand()%100) < fl_random_influence)
|
||||
{ //Move randomly
|
||||
switch (rand() % 3)
|
||||
{
|
||||
case 0:
|
||||
fl_direction += M_PI_4;
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
fl_direction -= M_PI_4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //Move based on environment
|
||||
|
||||
//Gather information
|
||||
float fl_l_pheromone, fl_s_pheromone, fl_r_pheromone, fl_test_dir = fl_direction;
|
||||
fl_xd = fl_lookahead_distance*cos(fl_test_dir);
|
||||
fl_yd = fl_lookahead_distance*sin(fl_test_dir);
|
||||
|
||||
fl_s_pheromone = field->get_pheromone_strength(fl_x+fl_xd, fl_y+fl_yd);
|
||||
|
||||
fl_test_dir += M_PI/6.0F;
|
||||
fl_xd = fl_lookahead_distance*cos(fl_test_dir);
|
||||
fl_yd = fl_lookahead_distance*sin(fl_test_dir);
|
||||
fl_l_pheromone = field->get_pheromone_strength(fl_x+fl_xd, fl_y+fl_yd);
|
||||
|
||||
fl_test_dir -= M_PI/3.0F;
|
||||
fl_xd = fl_lookahead_distance*cos(fl_test_dir);
|
||||
fl_yd = fl_lookahead_distance*sin(fl_test_dir);
|
||||
fl_r_pheromone = field->get_pheromone_strength(fl_x+fl_xd, fl_y+fl_yd);
|
||||
|
||||
if (fl_r_pheromone >= fl_s_pheromone && fl_r_pheromone >= fl_l_pheromone)
|
||||
{
|
||||
fl_direction -= M_PI/6.0;
|
||||
}
|
||||
else if (fl_l_pheromone >= fl_s_pheromone && fl_l_pheromone >= fl_r_pheromone)
|
||||
{
|
||||
fl_direction += M_PI/6.0;
|
||||
}
|
||||
}
|
||||
|
||||
//Move
|
||||
fl_xd = cos(fl_direction);
|
||||
fl_yd = sin(fl_direction);
|
||||
|
||||
if (fl_x + fl_xd < 0 || fl_x + fl_xd >= fl_w || fl_y + fl_yd < 0 || fl_y + fl_yd >= fl_h)
|
||||
{
|
||||
fl_x = fmin(fl_w,fmax(0.0f, fl_x+fl_xd));
|
||||
fl_y = fmin(fl_h,fmax(0.0f, fl_y+fl_yd));
|
||||
fl_direction = 2.0f*M_PI*((float)(rand()%100)/100.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
fl_x += fl_xd;
|
||||
fl_y += fl_yd;
|
||||
}
|
||||
|
||||
//Add pheromone to new position
|
||||
field->add_pheromone(fl_x, fl_y, fl_pheromone_strength);
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
#include "Field.hpp"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
Field::Field(int i_width, int i_height, float fl_pheromone_max)
|
||||
{
|
||||
this->i_width = i_width;
|
||||
this->i_height = i_height;
|
||||
|
||||
fl_ground = new float*[i_width];
|
||||
|
||||
for (int i = 0; i < i_width; i++)
|
||||
{
|
||||
fl_ground[i] = new float[i_height];
|
||||
|
||||
for(int j = 0; j < i_height; j++)
|
||||
{
|
||||
fl_ground[i][j] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
this->fl_pheromone_max = fl_pheromone_max;
|
||||
}
|
||||
|
||||
Field::~Field()
|
||||
{
|
||||
for(int i = 0; i < i_width; i++)
|
||||
{
|
||||
delete[] fl_ground[i];
|
||||
}
|
||||
|
||||
delete[] fl_ground;
|
||||
}
|
||||
|
||||
void Field::tick()
|
||||
{
|
||||
float** fl_temp_ground;
|
||||
fl_temp_ground = new float*[i_width];
|
||||
|
||||
for (int i = 0; i < i_width; i++)
|
||||
{
|
||||
fl_temp_ground[i] = new float[i_height];
|
||||
}
|
||||
|
||||
|
||||
for(int x = 0; x < i_width; x++)
|
||||
{
|
||||
for(int y = 0; y < i_height; y++)
|
||||
{
|
||||
|
||||
float fl_sum = 0.0f;
|
||||
float fl_count = 0.0f;
|
||||
|
||||
for (int i = x-1; i <= x+1; i++)
|
||||
{
|
||||
for (int j = y-1; j <= y+1; j++)
|
||||
{
|
||||
if (i < 0 || i >= i_width || j < 0 || j >= i_height)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fl_sum += fl_ground[i][j];
|
||||
fl_count += 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
fl_temp_ground[x][y] = fmax(0.0f, fl_sum/fl_count-0.005);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < i_width; i++)
|
||||
{
|
||||
memcpy(&fl_ground[i][0], &fl_temp_ground[i][0], sizeof(float)*i_height);
|
||||
delete[] fl_temp_ground[i];
|
||||
}
|
||||
|
||||
delete[] fl_temp_ground;
|
||||
}
|
||||
|
||||
void Field::add_pheromone(float fl_x, float fl_y, float fl_strength)
|
||||
{
|
||||
int i_x = (int)fl_x;
|
||||
int i_y = (int)fl_y;
|
||||
|
||||
if (i_x < 0 || i_x >= i_width || i_y < 0 || i_y >= i_height)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fl_ground[i_x][i_y] = fmin(fl_ground[i_x][i_y]+fl_strength, fl_pheromone_max);
|
||||
}
|
||||
|
||||
float Field::get_pheromone_strength(float fl_x, float fl_y)
|
||||
{
|
||||
int i_x = (int)fl_x, i_y = (int)fl_y;
|
||||
if (i_x < 0 || i_x >= i_width || i_y < 0 || i_y >= i_height)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return fl_ground[i_x][i_y];
|
||||
}
|
||||
|
||||
float Field::get_pheromone_strength(int i_x, int i_y)
|
||||
{
|
||||
if (i_x < 0 || i_x >= i_width || i_y < 0 || i_y >= i_height)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return fl_ground[i_x][i_y];
|
||||
}
|
||||
|
||||
float Field::get_pheromone_max()
|
||||
{
|
||||
return fl_pheromone_max;
|
||||
}
|
134
src/main.cpp
134
src/main.cpp
|
@ -1,9 +1,23 @@
|
|||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "Field.hpp"
|
||||
#include "Agent.hpp"
|
||||
|
||||
unsigned long long SYS_TIME_US()
|
||||
{
|
||||
return (unsigned long long)(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
srand(time(0));
|
||||
int width, height;
|
||||
|
||||
if (argc == 1)
|
||||
|
@ -23,25 +37,129 @@ int main(int argc, char* argv[])
|
|||
|
||||
SDL_Window* window = SDL_CreateWindow("Slime Mold Simulator", SDL_WINDOWPOS_CENTERED-width/2, SDL_WINDOWPOS_CENTERED-height/2, width, height, SDL_WINDOW_SHOWN);
|
||||
|
||||
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00);
|
||||
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_Texture* field_texture = SDL_CreateTexture(renderer, SDL_GetWindowPixelFormat(window), SDL_TEXTUREACCESS_TARGET, width, height);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
Field field(width, height, 1.0f);
|
||||
|
||||
SDL_Rect half_screen = (SDL_Rect){width/4, height/4, width/2, height/2};
|
||||
std::vector<Agent*> agents;
|
||||
|
||||
SDL_RenderFillRect(renderer, &half_screen);
|
||||
bool* start_positions = new bool[width*height];
|
||||
for(int i = 0; i < width*height; i++)
|
||||
{
|
||||
start_positions[i] = false;
|
||||
}
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
int created = 0;
|
||||
int index = 0;
|
||||
int max_count = (int)sqrt(width*height)*10;
|
||||
while(created < max_count)
|
||||
{
|
||||
int rng_cur = rand()%(width*height/max_count);
|
||||
if (rng_cur == 0 && !start_positions[index])
|
||||
{
|
||||
start_positions[index] = true;
|
||||
created++;
|
||||
}
|
||||
|
||||
SDL_Delay(2000);
|
||||
index = (index+1)%(width*height);
|
||||
}
|
||||
|
||||
for(int i = 0; i < width*height; i++)
|
||||
{
|
||||
if (start_positions[i])
|
||||
{
|
||||
Agent* next_agent = new Agent((float)(i%width), (float)(i/width), (float)width, (float)height, 2.0f*M_PI*((float)(rand()%100)/100.0f), 0.8f, 0.1f,3.0f);
|
||||
agents.push_back(next_agent);
|
||||
|
||||
field.add_pheromone((float)(i%width),(float)(i/width), 0.8f);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] start_positions;
|
||||
|
||||
SDL_Rect screen_rect = {0,0,width,height};
|
||||
|
||||
unsigned long long time_old, time_now;
|
||||
time_now = time_old = SYS_TIME_US();
|
||||
|
||||
int iteration_duration = 16666/10;
|
||||
int max_loops = 10000000/iteration_duration;
|
||||
bool pause = true;
|
||||
|
||||
while(true)
|
||||
{
|
||||
SDL_Event event;
|
||||
if (1 == SDL_PollEvent(&event))
|
||||
{
|
||||
if (event.type == SDL_KEYDOWN)
|
||||
{
|
||||
if (event.key.keysym.scancode == SDL_SCANCODE_Q)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (event.key.keysym.scancode == SDL_SCANCODE_P)
|
||||
{
|
||||
pause = !pause;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
time_now = SYS_TIME_US();
|
||||
if (time_now >= time_old + iteration_duration)
|
||||
{
|
||||
time_old = time_now;
|
||||
if (pause)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
field.tick();
|
||||
for(unsigned int i = 0; i < agents.size(); i++)
|
||||
{
|
||||
agents[i]->tick(&field);
|
||||
}
|
||||
|
||||
SDL_SetRenderTarget(renderer, field_texture);
|
||||
SDL_SetRenderDrawColor(renderer, 0,0,0,0);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
float max_strength = field.get_pheromone_max();
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
float cur_strength = field.get_pheromone_strength(x, y);
|
||||
|
||||
int color_val = std::max(0,std::min(255,(int)(255.0f * cur_strength / max_strength)));
|
||||
SDL_SetRenderDrawColor(renderer, color_val, color_val, color_val, 0xFF);
|
||||
|
||||
SDL_RenderDrawPoint(renderer, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_SetRenderTarget(renderer, NULL);
|
||||
SDL_SetRenderDrawColor(renderer, 0,0,0,0);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
SDL_RenderCopy(renderer, field_texture, &screen_rect, &screen_rect);
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
SDL_Quit();
|
||||
|
||||
for (unsigned int i = 0; i < agents.size(); i++)
|
||||
{
|
||||
delete agents[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue