added debug panel

This commit is contained in:
Anselme FRANÇOIS 2016-06-04 19:22:29 +02:00
parent 133e36d187
commit 5bd9acf2cf
23 changed files with 430 additions and 125 deletions

View File

@ -1,7 +1,7 @@
#include <cstdlib>
#include "behavior.h"
// g++ -shared simple.cpp -o simple.dll -I../src
// g++ -shared simple.cpp -o simple.dll -std=c++11 -I../src
// inspired of the old "purple.c" behavior
@ -14,6 +14,14 @@ struct purple_data{
Action::Type last_action;
};
extern "C" void debugOutput(char *outputString, const char *memory)
{
purple_data* data = (purple_data*)memory;
sprintf(outputString, "Simple Dude\ndistance to the spawn : (%d, %d)\n%s\n",
data->pos.x, data->pos.y,
data->brings_food ? "Bringing food to spawn" : "searching for food");
}
extern "C" void think(Action *action, char *memory, const Info *info)
{
int i;

BIN
img/cursor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

View File

@ -59,5 +59,6 @@
<qresource prefix="images">
<file>img/sky_front.png</file>
<file>img/sky_back.png</file>
<file>img/cursor.png</file>
</qresource>
</RCC>

View File

@ -7,6 +7,10 @@ uniform vec2 worldSize;
uniform float flatSphere;
uniform float surfaceRatio;
// debug cursor
uniform sampler2D debugCursorMap;
uniform vec2 debugCursorPos;
in vec2 texCoord;
in vec3 normal;
@ -31,9 +35,18 @@ void main()
nbRevolutions.x = int(floor(worldCoord.x / worldSize.x));
}
worldCoord = worldCoord - nbRevolutions*worldSize;
vec3 texColor = texelFetch(colorMap, ivec2(worldCoord.x, worldSize.y-worldCoord.y)).xyz;
worldCoord.y = worldSize.y-worldCoord.y;
vec3 texColor = texelFetch(colorMap, ivec2(worldCoord)).xyz;
// computing lighting
vec3 lighting = phongLighting(texColor, vec3(0.5), 50, vec3(1), normalize(normal), lightDir, normalize(lightDir+vec3(0, 0, -1)));
outColor = vec4(mix(lighting, texColor, flatSphere*0.8 + 0.2), 1.0);
vec2 dist = abs(worldCoord+vec2(0.5)-ceil(debugCursorPos));
if(dist.x < 1 && dist.y < 1)
{
vec3 cursorColor = texture(debugCursorMap, dist).xyz;
if(cursorColor.x > 0.1)
outColor = vec4(cursorColor, 1.0);
}
}

View File

@ -3,10 +3,12 @@
#include "pixeltype.h"
#include "coord.h"
#include <string>
#define DUDE_MEMORY_SIZE 128
#define LIBRARY_SIZE 128
#define COM_SIZE 32
#define DEBUG_OUTPUT_MAX_SIZE 2048
class Map;
@ -54,7 +56,22 @@ struct Info
/**
* must be named "think"
*
* this function should initialize the "action" struct,
* you can read and write in the dude's "memory"
* and you have access to additionnal information through "info"
*/
typedef void (*BehaviorFunction)(Action *action, char *memory, const Info *info);
/**
* must be named "debugOutput"
*
* This function is facultative, if you implement it,
* you must write a valid string in "outputString",
* you have a read access on the targeted dude's memory.
*
* The outputString has a max size of DEBUG_OUTPUT_MAX_SIZE.
*/
typedef void (*DebugBehaviorFunction)(char *outputString, const char *memory);
#endif // BEHAVIOR_H

View File

@ -34,7 +34,9 @@ struct Coord
}
}
bool operator==(const Coord &c) const
{ return x==c.x&&y==c.y;}
{ return x==c.x && y==c.y; }
bool operator!=(const Coord &c) const
{ return x!=c.x || y!=c.y; }
Coord operator+(const Coord &c) const
{ return Coord(x+c.x, y+c.y);}
Coord& operator+=(const Coord &c)

View File

@ -92,6 +92,44 @@ void DrawWidget::stopSimulation()
repaint();
}
void DrawWidget::debugPick(int x, int y)
{
if(m_pipeline && m_map != m_dummyMap)
{
Coord pos = m_pipeline->setCursorPosPicking(x, y);
if(m_lastCursorPos != pos)
{
m_lastCursorPos = pos;
emit debugPickChanged(m_lastCursorPos);
repaint();
}
}
}
void DrawWidget::setFlatSphere(int value)
{
if(m_pipeline != NULL)
m_pipeline->setFlatSphere(float(value)/100);
}
void DrawWidget::setSurfaceRatio(int value)
{
float fVal = float(value-50);
if(m_pipeline != NULL)
m_pipeline->setSurfaceRatio(fVal > 0 ? fVal/25 : fVal/60);
}
void DrawWidget::setCursorEnabled(bool isEnabled)
{
if(m_pipeline && m_map != m_dummyMap)
{
if(isEnabled)
m_pipeline->setCursorPos(m_lastCursorPos);
else
m_pipeline->setCursorPos(Coord(-1));
}
}
// INPUT EVENTS
void DrawWidget::mouseMoveEvent(QMouseEvent *event)
@ -101,10 +139,8 @@ void DrawWidget::mouseMoveEvent(QMouseEvent *event)
m_pipeline->cameraMove(event->globalX() - lastMousePos.x(), event->globalY() - lastMousePos.y());
repaint();
}
if(m_grabbedMouseRight && m_pipeline != NULL)
{
m_pipeline->getToreillerPos(event->x(), event->y());
}
if(m_grabbedMouseRight)
debugPick(event->x(), event->y());
lastMousePos = event->globalPos();
}
@ -117,6 +153,7 @@ void DrawWidget::mousePressEvent(QMouseEvent* event)
break;
case Qt::RightButton :
m_grabbedMouseRight = true;
debugPick(event->x(), event->y());
break;
default:
break;
@ -126,7 +163,7 @@ void DrawWidget::mousePressEvent(QMouseEvent* event)
void DrawWidget::mouseDoubleClickEvent(QMouseEvent * event)
{
debugPick(event->x(), event->y());
}
void DrawWidget::mouseReleaseEvent(QMouseEvent* event)
@ -152,16 +189,3 @@ void DrawWidget::wheelEvent(QWheelEvent *event)
repaint();
}
}
void DrawWidget::setFlatSphere(int value)
{
if(m_pipeline != NULL)
m_pipeline->setFlatSphere(float(value)/100);
}
void DrawWidget::setSurfaceRatio(int value)
{
float fVal = float(value-50);
if(m_pipeline != NULL)
m_pipeline->setSurfaceRatio(fVal > 0 ? fVal/25 : fVal/60);
}

View File

@ -30,8 +30,12 @@ class DrawWidget : public QOpenGLWidget
int m_width;
int m_height;
Coord m_lastCursorPos;
bool new_simulation;
bool update_needed;
void debugPick(int x, int y);
protected:
// Output
@ -56,6 +60,10 @@ class DrawWidget : public QOpenGLWidget
void updateDudesBehavior();
void setFlatSphere(int);
void setSurfaceRatio(int);
void setCursorEnabled(bool);
signals:
void debugPickChanged(Coord);
};
#endif // DRAWWIDGET_H

View File

@ -49,7 +49,12 @@ void Dude::update(BehaviorFunction func)
{
func(&m_action, m_memory, (Info*)this);
m_receivedComData = false;
memcpy(m_com_data.data, 0, COM_SIZE);
memset(m_com_data.data, 0, COM_SIZE);
}
void Dude::debugOutput(char *outputString, DebugBehaviorFunction func)
{
func(outputString, m_memory);
}
PixelType Dude::getNear(Dir d) const

View File

@ -21,8 +21,10 @@ private:
public:
Dude(const Coord &_pos, Map *_map, const int &_team);
//general use functions
void update(BehaviorFunction func);
void debugOutput(char *outputString, DebugBehaviorFunction func);
const Action& getAction() { return m_action; }
int getTeam(){ return m_team; }

View File

@ -7,7 +7,7 @@
int main(int argc, char *argv[])
{
#ifdef DEBUG_MODE
printf("Starting PixelWars %d.%d\n", VERSION_MAJOR, VERSION_MINOR);
printf("Starting PixelWars %d.%d\n", PixelWars_VERSION_MAJOR, PixelWars_VERSION_MINOR);
#endif
QSurfaceFormat format;
format.setMinorVersion(3);

View File

@ -7,6 +7,8 @@
#include <chrono>
#include <QTimer>
#include <QErrorMessage>
#include <QPalette>
#include "mapscene.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
@ -30,12 +32,16 @@ MainWindow::MainWindow(QWidget *parent) :
connect(ui->surfaceRatioSlider, SIGNAL(valueChanged(int)), ui->drawWidget, SLOT(setSurfaceRatio(int)));
connect(ui->flatSphereSlider, SIGNAL(valueChanged(int)), ui->drawWidget, SLOT(repaint()));
connect(ui->surfaceRatioSlider, SIGNAL(valueChanged(int)), ui->drawWidget, SLOT(repaint()));
connect(ui->actionDebug, SIGNAL(toggled(bool)), ui->drawWidget, SLOT(setCursorEnabled(bool)));
connect(ui->actionPlayPause, SIGNAL(toggled(bool)), this, SLOT(pauseSimu(bool)));
connect(ui->actionAction_step, SIGNAL(triggered(bool)), this, SLOT(stepSimu()));
connect(ui->actionStop, SIGNAL(triggered(bool)), this, SLOT(stopSimu()));
connect(ui->resetToDefaultAdvanced, SIGNAL(pressed()), this, SLOT(resetAdvancedToDefault()));
connect(ui->drawWidget, SIGNAL(debugPickChanged(Coord)), this, SLOT(changeDebugCursorPos(Coord)));
changeSimSpeed(ui->simSpeedSlider->value());
ui->advancedGroupBox->hide();
ui->debugGroupBox->hide();
ui->actionDebug->setEnabled(false);
}
MainWindow::~MainWindow()
@ -64,6 +70,7 @@ void MainWindow::openSimuDialog()
ui->actionAction_step->setEnabled(true);
ui->actionPlayPause->setEnabled(true);
ui->actionStop->setEnabled(true);
ui->actionDebug->setEnabled(true);
}
pauseSimu(false);
delete dialog;
@ -87,6 +94,8 @@ void MainWindow::updateSimu()
ui->drawWidget->updateDudesBehavior();
ui->drawWidget->setFlatSphere(ui->flatSphereSlider->value());
ui->drawWidget->setSurfaceRatio(ui->surfaceRatioSlider->value());
if(m_debugEnabled)
updateDebugMessage();
ui->drawWidget->repaint();
}
if(m_simSpeedChanged)
@ -118,6 +127,9 @@ void MainWindow::stopSimu()
ui->actionAction_step->setEnabled(false);
ui->actionPlayPause->setEnabled(false);
ui->actionStop->setEnabled(false);
if(ui->actionDebug->isChecked())
ui->actionDebug->toggle();
ui->actionDebug->setEnabled(false);
}
void MainWindow::resetAdvancedToDefault()
@ -136,3 +148,26 @@ void MainWindow::pauseSimu(bool pause)
m_simuTimer->start(m_simSpeed);
m_simSpeedChanged = false;
}
void MainWindow::updateDebugMessage()
{
static char buffer[DEBUG_OUTPUT_MAX_SIZE] = {0};
MapScene *map = p_simu->getMap();
Pixel &px = map->getPixel(m_debugCursorPos);
ui->pixelDescriptionArea->clear();
p_simu->getPixelInfoString((char*)buffer, px);
ui->pixelDescriptionArea->appendPlainText(QString(buffer));
ui->pixelNameLabel->setText(PixelProperty::getName(px.type));
glm::vec3 color = map->getColor(px);
color *= 255;
ui->pixelColorWidget->setStyleSheet(QString("QLineEdit {background-color: rgb(%1, %2, %3);}")
.arg(int(color.r)).arg(int(color.g)).arg(int(color.b)));
}
void MainWindow::changeDebugCursorPos(Coord pos)
{
if(!ui->actionDebug->isChecked())
ui->actionDebug->toggle();
m_debugCursorPos = pos;
updateDebugMessage();
}

View File

@ -2,6 +2,7 @@
#define MAINWINDOW_H
#include <QMainWindow>
#include "coord.h"
namespace Ui {
class MainWindow;
@ -25,6 +26,10 @@ private:
int m_simSpeed;
bool m_simSpeedChanged;
bool m_paused;
bool m_debugEnabled;
Coord m_debugCursorPos;
void updateDebugMessage();
private slots:
void openSimuDialog();
@ -34,6 +39,7 @@ private slots:
void stopSimu();
void resetAdvancedToDefault();
void pauseSimu(bool);
void changeDebugCursorPos(Coord);
};
#endif // MAINWINDOW_H

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>683</width>
<height>499</height>
<width>811</width>
<height>572</height>
</rect>
</property>
<property name="windowTitle">
@ -55,7 +55,7 @@
</property>
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,0,0">
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,0">
<property name="leftMargin">
<number>5</number>
</property>
@ -71,10 +71,10 @@
<property name="spacing">
<number>10</number>
</property>
<item row="6" column="1" colspan="2">
<widget class="QLabel" name="dateLabel">
<item row="6" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>0</string>
<string>Date</string>
</property>
</widget>
</item>
@ -85,88 +85,76 @@
</property>
</widget>
</item>
<item row="8" column="1" colspan="2">
<widget class="QLabel" name="populationLabel">
<property name="text">
<string>0</string>
<item row="12" column="0" colspan="2">
<widget class="QGroupBox" name="debugGroupBox">
<property name="title">
<string>Debug</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLineEdit" name="pixelColorWidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="pixelNameLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>PIXEL</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QPlainTextEdit" name="pixelDescriptionArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Consolas</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QSlider" name="simSpeedSlider">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>980</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="pageStep">
<number>10</number>
</property>
<property name="value">
<number>980</number>
</property>
<property name="sliderPosition">
<number>980</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 row="6" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Date</string>
</property>
</widget>
</item>
<item row="12" column="0" colspan="3">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Simulation Speed</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="3">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="11" column="0" colspan="3">
<item row="11" column="0" colspan="2">
<widget class="QGroupBox" name="advancedGroupBox">
<property name="title">
<string>Advanced Settings</string>
@ -273,13 +261,94 @@
</layout>
</widget>
</item>
<item row="10" column="0">
<item row="9" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QSlider" name="simSpeedSlider">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>980</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="pageStep">
<number>10</number>
</property>
<property name="value">
<number>980</number>
</property>
<property name="sliderPosition">
<number>980</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 row="6" column="1">
<widget class="QLabel" name="dateLabel">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="populationLabel">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Simulation Speed</string>
</property>
</widget>
</item>
<item row="10" column="0" colspan="2">
<widget class="QCheckBox" name="advancedCheckBox">
<property name="text">
<string>Advanced</string>
</property>
</widget>
</item>
<item row="13" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
@ -312,8 +381,8 @@
<addaction name="actionAction_step"/>
<addaction name="separator"/>
<addaction name="actionControl_Panel"/>
<addaction name="actionDebug"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionControl_Panel">
<property name="checkable">
<bool>true</bool>
@ -383,6 +452,17 @@
<string>Right</string>
</property>
</action>
<action name="actionDebug">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Debug</string>
</property>
<property name="toolTip">
<string>Enables pixel debugging</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
@ -455,5 +535,21 @@
</hint>
</hints>
</connection>
<connection>
<sender>actionDebug</sender>
<signal>toggled(bool)</signal>
<receiver>debugGroupBox</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>153</x>
<y>438</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -38,6 +38,7 @@ PixelPipeline::PixelPipeline(MapScene *map) :
m_height = 256;
m_surfaceRatio = 0;
m_flatSphere = 0;
debugCursorPos = glm::vec2(-1);
m_map->setPipeline(this);
m_targetFBO = FrameBuffer::screen;
m_mapFBO = new FrameBuffer();
@ -66,6 +67,8 @@ PixelPipeline::PixelPipeline(MapScene *map) :
m_skyboxShader = new Shader(vertSource, fragSource);
m_skyTexFront = new Texture(QtUtils::loadImage(":images/img/sky_front.png"));
m_skyTexBack = new Texture(QtUtils::loadImage(":images/img/sky_back.png"));
m_cursorTex = new Texture(QtUtils::loadImage(":images/img/cursor.png"));
m_cursorTex->setFiltering(GL_NEAREST);
updateChanges();
}
@ -79,6 +82,7 @@ PixelPipeline::~PixelPipeline()
delete m_mapTex;
delete m_skyTexBack;
delete m_skyTexFront;
delete m_cursorTex;
// framebuffers
delete m_mapFBO;
// meshes
@ -133,6 +137,11 @@ void PixelPipeline::renderGL(Scene *scene)
m_mapTex->bind(0);
m_renderShader->bindInteger(m_renderShader->getLocation("colorMap"), 0);
// debug
m_cursorTex->bind(1);
m_renderShader->bindInteger(m_renderShader->getLocation("debugCursorMap"), 1);
m_renderShader->bindVec2(m_renderShader->getLocation("debugCursorPos"), debugCursorPos);
glm::mat4 mvp = m_proj * m_view;
m_renderShader->bindMat4(m_renderShader->getLocation("mvp"), mvp);
m_toreiller->draw(m_renderShader);
@ -174,11 +183,18 @@ void PixelPipeline::cameraZoom(int nbScrolls)
m_camera.z = 1;
}
Coord PixelPipeline::getToreillerPos(int mouseX, int mouseY)
Coord PixelPipeline::setCursorPosPicking(int mouseX, int mouseY)
{
glm::vec2 pos(mouseX, mouseY);
pos /= glm::vec2(m_width, m_height); // part that depends on resolution
pos = (pos - glm::vec2(0.5f))*m_mapHeight/m_camera.z; // part that depends on camera zoom
pos += glm::vec2(m_camera.x + 0.5f, -m_camera.y + 0.5f)*m_mapHeight; // part that depends on camera offset
debugCursorPos = pos;
return Coord(pos.x, pos.y);
}
void PixelPipeline::setCursorPos(const Coord &pos)
{
debugCursorPos.x = pos.x + 0.5f;
debugCursorPos.y = pos.y + 0.5f;
}

View File

@ -3,6 +3,7 @@
#include <pipeline.h>
#include <glm/mat4x4.hpp>
#include <glm/vec2.hpp>
class FrameBuffer;
class Texture;
@ -31,6 +32,8 @@ private:
float m_surfaceRatio;
float m_flatSphere;
glm::vec3 m_camera;
glm::vec2 debugCursorPos;
Texture *m_cursorTex;
bool m_showToreiller;
Mesh *m_toreiller;
@ -54,7 +57,8 @@ public:
void setFlatSphere(float flatSphere) { m_flatSphere = flatSphere; }
void setShowToreiller(bool showToreiller) { m_showToreiller = showToreiller; }
Coord getToreillerPos(int mouseX, int mouseY);
Coord setCursorPosPicking(int mouseX, int mouseY);
void setCursorPos(const Coord &pos);
};
#endif // PIXELPIPELINE_H

View File

@ -11,6 +11,32 @@ enum PixelType {
struct PixelProperty
{
static const char *getName(PixelType target)
{
switch(target)
{
case WATER : return "WATER";
case GRASS : return "GRASS";
case MARK : return "MARK";
case ROCK : return "ROCK";
case IRON_ORE : return "IRON_ORE";
case TREE : return "TREE";
case BERRIES : return "BERRIES";
case FOOD : return "FOOD";
case WOOD : return "WOOD";
case STONE : return "STONE";
case IRON : return "IRON";
case DUDE : return "DUDE";
case SPAWN : return "SPAWN";
case WALL : return "WALL";
case ROAD : return "ROAD";
case SWORD : return "SWORD";
case LIBRARY : return "LIBRARY";
case DEAD_DUDE : return "DEAD_DUDE";
default : return "WTF";
}
}
static bool isWalkable(PixelType target)
{
return target == GRASS

View File

@ -10,14 +10,14 @@
#define MAX_RESOURCES_IN_STACK 5
Simulation::Simulation(MapScene *_map, std::vector<BehaviorFunction> &_behaviors):
Simulation::Simulation(MapScene *_map, std::vector<std::pair<BehaviorFunction, DebugBehaviorFunction>> &_behaviors):
p_map(_map)
{
int i=0;
for(BehaviorFunction &behavior : _behaviors){
for(std::pair<BehaviorFunction, DebugBehaviorFunction> &behavior : _behaviors){
glm::vec3 color;
color[i%3]=0.5f*(1 + i/3);
m_teams.push_back(Team(color, color*0.8f, behavior));
m_teams.push_back(Team(color, color*0.8f, behavior.first, behavior.second));
p_map->setColors(i, color, color*0.8f);
i++;
}
@ -29,6 +29,26 @@ Simulation::~Simulation()
delete d;
}
void Simulation::getPixelInfoString(char *outputString, const Pixel &px)
{
if(PixelProperty::isResource(px.type))
sprintf(outputString, "Stack size : %d", px.data.nbRes);
else if(px.type == SPAWN)
{
int teamId = px.data.teamId;
const Team &t = m_teams[teamId];
sprintf(outputString, "Team ID : %d\nFood storage : %d\nNext birth in %d turns", teamId, t.getFoodQuantity(), t.getSpawnCooldown());
}
else if(px.type == DUDE)
{
Dude *d = (Dude*)px.data.dudePtr;
const Team &t = m_teams[d->getTeam()];
t.getDudeDebugOutput(outputString, d);
}
else
outputString[0] = '\0';
}
void Simulation::update()
{
std::random_shuffle(m_dudes.begin(), m_dudes.end());

View File

@ -8,6 +8,7 @@
#include "team.h"
class MapScene;
class Pixel;
class Simulation
{
@ -28,8 +29,9 @@ private:
void resolveBattles();
public:
Simulation(MapScene *_map, std::vector<BehaviorFunction> &_behaviors);
Simulation(MapScene *_map, std::vector<std::pair<BehaviorFunction, DebugBehaviorFunction>> &_behaviors);
~Simulation();
void getPixelInfoString(char *outputString, const Pixel &px);
MapScene* getMap() { return (MapScene*) p_map; }
int getPopulation(){return m_dudes.size();}

View File

@ -13,6 +13,11 @@
#define LIB_SUFFIX "so"
#endif
void defaultDebugFunc(char *outputString, const char *memory)
{
sprintf(outputString, "no debug function defined");
}
SimulationDialog::SimulationDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SimulationDialog),
@ -25,9 +30,9 @@ SimulationDialog::SimulationDialog(QWidget *parent) :
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)));
updatePreview();
refreshBehaviors();
refreshGenerators();
updatePreview();
}
SimulationDialog::~SimulationDialog()
@ -171,10 +176,14 @@ void SimulationDialog::selectBehavior(const QModelIndex &index)
QLibrary lib(path);
if(lib.load())
{
BehaviorFunction func = (BehaviorFunction)lib.resolve("think");
if(func)
std::pair<BehaviorFunction, DebugBehaviorFunction> funcs;
funcs.first = (BehaviorFunction)lib.resolve("think");
funcs.second = (DebugBehaviorFunction)lib.resolve("debugOutput");
if(!funcs.second)
funcs.second = defaultDebugFunc;
if(funcs.first)
{
m_selectedBehaviors.push_back(func);
m_selectedBehaviors.push_back(funcs);
ui->selectedBehaviors->addItem(item->text());
}
else
@ -185,7 +194,7 @@ void SimulationDialog::selectBehavior(const QModelIndex &index)
Simulation* SimulationDialog::getSimulation()
{
if(m_map == NULL || m_map->getNbTeams() != m_selectedBehaviors.size())
if(m_map == NULL || m_map->getNbTeams() != int(m_selectedBehaviors.size()))
generateMap();
return new Simulation(m_map, m_selectedBehaviors);
}

View File

@ -38,7 +38,7 @@ private:
Ui::SimulationDialog *ui;
std::vector<QString> m_genList;
std::vector<QString> m_behaviorList;
std::vector<BehaviorFunction> m_selectedBehaviors;
std::vector<std::pair<BehaviorFunction, DebugBehaviorFunction>> m_selectedBehaviors;
MapScene *m_map;
QLibrary *m_currentGeneratorLib;
QImage *m_currentPreview;

View File

@ -1,13 +1,14 @@
#include "team.h"
#include "dude.h"
Team::Team(const glm::vec3 &spawnColor, const glm::vec3 &dudeColor, BehaviorFunction _behavior):
Team::Team(const glm::vec3 &spawnColor, const glm::vec3 &dudeColor, BehaviorFunction _behavior, DebugBehaviorFunction _debugFunc):
m_spawnColor(spawnColor),
m_dudeColor(dudeColor),
m_spawnCooldown(1),
m_foodQuantity(NB_STARTING_FOOD),
m_dudesReady(0),
m_behavior(_behavior)
m_behavior(_behavior),
m_debugFunc(_debugFunc)
{
}
@ -41,3 +42,8 @@ void Team::update(Dude *dude)
{
dude->update(m_behavior);
}
void Team::getDudeDebugOutput(char *outputString, Dude *dude) const
{
dude->debugOutput(outputString, m_debugFunc);
}

View File

@ -21,8 +21,9 @@ class Team
int m_foodQuantity;
int m_dudesReady;
BehaviorFunction m_behavior;
DebugBehaviorFunction m_debugFunc;
public:
Team(const glm::vec3 &spawnColor, const glm::vec3 &dudeColor, BehaviorFunction _behavior);
Team(const glm::vec3 &spawnColor, const glm::vec3 &dudeColor, BehaviorFunction _behavior, DebugBehaviorFunction _debugFunc);
bool updateSpawn();
void popDude();
void addFood() {m_foodQuantity++; }
@ -30,6 +31,10 @@ public:
void update(Dude*);
glm::vec3 getSpawnColor() { return m_spawnColor; }
glm::vec3 getDudeColor() { return m_dudeColor; }
int getFoodQuantity() const { return m_foodQuantity; }
int getSpawnCooldown() const { return m_spawnCooldown; }
void getDudeDebugOutput(char *outputString, Dude *dude) const;
};
#endif // TEAM_H