• Advertisement
Sign in to follow this  

Trouble With Global Variables

This topic is 4252 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I have most of my experience with Java and this is my first project in C++. (I've got about two weeks left before my deadline!) I made a mistake when I was designing a game engine for a simple 2D top down shooter. The sprite manager I created does not communicate with the game, so for example if the boss in level one is killed, the game won’t know to switch to level 2 because the sprite manager simply deletes the boss object. If there is a boss pointer in the game class, then oops! I’m going to get around this problem for now with a global variable. For example in “Primani.cpp” (The game’s name is Primani and with the Primani class I handle things like game cycle, game paint, game start, game end, handle keys…etc.) I place the following code at the top of the file.
//"Primani.cpp"

enum Level {LEVEL1,LEVEL2,LEVEL3};
     Level currentLevel = LEVEL1;



Now what I tried doing is modifying the “currentLevel” variable in the boss class. Then the game would know to move to the next level. I naively tried to do this:
//"Boss1.cpp"
extern Level LEVEL2;
extern Level currentLevel;

void Boss1::onCollisionWith(const Sprite* const sp){
	if(sp->getName() == "playerphoton"){
		life -= damageTaken;
		ScoreKeeper::raiseScoreBy(hitBossBonus);
		if(life <= 0){
			currentLevel = LEVEL2;  //Level is changed
			dead = true;
			ScoreKeeper::raiseScoreBy(killBossBonus);
		}
	}
}


But it doesn’t work. I got this from a tutorial I read but it’s not working too well. Could some one lend me a hand? [Edited by - Frank_Li on July 2, 2006 2:42:51 PM]

Share this post


Link to post
Share on other sites
Advertisement
Define "doesn't work". Does it not compile? Not link? Cause an access violation? Do little bunnies jump out of your screen and eat your cereal?

Share this post


Link to post
Share on other sites
Yeah, sorry here is the error:

Error4 error C2146: syntax error : missing ';' before identifier 'currentLevel'
Error1 error C2146: syntax error : missing ';' before identifier 'LEVEL2'
Error 5 error C4430: missing type specifier - int assumed.

The type specifier error points to the level type.

I'm not missing any ";" it's just one of those wierd errors that show up in VS.

Share this post


Link to post
Share on other sites
From the error messages it looks like your Boss.cpp file can't find the enumeration.
Try adding extern enum Level; before the two extern rows and see if that helps.

Share this post


Link to post
Share on other sites
I changed the code to this:


extern enum Level LEVEL2;
extern enum Level currentLevel;

void Boss1::onCollisionWith(const Sprite* const sp){
if(sp->getName() == "playerphoton"){
life -= damageTaken;
ScoreKeeper::raiseScoreBy(hitBossBonus);
if(life <= 0){
currentLevel = LEVEL2;
dead = true;
ScoreKeeper::raiseScoreBy(killBossBonus);
}
}
}



I get less errors. Here they are:

Error 1 error LNK2001: unresolved external symbol "enum Level LEVEL2"
Error 2 fatal error LNK1120: 1 unresolved externals

Share this post


Link to post
Share on other sites
Well it looks to me like you are not including the enum declaration into the boss file through a header.

Also though, when you say

extern Level LEVEL2;

you are declaring a variable of type Level with the name LEVEL2, but you have defined LEVEL2 as an enum constant.

Perhaps once the boss file can see the enum declaration, you would want to do:

extern Level NextLevel;

Then in the cpp file that actually declares this extern variable,

Level NextLevel=LEVEL2;

Then in the boss function, you can do:

currentLevel=NextLevel;

HTH Paul

Share this post


Link to post
Share on other sites
Ah, i think you misunderstood me, what i meant is changing your code to this:

//"Boss1.cpp"
extern enum Level;
extern Level LEVEL2; // you should be able to remove this, because
// now your boss1.cpp know about the whole Level
// enumeration
extern Level currentLevel;

void Boss1::onCollisionWith(const Sprite* const sp){
...


What the extern keyword does is tell your file that "this declaration exist in another file, so go ahead and use it".
So the explanation for you would be that your Boss1.cpp file couldn't find the enumeration, and therefore complained when you tried to declare variables with it. It didn't know what type to treat the variables as.

EDIT: Actually, why don't you go ahead and create a .h file for that enumeration and include it into Boss1.cpp. This would be an excellent place to use it =)

Share this post


Link to post
Share on other sites
If I put it in a .h file and I include it in the Primani.cpp and Boss.cpp, won't the compiler complain about it being defined twice?

Share this post


Link to post
Share on other sites
Not for the different .cpp files as they get compiled into separate objects. If you were to include your .h file in the same file twice, then yes, it wouldn't compile due to that error you said. What you usually do in .h files is to add a "fileguard".
The most usual way to do it (methinks) is to do like this:

// some_h_file.h
#ifndef __SOME_H_FILE_H
#define __SOME_H_FILE_H

// write the .h file as usual here

#endif // __SOME_H_FILE_H


This will work like this.
1. The compiler checks the first line, which says "if not defined __SOME_H_FILE". Since it isn't defined for this file yet, we define it with #define __SOME_H_FILE.
2. The next time this file try to read the .h file, the "if not defined" will fail when __SOME_H_FILE is declared, and the .h file won't be read again.

If you are using MSVC you can just add "#pragma once" to the top of your .h file and this will usually work just as well.

Share this post


Link to post
Share on other sites
Well, I'm glad things are working for you, but there does seem to be some confusion about enums and extern going on here.

The declaration of an enum doesn't create any storage. If I put:

enum Foo
{
Bar,
Baz,
Boo
};


into my code, the compiler knows about the values Bar, Baz, and Boo in the enum Foo, but it doesn't create any instances of Foo. When I say

Foo someThing = Baz;

the compiler will now create storage for a Foo, and it will be initialized with the value Baz.

So, extern tells the compiler that storage for something exists elsewhere, so your code can refer that thing, but it doesn't need to create storage in the current compilation unit. So I can say

extern Foo someThing;

in one module, and it will refer to someThing somewhere else. However, saying

extern enum Level;

is meaningless, because the enum doesn't need any storage, only instances of enums need storage.

With all that said, it's bad design to have the boss specify a target level change on death. It'd be better to have an endLevel() function on your game class, and have the boss call that when it dies. Then, the game class can be responsible for transitioning to level 2.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement