Archived

This topic is now archived and is closed to further replies.

nicho_tedja

no global variables?

Recommended Posts

Hi there, I''m wondering how do you make a big program (games) without using global variables at all. I heard you can do this with classes, but I still don''t get it how. The only way I can think of is using one single main source file: main.cpp // everything in here level.cpp // level class level.h monster.cpp // monster class monster.h etc... in main.cpp, I include all necessary .h files. But still, one source file? Isn''t that gonna make 20000 lines long in one file, and that''s very confusing and annoying looking at the tiny scroll thumb. Is there any other way to do this?
My compiler generates one error message: "does not compile."

Share this post


Link to post
Share on other sites
the first 2 games I wrote used globals (way too many of them in fact). Even though I''d just spent 3 years at uni learning the right way to code, for some reason I coded my first two games ala LaMothe style. (probably cos I was reading his books at that time).
The code was bloody awful but I did learn alot.
My third game was coded better (but still not great).

I code much better when not writing game projects (don''t know why though).

anyway the point is that I''d get in there and start doing it at least in the beginning.
You''ll get cleaner as you go along, however keep in mind that its not the best way to do things and you''ll be right.

Toby

Gobsmacked - by Toby Murray

Share this post


Link to post
Share on other sites
You could have a game class in one file to begin with. And it''s not forbidden to not put everything in one place. you could split it. Graphics, Sound, keyboard utilities doesn''t have to be in the same place. The Game class could then put things together...

happy coding!

Share this post


Link to post
Share on other sites
It''s actually pretty simple. Within your main()/WinMain()/etc:

{
CGame cApp;

cApp.Run(); //hehe hopefully you''ll see it run

return cApp.GetOSReturnCode();
}

CGame is then the class that takes care of it all. Within that, there may be several member class variables that call other classes to do work. I''ve actually done this several times before and it works quite well. Keeps main really small and lets the majority of your code be object oriented. I still like to use global variabes for some things, however.

Share this post


Link to post
Share on other sites
I wrote a goto the other day in memory of E W Dijkstra


"It is precisely because it is fashionable for Americans to know no science, even though they may be well educated otherwise, that they so easily fall prey to nonsense. They thus become part of the armies of the night, the purveyors of nitwittery, the retailers of intellectual junk food, the feeders on mental cardboard, for their ignorance keeps them from distinguishing nectar from sewage."
Isaac Asimov

Share this post


Link to post
Share on other sites
quote:
Original post by SilentReaper
It''s actually pretty simple. Within your main()/WinMain()/etc:

{
CGame cApp;

cApp.Run(); //hehe hopefully you''ll see it run

return cApp.GetOSReturnCode();
}


I hope that''s not how you do it

The "correct" way to do it would be to use a Singleton. Make a Google search.

Cédric

Share this post


Link to post
Share on other sites
quote:
Original post by cedricl
I hope that''s not how you do it

The "correct" way to do it would be to use a Singleton. Make a Google search.


Ergh... what would be the point of a singleton here? Without knowing anything more about CGame''s interface, it isn''t given that it needs to be globally accessible.

Share this post


Link to post
Share on other sites
Yueaahh. I regretted writing my previous post in such a confident manner afterwards. Feel free to bash me for what I wrote

SilentRaven''s technique works, but it just seems weird IMHO.

That was my strongest argument. Seriously, I don''t know. Would you do it that way?

I''m not even going to sign this...

Share this post


Link to post
Share on other sites
But how do you manage dialogs with that method? You can''t have callback functions as member functions unless they''re static. If they''re static, variables need to be static (the HWND and hInstance for example). And a static class member is kind of like a global var anyway. What''s wrong with globals? Lots I don''t like, but globals such as:

HWND myWindow;
HINSTANCE hThisInstance;
D3DWrapperClass *d3d;


Seem no problem. And they''re more elegant than passing extra parameters all over the place just for the sake of it. Windows is not a OO OS really - in fact the whole main() thing screws up OO. Acknowledge this and use a small about of global stuff where it makes your code more elegant both internally as well as saying "look - only one function gets called (App.Run)" when internally it''s all twisted just to look pretty. If you want a better OO language look at Java - the main is inside a class. In fact everything is a class!



Read about my game, project #1
NEW (13th August): A new screenshot is up, plus diaries for week #3


John 3:16

Share this post


Link to post
Share on other sites
Hi d000hg. Yes, indeed, static member functions for the callbacks. The way around it? What I normally do, is I have a file-scope variable (not global) called something like CClassName *pThis. In a constructor or initialization, before the callbacks would be called, I initialize pThis = this. Then it all works (at least for me).

EDIT:
I agree, some global variables are a good thing, but too many make things unreadable.

[edited by - SilentReaper on August 16, 2002 11:33:36 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by SilentReaper
EDIT:
I agree, some global variables are a good thing, but too many make things unreadable.



Yeah, that''s what my projects have. When I start my project, I just have very few globals, but later then, I got tons of those, and I hate them.

I hope you guys don''t misundestand me. What I mean by global variables are those variables shared among modules (.cpp).

If I just have:
// main.cpp
CGame *game=0;

int main()
{

}
// end of main.cpp

I wouldn''t mind, but if I have multiple source files such as this:

// main.cpp ------------
CGame *game=0;

int main()
{

}
// end of main.cpp

// start foo.cpp ------------
int somefunc()
{
game->start();
}
// end of foo.cpp

I hate it. I''ll look at singleton. Thanks for the replys guys.



My compiler generates one error message: "does not compile."

Share this post


Link to post
Share on other sites
Try making programs with Java. It won't allow you to use global variables so you need to come up with better solutions. I'm currently making a Civilization-type game with Java and I have zero singletons, zero static variables/methods and naturally zero globals. (ha, I lied there. I do have a static random-number generator method/variable.. I don't want to have any kind of control about the random numbers, so it's the simplest way)

I just pass the necessary objects to other classes in their constructor arguments, and let them keep reference to those objects. Using those objects, they can access all the variables/methods they need. This way the class relations become quite clear. Something like:

          
class Player {
LinkedList _units = new LinkedList();
void addUnit(int x, int y) {
_units.add(new Unit(x, y, this));
}
}

class Unit {
Player _owner;
int _x, _y;
Unit(int x, int y, Player owner) {
_x = x;
_y = y;
_owner = owner;
}
}

Now the unit knows who's its owner and it can call its operations when necessary. It doesn't need to know about any other objects in the system. And if it does (not likely), I just pass more arguments to it's constructor . Or access those objects via it's owner's fields. In a similar way, Player objects know about PlayerManager-object (which keeps track of players), and PlayerManager-object knows about WorldServer-object, which is the 'main' class of the project (server side, naturally).

Not sure if that's the best way to do it, it's actually my first attempt to make a largish project without globals. But at least I can understand it well and it makes the project clear.. In my previous C/C++ projects I always ended up having dozens of globals. But I don't see any benefits in using globals anymore. The speed difference is insignificant and so is the memory amount eaten by those object references.

[edited by - civguy on August 17, 2002 4:21:10 AM]

Share this post


Link to post
Share on other sites
I just don''t like that approach - you''re passing an extra parameter for one thing. Also I''d be really tempted to directly read the members of the object rather than calling all the Get() & Set() methods.



Read about my game, project #1
NEW (13th August): A new screenshot is up, plus diaries for week #3


John 3:16

Share this post


Link to post
Share on other sites
You can be tempted. but when you use a get or set function you can impose colateral effects, that stay invisible. Let`s say you need to check if the value that you are reading is valid or not (if points to a valid memory location as example). You can include the test iside the get, so that you only need to write it once.

The most important in get and set is that the MEMBERS of that class should be private or protected... only interface members should be public. So thta only by correct means you can access the internals of the class. That come to be very,very useful in large and complicated systems.

A good read for OOP is very instructive... if you program C++.. read Stroustrap... for any language You can look for Parnas. A very good book is Design Patterns (advanced application od OOP power)

If brute force does not solve your problem....you''re not using enough!

Share this post


Link to post
Share on other sites
You mean globals like what? I don't use globals at all in my programs. If I know i'll need some value from some class one aproach could be just adding a pointer to that class in the class I need and then access the value with a get method of the first class.


    
class CPepito
{
private:
int value;
public:
int getValue();
};
//------------------------

class CCorchito
{
public:
void setPepito(CPepito* pPepito);
private:
CPepito* m_pPepito;
void useValueFromPepito();
};
//------------------------

void CCorchito::useValueFromPepito()
{
int value;
value = m_pPepito->getValue();
}


[edited by - xaxa on August 17, 2002 7:52:57 AM]

Share this post


Link to post
Share on other sites
Thanks for fleshing out my point, d000hg
quote:
Original post by d000hg
I just don''t like that approach - you''re passing an extra parameter for one thing. Also I''d be really tempted to directly read the members of the object rather than calling all the Get() & Set() methods.

I agree. If you make the functions dealing with CGame non-members, you always have to pass CGame around all over the place, which is a pain.

On the other hand, if you make them member functions, they will be tempted to use the private and protected members of the class a lot more. Scott Meyers wrote "How Non-Member Functions Improve Encapsulation". It''s an interesting read.

Conclusion: Use Singletons if you don''t like global variables

Cédric

Share this post


Link to post
Share on other sites
Seems like xaxa used exactly the same approach I did
quote:
Original post by d000hg
I just don't like that approach - you're passing an extra parameter for one thing.
You're passing an extra parameter only once, in the constructor. That's hardly a burden. It also helps anyone know that that class needs the object for one reason or another. Globals and singletons can be used by any object randomly, so it makes it quite confusing.
quote:
Also I'd be really tempted to directly read the members of the object rather than calling all the Get() & Set() methods.
Well, that's impossible if the members are declared private/protected (like they should be). I don't see your point.

[edited by - civguy on August 17, 2002 12:19:21 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by cedricl

Conclusion: Use Singletons if you don''t like global variables




Singletons _are_ global variables.

Share this post


Link to post
Share on other sites
Not at all - you have way more control over the access to a singleton than a global variable. You can also control it''s lifetime, and it doesn''t even have to be a single instance(the GoF book discusses an implementation with multiple instances).

Share this post


Link to post
Share on other sites
"Is better than" only depends of your needs.

I choose a better data structure using clases, code rehusability, and protected member variables than the performance I could achieve without using them. I like to have everything on it place, so I always know where things are. I really do prefer to code a lot at first to code less at last. At final stages, the code is very simply and very human readable.

I have made a library that does al the DirectX stuff almost by itself, I do just inherit CGameEngine in my CGame class, initialize some values for the video mode, sound, input and the rest its a matter of playing with objects that are proper to the game.

For example, a tetris clone I made, has only this clases:

CGame :: public CGameEngine
CMenu :: public CSection, CSprite
CHighScores :: public CSection
CStage :: public CSection, CSprite
CBoard
CPiece
CBlock :: public CSprite
CAIPlayer :: public CPlayer

I'm scaling the library so I can do 2D using Direct3D or DirectDraw just seting a value to TRUE.

The main cpp looks like this:

    
#include "game.h"

LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){...}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
CGame Game(hInstance, MainWndProc);
return Game.MainLoop();
}


[edited by - xaxa on August 17, 2002 3:21:22 PM]

Share this post


Link to post
Share on other sites
quote:
quote:
--------------------------------------------------------------------------------
Original post by d000hg
I just don''t like that approach - you''re passing an extra parameter for one thing.
--------------------------------------------------------------------------------

You''re passing an extra parameter only once, in the constructor. That''s hardly a burden. It also helps anyone know that that class needs the object for one reason or another. Globals and singletons can be used by any object randomly, so it makes it quite confusing.


But this approach ties all the objects to a certain instance of the ''parent'' class - that doesn''t seem very object orientated. What if the object you store a link to is deleted, or replaced? Now you also have to put more extra safety code in. I just reckon a few globals is a lot easier.

What exactly is the merit of a main() that''s only 2 lines long? It''s just another layer of indirection to where you actually do stuff. Why not make main create all the top-level objects and load stuff?




Read about my game, project #1
NEW (13th August): A new screenshot is up, plus diaries for week #3


John 3:16

Share this post


Link to post
Share on other sites