Tutorial :Avoiding Global State



Question:

Currently I'm writing an app. If I want to avoid Singletons, do I have to simply pass references of everything around?

For example,

I have a "main" class.
Class: Main
+---- Screen
+---- Camera
+---- Terrain
+---- Vehicle
+---- PhysicsWorld

It contains my Camera, Terrain, and Vehicle,etc classes. Now, I have issues when I'm creating say, the Terrain object. Terrain wants to access Main classes Screen object so it can add its Terrain Graphics to the screen. It also wants to know about the Camera object for when it is drawing so it knows what scale to draw it. It also wants to know about my PhysicsWorld object so it can add itself to the physics engine.

Do I have to always lug these objects back and forth between constructors? I mean, when I create a Terrain object, do I simply have to pass around my screen object, my physicsWorld, camera, etc?

Another random scenario I have, is now.. inside my Vehicle class I need to call a Restart() method on my Main class. Does this mean I have to pass an instance of main to Vehicle? Really??

It feels cumbersome to constantly have to pass 4-5 things to my classes, especially in my scenario now where almost every in-game object I have needs a screen, physics, camera info, etc.

Any suggestions?


Solution:1

It feels cumbersome to constantly have to pass 4-5 things to my classes, especially in my scenario now where almost every in-game object I have needs a screen, physics, camera info, etc. Then the correct question to ask is "why do I need all 5 objects in all my classes?" Why on Earth does every in-gmae object need any of the mentioned things? An in-game object needs a position and whatever it needs to process its behavior. Then a separate renderer can, you know, render, the object. Which means that only the renderer needs the camera info and screen.

The physics could go either way. You could have a separate physics entity which updates the game object, or you could pass that physics object to every game object. But even if you do pass that around, we're down to one out of the three objects listed. :)

That's why globals and singletons are often best avoided. They disguise your dependencies so you end up with far more dependencies between your objects than you actually need. And then it becomes almost impossible to remove the globals.

However, if you do stick with globals, do yourself a favor, and at least avoid singletons. You don't need the additional constraints enforced by a singleton.

Terrain wants to access Main classes Screen object so it can add its Terrain Graphics to the screen. It also wants to know about the Camera object for when it is drawing so it knows what scale to draw it. It also wants to know about my PhysicsWorld object so it can add itself to the physics engine.

The terrain object needs to know one thing: What is the terrain like. Someone else can take responsibility for rendering it. That someone will need to know about the camera, screen and terrain graphics, sure, which suggests that the same object might plausibly be able to do other tasks involving these objects (such as other rendering tasks). Why should the terrain care about what scale it's drawn in? It needs to know the scale ingame, but not the scale in camera-space. And why can't someone else add the terrain to the physics engine? The main function might be able to do that, even. Create terrain, create physics engine, register terrain with physics engine, start game.


Solution:2

I don't know ActionScript, but assuming variables are passed by reference, the least you could do is construct a 'Environment' class holding Camera, Screen, Terrain, PhysicsWorld which you pass to the instances.


Solution:3

I have the exact same problem (also in actionscript 3, coincidentally).

I have been working on an RTS for flash and had found myself needing to pass around large numbers of references to each new class (e.g., gameGrid, currentSelection, visibleUnits, etc.).

I eventually realised that what I really should be doing is to have every class maintain it's own properties, and instead pass around references to these classes, (well objects).

But anyway, now what I'm doing is having static variables containing references to commonly used objects such as the main stage, interface, engine and display area inside a class called RTSGlobals. I'm also putting constants such as the screen size in there.

I know this doesn't really answer your question, but I figure sometimes it is worth ignoring a bit of OOP good practice in favour of an efficient solution.

If someone has a does have a good practice solution though, please tell :)


Solution:4

I suggest you take a look at XNA's samples projects (google it). They're well designed and might give you some hints.

Also, since you're using AS3, you could use the event system to dispatch message to other entities. For example, instead of passing your Main to your Vehicle class, make your Main (or whatever else interested) a listener of your Vehicle class. Then, let's say the car crash and you want to restart the game, dispatch an event, for example CAR_CRASHED. The listeners of your car should do something based on this message. If you want to understand the event system, type EventDispatcher, highlight it and hit F1 in your Flash IDE.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »