I'm making this snake game, and I've created a class to handle the snakes (players and AI snakes), this works out quite well, however, at the moment I'm declaring my main snake (player 1), as global, in terms of:

class Snake
   {
    //... Lots and lots of code.
   }
Snake Andy;

^^ this works out quite fine, however I'm interested in being able to call Andy in the running of the program, but still as a global variable, however I still need Andy to be global, since I've need to access him from a lot of different threads and functions. I've got about 10 threads running in real-time, and about half of them, are using Andy, so somehow pointing to Andy, and sending the pointer as argument, doesn't really satisfy me.

The reason I'm interested in calling Andy in the game code, is to be able to like send him some values doing the constructor, and to be able to declare my snakes on the fly, when they're introduced in the game, rather then having them created and being like, on 'standby'.

Beside of this, then I've got the following lines of code, to switch between full screen and windowed mode:

if (key == GLUT_KEY_F1)     // Toggle FullScreen
	{
	fullscreen = !fullscreen; // Toggle FullScreenBool
	if (fullscreen)
	    {
            glutGameModeString( "1280x800:32@60" );
            glutEnterGameMode();
            }
        else
	    {
	    glutLeaveGameMode();
            }
	}

^^however this seems to somehow 'crash', well the game keeps running, however I'm not entering or leaving fullscreen, and it somewhat freezes, I've tried to call the:

glutGameModeString( "1280x800:32@60" );
            glutEnterGameMode();

In main, and it works like a charm if called that way, however, then I'm unable to use, like windowed mode; i tried using the following code instead, for the fullscreen:

if (key == GLUT_KEY_F1)     // Toggle FullScreen
	{
	fullscreen = !fullscreen; // Toggle FullScreenBool
	if (fullscreen)
	    {
	    glutFullScreen();     // Enable Fullscreen
            }
        else
	    {
	    ResetWindowSize();    // Make Window, and resize
            ResetWindowSize();    // Dual call needed to make it work
            }
	}

The ResetWindowSize, is simply the following:

GLvoid ResetWindowSize(GLvoid)  // Reset WindowSize
    {
    glutReshapeWindow(800, 600);
    glutPositionWindow(0,0);
    }

This effectively fullscreens, however, if I'm calling variables instead of just 800x600 for the " glutReshapeWindow", then it wont leave fullscreen, I've made a thread about this here:
http://www.daniweb.com/forums/post1035534.html#post1035534

I should mention that my code is written using freeGLUT for graphics. - When talking about freeGLUT, anyone into making a menu in glut? - Since I've could need a helping hand there.

However I'm interrested in getting help to loading mp3 files into an OpenAL buffer, if anyone is able to help me with that as well, as the memory usage is quite heavy using wav files.

If anyone know a replacement for 'Createthread()' and the associated event system (handles; 'CreateEvent()'), please let me know, since I somewhat want it to be platform independend.

Crossing fingers for more responds, then to the last thread >.<
^^just answering parts of it, will be fine :)

Dani AI

Generated

Short practical guidance that ties the replies together and gives a few safe options for Andy, threading, fullscreen and audio.

Keep one owner for game state (preferred)

  • Give the main/game loop ownership of all game objects (Andy). Worker threads do I/O, AI, etc., and post commands/results into a thread-safe queue that the main loop applies each frame. This avoids fine-grained locking and most deadlocks; see the “Event Queue / Game Loop” pattern. (dokk.org)

If you must share Andy across threads

  • Protect updates with a mutex or use atomic/shared-pointer swaps for hot-reloadable construction. Example patterns (illustrative):
/* mutex-protected swap (works with C++11) */
std::shared_ptr<Snake> gAndy;
std::mutex gAndyMutex;

void setAndy(...) {
  auto tmp = std::make_shared<Snake>(...);
  std::lock_guard<std::mutex> lk(gAndyMutex);
  gAndy = tmp;
}

auto snapshot = [&]{ std::lock_guard<std::mutex> lk(gAndyMutex); return gAndy; }();
if (snapshot) snapshot->doSomething();
/* C++20: atomic shared_ptr (simpler readers) */
std::atomic<std::shared_ptr<Snake>> gAndy;
gAndy.store(std::make_shared<Snake>(...));
auto local = gAndy.load();

Synchronization primitive choice — mutex vs semaphore

  • For exclusive access use a mutex (ownership, lightweight, use RAII via std::lock_guard). Use semaphores when you need a counting resource or explicit producer/consumer signalling; C++20 adds std::counting_semaphore / binary_semaphore. ’s semaphore suggestion is valid — pick the primitive to match semantics. (cppreference.com)

Cross-platform threads & events

  • Prefer standard C++ threads and sync: std::thread, std::mutex, std::condition_variable, std::promise/std::future. They replace CreateThread / CreateEvent for portable code; use Boost.Thread only when stuck on pre-C++11 toolchains. There is no single cross-platform equivalent of WaitForMultipleObjects — use condition-variables, futures, or a small event-queue. (cppreference.com)

freeGLUT and audio notes

  • Call GLUT/freeGLUT window/context functions only from the main thread; entering/leaving game mode can recreate contexts so reinitialize GL state after a mode switch — instead toggle a flag and handle it from the main loop. For in-game music don’t load entire WAVs: decode (mpg123, libvorbis, stb_vorbis, etc.) and stream PCM packets into OpenAL with queued buffers to keep memory down. (freeglut.sourceforge.net)

Summary: prefer single-owner state + message queue, use std::mutex/RAII or atomic shared_ptr for safe swaps, use std::thread/condition_variable for portability, and do GL/fullscreen changes and OpenAL buffer management on the appropriate threads.

Recommended Answers

All 4 Replies

If you intend to modify Andy's contents from different threads then you need to synchronize the threads so that access to Andy is limited to one thread at a time. The most common way is via semiphores.

For platform independece -- you might check out the Boost libraries to see if it contains something to create and synchronize threads.

If you intend to modify Andy's contents from different threads then you need to synchronize the threads so that access to Andy is limited to one thread at a time. The most common way is via semiphores.

For platform independece -- you might check out the Boost libraries to see if it contains something to create and synchronize threads.

Uhm, about the access to Andy, then I've got that covered using handles, and like the WaitforMultipleObjects(), and SingleObjects, in like a mutex queue, can you tell me why a semiphore would be better/worse? - Just interested in optimizing a bit.

About boost, how's boost vs. pthreads?

What you are already doing should be ok. A semiphore is just another way of doing it.

What you are already doing should be ok. A semiphore is just another way of doing it.

Okay, like, wouldn't a semiphore be more efficient, and how does a semiphore like work?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.