changed UI, fixed lots of bugs, added dlls to gitignore

This commit is contained in:
Anselme FRANÇOIS 2016-05-19 00:11:03 +02:00
parent 84a9aad3e0
commit 4b30ae9011
22 changed files with 711 additions and 409 deletions

3
.gitignore vendored
View File

@ -1,4 +1,5 @@
*.user
build*
*.so
*.dll
teams/*.dll
generators/*.dll

View File

@ -16,38 +16,34 @@ extern "C" void generate(Map *mapPtr)
for(i=0; i<n; i++)
map.team(i) = Coord((w/(n*2))*(1+i*2), h/2);
if(n == 0)
n = 1;
int r = (w/n < h ? w/n : h)/2;
int r = h;
if(n != 0)
r = (w/n < h ? w/n : h)/2;
//génération de la carte
for (i=0;i<w;i++){
for(j=0;j<h;j++){
if (i == 0 || j == 0 || i == w-1 || j == h-1){
map[i][j].type = Pixel::BEDROCK;
int d = std::max(w, h);
if(n == 0)
d = h;
for(k=0; k<n; k++){
d = std::min(d, map.team(k).dist(i, j));
if(!d)
break;
}
if(d == 0){
map[i][j].type = Pixel::SPAWN;
map[i][j].data.nbRes = k;
}else{
int d = std::max(w, h);
if(n == 0)
d = 30;
for(k=0; k<n; k++){
d = std::min(d, map.team(k).dist(i, j));
if(!d)
break;
}
if(d == 0){
map[i][j].type = Pixel::SPAWN;
map[i][j].data.nbRes = k;
}else{
int l = (d-20)+(rand()%40);
if(l > r+15) // mountain
map[i][j].type = rand()%8 ? Pixel::ROCK : Pixel::IRON_ORE;
else if(l < r-15) // plains
map[i][j].type = rand()%15 ? Pixel::GRASS : Pixel::BERRIES;
else // forest
{
l = rand()%10;
map[i][j].type = l > 5 ? Pixel::TREE : l ? Pixel::GRASS : Pixel::BERRIES;
}
int l = (d-20)+(rand()%40);
if(l > r+15) // mountain
map[i][j].type = rand()%8 ? Pixel::ROCK : Pixel::IRON_ORE;
else if(l < r-15) // plains
map[i][j].type = rand()%15 ? Pixel::GRASS : Pixel::BERRIES;
else // forest
{
l = rand()%10;
map[i][j].type = l > 5 ? Pixel::TREE : l ? Pixel::GRASS : Pixel::BERRIES;
}
}
}

View File

@ -29,7 +29,7 @@ void main()
nbRevolutions.x = int(floor(worldCoord.x / worldSize.x));
}
worldCoord = worldCoord - nbRevolutions*worldSize;
vec3 texColor = texelFetch(colorMap, ivec2(worldCoord)).xyz;
vec3 texColor = texelFetch(colorMap, ivec2(worldCoord)-1).xyz;
vec3 lighting = phongLighting(texColor, vec3(0.5), 50, vec3(1), normalize(normal), lightDir, normalize(lightDir+vec3(0, 0, -1)));
outColor = vec4(texColor*0.2 + 0.8*lighting, 1.0);

View File

@ -51,6 +51,9 @@ struct Info
virtual int getInfo(Dir d) = 0;
};
/**
* must be named "think"
*/
typedef void (*BehaviorFunction)(Action *action, char *memory, const Info *info);
#endif // BEHAVIOR_H

View File

@ -7,12 +7,14 @@
#include <resource.h>
#include <glm/ext.hpp>
#include "mapscene.h"
#include "simulation.h"
#include "pixelpipeline.h"
#include <QCoreApplication>
DrawWidget::DrawWidget(QWidget *parent) :
QOpenGLWidget(parent),
m_Qt_fbo(NULL)
m_Qt_fbo(NULL),
m_pipeline(NULL)
{
new_simulation = false;
update_needed = false;
@ -20,8 +22,8 @@ DrawWidget::DrawWidget(QWidget *parent) :
DrawWidget::~DrawWidget()
{
delete m_pipeline;
delete m_map;
if(m_pipeline != NULL)
delete m_pipeline;
if(m_Qt_fbo != NULL && m_Qt_fbo != FrameBuffer::screen)
delete(m_Qt_fbo);
}
@ -29,7 +31,6 @@ DrawWidget::~DrawWidget()
void DrawWidget::initializeGL()
{
renderer.initGL(width(), height());
m_map = NULL;
renderer.setScene(m_map);
}
@ -37,6 +38,9 @@ void DrawWidget::paintGL()
{
if(new_simulation)
{
if(m_pipeline != NULL)
delete m_pipeline;
m_map->initDraw();
m_pipeline = new PixelPipeline(m_map);
m_pipeline->setTargetFBO(m_Qt_fbo);
m_pipeline->resizeGL(m_width, m_height);
@ -65,16 +69,9 @@ void DrawWidget::resizeGL(int w, int h)
m_pipeline->setTargetFBO(m_Qt_fbo);
}
void DrawWidget::startSimulation(GenerateFunction genFunc, std::vector<BehaviorFunction> behaveFuncs)
void DrawWidget::startSimulation(MapScene *map)
{
if(m_map != NULL)
{
delete m_map;
delete m_pipeline;
m_map = NULL;
}
m_map = new MapScene(behaveFuncs.size(), 300);
genFunc((Map*)m_map);
m_map = map;
new_simulation = true;
repaint();
}

View File

@ -10,6 +10,7 @@
class PixelPipeline;
class MapScene;
class FrameBuffer;
class Simulation;
class DrawWidget : public QOpenGLWidget
{
@ -46,10 +47,10 @@ class DrawWidget : public QOpenGLWidget
public:
DrawWidget(QWidget *parent = 0);
~DrawWidget();
void startSimulation(MapScene *map);
public slots:
void updateDudesBehavior();
void startSimulation(GenerateFunction, std::vector<BehaviorFunction>);
};
#endif // DRAWWIDGET_H

View File

@ -1,98 +0,0 @@
#include "libwidget.h"
#include "ui_libwidget.h"
#include <QDir>
#include <QLibrary>
#include <QList>
#ifdef Q_OS_WIN
#define LIB_SUFFIX "dll"
#else
#define LIB_SUFFIX "so"
#endif
LibWidget::LibWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::LibWidget)
{
ui->setupUi(this);
refreshBehaviors();
refreshGenerators();
connect(ui->behaviorsRefreshButton, SIGNAL(pressed()), this, SLOT(refreshBehaviors()));
connect(ui->generatorsRefreshButton, SIGNAL(pressed()), this, SLOT(refreshGenerators()));
connect(ui->launchButton, SIGNAL(pressed()), this, SLOT(launchSimulation()));
}
LibWidget::~LibWidget()
{
delete ui;
}
void LibWidget::refreshBehaviors()
{
while(ui->behaviorsList->count() > 0)
ui->behaviorsList->takeItem(0);
m_behaviorList.clear();
QDir teamDir(QCoreApplication::applicationDirPath());
if(teamDir.cd("../teams"))
{
for(const QFileInfo &info : teamDir.entryInfoList())
{
if(info.suffix().compare(LIB_SUFFIX) == 0)
{
QLibrary lib(info.absoluteFilePath());
if(lib.load())
{
BehaviorFunction func = (BehaviorFunction)lib.resolve("think");
if(func)
{
ui->behaviorsList->addItem(info.baseName());
m_behaviorList.push_back(func);
}
}
}
}
}
else
emit sendError(QString("ERROR : can't open the teams folder.\n"), 5000);
}
void LibWidget::refreshGenerators()
{
while(ui->generatorsList->count() > 0)
ui->generatorsList->takeItem(0);
m_genList.clear();
QDir genDir(QCoreApplication::applicationDirPath());
if(genDir.cd("../generators"))
{
for(const QFileInfo &info : genDir.entryInfoList())
{
if(info.suffix().compare(LIB_SUFFIX) == 0)
{
QLibrary lib(info.absoluteFilePath());
if(lib.load())
{
GenerateFunction func = (GenerateFunction)lib.resolve("generate");
if(func)
{
ui->generatorsList->addItem(info.baseName());
m_genList.push_back(func);
}
}
}
}
}
else
emit sendError(QString("ERROR : can't open the generators folder.\n"), 5000);
if(!m_genList.empty())
ui->generatorsList->item(0)->setSelected(true);
}
void LibWidget::launchSimulation()
{
GenerateFunction genFunc = m_genList[ui->generatorsList->currentRow()];
std::vector<BehaviorFunction> behaveFuncs;
for(QListWidgetItem *item : ui->behaviorsList->selectedItems())
behaveFuncs.push_back(m_behaviorList[ui->behaviorsList->row(item)]);
emit createSimulation(genFunc, behaveFuncs);
}

View File

@ -1,36 +0,0 @@
#ifndef LIBWIDGET_H
#define LIBWIDGET_H
#include <QWidget>
namespace Ui {
class LibWidget;
}
#include "behavior.h"
#include "map.h"
class LibWidget : public QWidget
{
Q_OBJECT
public:
explicit LibWidget(QWidget *parent = 0);
~LibWidget();
private slots:
void refreshBehaviors();
void refreshGenerators();
void launchSimulation();
private:
Ui::LibWidget *ui;
std::vector<GenerateFunction> m_genList;
std::vector<BehaviorFunction> m_behaviorList;
signals:
void sendError(QString, int);
void createSimulation(GenerateFunction, std::vector<BehaviorFunction>);
};
#endif // LIBWIDGET_H

View File

@ -1,106 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LibWidget</class>
<widget class="QWidget" name="LibWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>248</width>
<height>480</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item row="5" column="0" colspan="2">
<widget class="QListWidget" name="generatorsList">
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="generatorsRefreshButton">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="behaviorsRefreshButton">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="generatorsLabel">
<property name="text">
<string>Terrain generators</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="behaviorsLabel">
<property name="text">
<string>Pixel behaviors</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QListWidget" name="behaviorsList">
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QPushButton" name="launchButton">
<property name="text">
<string>Launch</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,16 +1,15 @@
#include "mainwindow.h"
#include "drawwidget.h"
#include "ui_mainwindow.h"
#include "simulationdialog.h"
#include "simulation.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->libWidget, SIGNAL(sendError(QString, int)), ui->statusBar, SLOT(showMessage(QString, int)));
connect(ui->libWidget, SIGNAL(createSimulation(GenerateFunction,std::vector<BehaviorFunction>)),
ui->drawWidget, SLOT (startSimulation( GenerateFunction,std::vector<BehaviorFunction>)));
connect(ui->startButton, SIGNAL(pressed()), this, SLOT(openSimuDialog()));
}
MainWindow::~MainWindow()
@ -18,3 +17,16 @@ MainWindow::~MainWindow()
delete ui;
}
void MainWindow::openSimuDialog()
{
SimulationDialog *dialog = new SimulationDialog(this);
dialog->setWindowTitle("Starting a new Simulation");
connect(dialog, SIGNAL(sendError(QString, int)), ui->statusBar, SLOT(showMessage(QString, int)));
int ret = dialog->exec();
if(ret == QDialog::Accepted)
{
Simulation *simu = dialog->getSimulation();
ui->drawWidget->startSimulation(simu->getMap());
// TODO set a timer to update the simulation
}
}

View File

@ -17,6 +17,9 @@ public:
private:
Ui::MainWindow *ui;
private slots:
void openSimuDialog();
};
#endif // MAINWINDOW_H

View File

@ -57,7 +57,7 @@
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
@ -74,7 +74,153 @@
<number>0</number>
</property>
<item>
<widget class="LibWidget" name="libWidget" native="true"/>
<widget class="QToolBox" name="toolBox">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="page_5">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>120</width>
<height>75</height>
</rect>
</property>
<attribute name="label">
<string>Settings</string>
</attribute>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="1">
<widget class="QSlider" name="horizontalSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Flat / Sphere</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>surface ratio</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="horizontalSlider_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Simulation Speed</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="horizontalSlider_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_6">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>260</width>
<height>344</height>
</rect>
</property>
<attribute name="label">
<string>Stats</string>
</attribute>
<layout class="QFormLayout" name="formLayout_2">
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Date</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Population</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_7">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="startButton">
<property name="text">
<string>START</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="stopButton">
<property name="text">
<string>STOP</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pauseButton">
<property name="text">
<string>PAUSE</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
@ -93,12 +239,6 @@
<extends>QOpenGLWidget</extends>
<header>drawwidget.h</header>
</customwidget>
<customwidget>
<class>LibWidget</class>
<extends>QWidget</extends>
<header>libwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>

View File

@ -17,7 +17,7 @@ struct Pixel
void* knowledge;
};
int type;
Type type;
PixelData data;
Pixel() : type(GRASS) {}
@ -68,6 +68,9 @@ public:
{ return m_map[m_height*c.x + c.y]; }
};
/**
* must be named "generate"
*/
typedef void (*GenerateFunction)(Map *map);
#endif // MAP_H

87
src/mapscene.cpp Normal file
View File

@ -0,0 +1,87 @@
#include <sparrowrenderer.h>
#include "mapscene.h"
#define HEX_TO_VEC3(hex) glm::vec3(float((hex & 0xFF0000) >> 16)/255, float((hex & 0x00FF00) >> 8)/255, float(hex & 0x0000FF)/255)
inline glm::vec3 getColor(Pixel::Type type)
{
switch(type){
case Pixel::BEDROCK : return HEX_TO_VEC3(0x101020);
case Pixel::GRASS : return HEX_TO_VEC3(0x719678);
case Pixel::MARK : return HEX_TO_VEC3(0x5D7B62);
case Pixel::ROCK : return HEX_TO_VEC3(0x8C8C8C);
case Pixel::IRON_ORE : return HEX_TO_VEC3(0x917B61);
case Pixel::TREE : return HEX_TO_VEC3(0x003800);
case Pixel::BERRIES : return HEX_TO_VEC3(0x4D6394);
case Pixel::FOOD : return HEX_TO_VEC3(0xFF7A7A);
case Pixel::WOOD : return HEX_TO_VEC3(0x634A22);
case Pixel::STONE : return HEX_TO_VEC3(0x454545);
case Pixel::IRON : return HEX_TO_VEC3(0x4A4036);
case Pixel::DUDE :
// TODO
return HEX_TO_VEC3(0x0000FF);
case Pixel::SPAWN :
// TODO
return HEX_TO_VEC3(0x0000FF);
case Pixel::WALL : return HEX_TO_VEC3(0xE6B2A1);
case Pixel::ROAD : return HEX_TO_VEC3(0xEDB287);
case Pixel::SWORD : return HEX_TO_VEC3(0xEBEBEB);
case Pixel::LIBRARY : return HEX_TO_VEC3(0xA37A50);
case Pixel::DEAD_DUDE : return HEX_TO_VEC3(0xFF0000);
default : return HEX_TO_VEC3(0x0000FF); // bleu absolu = bug
}
}
MapScene::~MapScene()
{
if(m_vao != 0)
{
glDeleteBuffers(1, &m_vbo);
glDeleteVertexArrays(1, &m_vao);
m_vao = 0;
}
}
void MapScene::changePixel(const Coord &c, glm::vec3 color)
{
m_pixels.push_back(Pix(glm::vec2(c.x, c.y), color));
}
void MapScene::changePixel(const Coord &c, Pixel::Type type)
{
m_pixels.push_back(Pix(glm::vec2(c.x, c.y), getColor(type)));
}
void MapScene::initDraw()
{
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Pix), (void*)(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Pix), (void*)(sizeof(glm::vec2)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
for(int i=0; i<getWidth(); ++i)
for(int j=0; j<getHeight(); ++j)
m_pixels.push_back(Pix(glm::vec2(i, j), getColor(getPixel(i, j).type)));
}
void MapScene::draw()
{
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, m_pixels.size() * sizeof(Pix), m_pixels.data(), GL_DYNAMIC_DRAW);
glDrawArrays(GL_POINTS, 0, m_pixels.size());
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
m_pixels.clear();
}

View File

@ -3,10 +3,33 @@
#include "map.h"
#include <scene.h>
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
struct MapScene : public Map, public BasicScene
{
MapScene(int n, int w, int h = 0) : Map(n, w, h) {}
public:
struct Pix
{
glm::vec2 pos;
glm::vec3 color;
Pix(glm::vec2 p, glm::vec3 c) : pos(p), color(c) {}
};
MapScene(int n, int w, int h=0) : Map(n, w, h) {}
~MapScene();
void changePixel(const Coord &c, glm::vec3 color);
void changePixel(const Coord &c, Pixel::Type type);
void initDraw();
bool updateNecessary() { return !m_pixels.empty(); }
void draw();
private:
unsigned int m_vao;
unsigned int m_vbo;
std::vector<Pix> m_pixels;
};
#endif // MAPSCENE_H

View File

@ -11,37 +11,6 @@
#define SCROLL_SPEED 0.998f
#define HEX_TO_VEC3(hex) glm::vec3(float((hex & 0xFF0000) >> 16)/255, float((hex & 0x00FF00) >> 8)/255, float(hex & 0x0000FF)/255)
inline glm::vec3 getColor(const Pixel &p)
{
switch(p.type){
case Pixel::BEDROCK : return HEX_TO_VEC3(0x101020);
case Pixel::GRASS : return HEX_TO_VEC3(0x719678);
case Pixel::MARK : return HEX_TO_VEC3(0x5D7B62);
case Pixel::ROCK : return HEX_TO_VEC3(0x8C8C8C);
case Pixel::IRON_ORE : return HEX_TO_VEC3(0x917B61);
case Pixel::TREE : return HEX_TO_VEC3(0x003800);
case Pixel::BERRIES : return HEX_TO_VEC3(0x4D6394);
case Pixel::FOOD : return HEX_TO_VEC3(0xFF7A7A);
case Pixel::WOOD : return HEX_TO_VEC3(0x634A22);
case Pixel::STONE : return HEX_TO_VEC3(0x454545);
case Pixel::IRON : return HEX_TO_VEC3(0x4A4036);
case Pixel::DUDE :
// TODO
return HEX_TO_VEC3(0x0000FF);
case Pixel::SPAWN :
// TODO
return HEX_TO_VEC3(0x0000FF);
case Pixel::WALL : return HEX_TO_VEC3(0xE6B2A1);
case Pixel::ROAD : return HEX_TO_VEC3(0xEDB287);
case Pixel::SWORD : return HEX_TO_VEC3(0xEBEBEB);
case Pixel::LIBRARY : return HEX_TO_VEC3(0xA37A50);
case Pixel::DEAD_DUDE : return HEX_TO_VEC3(0xFF0000);
default : return HEX_TO_VEC3(0x0000FF); // bleu absolu = bug
}
}
class ToreillerGenerator : public MeshGenerator
{
public:
@ -57,74 +26,17 @@ public:
}
};
// MESH (2D points)
class PixelMesh
{
private:
GLuint m_vao;
GLuint m_vbo;
public:
struct Pix
{
glm::vec2 pos;
glm::vec3 color;
};
std::vector<Pix> m_pixels;
PixelMesh(int size)
{
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Pix), (void*)(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Pix), (void*)(sizeof(glm::vec2)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
~PixelMesh()
{
if(m_vao != 0)
{
glDeleteBuffers(1, &m_vbo);
glDeleteVertexArrays(1, &m_vao);
m_vao = 0;
}
}
void draw()
{
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, m_pixels.size() * sizeof(Pix), m_pixels.data(), GL_DYNAMIC_DRAW);
glDrawArrays(GL_POINTS, 0, m_pixels.size());
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
m_pixels.clear();
}
};
// PIPELINE
PixelPipeline::PixelPipeline(MapScene *map) :
m_map(map),
m_mapWidth(map->getWidth()),
m_mapHeight(map->getHeight()),
m_camera(0, 0, 1)
{
m_width = 256;
m_height = 256;
map->setPipeline(this);
m_map->setPipeline(this);
m_targetFBO = FrameBuffer::screen;
m_mapFBO = new FrameBuffer();
m_mapTex = new Texture(GL_RGBA, GL_RGBA, m_mapWidth, m_mapHeight, GL_UNSIGNED_BYTE, GL_TEXTURE_RECTANGLE);
@ -147,10 +59,6 @@ PixelPipeline::PixelPipeline(MapScene *map) :
vertSource = QtUtils::fileToString(":shaders/shaders/world.vert.glsl").toStdString();
fragSource = QtUtils::fileToString(":shaders/shaders/world.frag.glsl").toStdString();
m_renderShader = new Shader(vertSource, fragSource);
m_changes = new PixelMesh(map->getWidth() * map->getHeight());
for(int i=0; i<map->getWidth(); ++i)
for(int j=0; j<map->getHeight(); ++j)
pushChange(glm::vec2(i, j), getColor((*map)[i][j]));
updateChanges();
}
@ -160,23 +68,18 @@ PixelPipeline::~PixelPipeline()
delete m_mapTex;
delete m_texMapShader;
delete m_renderShader;
delete m_changes;
}
void PixelPipeline::pushChange(const glm::vec2 &pos, const glm::vec3 &color)
{
m_changes->m_pixels.push_back({pos, color});
delete m_map;
}
void PixelPipeline::updateChanges()
{
if(!m_changes->m_pixels.empty())
if(m_map->updateNecessary())
{
m_mapFBO->bindFBO();
glViewport(0, 0, m_mapWidth, m_mapHeight);
m_texMapShader->bind();
m_texMapShader->bindVec2(m_texMapShader->getLocation("texRatio"), glm::vec2(2.0f/m_mapWidth, 2.0f/m_mapHeight));
m_changes->draw();
m_map->draw();
}
}

View File

@ -17,7 +17,7 @@ private:
FrameBuffer *m_mapFBO;
Texture *m_mapTex;
Shader *m_texMapShader;
PixelMesh *m_changes;
MapScene *m_map;
int m_mapWidth;
int m_mapHeight;
const FrameBuffer *m_targetFBO;
@ -33,8 +33,7 @@ private:
public:
PixelPipeline(MapScene *map);
~PixelPipeline();
void pushChange(const glm::vec2 &pos, const glm::vec3 &color);
void updateChanges();
void setTargetFBO(FrameBuffer *fbo) {m_targetFBO = fbo;}

View File

@ -1,8 +1,8 @@
#include "simulation.h"
#include "map.h"
#include "mapscene.h"
Simulation::Simulation(Map *_map, std::vector<BehaviorFunction> &_behaviors):
Simulation::Simulation(MapScene *_map, std::vector<BehaviorFunction> &_behaviors):
p_map(_map)
{
int i=0;

View File

@ -2,21 +2,21 @@
#define SIMULATION_H
#include <vector>
#include <map>
#include "behavior.h"
#include "team.h"
class Map;
class MapScene;
class Simulation
{
private:
Map *p_map;
MapScene* p_map;
std::vector<Team> m_teams;
public:
Simulation(Map *_map, std::vector<BehaviorFunction> &_behaviors);
Simulation(MapScene *_map, std::vector<BehaviorFunction> &_behaviors);
MapScene* getMap() { return p_map; }
/**
* @brief update runs one step of simulation
*/

151
src/simulationdialog.cpp Normal file
View File

@ -0,0 +1,151 @@
#include "simulationdialog.h"
#include "ui_simulationdialog.h"
#include "simulation.h"
#include "mapscene.h"
#include <QResizeEvent>
#include <QDir>
#include <QLibrary>
#include <QList>
#ifdef Q_OS_WIN
#define LIB_SUFFIX "dll"
#else
#define LIB_SUFFIX "so"
#endif
SimulationDialog::SimulationDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SimulationDialog),
m_map(NULL)
{
ui->setupUi(this);
connect(ui->behaviorsRefreshButton, SIGNAL(pressed()), this, SLOT(refreshBehaviors()));
connect(ui->generatorsRefreshButton, SIGNAL(pressed()), this, SLOT(refreshGenerators()));
connect(ui->generateButton, SIGNAL(pressed()), this, SLOT(generateMap()));
connect(ui->behaviorsList, SIGNAL(clicked(QModelIndex)), this, SLOT(selectBehavior(QModelIndex)));
refreshBehaviors();
refreshGenerators();
ui->generatorsList->setCurrentRow(0);
}
SimulationDialog::~SimulationDialog()
{
delete ui;
}
void SimulationDialog::resizeEvent(QResizeEvent *e)
{
int h = ui->mapPreview->height();
ui->mapPreview->resize(h*2, h);
}
void SimulationDialog::refreshBehaviors()
{
while(ui->behaviorsList->count() > 0)
ui->behaviorsList->takeItem(0);
m_behaviorList.clear();
m_selectedBehaviors.clear();
ui->selectedBehaviors->clear();
QDir teamDir(QCoreApplication::applicationDirPath());
if(teamDir.cd("../teams"))
{
for(const QFileInfo &info : teamDir.entryInfoList())
{
if(info.suffix().compare(LIB_SUFFIX) == 0)
{
QLibrary lib(info.absoluteFilePath());
if(lib.load())
{
BehaviorFunction func = (BehaviorFunction)lib.resolve("think");
if(func)
{
ui->behaviorsList->addItem(info.baseName());
m_behaviorList.push_back(info.absoluteFilePath());
}
lib.unload();
}
}
}
}
else
emit sendError(QString("ERROR : can't open the teams folder.\n"), 5000);
}
void SimulationDialog::refreshGenerators()
{
while(ui->generatorsList->count() > 0)
ui->generatorsList->takeItem(0);
m_genList.clear();
QDir genDir(QCoreApplication::applicationDirPath());
if(genDir.cd("../generators"))
{
for(const QFileInfo &info : genDir.entryInfoList())
{
if(info.suffix().compare(LIB_SUFFIX) == 0)
{
QLibrary lib(info.absoluteFilePath());
if(lib.load())
{
GenerateFunction func = (GenerateFunction)lib.resolve("generate");
if(func)
{
ui->generatorsList->addItem(info.baseName());
m_genList.push_back(info.absoluteFilePath());
}
lib.unload();
}
}
}
}
else
emit sendError(QString("ERROR : can't open the generators folder.\n"), 5000);
if(!m_genList.empty())
ui->generatorsList->item(0)->setSelected(true);
}
void SimulationDialog::generateMap()
{
if(m_map != NULL)
delete m_map;
m_map = NULL;
QString path = m_genList[ui->generatorsList->currentRow()];
QLibrary lib(path);
if(lib.load())
{
GenerateFunction func = (GenerateFunction)lib.resolve("generate");
if(func)
{
m_map = new MapScene(m_selectedBehaviors.size(), ui->mapSizeSpinBox->value());
func((Map*)m_map);
// QPixmap preview();
// TODO : display map in preview
}
lib.unload();
}
}
void SimulationDialog::selectBehavior(const QModelIndex &index)
{
QListWidgetItem* item = ui->behaviorsList->item(index.row());
QString path = m_behaviorList[ui->behaviorsList->row(item)];
QLibrary lib(path);
if(lib.load())
{
BehaviorFunction func = (BehaviorFunction)lib.resolve("think");
if(func)
{
m_selectedBehaviors.push_back(func);
ui->selectedBehaviors->addItem(item->text());
}
else
lib.unload();
}
// TODO : unload later
}
Simulation* SimulationDialog::getSimulation()
{
if(m_map == NULL || m_map->getNbTeams() != m_selectedBehaviors.size())
generateMap();
return new Simulation(m_map, m_selectedBehaviors);
}

48
src/simulationdialog.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef SIMULATIONDIALOG_H
#define SIMULATIONDIALOG_H
#include <QDialog>
#include "behavior.h"
#include "map.h"
class Simulation;
class MapScene;
class QListWidgetItem;
class QLibrary;
namespace Ui {
class SimulationDialog;
}
class SimulationDialog : public QDialog
{
Q_OBJECT
public:
explicit SimulationDialog(QWidget *parent = 0);
~SimulationDialog();
Simulation* getSimulation();
protected:
virtual void resizeEvent(QResizeEvent *);
private slots:
void refreshBehaviors();
void refreshGenerators();
void generateMap();
void selectBehavior(const QModelIndex &index);
private:
Ui::SimulationDialog *ui;
std::vector<QString> m_genList;
std::vector<QString> m_behaviorList;
std::vector<BehaviorFunction> m_selectedBehaviors;
MapScene *m_map;
QLibrary *m_currentGeneratorLib;
signals:
void sendError(QString, int);
};
#endif // SIMULATIONDIALOG_H

175
src/simulationdialog.ui Normal file
View File

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SimulationDialog</class>
<widget class="QDialog" name="SimulationDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>596</width>
<height>483</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="behaviorsGroup">
<property name="title">
<string>Pixel behaviors</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QListWidget" name="behaviorsList">
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="behaviorsRefreshButton">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QListWidget" name="selectedBehaviors">
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="generatorsGroup">
<property name="title">
<string>Terrain generators</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="6" column="2">
<widget class="QPushButton" name="generateButton">
<property name="text">
<string>Generate</string>
</property>
</widget>
</item>
<item row="8" column="0" colspan="3">
<widget class="QLabel" name="mapPreview">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>this is a preview</string>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0" rowspan="4">
<widget class="QListWidget" name="generatorsList">
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QPushButton" name="generatorsRefreshButton">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="mapSizeLabel">
<property name="text">
<string>Map size</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QSpinBox" name="mapSizeSpinBox">
<property name="suffix">
<string> pixels</string>
</property>
<property name="minimum">
<number>50</number>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="singleStep">
<number>2</number>
</property>
<property name="value">
<number>300</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SimulationDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SimulationDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>