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.
Related
I am writing a small game on my phone in SDL2. In main I have a while loop and basic game control conditions which are bools. I pass 'initialise', 'update', 'quit' and the 'renderer' to a game function by reference that deals with the game logic. Now it's getting more complicated I want to separate certain logic to outside of game, and to do that I have to pass the references from main, to game, to more functions outside of game. Main would pass to game, game would pass to func2, and possibly func2 needs to pass to func3.
Do the C++ standards/specification limit the use of pass by reference? You could have a chain of 10+ functions passing down quit, update, etc.
//
// extra functions here
// which break up game
// each need quit, initialise, update and renderer
// so I pass by reference
//
// void func2(&rend, &quit, &update, &initialise)
void game(SDL_Renderer *rend, bool &initialise, bool &quit, bool &update)
{
static Table t{};
if (initialise)
{
// setup game
func2(rend, initialise, quit, update);
}
if(update)
{
// refresh screen
}
while (PollTouchEvent)
{
// touching screen
// can quit here
}
}
int main(int argc, char *argv[])
{
// initialise SDL
// ...
// game stuff
bool quit = false;
bool update = true;
bool initialise = true;
while (!quit)
{
game(renderer, initialise, quit, update);
}
// quit SDL
return 0;
}
There is no limit to the number of times you can pass a variable by reference, other than perhaps the size of the stack — i.e. the address of a variable that is passed by reference may need to be placed on the stack, and in extreme cases (read: deeply recursive functions) that might exceed the stack’s capacity. Such a problem isn’t very common, though.
Whether it’s a good approach to be passing lots of variables by reference is a different question. In particular, if you find yourself passing the same set of references to many different functions, consider creating a struct or class-object containing all of that information as member variables and just passing around a single reference to that object instead; that will be more efficient and also much easier to maintain/update as your program changes.
Also note that modern c++ compilers can often perform optimizations more effectively on arguments that are passed by-value than on arguments passed by-reference, since in the by-value case the optimizer doesn’t have to worry about the possibility of aliasing. Whether one approach or the other is faster would have to be measured on a case-by-case basis, though, as performance can depend a lot on the details of what is being done.
I am working on an event system for a game. My original way of going about this was to have a group of listeners stored in a map with a string as the key (event name) and callback for when the event is triggered. This worked fine (In my head, no actual tests done yet), but it didn't take long to find some flaws.
Speed - I hope to make this a medium sized game. This would mean 100's of "listeners" waiting different events. After an event is called, the search would have to go through every listener string name to find a match. A huge amount of events will be sent and processed as fast as possible to avoid hogging all the time in each frame.
Naming - "Shoot_arrow_player", "Shoot_arrow_ai", "Shoot_arrow_player3". It's not a very easy system having to remember every event name and could easily have typos and make for annoying debugging.
Then I thought of an odd (In my mind) solution to this. Using enums to categorize and speed up performance.
Don't worry I'm getting to my question.
This was the way I setup the enum list:
struct Events
{
enum class Player {
Start = 1,
Shoot_arrow,
Reloading_bow,
Draw_Bow,
End
};
enum class Enemy {
Start = (int)Player::End+1,
Check_for_object,
Object_spotted,
Attacking_object,
End
};
enum class Car {
Start = (int)Enemy::End+1,
Starting_engine,
Out_of_gas,
Car_started,
End
};
};
With this system, I can use an even faster way of searching for an event if I "categorize" the events. I was thinking of doing something like having a map where the key is the category (start int for each category) and the data is another map, in that map the key is the event (int) and data is the callback. This way I could quickly find the category and then have a lot less to search through. This would be a single function that could return the category:
if (event > Event::Enemy)
return Event::Bear::Start;
else if (event < Event::Enemy)
return Event::Player::Start;
else
return Event::Enemy::Start;
Then you could search for the event with a much smaller list of possibilities than searching through ever single event. The only downside (That I can think of) is the amount of hard coding I will be doing for each category.
Now, my question is if this is a correct way to use enums. I know that the compiler shouldn't throw any errors but I'm wandering if I were to publish this would this be considered bad programming. I'm trying to avoid not being constructive as much as I can but since this will be a critical system I need to make sure it is not a bad thing to do.
I suggest you send information in your event structure rather than in the enum name.
enum Player {/*...*/};
enum Action {Shoot, /*...*/};
enum Weapon {Bow_Arrow, /*...*/};
struct Event
{
Player receiving_player;
Action event_action;
Weapon event_weapon;
};
//...
Event e = {Enemy1, Shoot, Bow_Arrow};
Send_Events(e);
This technique can be expanded, such as having a parent event or other events (such as movement).
The concept here is to place the information into a variable rather than the identifier name.
Edit 1: Player receiving from enemy.
Let's add another field to the event:
struct Event
{
Player sending_player;
Player receiving_player;
Action event_action;
Weapon event_weapon;
};
The event creator would fill in the fields:
Event e = {Enemy1, Player2, Shoot, Bow_Arrow);
The above event describes the action of Enemy1 shooting an arrow from a bow at Player2.
The next thing is to have an event handler that sends the event to zero or more listeners:
struct Event_Listener
{
virtual void receive_event(const Event& e) = 0;
};
typedef std::vector<Event_Listener *> Event_Listener_Container;
//...
Event_Listener_Container listeners;
Event_Listener_Container::iterator iter;
for (iter = listeners.begin();
iter != listeners.end();
++iter)
{
(*iter)->receive_event(e);
}
Keep in mind, there are various implementations of Listeners, Subscribers and Publishers. Look up these design patterns.
IMHO your proposed use of enums smells to high heaven and is dependent on what I would call coding by coincidence. It will be fragile, and once broken really really hard to debug.
For example, suppose I code a reasonable (from the point of view of the language) change to your enums:
struct Events
{
enum class Player {
Start = 1,
Shoot_arrow,
Reloading_bow,
Draw_Bow,
End = 0
};
enum class Enemy {
Start = (int)Player::End+1,
Check_for_object,
Object_spotted,
Attacking_object,
End
};
enum class Car {
Start = (int)Enemy::End+1,
Starting_engine,
Out_of_gas,
Car_started,
End
};
};
Then your whole strategy is toast. Your code should not break so easily.
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
}
I have used it in another programming language and It's very usefull.
I cannot find anything about this for C++.
Let's for example take the following code:
void change();
enum
{
end = 0,
gmx
}
int
gExitType;
int main()
{
gExitType = end;
SetTimer(&change, 10000, 0);
return 0;
}
void ApplicationExit()
{
switch (gExitType)
{
case end:
printf("This application was ended by the server");
case gmx:
printf("This application was ended by the timer");
}
::exit(0);
}
void change()
{
gExitType = gmx;
ApplicationExit();
}
That's kind of how we would do it in C++, but when using state machine/automata I could do something like this in the other language:
void change();
int main()
{
state exitType:end;
SetTimer(&change, 10000, 0);
return 0;
}
void ApplicationExit() <exitType:end>
{
printf("This application was ended by the server");
}
void ApplicationExit() <exitType:gmx>
{
printf("This application ended by the timer");
}
void change()
{
state exitType:gmx;
ApplicationExit();
}
In my opition this is a really elegant way to achieve things.
How would I do this in C++? This code doesn't seem to work (obviously as I cannot find anything automata related to C++)
To clarify my opinion:
So what are the advantages to using this technique? Well, as you can clearly see the code is smaller; granted I added an enum to the first version to make the examples more similar but the ApplicationExit functions are definately smaller. It's also alot more explicit - you don't need large switch statements in functions to determine what's going on, if you wanted you could put the different ApplicationExits in different files to handle different sets of code independently. It also uses less global variables.
There are C++ libraries like Boost.statechart that specifically try to provide rich support for encoding state machines:
http://www.boost.org/doc/libs/1_54_0/libs/statechart/doc/tutorial.html
Besides this, one very elegant way to encode certain types of state machines is by defining them as a couroutine:
http://c2.com/cgi/wiki?CoRoutine
http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/
Coroutines are not directly supported in C++, but there are two possible approaches for
implementing them:
1) Using a technique similar to implementing a duff's device, explained in details here:
http://blog.think-async.com/search/label/coroutines
This is very similar to how C#'s iterators work for example and one limitation is that yielding form the coroutine can be done only from the topmost function in the coroutine call-stack. OTOH, the advantage of this method is that very little memory is required for each instance of the coroutine.
2) Allocating a separate stack and registers space for each coroutine.
This essentially makes the coroutine a full-blown thread of execution with the only difference that the user has full responsibility for the thread scheduling (also known as cooperative multi-tasking).
A portable implementation is available from boost:
http://www.boost.org/doc/libs/1_54_0/libs/coroutine/doc/html/coroutine/intro.html
For this particular example, you could use objects and polymorphism to represent the different states. For example:
class StateObject
{
public:
virtual void action(void) = 0;
};
class EndedBy : public StateObject
{
private:
const char *const reason;
public:
EndedBy( const char *const reason_ ) : reason( reason_ ) { }
virtual void action(void)
{
puts(reason);
}
};
EndedBy EndedByServer("This application was ended by the server");
EndedBy EndedByTimer ("This application ended by the timer");
StateObject *state = &EndedByServer;
void change()
{
state = &EndedByTimer;
}
void ApplicationExit()
{
state->action();
::exit(0);
}
int main()
{
SetTimer(&change, 10000, 0);
// whatever stuff here...
// presumably eventually causes ApplicationExit() to get called before return 0;
return 0;
}
That said, this isn't great design, and it isn't an FSM in the general sense. But, it would implement your immediate need.
You might look up the State Pattern (one reference: http://en.wikipedia.org/wiki/State_pattern ) for a more general treatment of this pattern.
The basic idea, though, is that each state is a subclass of some common "state" class, and you can use polymorphism to determine the different actions and behaviors represented by each state. A pointer to the common "state" base class then keeps track of the state you're currently in.
The state objects may be different types, or as in my example above, different instances of the same object configured differently, or a blend.
You can use Template value specialization over an int to achieve pretty much what you want.
(Sorry I'm at my tablet so I cannot provide an example, I will update on Sunday)
I have a question about use of the goto statement in C++. I understand that this topic is controversial, and am not interested in any sweeping advice or arguments (I usually stray from using goto). Rather, I have a specific situation and want to understand whether my solution, which makes use of the goto statement, is a good one or not. I would not call myself new to C++, but would not classify myself as a professional-level programmer either. The part of the code which has generated my question spins in an infinite loop once started. The general flow of the thread in pseudocode is as follows:
void ControlLoop::main_loop()
{
InitializeAndCheckHardware(pHardware) //pHardware is a pointer given from outside
//The main loop
while (m_bIsRunning)
{
simulated_time += time_increment; //this will probably be += 0.001 seconds
ReadSensorData();
if (data_is_bad) {
m_bIsRunning = false;
goto loop_end;
}
ApplyFilterToData();
ComputeControllerOutput();
SendOutputToHardware();
ProcessPendingEvents();
while ( GetWallClockTime() < simulated_time ) {}
if ( end_condition_is_satisified ) m_bIsRunning = false;
}
loop_end:
DeInitializeHardware(pHardware);
}
The pHardware pointer is passed in from outside the ControlLoop object and has a polymorphic type, so it doesn't make much sense for me to make use of RAII and to create and destruct the hardware interface itself inside main_loop. I suppose I could have pHardware create a temporary object representing a sort of "session" or "use" of the hardware which could be automatically cleaned up at exit of main_loop, but I'm not sure whether that idea would make it clearer to somebody else what my intent is. There will only ever be three ways out of the loop: the first is if bad data is read from the external hardware; the second is if ProcessPendingEvents() indicates a user-initiated abort, which simply causes m_bIsRunning to become false; and the last is if the end-condition is satisfied at the bottom of the loop. I should maybe also note that main_loop could be started and finished multiple times over the life of the ControlLoop object, so it should exit cleanly with m_bIsRunning = false afterwards.
Also, I realize that I could use the break keyword here, but most of these pseudocode function calls inside main_loop are not really encapsulated as functions, simply because they would need to either have many arguments or they would all need access to member variables. Both of these cases would be more confusing, in my opinion, than simply leaving main_loop as a longer function, and because of the length of the big while loop, a statement like goto loop_end seems to read clearer to me.
Now for the question: Would this solution make you uncomfortable if you were to write it in your own code? It does feel a little wrong to me, but then I've never made use of the goto statement before in C++ code -- hence my request for help from experts. Are there any other basic ideas which I am missing that would make this code clearer?
Thanks.
Avoiding the use of goto is a pretty solid thing to do in object oriented development in general.
In your case, why not just use break to exit the loop?
while (true)
{
if (condition_is_met)
{
// cleanup
break;
}
}
As for your question: your use of goto would make me uncomfortable. The only reason that break is less readable is your admittance to not being a strong C++ developer. To any seasoned developer of a C-like language, break will both read better, as well as provide a cleaner solution than goto.
In particular, I simply do not agree that
if (something)
{
goto loop_end;
}
is more readable than
if (something)
{
break;
}
which literally says the same thing with built-in syntax.
With your one, singular condition which causes the loop to break early I would simply use a break. No need for a goto that's what break is for.
However, if any of those function calls can throw an exception or if you end up needing multiple breaks I would prefer an RAII style container, this is the exact sort of thing destructors are for. You always perform the call to DeInitializeHardware, so...
// todo: add error checking if needed
class HardwareWrapper {
public:
HardwareWrapper(Hardware *pH)
: _pHardware(pH) {
InitializeAndCheckHardware(_pHardware);
}
~HardwareWrapper() {
DeInitializeHardware(_pHardware);
}
const Hardware *getHardware() const {
return _pHardware;
}
const Hardware *operator->() const {
return _pHardware;
}
const Hardware& operator*() const {
return *_pHardware;
}
private:
Hardware *_pHardware;
// if you don't want to allow copies...
HardwareWrapper(const HardwareWrapper &other);
HardwareWrapper& operator=(const HardwareWrapper &other);
}
// ...
void ControlLoop::main_loop()
{
HardwareWrapper hw(pHardware);
// code
}
Now, no matter what happens, you will always call DeInitializeHardware when that function returns.
UPDATE
If your main concern is the while loop is too long, then you should aim at make it shorter, C++ is an OO language and OO is for split things to small pieces and component, even in general non-OO language we generally still think we should break a method/loop into small one and make it short easy for read. If a loop has 300 lines in it, no matter break/goto doesn't really save your time there isn't it?
UPDATE
I'm not against goto but I won't use it here as you do, I prefer just use break, generally to a developer that he saw a break there he know it means goto to the end of the while, and with that m_bIsRunning = false he can easily aware of that it's actually exit the loop within seconds. Yes a goto may save the time for seconds to understand it but it may also make people feel nervous about your code.
The thing I can imagine that I'm using a goto would be to exit a two level loop:
while(running)
{
...
while(runnning2)
{
if(bad_data)
{
goto loop_end;
}
}
...
}
loop_end:
Instead of using goto, you should use break; to escape loops.
There are several alternative to goto: break, continue and return depending on the situation.
However, you need to keep in mind that both break and continue are limited in that they only affect the most inner loop. return on the other hand is not affected by this limitation.
In general, if you use a goto to exit a particular scope, then you can refactor using another function and a return statement instead. It is likely that it will make the code easier to read as a bonus:
// Original
void foo() {
DoSetup();
while (...) {
for (;;) {
if () {
goto X;
}
}
}
label X: DoTearDown();
}
// Refactored
void foo_in() {
while (...) {
for (;;) {
if () {
return;
}
}
}
}
void foo() {
DoSetup();
foo_in();
DoTearDown();
}
Note: if your function body cannot fit comfortably on your screen, you are doing it wrong.
Goto is not good practice for exiting from loop when break is an option.
Also, in complex routines, it is good to have only one exit logic (with cleaning up) placed at the end. Goto is sometimes used to jump to the return logic.
Example from QEMU vmdk block driver:
static int vmdk_open(BlockDriverState *bs, int flags)
{
int ret;
BDRVVmdkState *s = bs->opaque;
if (vmdk_open_sparse(bs, bs->file, flags) == 0) {
s->desc_offset = 0x200;
} else {
ret = vmdk_open_desc_file(bs, flags, 0);
if (ret) {
goto fail;
}
}
/* try to open parent images, if exist */
ret = vmdk_parent_open(bs);
if (ret) {
goto fail;
}
s->parent_cid = vmdk_read_cid(bs, 1);
qemu_co_mutex_init(&s->lock);
/* Disable migration when VMDK images are used */
error_set(&s->migration_blocker,
QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
"vmdk", bs->device_name, "live migration");
migrate_add_blocker(s->migration_blocker);
return 0;
fail:
vmdk_free_extents(bs);
return ret;
}
I'm seeing loads of people suggesting break instead of goto. But break is no "better" (or "worse") than goto.
The inquisition against goto effectively started with Dijkstra's "Go To Considered Harmful" paper back in 1968, when spaghetti code was the rule and things like block-structured if and while statements were still considered cutting-edge. ALGOL 60 had them, but it was essentially a research language used by academics (cf. ML today); Fortran, one of the dominant languages at the time, would not get them for another 9 years!
The main points in Dijkstra's paper are:
Humans are good at spatial reasoning, and block-structured programs capitalise on that because program actions that occur near each other in time are described near each other in "space" (program code);
If you avoid goto in all its various forms, then it's possible to know things about the possible states of variables at each lexical position in the program. In particular, at the end of a while loop, you know that that loop's condition must be false. This is useful for debugging. (Dijkstra doesn't quite say this, but you can infer it.)
break, just like goto (and early returns, and exceptions...), reduces (1) and eliminates (2). Of course, using break often lets you avoid writing convoluted logic for the while condition, getting you a net gain in understandability -- and exactly the same applies for goto.