Do I need concurrent loops? - c++

I'm making a text based game using the Curses library. There is a part of the game where the player enters an "arena". When inside of the arena the program needs to run a loop(1) that allows the player to move, and it also needs to run a loop(2) that moves the enemies around. Loop(2) needs to be delayed using Sleep so that the enemies move slower than the player. In researching this question I've come across something called multi-threading. I'm not sure that I need to learn this in order to get the results I want. I need to have one of these functions loop slower than the other.
While ( true )
{
movePlayer(player_xy);
arena.moveEnemies();
}

The structure of a simple game will update the positions before rendering every frame.
Here's a simplified example that should suit your needs. For some information visit gamedev.net, there you'll find loads of tutorials and guides for your game.
Pseudocode below
MainLoop()
{
// Get Keyboard Input
...
// Game Logic Impl
...
// Update Positions
UpdatePlayerPosition();
for each ai
UpdateAiPosition();
// Check for sound triggers
ProcessSoundTriggers();
// Draw the scene if needed, you can skip some to limit the FPS
DrawScene();
// Flip the buffers if needed ...
DoubleBufferFlip();
}

You shouldn't need to use multithreading for this. One approach you can use is to calculate the amount of time that has elapsed between the each calling of the main loop and use that to update the position of the players. You can also check for user input and use that to update the user's position. You can multiply the elapsed time by different constants to control the relative rates of movement. A more detailed explanation of the game loop can be found here: http://www.koonsolo.com/news/dewitters-gameloop/

use stl library header file <thread>
you can define loops in two functions
For Example:
#include<chrono>
#include<thread>
void fun1(){
while(/*condition*/){
//statments
std::this_thread::sleep_for (std::chrono::seconds(1));
}
}
void fun2(int y){
while(/*codition*/){
//statments
std::this_thread::sleep_for (std::chrono::seconds(2));
}
}
void main(){
std::thread th1(fun1);
std::thread th2(fun2,5);
//now both thread are running concurrently
}
For more details refer to link:
http://www.cplusplus.com/reference/thread/thread/

If you'd like to avoid multi-threading you can run a loop at high frequency and have the player able to move every X loops, while the enemies can only move every Y loops. In that way you can vary the player:enemy movement speed ratio and you can set offsets so that different enemies move at different times (i.e. during a different cycle of the loop).
Something like this (pseudocode):
int loop_counter = 0;
while(doing_battle)
{
if (loop_counter is a multiple of X)
{
Move player;
}
if (loop_counter is a multiple of Y)
{
Move evenmy_0;
}
if ((loop_counter + offset_1) is a multiple of Y)
{
Move enemy_1; // This enemy will move at a different time from enemy_0
}
loop_counter++;
delay(); // Will vary based on how quickly things need to move and how long your loop takes to complete
}

Related

Not executing all writes before end of program

For a school project we were tasked with writing a ray tracer. I chose to use C++ since it's the language I'm most comfortable with, but I've been getting some weird artifacts.
Please keep in mind that we are still in the first few lessons of the class, so right now we are limited to checking whether or not a ray hits a certain object.
When my raytracer finishes quickly (less than 1 second spent on actual ray tracing) I've noticed that not all hits get registered in my "framebuffer".
To illustrate, here are two examples:
1.:
2.:
In the first image, you can clearly see that there are horizontal artifacts.
The second image contains a vertical artifact.
I was wondering if anyone could help me to figure out why this is happening?
I should mention that my application is multi-threaded, the multithreaded portion of the code looks like this:
Stats RayTracer::runParallel(const std::vector<Math::ivec2>& pixelList, const Math::vec3& eyePos, const Math::vec3& screenCenter, long numThreads) noexcept
{
//...
for (int i = 0; i < threads.size(); i++)
{
threads[i] = std::thread(&RayTracer::run, this, splitPixels[i], eyePos, screenCenter);
}
for (std::thread& thread: threads)
{
thread.join();
}
//...
}
The RayTracer::run method access the framebuffer as follows:
Stats RayTracer::run(const std::vector<Math::ivec2>& pixelList, const Math::vec3& eyePos, const Math::vec3& screenCenter) noexcept
{
this->frameBuffer.clear(RayTracer::CLEAR_COLOUR);
// ...
for (const Math::ivec2& pixel : pixelList)
{
// ...
for (const std::shared_ptr<Objects::Object>& object : this->objects)
{
std::optional<Objects::Hit> hit = object->hit(ray, pixelPos);
if (hit)
{
// ...
if (dist < minDist)
{
std::lock_guard lock (this->frameBufferMutex);
// ...
this->frameBuffer(pixel.y, pixel.x) = hit->getColor();
}
}
}
}
// ...
}
This is the operator() for the framebuffer class
class FrameBuffer
{
private:
PixelBuffer buffer;
public:
// ...
Color& FrameBuffer::operator()(int row, int col) noexcept
{
return this->buffer(row, col);
}
// ...
}
Which make use of the PixelBuffer's operator()
class PixelBuffer
{
private:
int mRows;
int mCols;
Color* mBuffer;
public:
// ...
Color& PixelBuffer::operator()(int row, int col) noexcept
{
return this->mBuffer[this->flattenIndex(row, col)];
}
// ...
}
I didn't bother to use any synchronization primitives because each thread gets assigned a certain subset of pixels from the complete image. The thread casts a ray for each of its assigned pixels and writes the resultant color back to the color buffer in that pixel's slot. This means that, while all my threads are concurrently accessing (and writing to) the same object, they don't write to the same memory locations.
After some initial testing, using a std::lock_guard to protect the shared framebuffer seems to help, but it's not a perfect solution, artifacts still occur (although much less common).
It should be noted that the way I divide pixels between threads determines the direction of the artifacts. If I give each thread a set of rows the artifacts will be horizontal lines, if I give each thread a set of columns, the artifacts will be vertical lines.
Another interesting conclusion is that when I trace more complex objects (These take anywhere between 30 seconds and 2 minutes) these aretifacts are extremely rare (I've seen it once in my 100's-1000's of traces so far)
I can't help but feel like this is a problem related to multithreading, but I don't really understand why std::lock_guard wouldn't completely solve the problem.
Edit: After suggestions by Jeremy Friesner I ran the raytracer about 10 times on a single thread, without any issues, so the problem does indeed appear to be a race condition.
I solved the problem thanks to Jeremy Friesner.
As you can see in the code, every thread calls framebuffer.clear() separately (without locking the mutex!). This means that thread A might have already hit 5-10 pixels because it was started first when thread B clears the framebuffer. this would erase thread A's already hit pixels.
By moving the framebuffer.clear() call to the beginning of the runParallel() method I was able to solve the issue.

Multiple threads access shared resources

I'm currently working on a particle system, which uses one thread in which the particles are first updated, then drawn. The particles are stored in a std::vector. I would like to move the update function to a separate thread to improve the systems performance. However this means that I encounter problems when the update thread and the draw thread are accessing the std::vector at the same time. My update function will change the values for the position, and colour of all particles, and also almost always resize the std::vector.
Single thread approach:
std::vector<Particle> particles;
void tick() //tick would be called from main update loop
{
//slow as must wait for update to draw
updateParticles();
drawParticles();
}
Multithreaded:
std::vector<Particle> particles;
//quicker as no longer need to wait to draw and update
//crashes when both threads access the same data, or update resizes vector
void updateThread()
{
updateParticles();
}
void drawThread()
{
drawParticles();
}
To fix this problem I have investigated using std::mutex however in practice, with a large amount of particles, the constant locking of threads meant that performance didn't increase. I have also investigated std::atomic however, neither the particles nor std::vector are trivially copyable and so can't use this either.
Multithreaded using mutex:
NOTE: I am using SDL mutex, as far as I am aware, the principles are the same.
SDL_mutex mutex = SDL_CreateMutex();
SDL_cond canDraw = SDL_CreateCond();
SDL_cond canUpdate = SDL_CreateCond();
std::vector<Particle> particles;
//locking the threads leads to the same problems as before,
//now each thread must wait for the other one
void updateThread()
{
SDL_LockMutex(lock);
while(!canUpdate)
{
SDL_CondWait(canUpdate, lock);
}
updateParticles();
SDL_UnlockMutex(lock);
SDL_CondSignal(canDraw);
}
void drawThread()
{
SDL_LockMutex(lock);
while(!canDraw)
{
SDL_CondWait(canDraw, lock);
}
drawParticles();
SDL_UnlockMutex(lock);
SDL_CondSignal(canUpdate);
}
I am wondering if there are any other ways to implement the multi threaded approach? Essentially preventing the same data from being accessed by both threads at the same time, without having to make each thread wait for the other. I have thought about making a local copy of the vector to draw from, but this seems like it would be inefficient, and may run into the same problems if the update thread changes the vector while it's being copied?
I would use a more granular locking strategy. Instead of storing a particle object in your vector, I would store a pointer to a different object.
struct lockedParticle {
particle* containedParticle;
SDL_mutex lockingObject;
};
In updateParticles() I would attempt to obtain the individual locking objects using SDL_TryLockMutex() - if I fail to obtain control of the mutex I would add the pointer to this particular lockedParticle instance to another vector, and retry later to update them.
I would follow a similar strategy inside the drawParticles(). This relies on the fact that draw order does not matter for particles, which is often the case.
If data consistency is not a concern you can avoid blocking the whole vector by encapsulating vector in a custom class and setting mutex on single read/write operations only, something like:
struct SharedVector
{
// ...
std::vector<Particle> vec;
void push( const& Particle particle )
{
SDL_LockMutex(lock);
vec.push_back(particle);
SDL_UnlockMutex(lock);
}
}
//...
SharedVector particles;
Then of course, you need to amend updateParticles() and drawParticles() to use new type instead of std::vector.
EDIT:
You can avoid creating new structure by using mutexes in updateParticles() and drawParticles() methods, e.g.
void updateParticles()
{
//... get Particle particle object
SDL_LockMutex(lock);
particles.push_back(particle);
SDL_UnlockMutex(lock);
}
The same should be done for drawParticles() as well.
If the vector is changing all the time, you can use two vectors. drawParticles would have its own copy, and updateParticles would write to another one. Once both functions are done, swap, copy, or move the vector used by updateParticles to the to be used by drawParticles. (updateParticles can read from the same vector used by drawParticles to get at the current particle positions, so you shouldn't need to create a complete new copy.) No locking necessary.

Synchronizing very fast threads

In the following example (an idealized "game") there are two threads. The main thread which updates data and RenderThread which "renders" it to the screen. What I need it those two to be synchronized. I cannot afford to run several update iteration without running a render for every single one of them.
I use a condition_variable to sync those two, so ideally the faster thread will spend some time waiting for the slower. However condition variables don't seem to do the job if one of the threads completes an iteration for a very small amount of time. It seems to quickly reacquire the lock of the mutex before wait in the other thread is able to acquire it. Even though notify_one is called
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <functional>
#include <mutex>
#include <condition_variable>
using namespace std;
bool isMultiThreaded = true;
struct RenderThread
{
RenderThread()
{
end = false;
drawing = false;
readyToDraw = false;
}
void Run()
{
while (!end)
{
DoJob();
}
}
void DoJob()
{
unique_lock<mutex> lk(renderReadyMutex);
renderReady.wait(lk, [this](){ return readyToDraw; });
drawing = true;
// RENDER DATA
this_thread::sleep_for(chrono::milliseconds(15)); // simulated render time
cout << "frame " << count << ": " << frame << endl;
++count;
drawing = false;
readyToDraw = false;
lk.unlock();
renderReady.notify_one();
}
atomic<bool> end;
mutex renderReadyMutex;
condition_variable renderReady;
//mutex frame_mutex;
int frame = -10;
int count = 0;
bool readyToDraw;
bool drawing;
};
struct UpdateThread
{
UpdateThread(RenderThread& rt)
: m_rt(rt)
{}
void Run()
{
this_thread::sleep_for(chrono::milliseconds(500));
for (int i = 0; i < 20; ++i)
{
// DO GAME UPDATE
// when this is uncommented everything is fine
// this_thread::sleep_for(chrono::milliseconds(10)); // simulated update time
// PREPARE RENDER THREAD
unique_lock<mutex> lk(m_rt.renderReadyMutex);
m_rt.renderReady.wait(lk, [this](){ return !m_rt.drawing; });
m_rt.readyToDraw = true;
// SUPPLY RENDER THREAD WITH DATA TO RENDER
m_rt.frame = i;
lk.unlock();
m_rt.renderReady.notify_one();
if (!isMultiThreaded)
m_rt.DoJob();
}
m_rt.end = true;
}
RenderThread& m_rt;
};
int main()
{
auto start = chrono::high_resolution_clock::now();
RenderThread rt;
UpdateThread u(rt);
thread* rendering = nullptr;
if (isMultiThreaded)
rendering = new thread(bind(&RenderThread::Run, &rt));
u.Run();
if (rendering)
rendering->join();
auto duration = chrono::high_resolution_clock::now() - start;
cout << "Duration: " << double(chrono::duration_cast<chrono::microseconds>(duration).count())/1000 << endl;
return 0;
}
Here is the source of this small example code, and as you can see even on ideone's run the output is frame 0: 19 (this means that the render thread has completed a single iteration, while the update thread has completed all 20 of its).
If we uncomment line 75 (ie simulate some time for the update loop) everything runs fine. Every update iteration has an associated render iteration.
Is there a way to really truly sync those threads, even if one of them completes an iteration in mere nanoseconds, but also without having a performance penalty if they both take some reasonable amount of milliseconds to complete?
If I understand correctly, you want the 2 threads to work alternately: updater wait until the renderer finish before to iterate again, and the renderer wait until the updater finish before to iterate again. Part of the computation could be parallel, but the number of iteration shall be similar between both.
You need 2 locks:
one for the updating
one for the rendering
Updater:
wait (renderingLk)
update
signal(updaterLk)
Renderer:
wait (updaterLk)
render
signal(renderingLk)
EDITED:
Even if it look simple, there are several problems to solve:
Allowing part of the calculations to be made in parallel: As in the above snippet, update and render will not be parallel but sequential, so there is no benefit to have multi-thread. To a real solution, some the calculation should be made before the wait, and only the copy of the new values need to be between the wait and the signal. Same for rendering: all the render need to be made after the signal, and only getting the value between the wait and the signal.
The implementation need to care also about the initial state: so no rendering is performed before the first update.
The termination of both thread: so no one will stay locked or loop infinitely after the other terminate.
I think a mutex (alone) is not the right tool for the job. You might want to consider using a semaphore (or something similar) instead. What you describe sound a lot like a producer/consumer problem, i.e., one process is allowed to run once everytime another process has finnished a task. Therefore you might also have a look at producer/consumer patterns. For example this series might get you some ideas:
A multi-threaded Producer Consumer with C++11
There a std::mutex is combined with a std::condition_variable to mimic the behavior of a semaphore. An approach that appears quite reasonable. You would probably not count up and down but rather toggle true and false a variable with needs redraw semantics.
For reference:
http://en.cppreference.com/w/cpp/thread/condition_variable
C++0x has no semaphores? How to synchronize threads?
This is because you use a separate drawing variable that is only set when the rendering thread reacquires the mutex after a wait, which may be too late. The problem disappears when the drawing variable is removed and the check for wait in the update thread is replaced with ! m_rt.readyToDraw (which is already set by the update thread and hence not susceptible to the logical race.
Modified code and results
That said, since the threads do not work in parallel, I don't really get the point of having two threads. Unless you should choose to implement double (or even triple) buffering later.
A technique often used in computer graphics is to use a double-buffer. Instead of having the renderer and the producer operate on the same data in memory, each one has its own buffer. This is implemented by using two independent buffers, and switch them when needed. The producer updates one buffer, and when it is done, it switches the buffer and fills the second buffer with the next data. Now, while the producer is processing the second buffer, the renderer works with the first one and displays it.
You could use this technique by letting the renderer lock the swap operation such that the producer may have to wait until rendering is finished.

C++ Updating data and rendering

I'm making a program that can update the states of objects whilst rendering.
So my first approach was the obvious draw and update in the main while loop, but this problem limited the update state part to the speed of rendering (the computer speed) so this wasn't a good approach.
So I tried to think about the problem and came up with a solution that making a detached thread whose purpose is to update the game. Here is my code of this:
//DEFAULT
#include <iostream>
#include <chrono>
#include <thread>
//SFML
#include <SFML/Graphics.hpp>
void sleep_fnc(bool*);
void update_game(bool*/*, Some objects...*/);
#define cycles_per_milisecond 1000/30
int main() {
bool flag = true;
sf::RenderWindow window(sf::VideoMode(680, 480), "I work!");
std::thread (sleep_fnc, &flag).detach();
std::thread(update_game, &flag/*, Some objects...*/).detach();
if (window.isOpen()) {
window.clear();
//DRAW STUFF HERE
window.display();
}
return 0;
}
void sleep_fnc(bool *flag_ptr) {
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(cycles_per_milisecond));
*flag_ptr = true;
}
}
void update_game(bool *flag_ptr/*, Some objects...*/) {
while (true) {
if (*flag_ptr) {
//Do update stuff
*flag_ptr = false;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
After I fiddled around with this code someone else realized that this wasn't such a good solution (thanks to you whomever pointed it out). The reason for this is if one object is being modified by the update loop WHILE the render loop is in its cycle something undefined would probably be the outcome, so I went back and started thinking again.
After thinking I came up with a solution that every class could inherit some universal class that had a boolean whether the object was being used by the draw loop or update loop, if it was in use, one of the loops would wait until the boolean flag indicated that it was ready for use again. It would probably be best if the update loop wasn't the one to wait.
Then it finally hit me that drawing the objects would be useless if they hadn't been updated. I believe that using a timer to test execution time and using that is unreliable, and there must be some other way than limiting the frame rate.
Would this prove that a frame rate higher than the update-rate is useless and is there some other approach that doesn't involve testing the execution time of last cycle and using that?

Structuring Pong

I am making Pong using C++ and OpenGL using Visual Express 2010. It is one of the first games I have made, and I am wondering how to best structure it. The main part that is stumping me is the game menu. Should I put the different game modes in different functions, and have a switch in my main function? For example, in Main.cpp, I would include the line
glutDisplayFunction(maincode)
In another file, I would define maincode as something like such (again, psuedocode):
maincode():
switch m:
case 1:
singleplayer = true
multiplayer = false
menu = false
case 2:
singleplayer = false
multiplayer = true
menu = false
case 3:
singleplayer = false
multiplayer = false
menu = true
I would then, in each file, check to see the values of singleplayer, multiplayer, and menu to determine which mode I am in, then display code accordingly.
However, I get the feeling that this method would get much more complicated as the game gets more complicated, so I don't think this is the proper way to do it.
How should I structure the game and menu?
P.S. I am a C++ programmer for a living, but I just don't have experience programming games.
It's just unnecessary complexity to have 3 distinct bools (totaling to 8 different states, 3 of which would be valid) when the only information you need is which mode you are currently in.
Better use an enumeration, i.e.
enum GameMode {
GM_SinglePlayer, GM_Multiplayer, GM_Menu
};
and a single variable of type GameMode:
GameMode mode;
mode = GM_Menu;
Having different, mutually exclusive (that's the point that you missed here!) states to switch in between is an important concept in programming, so you are definitely on the right track. Keep working.
The best way to organize a GUI application is using the MVC design pattern. Either that, or it's small modification presenter first.
Knowing that, answers to such questions as your are simple to answer (Alexander Gessler's answer is quite ok)
glutDisplayFunc() is a quick way to display stuff but it quickly becomes more trouble than it's worth when writing simple projects.
Unless you're multithreading and keeping a constant copy of your game-state for glutDisplayFunc() to read, I'd say avoid using it - and even then, probably, too.
For game loops, I believe it's better to drive OpenGL rather than let it drive you.
enum EMode { ...etc };
EMode menu();
void single();
void multi();
int main()
{
init(...);
bool loop = true;
while(loop)
{
switch(menu())
{
case EMode.single:
game_loop(1);
break;
case EMode.multi:
game_loop(2);
break;
case quit:
loop = false;
...etc
}
}
finish(...);
return 0;
}
Simple menu loop. (Forgive my code style it's different than usual).
It's not a great layout, but it would work for a simple game.
init() initializes openGL.
menu(), single() and multi() each have their own loops, which render and swap the buffers manually.
menu() returns a value specifying which menu item was chosen.
Game loop that runs at constant speed and doesn't waste CPU.
void game_loop(int players)
{
CGame game = new Game(players);
bool loop = true;
time_type next_frame = get_time() - 1;
while(loop)
{
time_type time = get_time();
if(time > next_frame)
{
do_input(game);
while(time > next_frame)
{
game.tick();
next_frame += frame_period;
}
do_render(game); // draw stuff here, and swap buffers.
}
else
{
// Don't waste CPU (optional).
wait_till(next_frame);
}
}
}
Again, not wonderful, but function enough. (I use something like this).
CGame is the game class (if you want to be OO).
get_time(), wait_till(), time_type etc are all made up. Use whatever function/type suits.
Quick and off the top of my head - probably even has some bugs - but it could give you an idea.