updated interface, simSpeed control and pause is now working, updateing pixel position after move also works

This commit is contained in:
Anselme 2016-05-27 11:58:28 +02:00
parent 49d1ffb0c4
commit 67c18703a1
12 changed files with 247 additions and 57 deletions

View File

@ -11,6 +11,11 @@ Dude::Dude(const Coord &_pos, Map *_map, int &_team) :
m_inventory(EMPTY)
{
std::memset(&m_memory, 0, DUDE_MEMORY_SIZE);
m_under = p_map->getPixel(m_pos).type;
if(isResource(m_under))
m_underResCount = p_map->getPixel(m_pos).data.nbRes;
p_map->getPixel(m_pos).type = DUDE;
p_map->getPixel(m_pos).data.dudePtr = this;
}
char* Dude::getMemory()
@ -20,9 +25,19 @@ char* Dude::getMemory()
void Dude::move(Dir d)
{
p_map->getPixel(m_pos).type = m_under;
if(isResource(m_under))
p_map->getPixel(m_pos).data.nbRes = m_underResCount;
p_map->getPixel(m_pos).data.dudePtr = NULL;
m_pos += Coord(d);
m_pos.x %= p_map->getWidth();
m_pos.y %= p_map->getHeight();
m_under = p_map->getPixel(m_pos).type;
if(isResource(m_under))
m_underResCount = p_map->getPixel(m_pos).data.nbRes;
p_map->getPixel(m_pos).type = DUDE;
p_map->getPixel(m_pos).data.dudePtr = this;
p_map->toreillerLoop(m_pos);
}
void Dude::receiveComData(const Com &comData)

View File

@ -12,6 +12,8 @@ private:
bool m_dead;
bool m_success;
PixelType m_inventory;
PixelType m_under;
int m_underResCount;
char m_memory[DUDE_MEMORY_SIZE];
Com m_comData;

View File

@ -10,10 +10,18 @@
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
m_simSpeed(500)
p_simu(NULL),
m_simSpeed(500),
m_simSpeedChanged(false),
m_paused(false)
{
ui->setupUi(this);
m_simuTimer = new QTimer(this);
connect(m_simuTimer,SIGNAL(timeout()),this, SLOT(updateSimu()));
m_simuTimer->start(m_simSpeed);
connect(ui->startButton, SIGNAL(pressed()), this, SLOT(openSimuDialog()));
connect(ui->simSpeedSlider, SIGNAL(valueChanged(int)), this, SLOT(changeSimSpeed(int)));
connect(ui->pauseButton, SIGNAL(toggled(bool)), this, SLOT(pauseSimu(bool)));
}
MainWindow::~MainWindow()
@ -23,26 +31,62 @@ MainWindow::~MainWindow()
void MainWindow::openSimuDialog()
{
pauseSimu(true);
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)
{
if(p_simu != NULL)
delete p_simu;
p_simu = dialog->getSimulation();
ui->drawWidget->startSimulation(p_simu->getMap());
QTimer *timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this, SLOT(updateSimu()));
timer->start(m_simSpeed);
m_date = 0;
}
pauseSimu(false);
}
void MainWindow::changeSimSpeed(int newSpeed)
{
m_simSpeedChanged = true;
m_simSpeed = newSpeed;
}
void MainWindow::updateSimu()
{
p_simu->update();
ui->dateLabel->setText(QString::number(++m_date));
ui->populationLabel->setText(QString::number(p_simu->getPopulation()));
ui->drawWidget->updateDudesBehavior();
ui->drawWidget->repaint();
if(!m_paused)
{
if(p_simu != NULL)
{
p_simu->update();
ui->dateLabel->setText(QString::number(++m_date));
ui->populationLabel->setText(QString::number(p_simu->getPopulation()));
ui->drawWidget->updateDudesBehavior();
ui->drawWidget->repaint();
}
if(m_simSpeedChanged)
{
m_simuTimer->stop();
m_simuTimer->start(m_simSpeed);
m_simSpeedChanged = false;
}
}
}
void MainWindow::pauseSimu(bool pause)
{
m_paused = pause;
ui->pauseButton->setChecked(m_paused);
if(m_paused)
{
m_simuTimer->stop();
ui->pauseButton->setText("RESUME");
}
else
{
m_simuTimer->start(m_simSpeed);
ui->pauseButton->setText("PAUSE");
}
m_simSpeedChanged = false;
}

View File

@ -19,13 +19,18 @@ public:
private:
Ui::MainWindow *ui;
QTimer *m_simuTimer;
Simulation* p_simu;
int m_date;
int m_simSpeed;
bool m_simSpeedChanged;
bool m_paused;
private slots:
void openSimuDialog();
void changeSimSpeed(int newSpeed);
void updateSimu();
void pauseSimu(bool);
};
#endif // MAINWINDOW_H

View File

@ -41,13 +41,15 @@
<x>0</x>
<y>0</y>
<width>744</width>
<height>20</height>
<height>18</height>
</rect>
</property>
<widget class="QMenu" name="menuMenu">
<property name="title">
<string>Menu</string>
</property>
<addaction name="actionControl_Panel"/>
<addaction name="separator"/>
<addaction name="actionQuit"/>
</widget>
<addaction name="menuMenu"/>
@ -84,7 +86,7 @@
<x>0</x>
<y>0</y>
<width>260</width>
<height>344</height>
<height>346</height>
</rect>
</property>
<attribute name="label">
@ -99,7 +101,7 @@
</widget>
</item>
<item>
<widget class="QSlider" name="horizontalSlider">
<widget class="QSlider" name="flatSphereSlider">
<property name="enabled">
<bool>false</bool>
</property>
@ -116,7 +118,7 @@
</widget>
</item>
<item>
<widget class="QSlider" name="horizontalSlider_2">
<widget class="QSlider" name="surfaceRatioSlider">
<property name="enabled">
<bool>false</bool>
</property>
@ -133,13 +135,43 @@
</widget>
</item>
<item>
<widget class="QSlider" name="horizontalSlider_3">
<widget class="QSlider" name="simSpeedSlider">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="minimum">
<number>100</number>
</property>
<property name="maximum">
<number>2000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="pageStep">
<number>100</number>
</property>
<property name="value">
<number>500</number>
</property>
<property name="sliderPosition">
<number>500</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
<property name="invertedControls">
<bool>false</bool>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>100</number>
</property>
</widget>
</item>
<item>
@ -163,7 +195,7 @@
<x>0</x>
<y>0</y>
<width>260</width>
<height>344</height>
<height>346</height>
</rect>
</property>
<attribute name="label">
@ -222,6 +254,9 @@
</property>
<item>
<widget class="QPushButton" name="startButton">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>START</string>
</property>
@ -229,6 +264,12 @@
</item>
<item>
<widget class="QPushButton" name="stopButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>STOP</string>
</property>
@ -236,9 +277,18 @@
</item>
<item>
<widget class="QPushButton" name="pauseButton">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>PAUSE</string>
</property>
<property name="shortcut">
<string>Space</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
@ -253,6 +303,17 @@
<string>Quit</string>
</property>
</action>
<action name="actionControl_Panel">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Control Panel</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
@ -280,5 +341,37 @@
</hint>
</hints>
</connection>
<connection>
<sender>actionControl_Panel</sender>
<signal>toggled(bool)</signal>
<receiver>dockWidget</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>129</x>
<y>242</y>
</hint>
</hints>
</connection>
<connection>
<sender>dockWidget</sender>
<signal>visibilityChanged(bool)</signal>
<receiver>actionControl_Panel</receiver>
<slot>setChecked(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>129</x>
<y>242</y>
</hint>
<hint type="destinationlabel">
<x>-1</x>
<y>-1</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -9,9 +9,10 @@ class Dude;
struct Pixel
{
union PixelData {
int nbRes;
int teamId;
Dude* dudePtr;
int nbRes; // RESOURCES
char *knowledge; // LIBRARY
int teamId; // SPAWN
Dude* dudePtr; // DUDE
};
PixelType type;
@ -63,6 +64,21 @@ public:
{ return m_map + m_height*i; }
Pixel &operator[](const Coord &c)
{ return m_map[m_height*c.x + c.y]; }
Coord &toreillerLoop(Coord &c)
{
// this is the shader implementation of the toreiller
Coord nbRevolutions(c.x/m_width, c.y/m_height);
if(abs(nbRevolutions.y % 2))
{
c.x += m_width/2;
nbRevolutions.x = c.x/m_width;
}
c -= Coord(nbRevolutions.x*m_width, nbRevolutions.y*m_height);
return c;
}
Coord toreillerLoop(const Coord &c)
{ Coord myCoord = c; toreillerLoop(myCoord); return myCoord; }
};
/**

View File

@ -44,12 +44,11 @@ MapScene::~MapScene()
void MapScene::updatePixel(const Coord &c)
{
QMutexLocker lock(&m_mutex);
auto it = m_updatedCoordMap.find(c);
if(it != m_updatedCoordMap.end())
m_pixels[it->second].color = getColor(getPixel(c));
if(m_updatedCoordMap.count(c))
m_pixels[m_updatedCoordMap[c]].color = getColor(getPixel(c));
else
{
it->second = m_pixels.size();
m_updatedCoordMap[c] = m_pixels.size();
m_pixels.push_back(Pix(glm::vec2(c.x+0.5f, c.y+0.5f), getColor(getPixel(c))));
}
}

View File

@ -3,7 +3,17 @@
bool isWalkable(PixelType target){
return target != WALL && target != ROCK && target != BEDROCK
&& target != IRON_ORE && target != TREE && target != LIBRARY;
&& target != IRON_ORE && target != TREE && target != LIBRARY
&& target != DUDE && target != SPAWN;
}
bool isResource(PixelType target)
{
return target == FOOD
|| target == WOOD
|| target == STONE
|| target == IRON
|| target == SWORD;
}
bool isDestroyable(PixelType target){

View File

@ -12,5 +12,6 @@ enum PixelType {
//we might have to place these function elsewhere ?
bool isWalkable(PixelType target);
bool isDestroyable(PixelType target);
bool isResource(PixelType target);
#endif // PIXELTYPE_H

View File

@ -25,42 +25,46 @@ void Simulation::update()
std::random_shuffle(m_dudes.begin(), m_dudes.end());
for (int i=0; i<m_dudes.size(); ++i){
Dude *dude = m_dudes[i];
auto action = m_teams[dude->getTeam()].update(dude); //get action for this dude from behavior function in team
handleAction(action, dude);
Action *action = m_teams[dude->getTeam()].update(dude); //get action for this dude from behavior function in team
handleAction(*action, dude);
delete action;
}
// for each team, spawn dude if condition met
for(int i=0; i<m_teams.size(); ++i){
Team &t = m_teams[i];
if (t.updateSpawn())
if(t.updateSpawn())
{
//TODO: check if target pixel is walkable and has no dude
Coord spawnPos = p_map->team(i) + Coord(Dir(rand()%4));
Dude *dude = new Dude(spawnPos,p_map,i);
(*p_map)[spawnPos].data.dudePtr = dude;
p_map->updatePixel(spawnPos);
m_dudes.push_back(dude);
if(isWalkable(p_map->getPixel(spawnPos).type))
{
Dude *dude = new Dude(spawnPos,p_map,i);
(*p_map)[spawnPos].data.dudePtr = dude;
p_map->updatePixel(spawnPos);
m_dudes.push_back(dude);
}/*
else
// TODO delay the spawning
*/
}
}
}
// TODO finish conversion of handleAction()
void Simulation::handleAction(Action *action, Dude *dude){
void Simulation::handleAction(const Action &action, Dude *dude){
// initialisation
Coord currentPos(dude->getPos());
Coord targetPos(currentPos + Coord(action->dir));
Pixel source = (*p_map)[currentPos];
Pixel target = (*p_map)[targetPos];
Dude* targetDude;
Coord targetPos = p_map->toreillerLoop(currentPos + Coord(action.dir));
Pixel &source = p_map->getPixel(currentPos);
Pixel &target = p_map->getPixel(targetPos);
dude->setSuccess(false);
if(action == NULL) return;
switch(action->type){
case Action::MOVE:
if (isWalkable(target.type) && target.data.dudePtr == NULL){
source.data.dudePtr = NULL;
target.data.dudePtr = dude;
dude->move(action->dir);
switch(action.type){
case Action::MOVE: // DONE
if(isWalkable(target.type)){
dude->move(action.dir);
p_map->updatePixel(currentPos);
p_map->updatePixel(targetPos);
std::cout << "Moving to [" << targetPos.x << "," << targetPos.y << "]"<< std::endl;
dude->setSuccess(true);
}
break;
case Action::ATTACK:
@ -167,22 +171,23 @@ void Simulation::handleAction(Action *action, Dude *dude){
case Action::COMMUNICATE:
switch(target.type){
case DUDE:
action->com_data.flag = (action->dir+2)%4;
// TODO : find a way to get targetDude
//targetDude =
{
// WTF ? -> action.com_data.flag = (action.dir+2)%4;
Dude *targetDude = target.data.dudePtr;
if(targetDude->getCom().data == NULL){
targetDude->receiveComData(action->com_data);
targetDude->receiveComData(action.com_data);
dude->setSuccess(true);
}else
dude->setSuccess(false);
break;
}
case LIBRARY:
if(action->com_data.flag & Com::READ)
if(action.com_data.flag & Com::READ)
{
if(dude->getCom().data == NULL)
{
action->com_data.flag = action->dir;
dude->receiveComData(action->com_data);
// WTF ? -> action.com_data.flag = action.dir;
dude->receiveComData(action.com_data);
// TODO: understand what the fuck this line is doing
//memcpy(dude->getCom() + sizeof(int), target.data.knowledge + (action->com_data.flag | 3), COM_SIZE);
}
@ -199,7 +204,6 @@ void Simulation::handleAction(Action *action, Dude *dude){
}
break;
default:
dude->setSuccess(false);
break;
}
}

View File

@ -22,7 +22,7 @@ public:
* @brief update runs one step of simulation
*/
void update();
void handleAction(Action*, Dude* dude);
void handleAction(const Action &action, Dude* dude);
};
#endif // SIMULATION_H

View File

@ -24,6 +24,7 @@ bool Team::updateSpawn()
}
return false;
}
void Team::destroySpawn(){
m_spawnCooldown = 0;
m_foodQuantity = 0;