Skip to content
Snippets Groups Projects
Commit 40f43a3a authored by Armin Co's avatar Armin Co
Browse files

Using threads instead of omp

parent 90306882
Branches
No related tags found
No related merge requests found
# QPong – Quanten-Pong
#### This is the new pong ;)e
#### This is the new pong ;)
Controls for Player one: a & q and for Player two ö & ü.
......@@ -27,5 +27,5 @@ make
## Erweiterungsideen
- Konfiguration über die GUI, evt. mit speichern
- Spalt & Interferen
- Spalt & Interferenz
- Controller-Schnittstelle (für z.B. Mikrofon, Joysticks oder Potis)
\ No newline at end of file
......@@ -4,6 +4,8 @@ add_library(qpong
ParticleImage.cpp
QWindow.cpp
QDrawingArea.cpp
QPlayer.cpp
Profiler.cpp
)
## create the application
......@@ -20,9 +22,6 @@ pkg_check_modules(GTKMM gtkmm-3.0)
link_directories(${GTKMM_LIBRARY_DIRS})
include_directories(${GTKMM_INCLUDE_DIRS})
# Use parallel for loops
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --openmp")
## link all necessary libs to the target
target_link_libraries(qpong.app
qpong
......
......@@ -9,8 +9,8 @@
namespace QPong
{
constexpr int arrayWidth = 256;
constexpr int arrayHeight = 256;
constexpr int arrayWidth = 512;
constexpr int arrayHeight = 512;
constexpr unsigned arraySize = arrayWidth * arrayHeight;
......
......@@ -6,12 +6,14 @@
///
#include <iostream>
#include <chrono>
#include <thread>
#include <vector>
#include <gtk/gtk.h>
#include "Common.hpp"
#include "Particle.hpp"
#include "Profiler.hpp"
/// @brief Planck constant.
///
......@@ -27,35 +29,26 @@ const T sqr(const T n)
return n * n;
}
const double xAt(int i)
/// @brief Takes the row index of an array and turns it
/// into a position.
///
const double xAt(int x)
{
constexpr double dx = 2.0 / QPong::arrayWidth;
return i * dx - 1.0;
return 2.0 * x / QPong::arrayWidth - 1.0;
}
const double yAt(int iy)
/// @brief Takes the line index of an array and turns it
/// into a position.
///
const double yAt(int y)
{
constexpr double dy = 2.0 / QPong::arrayHeight;
return iy * dy - 1.0;
return 2.0 * y / QPong::arrayHeight - 1.0;
}
const double pxAt(int ix)
{
if (ix > QPong::arrayWidth / 2)
ix -= QPong::arrayWidth;
return ix * M_PI * hbar;
}
const double pyAt(int iy)
{
if (iy > QPong::arrayHeight / 2)
iy -= QPong::arrayHeight;
return iy * M_PI * hbar;
}
const double obstaclePotential(double x, double y, double x0, double y0)
const double batPotential(double x, double y, Position pos)
{
y -= y0;
y -= pos.y;
constexpr double vx = 100000.0 / 2.0;
double E = 0.0;
......@@ -63,22 +56,22 @@ const double obstaclePotential(double x, double y, double x0, double y0)
if (y >= height)
{
double d = sqr(x-x0) + sqr(y-height);
double d = sqr(x-pos.x) + sqr(y-height);
E = 1.0 / (sqrt(d) * vx);
}
else if (y <= (-height))
{
double d = sqr(x-x0) + sqr((-y)-height);
double d = sqr(x-pos.x) + sqr((-y)-height);
E = 1.0 / (sqrt(d) * vx);
}
else if ( x >= x0 && y < height && y>-height)
else if ( x >= pos.x && y < height && y>-height)
{
double d = x-x0;
double d = x-pos.x;
E = 1.0 / (d * vx);
}
else if (x < x0 && y < height && y > -height)
else if (x < pos.x && y < height && y > -height)
{
double d = x0-x;
double d = pos.x-x;
E = 1.0 / (d * vx);
}
return E;
......@@ -87,7 +80,6 @@ const double obstaclePotential(double x, double y, double x0, double y0)
double sumAtInit = 0.0;
void Particle::initMomentum()
{
std::cout << "Initialising particle" << std::endl;
sumAtInit = 0.0;
for (unsigned iy = 0; iy < QPong::arrayHeight; iy++)
{
......@@ -107,10 +99,6 @@ void Particle::initMomentum()
sumAtInit += sqr(real(m_psi[index])) + sqr(imag(m_psi[index]));
}
}
for (auto p : m_players)
{
m_players[p.first].score = 0;
}
for (unsigned iy = 0; iy < QPong::arrayHeight; iy++)
{
......@@ -122,20 +110,16 @@ void Particle::initMomentum()
m_psi[index] *= 1.0 / sqrt(sumAtInit);
}
}
std::cout << sumAtInit << std::endl;
}
constexpr double playerOneStartX = -0.7;
constexpr double playerTwoStartX = 0.7;
Particle::Particle(ParticleImage *momentum, ParticleImage *position)
Particle::Particle(ParticleImage *momentum, ParticleImage *position, std::map<Player, std::shared_ptr<QPlayer>> players)
: m_bufMomentumRepresentation{momentum}
, m_bufPositionRepresentation{position}
, m_ready{false}
, m_players {players}
{
m_players.insert(std::make_pair(Player::One, PlayerData {playerOneStartX, 0.0}));
m_players.insert(std::make_pair(Player::Two, PlayerData {playerTwoStartX, 0.0}));
fftw_init_threads();
......@@ -163,176 +147,159 @@ bool Particle::notReady()
return !m_ready;
}
void Particle::propagate()
double Particle::removeParticle(int index, double cx)
{
updatePlayers();
constexpr double dt = 0.05;
sumAtInit = 0;
// #pragma omp parallel for
for (unsigned iy = 0; iy < QPong::arrayHeight; iy++)
double e = cos(cx) * cos(cx);
double normPre = sqr(std::real(m_psi[index])) + sqr(std::real(m_psi[index]));
m_psi[index] *= e;
double dif = normPre - (sqr(std::real(m_psi[index])) + sqr(std::real(m_psi[index])));
return dif;
}
const double pxAt(int ix)
{
double y = yAt(iy);
// #pragma omp parallel for
for (unsigned long ix = 0; ix < QPong::arrayWidth; ix++)
if (ix > QPong::arrayWidth / 2)
ix -= QPong::arrayWidth;
return ix * M_PI * hbar;
}
const double pyAt(int iy)
{
if (iy > QPong::arrayHeight / 2)
iy -= QPong::arrayHeight;
return iy * M_PI * hbar;
}
double x = xAt(ix);
int index = QPong::arrayWidth * iy + ix;
sumAtInit += sqr(real(m_psi[index])) + sqr(imag(m_psi[index]));
constexpr double dt = 0.05;
// destroy ^^
if (x < playerOneStartX) //< expexts p1.x < 0
void Particle::manipulateParticleInPosition(int indexFrom, int indexTo)
{
double cx = -playerOneStartX + x;
cx = cx * (M_PI / 2) / (1.0 + playerOneStartX);
double e = cos(cx) * cos(cx);
double normPre = sqr(std::real(m_psi[index])) + sqr(std::real(m_psi[index]));
m_psi[index] *= e;
double dif = normPre - (sqr(std::real(m_psi[index])) + sqr(std::real(m_psi[index])));
m_players[Player::Two].score += dif;
sumAtInit = 0;
auto pOneX = m_players[Player::One]->getPosition().x;
auto pTwoX = m_players[Player::Two]->getPosition().x;
float sumScorePlayerOne = 0.0;
float sumScorePlayerTwo = 0.0;
for (int index = indexFrom; index < indexTo; index++)
{
double x = xAt(index % QPong::arrayWidth);
double y = yAt(index / QPong::arrayWidth);
if (x < pOneX) //< expects p1.x < 0
{
double cx = -pOneX + x;
cx = cx * (M_PI / 2) / (1.0 + pOneX);
double dif = removeParticle(index, cx);
sumScorePlayerTwo += dif;
}
if (x > playerTwoStartX) //< expects p2.x > 0
if (x > pTwoX) //< expects p2.x > 0
{
double cx = x - playerTwoStartX;
cx = cx * (M_PI / 2) / (1.0 - playerTwoStartX);
double e = cos(cx) * cos(cx);
double normPre = sqr(std::real(m_psi[index])) + sqr(std::real(m_psi[index]));
m_psi[index] *= e;
double dif = normPre - (sqr(std::real(m_psi[index])) + sqr(std::real(m_psi[index])));
m_players[Player::One].score += dif;
double cx = x - pTwoX;
cx = cx * (M_PI / 2) / (1.0 - pTwoX);
double dif = removeParticle(index, cx);
sumScorePlayerOne += dif;
}
// obstacles
double E = obstaclePotential(x, y, m_players[Player::One].x, m_players[Player::One].y);
double E2 = obstaclePotential(x, y, m_players[Player::Two].x, m_players[Player::Two].y);
double E3 = sqr(y) * sqr(y) * sqr(y) * sqr(y) * 0.002;
std::complex<double> tmp = m_psi[index] * exp(-Ci * dt / hbar * (E + E2 + E3));
double playerOneBat = batPotential(x, y, m_players[Player::One]->getPosition());
double playerTwoBat = batPotential(x, y, m_players[Player::Two]->getPosition());
double horizontalBorders = sqr(y) * sqr(y) * sqr(y) * sqr(y) * 0.002;
std::complex<double> tmp = m_psi[index] * exp(-Ci * dt / hbar * (playerOneBat + playerTwoBat + horizontalBorders));
m_psi[index] = tmp;
m_bufPositionRepresentation->updateBuffer(index, tmp * 95.0, (E+E2+E3*0.8)*600);
m_bufPositionRepresentation->updateBuffer(index, tmp * 75.0, (playerOneBat + playerTwoBat + horizontalBorders)*400);
}
m_players[Player::One]->addScore(sumScorePlayerOne);
m_players[Player::Two]->addScore(sumScorePlayerTwo);
}
fftw_execute (m_planForward); // transform into momentum repr.
#pragma omp parallel for
for (unsigned iy = 0; iy < QPong::arrayHeight; iy++)
void Particle::moveStep(int indexFrom, int indexTo)
{
double py = pyAt(iy);
#pragma omp parallel for
for (unsigned long ix = 0; ix < QPong::arrayWidth; ix++)
for (int i = indexFrom; i < indexTo; i++)
{
double px = pxAt(ix);
double py = pyAt(i / QPong::arrayWidth);
double px = pxAt(i % QPong::arrayWidth);
constexpr double m = 1.0;
double E = (sqr(px) + sqr(py)) / (2.0 * m);
constexpr double N = 1.0 / QPong::arraySize;
int index = QPong::arrayWidth * iy + ix;
m_psi[index] *= exp(-Ci * dt / hbar * E) * N;
}
double E = (sqr(px) + sqr(py)) / (2.0 * m);
m_psi[i] *= exp(-Ci * dt / hbar * E) * N;
}
updateMomentumImage(); //momentum
fftw_execute(m_planBackward); // transform into position repr.
}
void Particle::updateMomentumImage()
{
unsigned px = 0;
unsigned py = 0;
unsigned long momentum_index = 0;
unsigned long array_index = 0;
#pragma omp parallel for
for (unsigned y = 0; y < QPong::arrayHeight; y++)
void Particle::propagate()
{
for (unsigned x = 0; x < QPong::arrayWidth; x++)
std::cout << std::endl;
constexpr int threadCount = 8;
Profiler p {"propagate", Verbose::True};
{
if (y >= QPong::arrayHeight / 2)
Profiler manipulation {"manipulation", Verbose::True};
std::vector<std::thread> threads;
for (int i = 0; i < threadCount; i++)
{
py = y - QPong::arrayHeight / 2;
threads.emplace_back(&Particle::manipulateParticleInPosition, this, i * (QPong::arraySize/threadCount), (i+1) * (QPong::arraySize/threadCount));
}
else
for (auto &thread : threads)
{
py = y + QPong::arrayHeight / 2;
thread.join();
}
if (x >= QPong::arrayWidth / 2)
{
px = x - QPong::arrayWidth / 2;
}
else
{
px = x + QPong::arrayWidth / 2;
}
constexpr double scale = 164.0 * 95.0;
array_index = y * QPong::arrayWidth + x;
momentum_index = py * QPong::arrayWidth + px;
m_bufMomentumRepresentation->updateBuffer(array_index, (m_psi[momentum_index] * scale), 0.0);
}
}
Profiler f {"fourier_forward", Verbose::True};
fftw_execute (m_planForward); // transform into momentum repr.
}
constexpr double speedStepSize = 0.0005;
void Particle::updateObstacle(Player player, Move direction)
{
constexpr double addSpped = 3;
switch (direction)
Profiler move {"move", Verbose::True};
std::vector<std::thread> threads;
for (int i = 0; i < threadCount; i++)
{
case Move::Up:
m_players[player].vy -= speedStepSize * addSpped;
break;
case Move::Down:
m_players[player].vy += speedStepSize * addSpped;
break;
threads.emplace_back(&Particle::moveStep, this, i * (QPong::arraySize / threadCount), (i + 1) * (QPong::arraySize / threadCount));
}
for (auto &thread : threads)
{
thread.join();
}
}
constexpr double maxSpeedScale = 33;
if (m_players[player].vy > speedStepSize * maxSpeedScale)
{
m_players[player].vy = speedStepSize * maxSpeedScale;
Profiler image {"image", Verbose::True};
updateMomentumImage(); //momentum
}
if (m_players[player].vy < -speedStepSize * maxSpeedScale)
{
m_players[player].vy = -speedStepSize * maxSpeedScale;
Profiler f {"fourier_backward", Verbose::True};
fftw_execute(m_planBackward); // transform into position repr.
}
}
void Particle::updatePlayers()
{
constexpr double negativeAccelScale = 1.5;
for (auto p : m_players)
{
m_players[p.first].y += m_players[p.first].vy;
if (m_players[p.first].vy > 0.0)
void Particle::updateMomentumImage()
{
m_players[p.first].vy -= speedStepSize * negativeAccelScale;
}
if (m_players[p.first].vy < 0.0)
for (int index = 0; index < QPong::arraySize; index++)
{
auto y = index / QPong::arrayWidth;
unsigned py = 0;
if (y >= QPong::arrayHeight / 2)
{
m_players[p.first].vy += speedStepSize * negativeAccelScale;
py = y - QPong::arrayHeight / 2;
}
if (m_players[p.first].vy < speedStepSize* negativeAccelScale && m_players[p.first].vy > -speedStepSize * negativeAccelScale)
else
{
m_players[p.first].vy = 0.0;
py = y + QPong::arrayHeight / 2;
}
constexpr double maxY = 1.3;
if (m_players[p.first].y > maxY)
auto x = index % QPong::arrayWidth;
unsigned px = 0;
if (x >= QPong::arrayWidth / 2)
{
m_players[p.first].y = maxY;
px = x - QPong::arrayWidth / 2;
}
if (m_players[p.first].y < -maxY)
else
{
m_players[p.first].y = -maxY;
}
}
px = x + QPong::arrayWidth / 2;
}
double Particle::getScore(Player player)
{
return m_players[player].score;
constexpr double scale = 15580.0;;
auto array_index = y * QPong::arrayWidth + x;
auto momentum_index = py * QPong::arrayWidth + px;
m_bufMomentumRepresentation->updateBuffer(array_index, (m_psi[momentum_index] * scale), 0.0);
}
}
......@@ -9,39 +9,21 @@
#define QPONG_PARTICLE_HPP
#include <complex>
#include <memory>
#include <map>
#include <math.h>
#include <fftw3.h>
#include "ParticleImage.hpp"
#include "QPlayer.hpp"
enum class Player
{
One,
Two
};
enum class Move
{
Up,
Down
};
struct PlayerData
{
double x;
double y;
double vx = 0;
double vy = 0;
double score = 0;
};
class Particle
{
public:
Particle() = delete;
Particle(ParticleImage *momentum, ParticleImage *position);
Particle(ParticleImage *momentum, ParticleImage *position, std::map<Player, std::shared_ptr<QPlayer>> players);
~Particle();
/// @brief Execute one step of the simulation.
......@@ -53,19 +35,11 @@ public:
///
void initMomentum();
/// @brief Update obstacle position
/// @param player
/// @param direction
///
void updateObstacle(Player player, Move direction);
/// @brief Check if everything is initialised.
///
bool notReady();
/// @brief Get the score of the given player
///
double getScore(Player player);
/// @brief Add a new player
private:
std::complex<double> *m_psi;
......@@ -73,7 +47,7 @@ private:
fftw_plan m_planBackward;
bool m_ready;
std::map<Player, PlayerData> m_players;
std::map<Player, std::shared_ptr<QPlayer>> m_players;
ParticleImage *m_bufPositionRepresentation;
ParticleImage *m_bufMomentumRepresentation;
......@@ -82,7 +56,22 @@ private:
///
void updateMomentumImage();
void updatePlayers();
/// @brief Manipulate particle in position representation
/// For bats and borders potentials are used.
/// Removing the particle behind the bat with a cos2
///
void manipulateParticleInPosition(int from, int to);
/// @brief Move the particle one step forward in momentum representation
///
void moveStep(int indexFrom, int indexTo);
/// @brief Remove parts of the particle that are behind the bat.
///
double removeParticle(int index, double cx);
};
#endif
\ No newline at end of file
......@@ -7,6 +7,8 @@
#include "ParticleImage.hpp"
#include "Common.hpp"
#include "Profiler.hpp"
constexpr unsigned maxBufferCount = 2;
ParticleImage::ParticleImage()
......
///
/// @file Profiler.cpp
/// @author Armin Co
///
/// @brief
#include "Profiler.hpp"
Profiler::Profiler(const char* name)
: m_name {name}
, m_stopped {false}
, m_verbose {Verbose::False}
{
m_startTimepoint = std::chrono::high_resolution_clock::now();
}
Profiler::Profiler(const char* name, Verbose v)
: m_verbose {v}
, m_name {name}
, m_stopped {false}
{
m_startTimepoint = std::chrono::high_resolution_clock::now();
}
Profiler::~Profiler()
{
if (!m_stopped)
{
stop();
}
}
long Profiler::stop()
{
auto endTimepoint = std::chrono::high_resolution_clock::now();
m_stopped = true;
long mus = std::chrono::duration_cast<std::chrono::nanoseconds>(endTimepoint - m_startTimepoint).count();
if (m_verbose == Verbose::True)
{
std::cout << m_name << ": " << mus / 1000.0 / 1000.0<< "ms" << std::endl;
}
return mus;
}
\ No newline at end of file
///
/// @file Profiler.hpp
/// @author Armin Co
///
/// @brief Class to do some basic timing and profiling.
///
#ifndef QPONG_PROFILER_HPP
#define QPONG_PROFILER_HPP
#include <chrono>
#include <iostream>
enum class Verbose
{
True,
False
};
class Profiler
{
public:
Profiler(const char* name);
Profiler(const char* name, Verbose v);
~Profiler();
long stop();
private:
const char* m_name;
Verbose m_verbose;
std::chrono::time_point<std::chrono::system_clock> m_startTimepoint;
bool m_stopped;
};
#endif
\ No newline at end of file
......@@ -3,8 +3,6 @@
/// @author Armin Co
///
#include <thread>
#include "QDrawingArea.hpp"
QDrawingArea::QDrawingArea()
......@@ -17,7 +15,6 @@ void QDrawingArea::redraw()
m_dispatcher.emit();
}
void QDrawingArea::setPixbuf(Glib::RefPtr<Gdk::Pixbuf> pixbuf)
{
m_image = pixbuf;
......@@ -36,4 +33,3 @@ bool QDrawingArea::on_draw(const Cairo::RefPtr<Cairo::Context> &cr)
cr->restore();
return true;
}
......@@ -2,6 +2,8 @@
/// @file QDrawingArea.hpp
/// @author Armin Co
///
/// @brief QDrawingArea is a class which can show a Gdk::Pixbuf.
///
#ifndef QPONG_DRAWING_AREA_HPP
#define QPONG_DRAWING_AREA_HPP
......@@ -9,21 +11,31 @@
#include <gtkmm.h>
#include <gdkmm.h>
/// @brief QDrawingArea is derived from Gtk::DrawingArea.
/// An object of this class stores a reference to Gdk::Pixbuf which can be shown and updated.
///
class QDrawingArea : public Gtk::DrawingArea
{
public:
QDrawingArea();
virtual ~QDrawingArea(){};
/// @brief Request a redraw of the drawing area.
///
void redraw();
/// @brief Set a new pixbuf reference.
///
void setPixbuf(Glib::RefPtr<Gdk::Pixbuf> pixbuf);
protected:
/// @brief Signal handler which is called when a redraw of the drawing area is requested.
///
bool on_draw(const Cairo::RefPtr<Cairo::Context> &cr) override;
private:
Glib::RefPtr<Gdk::Pixbuf> m_image;
Glib::Dispatcher m_dispatcher;
Glib::RefPtr<Gdk::Pixbuf> m_image; ///< Reference a pixbuf.
Glib::Dispatcher m_dispatcher; ///< Dispatcher is used to trigger thread safe redraws.
};
#endif
\ No newline at end of file
///
/// @file QPlayer.cpp
/// @author Armin Co
///
#include "QPlayer.hpp"
#include <mutex>
constexpr double speedStepSize = 0.0005;
QPlayer::QPlayer(Player pl, Position pos)
: m_id {pl}
, m_x {pos.x}
, m_y {pos.y}
{
}
void QPlayer::update()
{
constexpr double negativeAccelScale = 1.5;
m_y += m_vy;
if (m_vy > 0.0)
{
m_vy -= speedStepSize * negativeAccelScale;
}
if (m_vy < 0.0)
{
m_vy += speedStepSize * negativeAccelScale;
}
if (m_vy < speedStepSize* negativeAccelScale && m_vy > -speedStepSize * negativeAccelScale)
{
m_vy = 0.0;
}
constexpr double maxY = 1.3;
if (m_y > maxY)
{
m_y = maxY;
}
if (m_y < -maxY)
{
m_y = -maxY;
}
}
void QPlayer::move(Direction direction)
{
constexpr double addSpped = 3;
switch (direction)
{
case Direction::Up:
m_vy -= speedStepSize * addSpped;
break;
case Direction::Down:
m_vy += speedStepSize * addSpped;
break;
}
constexpr double maxSpeedScale = 33;
if (m_vy > speedStepSize * maxSpeedScale)
{
m_vy = speedStepSize * maxSpeedScale;
}
if (m_vy < -speedStepSize * maxSpeedScale)
{
m_vy = -speedStepSize * maxSpeedScale;
}
}
float QPlayer::getScore()
{
return m_score * 100;
}
std::mutex mtx;
void QPlayer::addScore(float score)
{
std::lock_guard<std::mutex> lockScore(mtx);
m_score += score;
}
Position QPlayer::getPosition()
{
return {m_x, m_y};
}
void QPlayer::reset()
{
m_score = 0;
}
\ No newline at end of file
///
/// @file Qlayer.hpp
/// @author Armin Co
///
/// @brief Player class.
///
#ifndef QPONG_QPLAYER_HPP
#define QPONG_QPLAYER_HPP
enum class Player
{
One,
Two
};
enum class Direction
{
Up,
Down
};
struct Position
{
double x;
double y;
};
class QPlayer
{
public:
QPlayer(Player pl, Position pos);
void update();
void move(Direction d);
float getScore();
void addScore(float score);
void reset();
Position getPosition();
private:
Player m_id;
double m_x;
double m_y;
double m_vx = 0;
double m_vy = 0;
double m_score = 0;
};
#endif
\ No newline at end of file
......@@ -4,6 +4,8 @@
#include "QWindow.hpp"
#include "Profiler.hpp"
bool propagating = true;
int propRate = 0;
int renderRate = 0;
......@@ -15,32 +17,39 @@ bool downPressed = false;
/// @brief This functino has to run in its own thread and propagates the particle as fast as possible.
///
void simulation(Particle *p)
void QWindow::simulation()
{
do
{
auto start = std::chrono::system_clock::now();
p->propagate();
for (auto player : m_players)
{
player.second->update();
}
m_particle->propagate();
propRate = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - start).count();
if (qPressed)
p->updateObstacle(Player::One, Move::Up);
m_players[Player::One]->move(Direction::Up);
if (aPressed)
p->updateObstacle(Player::One, Move::Down);
m_players[Player::One]->move(Direction::Down);
if (upPressed)
p->updateObstacle(Player::Two, Move::Up);
m_players[Player::Two]->move(Direction::Up);
if (downPressed)
p->updateObstacle(Player::Two, Move::Down);
m_players[Player::Two]->move(Direction::Down);
// Sync propagating with drawing if prop is faster.
// Limit the speed of the simulation.
auto dt = std::chrono::system_clock::now() - start;
constexpr int propTime = 150;
if (dt.count() < propTime)
auto dtMillis = std::chrono::duration_cast<std::chrono::milliseconds>(dt).count();
constexpr int propTime = 10;
if (dtMillis < propTime)
{
std::this_thread::sleep_for(std::chrono::milliseconds(propTime - dt.count()));
std::this_thread::sleep_for(std::chrono::milliseconds(propTime - dtMillis));
}
}
while (propagating);
......@@ -68,9 +77,14 @@ QWindow::QWindow()
{
set_border_width(5);
constexpr double playerOneStartX = -0.7;
constexpr double playerTwoStartX = 0.7;
m_players.insert(std::make_pair<Player, std::shared_ptr<QPlayer>>(Player::One, std::make_shared<QPlayer>(Player::One, Position{-0.7, 0})));
m_players.insert(std::make_pair<Player, std::shared_ptr<QPlayer>>(Player::Two, std::make_shared<QPlayer>(Player::Two, Position{ 0.7, 0})));
m_momentum = new ParticleImage;
m_position = new ParticleImage;
m_particle = new Particle(m_momentum, m_position);
m_particle = new Particle(m_momentum, m_position, m_players);
add(m_box);
m_box.pack_start(m_vBox);
......@@ -111,7 +125,7 @@ QWindow::QWindow()
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
m_propagatingThread = std::thread(simulation, m_particle);
m_propagatingThread = std::thread(&QWindow::simulation, this);
m_propagatingThread.detach();
std::thread rendering(render, this);
......@@ -138,7 +152,7 @@ void QWindow::updateGui()
ss = std::stringstream();
ss << "Score Player 1: ";
double score = m_particle->getScore(Player::One) * 100;
auto score = m_players[Player::One]->getScore();
ss << std::setprecision(2) << std::setw(7) << score << "%";
if (score > 50.0)
{
......@@ -149,7 +163,7 @@ void QWindow::updateGui()
ss = std::stringstream();
ss << "Score Player 2: ";
score = m_particle->getScore(Player::Two) * 100;
score = m_players[Player::Two]->getScore();
ss << std::setprecision(2) << std::setw(7) << score << "%";
if (score > 50.0)
{
......@@ -179,8 +193,7 @@ bool QWindow::onKeyPress(GdkEventKey* event)
if (event->keyval == oe)
downPressed = true;
}
if (event->type == GdkEventType::GDK_KEY_RELEASE)
else if (event->type == GdkEventType::GDK_KEY_RELEASE)
{
if (event->keyval == q)
qPressed = false;
......@@ -211,12 +224,17 @@ void QWindow::updateImage()
void QWindow::onButtonPress()
{
propagating = false;
std::this_thread::sleep_for((std::chrono::seconds)1);
m_particle->initMomentum();
m_propagatingThread = std::thread(simulation, m_particle);
for (auto player : m_players)
{
player.second->reset();
}
m_propagatingThread = std::thread(&QWindow::simulation, this);
propagating = true;
m_propagatingThread.detach();
}
\ No newline at end of file
......@@ -7,7 +7,8 @@
#define Q_WINDOW_HPP
#include <thread>
#include <map>
#include <memory>
#include <gtkmm.h>
#include "Particle.hpp"
......@@ -28,7 +29,7 @@ public:
virtual ~QWindow(){}
/// @brief Sends a signal to GTK to redraw
/// @brief Sends a signal to GTK to update drawing areas.
void updateView();
protected:
......@@ -46,6 +47,10 @@ private:
///
void updateGui();
/// @brief Loop throug iteratins of the simulation
///
void simulation();
Gtk::Box m_box;
Gtk::VBox m_vBox;
Gtk::HBox m_hBox;
......@@ -72,6 +77,8 @@ private:
ParticleImage *m_momentum;
ParticleImage *m_position;
ParticleImage *m_obstacle;
std::map<Player, std::shared_ptr<QPlayer>> m_players;
};
#endif
\ No newline at end of file
......@@ -2,7 +2,7 @@
/// @file main.cpp
/// @author Armin Co
///
/// @brief Application
/// @brief The QPong game.
///
#include <iostream>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment