Local / Global Variables - Why?
BlitzMax Forums/BlitzMax Beginners Area/Local / Global Variables - Why?
| ||
From various reading over the last few days, I've come to learn that Global variables, should, where possible, be avoided - I assume mainly down to the memory that they require. However, I'm struggling to get my head around how to use mainly local variables. I tend to have my programmes set up in the following order: -General Setup & Variable / Media Declarations -Main Loop -Function / Type Declarations The trouble is, at the moment, most of my code ends up like this: Global mvinylrotate Global introbackrotate:Float Global mvinylscale:Float=0 Global copyrightscale:Float=4 Global introfadeout Global introfadecounter Global introalpha:Float=1 Global yearalpha:Float=0 Global introplaysound Global intromvinylsound Global titlefadein:Float=0 Global titlestaralpha:Float=0 Global titlestarrotate Global titlecreditsticker=800 Global titlescale:Float=1 Global titlescaleflag Global titlerotate:Float=0 Global titlerotateflag Global s1flag Global s2flag Global s3flag Global titlevolume:Float=0 Global gamestate=1 Whereas, I can't recal a time I've seen this in anyone elses code. :( Here's the current code I'm working on: ' Slider v0.1 (alpha) - By Matt Vinyl 2007 '----------------------------------------------------------- ' General Setup--------------------------------------------- AppTitle="Slider - By Matt Vinyl 2007" Graphics(1024,768) SetMaskColor 255,0,255 SetBlend(ALPHABLEND) SetAlpha 0 SeedRnd MilliSecs() Global GAMEMODE=2 'Global flag for master game flow '0=Titlescreen '1=Start game '2=Main gameplay Global GFX_L1BACK=LoadImage("gfx\back.png") Global FADEIN:Float ' Main Loop------------------------------------------------- Repeat Cls If GAMEMODE=0 End If If GAMEMODE=1 End If If GAMEMODE=2 DRAWGAME() End If Flip Until KeyHit(KEY_ESCAPE) ' Functions------------------------------------------------- Function DRAWGAME() DrawImage GFX_L1BACK,0,0 If FADEIN<1 FADEIN:+0.01 SetAlpha FADEIN End If End Function This works as expected, but relies on global variables again. I tried: Function DRAWGAME() DrawImage GFX_L1BACK,0,0 Local FADEIN:Float If FADEIN<1 FADEIN:+0.01 SetAlpha FADEIN End If End Function and removed the Global declaration, but it doesn't fade in as expected. I'm guessing this is because the local variable is being 'reset' every time the 'Local' line is read. Could anyone provide me with some general guidelines on how to go about using mainly local variables? Pwweeaassee! ;) |
| ||
Whoops, sorry about the length of those lines, forgot my res is set at 1920 x 1200...! |
| ||
1) GO and delete the -------- from the post 2) Just make one type TGlobal, and stick all your globals in that. The main reason ppl moan, is Namespace, not speed. Dont get me wrong, in OOP the Global should really belong to some object, (As a Global of that object), so if you find that you are only using a certain global with a certain Object. Then you should accociate that global with that object by moveing it inside (Notice "Object/Type" not "Instace") |
| ||
That's a tough one. Personally I'd try keeping fadin as a global because it's just simpler that way. Why the capitals? Traditionally only constants are in capitals. Although BMax isn't case-sensitive it doesn't matter, caps is just an odd style for variables and functions. gamemode is a variable that could be local, as it is not used in any functions. You don't even need gamemode. Just make three repeat loops for each stage, using exit to get out. Images can be made local variables and sent as parameters to functions. However for simple games it's not so important. If you give some code of a more complete program it would be easier to see how you are using the variables. I think you might need to change your way of design. Global variables are bad for two reasons. They encourage bad design, as you can end up with parts of the program depending upon other parts. Then if you change something, you could create errors spreading unexpectadly throughout the program. Secondly, they are slower to access than local variables (I've heard). But they use the same amount of memory. Hope this helps. |
| ||
(Code lines tidied!) Thanks for the suggestions. I just use CAPS for vars and functions as I find they 'stand out' easier for me. I'm more than open for suggestions as to change my approach - it's just always worked fine for me, but to be fair, I've only really ever made small programs (and I'm much more used to B3D!) Cheers, M. |
| ||
I use quite a lot of globals. Why? Because its far easier when variables are regularly needed by a range of different functions. You have two choices. Pass variables from function to function, or make them global. For temporary variables (Such as 'For X = 1 to 10') - I would define the X as Local within a function, for instance. Reason being, I may use that variable in many different functions, but its a generic variable that I would use for many purposes. What I DO tend to do, is have, for example, a tScore type. Within that type, I can add various fields pertaining to the game scoring system. Then at the start, all I need to do is create one tScore object, and I can access all the score variables from there. But I digress. |
| ||
What I DO tend to do, is have, for example, a tScore type. Within that type, I can add various fields pertaining to the game scoring system. Then at the start, all I need to do is create one tScore object, and I can access all the score variables from there. But I digress I dont think that is a digresstion, I think thats what I did/whould recomend doing. (Mostly cos Im rubish at remembering names, and Blide/protean's code completion helps |
| ||
namespace, in combination with multiple instances of your stuff. From your list of globals there's a lot more to tell however as your variables seem related to visualisation/timing of, say, a titlescreen. Whether or not these are globals is not even relevant, the fact that you use named variables like these for this kind of stuff is equally limiting, namespace-wise. What you *really* want is an animation system where you define animating... 'things', let's call them "entities" to stick a bit to Blitz. Each entity could have fields like these: (and I'll start simple, but I'll pull some strings later) x y z imagehandle sound rotatex rotatey rotatez fadeinspeed fadeoutspeed alpha etc. What you then need to do is build up your titlescreen using these entities, meaning that you'll end up with this: title:TAnimEntity=New TAnimEntity title.x=5 title.rotatex=5 [..] copyright:TAnimEntity=New TAnimEntity copyright.alpha=.5 copyright.rotatey=45 [..] By using this, the only variable you're really using is these entity names 'title', 'copyright', etc. With this you already wiped most of your initial vars. So, I announced to pull some strings: You don't want title:TAnimEntity and copyright:TAnimEntity at all, because with those names you're actually hardcoding something, and hardcoding sucks! You want an array of TAnimEntity's, and just fill it with all these entities, preferably using an external scriptfile.. perhaps XML even.. Why's that? With this array you can actually design your whole titlescreen outside your sourcecode using that scriptfile in notepad. Each entity the parser sees in your script reslices your array, and so your titlescreen with all its things can become really big -without bloating your code!-. More strings to pull: You don't want fadein and fadeout variables in your TAnimEntity type, as that's more or less hardcoding again. What you want is a TEnvelope, and readout an envelope-value based on a phase-index. This TEnvelope is a seperate object again which can be as complex as anything.. a simple attack, attack-decay, or decay.. but also a multisstage/segment envelope, or perhaps you could even use beziers to readout such a multistage/segment envelope. If you have this, this whole TEnvelope is *at once* perfectly suitable to move *anything*, and not just coordinates, but also alpha or soundvolume for all I care. Normally you'd have tons and tons of volumefadein, volumefadeout -like variables for all that, and fadein and fadeout are just mere attack-decay movements, nothing like the bezier-goodies you could have. So, back to this TAnimEntity array.. from your whole list we just reduced it to one single array instance. Want to get rid of that one too? Make it a field in your TGame, and in the end, one game:TGame is everything you have! The real problems here are not the difficulties of a game, but the opportunities and possibilities! Once you get the hang of it you keep studying possible futures and you keep splitting things up. Eventually the work will pay itself back, but until that time you'll have to accept that small-scope/oneshot procedural coders are running circles around you. |
| ||
What I'd do with the fading is have a local fadein variable in the main loop and pass it to the DrawGame() function as Float Var. This way DrawGame can be used by other functions, with different fade variables. If the program were more complicated, I would consider using some kind of type structure (CS_TBL explained it well), but for something that simple it's unnecessary. By the way, I always have the main loop in a function, and call it after initialization. I don't know if it's a good idea in a simple program, but at least it makes the code clearer to me. |