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

Merge branch 'master' into feature_config

parents f4ff95e2 54680e76
No related branches found
No related tags found
No related merge requests found
......@@ -9,16 +9,18 @@
#include <complex>
namespace QPong
{
/// @brief Convinient conatiner to store a RGB value.
/// {r, g, b}
struct QColor
{
float r = 0;
float g = 0;
float b = 0;
float r = 0.0f;
float g = 0.0f;
float b = 0.0f;
};
/// @brief Class ImageBuffer
///
class ImageBuffer
......@@ -28,7 +30,6 @@ public:
///
ImageBuffer();
/// @brief Update the buffer at the given position.
/// @param index Index of the value that should be changed.
/// @param v The value as a complex number which will be interpreted as a color.
......@@ -36,15 +37,15 @@ public:
///
void updateAt(unsigned index, std::complex<double> v, double pot);
/// @return Get color value from particle at array index.
///
const QColor getValue(unsigned index);
private:
double *m_potbuf;
std::complex<double> *m_complexBuffer;
};
} // namespace QPong
#endif
......@@ -11,9 +11,10 @@
#include "Common.hpp"
#include "Particle.hpp"
#include "Profiler.hpp"
#include "Config.hpp"
using namespace QPong;
const std::complex<double> Ci(0.0, 1.0);
......@@ -69,7 +70,7 @@ void Particle::initMomentum()
}
Particle::Particle(ImageBuffer *momentum, ImageBuffer *position, std::map<Player, std::shared_ptr<QPlayer>> players)
Particle::Particle(ImageBuffer *momentum, ImageBuffer *position, std::map<Player::Id, std::shared_ptr<Player>> players)
: m_bufMomentumRepresentation{momentum}
, m_bufPositionRepresentation{position}
, m_ready{false}
......@@ -101,31 +102,15 @@ bool Particle::notReady()
double Particle::removeParticle(int index, double cx)
{
double e = cos(cx) * cos(cx);
double normPre = sqr(std::real(m_psi[index])) + sqr(std::real(m_psi[index]));
double normPre = sqr(std::real(m_psi[index])) + sqr(std::imag(m_psi[index]));
double e = sqr(cos(cx));
m_psi[index] *= e;
double dif = normPre - (sqr(std::real(m_psi[index])) + sqr(std::real(m_psi[index])));
double dif = normPre - (sqr(std::real(m_psi[index])) + sqr(std::imag(m_psi[index])));
return dif;
}
const double pxAt(int ix)
{
if (ix > Config::getArrayWidth() / 2)
ix -= Config::getArrayWidth();
return ix * M_PI * Config::getHbar();
}
const double pyAt(int iy)
{
if (iy > Config::getArrayHeight() / 2)
iy -= Config::getArrayHeight();
return iy * M_PI * Config::getHbar();
}
const double batPotential(double x, double y, Position pos)
const double batPotential(double x, double y, Player::Position pos)
{
y -= pos.y;
double E = 0.0;
......@@ -154,8 +139,8 @@ const double batPotential(double x, double y, Position pos)
constexpr double dt = 0.15;
void Particle::manipulateParticleInPosition(int indexFrom, int indexTo)
{
auto pOneX = m_players[Player::One]->getPosition().x;
auto pTwoX = m_players[Player::Two]->getPosition().x;
auto pOneX = m_players[Player::Id::One]->getPosition().x;
auto pTwoX = m_players[Player::Id::Two]->getPosition().x;
float sumScorePlayerOne = 0.0;
float sumScorePlayerTwo = 0.0;
......@@ -166,41 +151,62 @@ void Particle::manipulateParticleInPosition(int indexFrom, int indexTo)
if (x < pOneX) //< expects p1.x < 0
{
double cx = -pOneX + x;
cx = cx * (M_PI / 2) / (1.0 + pOneX);
cx = cx * (M_PI / 2.0) / (1.0 + pOneX);
double dif = removeParticle(index, cx);
sumScorePlayerTwo += dif;
}
if (x > pTwoX) //< expects p2.x > 0
{
double cx = x - pTwoX;
cx = cx * (M_PI / 2) / (1.0 - pTwoX);
cx = cx * (M_PI / 2.0) / (1.0 - pTwoX);
double dif = removeParticle(index, cx);
sumScorePlayerOne += dif;
}
double playerOneBat = batPotential(x, y, m_players[Player::One]->getPosition());
double playerTwoBat = batPotential(x, y, m_players[Player::Two]->getPosition());
double playerOneBat = batPotential(x, y, m_players[Player::Id::One]->getPosition());
double playerTwoBat = batPotential(x, y, m_players[Player::Id::Two]->getPosition());
double horizontalBorders = sqr(y) * sqr(y) * sqr(y) * sqr(y) * 0.01;
std::complex<double> tmp = m_psi[index] * exp(-Ci * dt / Config::getHbar() * (playerOneBat + playerTwoBat + horizontalBorders));
m_psi[index] = tmp;
m_bufPositionRepresentation->updateAt(index, tmp * 125.0, (playerOneBat + playerTwoBat + horizontalBorders) * 150);
auto potentialSum = playerOneBat + playerTwoBat + horizontalBorders;
auto tmpPsi = m_psi[index] * exp(-Ci * dt / hbar * potentialSum);
m_psi[index] = tmpPsi;
m_bufPositionRepresentation->updateAt(index, tmpPsi * 125.0, potentialSum * 150);
}
m_players[Player::One]->addScore(sumScorePlayerOne);
m_players[Player::Two]->addScore(sumScorePlayerTwo);
m_players[Player::Id::One]->addScore(sumScorePlayerOne);
m_players[Player::Id::Two]->addScore(sumScorePlayerTwo);
}
double flattenMomentum(double x, double y)
{
double distanceToCenter = sqr(x) + sqr(y);
double offset = Config::getFlattenMomentumCutOff();
if (distanceToCenter < offset)
constexpr double offset = 0.012;
if (distanceToCenter > offset)
{
return 1.0;
return 1.0 / (1.0 + (distanceToCenter * 2.5));
}
else
{
return 1.0 / (1.0 + (distanceToCenter * Config::getFlattenMomentumFallOff()));
return 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;
}
......@@ -213,7 +219,9 @@ void Particle::moveStep(int indexFrom, int indexTo)
constexpr double m = 1.0;
double N = 1.0 / Config::getArraySize();
double E = (sqr(px) + sqr(py)) / (2.0 * m);
m_psi[i] *= exp(-Ci * dt / Config::getHbar() * E) * N * flattenMomentum(px, py);
auto f = flattenMomentum(px, py);
m_psi[i] *= exp(-Ci * dt / hbar * E) * N * f;
// m_psi[i] = flattenMomentum(px, py) * 0.00001;
}
}
......
///
/// @file Particle.hpp
/// @author Armin Co
///
/// @brief Particle class header.
///
......@@ -16,8 +15,9 @@
#include <fftw3.h>
#include "ImageBuffer.hpp"
#include "QPlayer.hpp"
#include "Player.hpp"
namespace QPong {
class Particle
{
......@@ -25,7 +25,7 @@ public:
/// @brief Contructor
///
Particle(ImageBuffer *momentum, ImageBuffer *position, std::map<Player, std::shared_ptr<QPlayer>> players);
Particle(ImageBuffer *momentum, ImageBuffer *position, std::map<Player::Id, std::shared_ptr<Player>> players);
/// @brief Destructor
......@@ -50,17 +50,6 @@ public:
private:
std::complex<double> *m_psi;
fftw_plan m_planForward;
fftw_plan m_planBackward;
bool m_ready;
std::map<Player, std::shared_ptr<QPlayer>> m_players;
ImageBuffer *m_bufPositionRepresentation;
ImageBuffer *m_bufMomentumRepresentation;
/// @brief Update the array at the ArrayCanvas
///
void updateMomentumImage();
......@@ -83,7 +72,22 @@ private:
double removeParticle(int index, double cx);
std::complex<double> *m_psi;
fftw_plan m_planForward;
fftw_plan m_planBackward;
bool m_ready;
std::map<Player::Id, std::shared_ptr<Player>> m_players;
ImageBuffer *m_bufPositionRepresentation;
ImageBuffer *m_bufMomentumRepresentation;
Particle() = delete;
};
} // namespace QPong
#endif
\ No newline at end of file
......@@ -3,23 +3,24 @@
/// @author Armin Co
///
#include "QPlayer.hpp"
#include <mutex>
#include "Player.hpp"
using namespace QPong;
constexpr double speedStepSize = 0.0005;
QPlayer::QPlayer(Player pl, Position pos)
Player::Player(Player::Id pl, Player::Position pos)
: m_id {pl}
, m_x {pos.x}
, m_y {pos.y}
{
}
void QPlayer::update(double dt)
void Player::update(double dt)
{
constexpr double negativeAccelScale = 1.5;
m_y += (m_vy * dt * 4);
......@@ -49,7 +50,7 @@ void QPlayer::update(double dt)
}
void QPlayer::move(Direction direction)
void Player::move(Direction direction)
{
constexpr double addSpped = 3;
switch (direction)
......@@ -74,28 +75,27 @@ void QPlayer::move(Direction direction)
}
float QPlayer::getScore()
float Player::getScore()
{
return m_score * 100;
}
std::mutex mtx;
void QPlayer::addScore(float score)
std::mutex scoreMtx;
void Player::addScore(float score)
{
std::lock_guard<std::mutex> lockScore(mtx);
std::lock_guard<std::mutex> lockScore(scoreMtx);
m_score += score;
}
Position QPlayer::getPosition()
Player::Position Player::getPosition()
{
return {m_x, m_y};
}
void QPlayer::reset()
void Player::reset()
{
m_score = 0;
}
\ No newline at end of file
......@@ -8,21 +8,19 @@
#ifndef QPONG_QPLAYER_HPP
#define QPONG_QPLAYER_HPP
/// @brief Available players
namespace QPong {
/// @brief Class wraps all values of one Player.
///
enum class Player
class Player
{
public:
enum class Id
{
One,
Two
};
/// @brief The bat can be moved up and down.
///
enum class Direction
{
Up,
Down
};
struct Position
{
......@@ -30,20 +28,24 @@ struct Position
double y;
};
class QPlayer
enum class Direction
{
public:
QPlayer(Player pl, Position pos);
Up,
Down
};
Player(Id pl, Position pos);
void update(double dt);
void move(Direction d);
float getScore();
void addScore(float score);
void reset();
float getScore();
Position getPosition();
private:
Player m_id;
Id m_id;
double m_x;
double m_y;
double m_vx = 0;
......@@ -51,4 +53,6 @@ private:
double m_score = 0;
};
} // namespace QPong
#endif
\ No newline at end of file
///
/// @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()
{
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();
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
enable_testing()
include_directories(
${gtest_SOURCE_DIR}/include
${gtest_SOURCE_DIR}
)
add_executable(
runUnitTests
test_qpong.cpp
)
target_link_libraries(
runUnitTests
gtest
gtest_main
)
target_link_libraries(
runUnitTests
qpong_core
)
#include <iostream>
#include "gtest/gtest.h"
#include "ImageBuffer.hpp"
/// @brief Creating a test fixture frequently used objects for tests
///
class QPongLib : public testing::Test
{
protected:
ImageBuffer *momentumImage;
ImageBuffer *positionImage;
// members
// called before any test
void SetUp() override
{
}
virtual void TearDown()
{
}
};
/// @brief A simple function to test
///
int addInts(int a, int b)
{
return a + b;
}
TEST(ImageBuffer, getValue)
{
const ImageBuffer imbf;
const ImageBuffer imbff;
const ImageBuffer imbfff;
}
TEST(addInts, positiveValues)
{
int a {1};
int b {3};
ASSERT_EQ(addInts(a, b), 4);
}
TEST(addInts, shouldBreak)
{
EXPECT_NE(3+1, 0) << "Yes yes, because it is just a test!";
}
TEST(addInts, negativeValues)
{
ASSERT_EQ(-3 + -5, -8);
}
/// @todo Example for mocks and an explanation what they are.
///
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment