Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » multiple definition of `_currentLevel'

This thread is locked; no one can reply to it. rss feed Print
multiple definition of `_currentLevel'
AmnesiA
Member #15,195
June 2013
avatar

I am still working on my first game and I created a globals.h file that keeps all of the globals for the game. This has worked flawlessly for all of my constants but now I tried to add a variable (int currentLevel) and now I get an error in every file that includes "globals.h" that looks like this:

obj\Debug\sprite.o:sprite.cpp:(.data+0x0): multiple definition of `_currentLevel'
obj\Debug\main.o:main.cpp:(.data+0x0): first defined here

I don't know why this is causing problems for a variable but not for constants.

globals.h

#SelectExpand
1#ifndef GLOBALS_H 2#define GLOBALS_H 3 4const int DISPLAY_W = 640; 5const int DISPLAY_H = 640; 6const int FPS = 60; 7const double PI = 3.14159265359; 8 9enum MYKEYS{ 10 UP, DOWN, LEFT, RIGHT 11}; 12enum ROOMS{ 13 RM_LOAD, RM_MENU, RM_GAME, RM_CREDITS 14}; 15enum BG_TYPES{ 16 BG_TILED, BG_STRETCH, BG_CENTER 17}; 18 19int currentLevel = RM_GAME; 20 21#endif //GLOBALS_H

main.cpp

#SelectExpand
1#include<stdio.h> 2#include<allegro5/allegro.h> 3#include<allegro5/allegro_image.h> 4#include<allegro5/allegro_primitives.h> 5#include<allegro5/allegro_font.h> 6#include<allegro5/allegro_ttf.h> 7#include<allegro5/allegro_audio.h> 8#include<allegro5/allegro_acodec.h> 9 10#include "globals.h" 11#include "sprite_library.h" 12 13ALLEGRO_DISPLAY* display; 14ALLEGRO_EVENT_QUEUE* eventQueue; 15ALLEGRO_TIMER* timer; 16 17SPRITE_LIBRARY spriteLib; 18//Create OBJECT_LIBRARY > OBJECT 19//Create ROOM > BG_CTRL 20 21extern const int DISPLAY_W; 22extern const int DISPLAY_H; 23extern const int FPS; 24 25extern int currentLevel; 26 27bool key[4]; 28bool done; 29 30void shutdown(){ 31 if(timer) 32 al_destroy_timer(timer); 33 if(display) 34 al_destroy_display(display); 35 if(eventQueue) 36 al_destroy_event_queue(eventQueue); 37} 38 39void abort_game( const char* message){ 40 printf("%s \n", message); 41 shutdown(); 42 exit(1); 43} 44 45void init(){ 46 //Standard Allegro initialization 47 if(!al_init()) 48 abort_game( "Failed to initialize Allegro!"); 49 if(!al_init_image_addon()) 50 abort_game( "Failed to initialize Image Addon!"); 51 if(!al_install_keyboard()) 52 abort_game( "Failed to access keyboard!"); 53 for( int i = 0; i < 4; ++i) 54 key[i] = false; 55 timer = al_create_timer(1.0 / 60); 56 if(!timer) 57 abort_game( "Failed to create timer!"); 58 al_set_new_display_flags(ALLEGRO_WINDOWED); 59 display = al_create_display( DISPLAY_W, DISPLAY_H); 60 if(!display) 61 abort_game( "Failed to create display!"); 62 eventQueue = al_create_event_queue(); 63 if(!eventQueue) 64 abort_game( "Failed to create Event Queue!"); 65 al_register_event_source( eventQueue, al_get_keyboard_event_source()); 66 al_register_event_source( eventQueue, al_get_timer_event_source(timer)); 67 al_register_event_source( eventQueue, al_get_display_event_source(display)); 68 69 //Object initialization 70 spriteLib.init(); 71 72 //Define variables 73 done = false; 74} 75 76void game_loop(){ 77 //Use rooms for game loop, pass which keys are being pressed 78 //while(!done){ 79 //get input 80 //handle anything like escaping out of the game, pausing, etc 81 //ROOM[currentLevel]::step(key[]); 82 //ROOM[currentLevel]::draw(); 83 //} 84} 85 86int main( int argc, char** argv){ 87 init(); 88 game_loop(); 89 shutdown(); 90 91 return 0; 92}

And then just for reference:
sprite.h

#SelectExpand
1#ifndef SPRITE_H 2#define SPRITE_H 3 4#include<vector> 5#include<allegro5/allegro.h> 6#include<allegro5/allegro_image.h> 7#include<allegro5/allegro_primitives.h> 8#include "globals.h" 9 10using std::vector; 11 12class SPRITE{ 13 14public: 15 SPRITE(); 16 ~SPRITE(); 17 18 SPRITE& operator=( SPRITE &rhs); 19 20 int load_from_file( const char* file_name, int sx, int sy, int sw, int sh, 21 int image_count, bool visible = true, int speed = 1, int offset = 1 22 ); 23 int load_from_bitmap( ALLEGRO_BITMAP* temp_bitmap, int sx, int sy, int sw, int sh, 24 int image_count, bool visible = true, int speed = 1, int offset = 1 25 ); 26 void set_image_index( int image_index); 27 void set_speed( int speed); 28 void set_visibility( bool visibile); 29 int get_frame(); 30 int get_image_count(); 31 int get_image_width(); 32 int get_image_height(); 33 int get_current_image(); 34 int get_speed(); 35 bool get_visibility(); 36 vector<ALLEGRO_BITMAP*> get_image_index(); 37 38 void step(); 39 void draw( int x, int y); 40 41protected: 42 int errorSprite(); 43 ALLEGRO_BITMAP* errorBitmap(); 44 45 vector<ALLEGRO_BITMAP*> imageIndex; 46 bool isVisible; 47 int imageCount; 48 int IMAGE_WIDTH, IMAGE_HEIGHT; 49 ALLEGRO_COLOR alphaColor; 50 int frame, spf; //steps per frame 51 int stepCount; 52 53}; 54 55#endif //SPRITE_H

sprite.cpp

#SelectExpand
1#include "sprite.h" 2 3SPRITE::SPRITE(){} 4SPRITE::~SPRITE(){} 5 6SPRITE& SPRITE::operator=( SPRITE &rhs){ //Copy all elements from right hand to left hand 7 imageIndex = rhs.get_image_index(); 8 isVisible = rhs.get_visibility(); 9 imageCount = rhs.get_image_count(); 10 IMAGE_WIDTH = rhs.get_image_width(); 11 IMAGE_HEIGHT = rhs.get_image_height(); 12 frame = rhs.get_frame(); 13 spf = rhs.get_speed(); 14 15 return *this; 16} 17 18int SPRITE::load_from_file( const char* file_name, int sx, int sy, int sw, int sh, 19 int image_count, bool visible, int speed, int offset 20 ){ //load specific sprite from file 21 ALLEGRO_BITMAP* targetBitmap = al_get_target_bitmap(); 22 //Set variables 23 imageCount = image_count; 24 IMAGE_WIDTH = sw; 25 IMAGE_HEIGHT = sh; 26 isVisible = visible; 27 spf = speed; 28 ALLEGRO_BITMAP* tempBitmap = al_load_bitmap( file_name); 29 if(!tempBitmap){ //if it didn't load, try to create an error sprite 30 if( !errorSprite()) 31 return -1; 32 }else{ 33 //Load series of images into imageIndex 34 al_convert_mask_to_alpha( tempBitmap, al_get_pixel( tempBitmap, sx, sy)); //set top left pixel as transparent color 35 for( int i = 0; i < imageCount; ++i){ 36 imageIndex.push_back( al_create_bitmap( IMAGE_WIDTH, IMAGE_HEIGHT)); 37 if(!imageIndex[i]){ //if the bitmap couldn't be created, try to create a missing image bitmap 38 imageIndex[i] = errorBitmap(); 39 if(!imageIndex[i]) //If that still can't be craeted, create an error 40 return -1; 41 } 42 al_set_target_bitmap(imageIndex[i]); 43 al_draw_bitmap_region( tempBitmap, 44 sx + (IMAGE_WIDTH + offset) * i, sy, 45 IMAGE_WIDTH, IMAGE_HEIGHT, 0, 0, 0 46 ); 47 } 48 } 49 al_set_target_bitmap(targetBitmap); 50 frame = 0; 51 stepCount = 0; 52 return 1; 53} 54 55int SPRITE::load_from_bitmap( ALLEGRO_BITMAP* temp_bitmap, int sx, int sy, int sw, int sh, 56 int image_count, bool visible, int speed, int offset 57 ){ 58 ALLEGRO_BITMAP* targetBitmap = al_get_target_bitmap(); 59 imageCount = image_count; 60 IMAGE_WIDTH = sw; 61 IMAGE_HEIGHT = sh; 62 isVisible = visible; 63 spf = speed; 64 al_convert_mask_to_alpha( temp_bitmap, al_get_pixel( temp_bitmap, sx, sy)); 65 for( int i = 0; i < imageCount; ++i){ 66 imageIndex.push_back( al_create_bitmap( IMAGE_WIDTH, IMAGE_HEIGHT)); 67 if(!imageIndex[i]){ 68 imageIndex[i] = errorBitmap(); 69 if(!imageIndex[i]) 70 return -1; 71 } 72 al_set_target_bitmap(imageIndex[i]); 73 al_draw_bitmap_region( temp_bitmap, 74 sx + (IMAGE_WIDTH + offset) * i, sy, 75 IMAGE_WIDTH, IMAGE_HEIGHT, 0, 0, 0 76 ); 77 } 78 al_set_target_bitmap(targetBitmap); 79 frame = 0; 80 stepCount = 0; 81 return 1; 82} 83 84void SPRITE::set_image_index( int image_index){ 85 frame = image_index; 86} 87 88void SPRITE::set_speed( int speed){ 89 spf = speed; 90} 91 92void SPRITE::set_visibility( bool visible){ 93 isVisible = visible; 94} 95 96int SPRITE::get_frame(){ 97 return frame; 98} 99 100int SPRITE::get_image_count(){ 101 return imageCount; 102} 103 104int SPRITE::get_image_width(){ 105 return IMAGE_WIDTH; 106} 107 108int SPRITE::get_image_height(){ 109 return IMAGE_HEIGHT; 110} 111 112int SPRITE::get_current_image(){ 113 return frame; 114} 115 116int SPRITE::get_speed(){ 117 return spf; 118} 119 120bool SPRITE::get_visibility(){ 121 return isVisible; 122} 123 124vector<ALLEGRO_BITMAP*> SPRITE::get_image_index(){ 125 return imageIndex; 126} 127 128void SPRITE::step(){ 129 if( ++stepCount >= spf){ 130 stepCount = 0; 131 if( ++frame >= imageCount){ 132 frame = 0; 133 } 134 } 135} 136 137void SPRITE::draw( int x, int y){ 138 al_draw_bitmap( imageIndex[frame], x, y, 0); 139} 140 141int SPRITE::errorSprite(){ 142 ALLEGRO_BITMAP* targetBitmap = al_get_target_bitmap(); 143 for( int i = 0; i < imageCount; ++i){ 144 imageIndex.push_back(errorBitmap()); 145 if(!imageIndex[i]) 146 return -1; 147 } 148 al_set_target_bitmap( targetBitmap); 149 return 1; 150} 151 152ALLEGRO_BITMAP* SPRITE::errorBitmap(){ 153 ALLEGRO_BITMAP* targetBitmap = al_get_target_bitmap(); 154 ALLEGRO_BITMAP* tempBitmap = al_create_bitmap( IMAGE_WIDTH, IMAGE_HEIGHT); 155 if(!tempBitmap) 156 return tempBitmap; 157 al_set_target_bitmap(tempBitmap); 158 al_clear_to_color( al_map_rgb(0,0,160)); 159 al_draw_line( 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, al_map_rgb(255,0,0), 1); 160 al_draw_line( IMAGE_WIDTH, 0, 0, IMAGE_HEIGHT, al_map_rgb(255,0,0), 1); 161 al_set_target_bitmap( targetBitmap); 162 return tempBitmap; 163}

My game loop does nothing yet, obviously, I'm just using the comments to brainstorm how I'm going to implement different parts.

EDIT: I forgot to mention, doing a search off all of the project files for "currentLevel" yields:

File        Line    Text
globals.h   19      int currentLevel = RM_GAME;
main.cpp    25      extern int currentLevel;
main.cpp    81      //ROOM[currentLevel]::step(key[]);
main.cpp    82      //ROOM[currentLevel]::draw();

Which shows that the only time the compiler would read "currentLevel is on line 19 of globals.h and line 25 of main.cpp which tells me that the problem must lie in linking the globals.h file BUT it shouldn't be an issue (if I understand this correctly) because of the #ifndef at the start.

=======================
Website
My first game!

Edgar Reynaldo
Member #8,592
May 2007
avatar

Your problem is with the globals.h file. Objects that need to be accessible to other modules should be declared in a header preceeded by the keyword 'extern'.

globals.hpp

#ifndef HEADER
#define HEADER

extern int global_integer;

#endif // #ifndef HEADER

After that, you define them (ONCE) in a source module.

globals.cpp

#include "globals.hpp"

int global_integer = 0;

The reason you are getting that error is that each of your source file included code that defines an integer named current_level. But the compiler doesn't know or care about that. The linker does though, and when it tries to link everything it sees that more than one module defines current_level.

AmnesiA
Member #15,195
June 2013
avatar

Thank you, I changed the declaration in globals.h to extern int currentLevel; and declared int currentLevel; in main.cpp and defined it in the init() function of main.cpp and it works beautifully. Thanks again!

=======================
Website
My first game!

Go to: