2017-01-05 6 views
0

Итак, я работаю над игрой для своего класса компьютерных наук, используя Dev-C++ 5.11 и Allegro 4.2, я добираюсь до конца проекта, и я хочу, наконец, исправить проблему, с которой я столкнулся какое-то время. Мой код довольно длинный, чтобы использовать один .cpp-файл, но когда я пытаюсь разместить свои функции в отдельном файле, я получаю серию «множественных определений ошибок« впервые определенных здесь ». Я посмотрел онлайн, и большинство людей, у которых есть эта проблема, включили их .cpp-файл в свой основной или что-то подобное, но я этого не сделал и не могу понять, почему это не сработает. Ошибки указывают на все переменные, объявляемые в заголовке (растровые изображения, а также массив символов и ints).Ошибки множественного определения; C++ работает с Allegro

Файлы:

asteroidsMain.cpp 
functions.cpp 
asteroids.h 

Я также использовать файл данных.

Главный файл:

#include <allegro.h> 
#include <alfont.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include "asteroids.h" 
#include "asteroids_data.h" 

//Creating movement timer (also used for typing) 
volatile long speed_counterA = 0; 

void increment_speed_counterA() { 
    speed_counterA++; 
} 
END_OF_FUNCTION(increment_speed_counterA); 

//Creating laser timer 
volatile long speed_counterB = 0; 

void increment_speed_counterB() { 
    speed_counterB++; 
} 
END_OF_FUNCTION(increment_speed_counterB); 

//Creating asteroid timer 
volatile long speed_counterC = 0; 

void increment_speed_counterC() { 
    speed_counterC++; 
} 
END_OF_FUNCTION(increment_speed_counterC); 


int main() { 
    //Initializations 
    allegro_init(); 
    alfont_init(); 
    set_color_depth(desktop_color_depth()); 
    set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0); 
    install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL); 
    install_keyboard(); 
    install_mouse(); 
    install_timer(); 

    //Movement timer 
    LOCK_VARIABLE(speed_counterA); 
    LOCK_FUNCTION(increment_speed_counterA); 
    install_int_ex(increment_speed_counterA, BPS_TO_TIMER(60)); 
    //Laser firing timer 
    LOCK_VARIABLE(speed_counterB); 
    LOCK_FUNCTION(increment_speed_counterB); 
    install_int_ex(increment_speed_counterB, BPS_TO_TIMER(60)); 
    //Asteroid generation timer 
    LOCK_VARIABLE(speed_counterC); 
    LOCK_FUNCTION(increment_speed_counterC); 
    install_int_ex(increment_speed_counterC, BPS_TO_TIMER(60)); 

    //Randomizing seed 
    srand(time(0)); 

    //Creating/loading BITMAPs formain game 
    BITMAP *buffer = create_bitmap(800, 600); 
    shipStopped = loadImage("shipStopped"); 
    shipMoving = loadImage("shipMoving"); 
    laserSprite = loadImage("laser"); 
    smallAsteroid = loadImage("small_Asteroid"); 
    medAsteroid = loadImage("med_Asteroid"); 
    largeAsteroid = loadImage("large_Asteroid"); 

    //General use variables for screen control 
    int onScreen = 0, i = 0, j = 0; 
    bool quit = false; 

    //Retrieving and sorting scores 
    numOfScores = getHighs(name, score); 
    sortHighs(name, score); 

    //Loads main screen 
    onScreen = changeScreen(0); 

    while (!quit) { 
     //If there was an issue loading datafile, error is returned 
     if (onScreen == -1) { 
      return 1; 
     } 
     else if (onScreen == 0) { 
      while (onScreen == 0) { 
       //Primary check is for quitting program, other buttons lead to separate screens 
       if ((mouse_b & 1) && mouse_x > 400 - 75 && 
       mouse_x < 400 + 75 && mouse_y > 450 && mouse_y < 4505 + quitButton->h) { //For clicking Quit 
        quit = true; 
        onScreen = -2; 
       } 
       else if ((mouse_b & 1) && mouse_x > 400 - 75 && 
       mouse_x < 400 + 75 && mouse_y > 150 && mouse_y < 150 + playButton->h) { //For clicking Play 
        onScreen = changeScreen(2); 
       } 
       else if ((mouse_b & 1) && mouse_x > 400 - 75 && 
       mouse_x < 400 + 75 && mouse_y > 250 && mouse_y < 250 + highsButton->h) { //For clicking Highscores 
        onScreen = changeScreen(3); 
       } 
       else if((mouse_b & 1) && mouse_x > 400 - 75 && 
       mouse_x < 400 + 75 && mouse_y > 350 && mouse_y < 350 + creditsButton->h) { //For clicking Credits 
        onScreen = changeScreen(4); 
       } 
      } 
     } 
     else if (onScreen == 2) { //Difficulty choice screen 
      if ((mouse_b & 1) && mouse_x > 600 - (playButton->w/2) && 
       mouse_x < 600 + (playButton->w/2) && mouse_y > 192 && mouse_y < 192 + playButton->h) { 
        onScreen = changeScreen(1); 
     } 
      else if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 && 
      mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu 
       onScreen = changeScreen(0); 
      } 
     } 
     else if (onScreen == 3) { //Highscore screen 
      if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 && 
      mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu 
       onScreen = changeScreen(0); 
      } 
     } 
     else if (onScreen == 4) { //Credit screen 
      if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 && 
      mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu 
       onScreen = changeScreen(0); 
      } 
     } 
     else if (onScreen == 51) { //Game over screen 

      if (points <= score[9]) { 
       if ((mouse_b & 1) && mouse_x > 25 && mouse_x < 175 && 
        mouse_y > 575 - menuButton->h && mouse_y < 575) { //Begins a new game 
        onScreen = changeScreen(2); 
       } 
       else if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 && 
         mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu 
        onScreen = changeScreen(0); 
       } 
      } 
      else { 
       if (mouse_b & 1) { 
        //Adding new highschore to array 
        score[9] = points; 
        strcpy(name[9], ""); 

        if (numOfScores < 10) { 
         numOfScores++; 
        } 
        onScreen = changeScreen(52); 
       } 
      } 
     } 
     else if (onScreen == 52) { 
      speed_counterA = 0; 

      int keyEnt = 0, len = 0; 
      char keyHold; 

      //Text entering for highscore name, moves to next screen on enter 
      while (!key[KEY_ENTER]) { 
       //Preventing multiple printing of same key 
       while (keypressed() && speed_counterA % 3 == 0) { 
        //Reading key from keyboard and making it useable 
        keyEnt = readkey(); 
        keyHold = keyEnt & 0xff; 

        if (keyHold >= 32 && keyHold <= 126) { //Adding chars to name string 
         len = strlen(name[9]); 

         if (len < 19) { //Restricting the number of characters you can enter, beyond this does not save properly 
         name[9][len] = keyHold; 
         name[9][len + 1] = '\0'; 
        } 
        } 
        else if (key[KEY_BACKSPACE]) { //Deleting if backspace char is pressed 
         name[9][len] = '\0'; 
         len--; 
        } 
        clear_keybuf(); 
       } 
       //Printing text 
       textprintf_centre_ex(buffer, font, 400, 300, WHITE, -1, "What is your name: %s", name[9]); 
       textprintf_centre_ex(buffer, font, 400, 500, WHITE, -1, "** press enter to conitue **"); 
       // Blit the buffer 
       blit(buffer, screen, 0, 0, 0, 0, 800, 600); 
       clear(buffer); 

      } 
      onScreen = changeScreen(53); 
     } 
     else if (onScreen == 53) { 
      if ((mouse_b & 1) && mouse_x > 25 && mouse_x < 175 && 
       mouse_y > 575 - menuButton->h && mouse_y < 575) { //Begins a new game 
       onScreen = changeScreen(2); 
      } 
      else if ((mouse_b & 1) && mouse_x > 635 && mouse_x < 775 && 
        mouse_y > 575 - menuButton->h && mouse_y < 575) { //Returns to main menu 
       onScreen = changeScreen(0); 
      } 
     } 
     else if (onScreen == 1) { //Game screen 
      //Defining 
      Laser laser[50]; 
      Asteroid asteroid[10]; 

      //Initializing lasers and asteroids 
      for (i = 0; i < 50; i++) { 
       laser[i].pos.x = 0; 
       laser[i].pos.y = 0; 
       laser[i].angle = 0; 
       laser[i].onScreen = false; 
      } 
      for (i = 0; i < 10; i++) { 
       asteroid[i].pos.x = 0; 
       asteroid[i].pos.y = 0; 
       asteroid[i].angle = 0; 
       asteroid[i].onScreen = false; 
      } 

      //Game specific variables, reset for every new game 
      int move = 0, lasers= 0, asteroids = 0; 
      float angle = 0; 
      bool collide = false; 

      points = 0; 

      //Spawning ship when game screen loads 
      Coordinate ship; 
      ship.x = 400 - (shipStopped->w/2); 
      ship.y = 300 - (shipStopped->h/2); 

      //Reseting game timers 
      speed_counterA = 0; 
      speed_counterB = 0; 
      speed_counterC = 0; 

      while (onScreen == 1) { //Game screen 
       while (speed_counterA > 0) { 

        //Ship movement 
        if (key[KEY_UP] && key[KEY_RIGHT]){ 
         ship.y -= 3; 
         ship.x += 3; 
         angle = 32; 
        } 
        else if (key[KEY_UP] && key[KEY_LEFT]){ 
         ship.y -= 3; 
         ship.x -= 3; 
         angle = 224; 
        } 
        else if (key[KEY_DOWN] && key[KEY_RIGHT]) { 
         ship.y += 3; 
         ship.x += 3; 
         angle = 96; 
        } 
        else if (key[KEY_DOWN] && key[KEY_LEFT]) { 
         ship.y += 3; 
         ship.x -= 3; 
         angle = 160; 
        } 
        else if (key[KEY_UP]){ 
         ship.y -= 6; 
         angle = 0; 
        } 
        else if (key[KEY_RIGHT]) { 
         ship.x += 6; 
         angle = 64; 
        } 
        else if (key[KEY_LEFT]) { 
         ship.x -= 6; 
         angle = 192; 
        } 
        else if (key[KEY_DOWN]) { 
         ship.y += 6; 
         angle = 128; 
        } 

        //Laser movement 
        for (i = 0; i < 50; i++) { 
         laser[i] = moveLaser(laser[i]); 
        } 

        //Asteroid movement 
        for (i = 0; i < 10; i++) { 
         asteroid[i] = moveAsteroid(asteroid[i]); 
        } 

        speed_counterA--; 
       } 

       //Key trigger for laser firing, if is first as having timer first 
       //would cause many hits not to be properly registered especially if 
       //tapping too fast, this allows firing at will with a fastest firing of every 0.15s 
       if (key[KEY_SPACE]) { 
        //Laser firing timer 
        while (speed_counterB > 9) { 
         //Laser shooting 
         laser[lasers] = fireLaser(angle, ship.x, ship.y); 

         if (lasers >= 49) { 
          lasers = 0; 
         } 

         lasers++; 

        speed_counterB -= 10; 
        } 
       } 

       //Asteroid spawning counter 
       while (speed_counterC > 59) { //Spawns an asteroiud every second 

        //Keeping asteroids within array range 
        if (asteroids >= 9){ 
         asteroids = 0; 
        } 

        //Generating asteroid 
        asteroid[asteroids] = genAsteroid(1, -1); 

        asteroids++; 
        speed_counterC -= 60; 
       } 

       //If ship goes out top, it comes in bottom; vice versa 
       if (ship.y <= 0 - ((shipStopped->h/2))) { 
        ship.y += (600); 
       } 
       else if (ship.y >= 600 - ((shipStopped->h/2))) { 
        ship.y -= (600); 
       } 

       //If ship goes out left, it comes in right; vice versa 
       if (ship.x <= 0 - ((shipStopped->w/2))) { 
        ship.x += (800); 
       } 
       else if (ship.x >= 800 - ((shipStopped->w/2))) { 
        ship.x -= (800); 
       } 

       //Drawing lasers 
       for (i = 0; i < 50; i++) { 
        if (laser[i].onScreen) { 
         rotate_sprite(buffer, laserSprite, laser[i].pos.x, laser[i].pos.y, ftofix(laser[i].angle)); 
        } 
       } 

       //Drawing ship 
       if (key[KEY_UP] || key[KEY_DOWN] || key[KEY_LEFT] || key[KEY_RIGHT]) { 
        rotate_sprite(buffer, shipMoving, ship.x, ship.y, ftofix(angle)); //Ship sprite with engines firing 
       } 
       else { 
        rotate_sprite(buffer, shipStopped, ship.x, ship.y, ftofix(angle)); //Ship sprite no flames 

       } 

       //Drawing asteroids 
       for (i = 0; i < 10; i++) { 
        if (asteroid[i].onScreen == true) { 
         //Drawing sprite based on asteroid type 
         if (asteroid[i].type == 1) { //Large asteroid 
          draw_sprite(buffer, largeAsteroid, asteroid[i].pos.x, asteroid[i].pos.y); 
         } 
         else if (asteroid[i].type == 2) { //Medium asteroid 
          draw_sprite(buffer, medAsteroid, asteroid[i].pos.x, asteroid[i].pos.y); 
         } 
         else if (asteroid[i].type == 3) { //Small asteroid 
          draw_sprite(buffer, smallAsteroid, asteroid[i].pos.x, asteroid[i].pos.y); 
         } 
        } 
       } 

       //Checks bb collisions 
       for (i = 0; i < 50; i++) { 
        for (j = 0; j < 10; j++) { 
         if (laser[i].onScreen && asteroid[j].onScreen) { 
          collide = checkCollision(asteroid[j].type, 0, asteroid[j].pos, laser[i].pos); 
          if (collide) { 
           laser[i].onScreen = false; 
           asteroid[j].onScreen = false; 

           points += 100 * asteroid[j].type; 

           //Splitting med or large asteroids into 2 asteroids one type down 
           if (asteroid[j].type < 3) { 
            asteroid[asteroids] = splitAsteroid(1, asteroid[j]); 
            asteroid[j] = splitAsteroid(2, asteroid[j]); 
            asteroids++; 
           } 
          } 
         } 
        } 
       } 

       //Printing score 
       textprintf_ex(buffer, font, 10, 5, WHITE, -1, "Score: %d", points); 
       textprintf_ex(buffer, font, 660, 5, WHITE, -1, "Press esc to quit"); 

       // Blit the buffer 
       blit(buffer, screen, 0, 0, 0, 0, 800, 600); 
       clear(buffer); 

       for (i = 0; i < 10; i++) { 
        if (asteroid[i].onScreen) { 
         collide = checkCollision(asteroid[i].type, 1, asteroid[i].pos, ship); 

         if (collide) { 
          onScreen = changeScreen(51); 
         } 
        } 
       } 

       //To leave game screen and return to main menu 
       if (key[KEY_ESC]) { 
        onScreen = changeScreen(0); 
       } 
      } 
     } 
    } 

    //Freeing memory 
    destroy_bitmap(playButton); 
    destroy_bitmap(highsButton); 
    destroy_bitmap(creditsButton); 
    destroy_bitmap(quitButton); 
    destroy_bitmap(shipStopped); 
    destroy_bitmap(shipMoving); 
    destroy_bitmap(laserSprite); 
    destroy_bitmap(smallAsteroid); 
    destroy_bitmap(medAsteroid); 
    destroy_bitmap(largeAsteroid); 

    return 0; 
} 
END_OF_MAIN() 

Заголовок файл:

#ifndef ASTEROIDS_H_ 
#define ASTEROIDS_H_ 

#define WHITE makecol(255, 255, 255) 
#define BLACK makecol(0, 0, 0) 

#include <allegro.h> 
#include <alfont.h> 

//Made global so size pointers can be used throughout 
BITMAP *playButton; 
BITMAP *playAgainButton; 
BITMAP *highsButton; 
BITMAP *creditsButton; 
BITMAP *quitButton; 
BITMAP *menuButton; 
BITMAP *shipStopped; 
BITMAP *shipMoving; 
BITMAP *laserSprite; 
BITMAP *smallAsteroid; 
BITMAP *medAsteroid; 
BITMAP *largeAsteroid; 

//Highscore variables are made global; technically bad, 
//but makes simplifies printing greatly 
int score[10], numOfScores, points; 
char name[10][20]; 

struct Coordinate { 
    int x, y; 
}; 

struct Laser { 
    Coordinate pos; 
    float angle; 
    bool onScreen; 
}; 

struct Asteroid { 
    Coordinate pos; 
    int type; 
    int angle; 
    bool onScreen; 
}; 

int changeScreen(int toLoad); 
BITMAP* loadImage(const char image[20]); 
int getHighs(char name[][20], int high[]); 
void sortHighs(char name[][20], int score[]); 
void saveHighs(const char name[][20], const int score[], int numOfScores); 
Laser fireLaser(float angle, int ship_x, int ship_y); 
Laser moveLaser(Laser laser); 
Asteroid genAsteroid(int difficulty, int type); 
Asteroid splitAsteroid(int order, Asteroid asteroid); 
Asteroid moveAsteroid(Asteroid asteroid); 
bool checkCollision(int typeA, int typeB, Coordinate asteroid, Coordinate object); 

#endif 

Функция файл сводится к:

#include <allegro.h> 
#include <alfont.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include "asteroids.h" 
#include "asteroids_data.h" 

/*~500 lines of functions*/ 

Все работает, когда я просто поставил функцию ниже основной

Копия журнала компиляции:

g++.exe -c asteroidsMain.cpp -o asteroidsMain.o -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include/c++" -I"C:/Program Files (x86)/Dev-Cpp/include" -m32 
g++.exe asteroidsMain.o functions.o -o POPE_Greg_Asteroids.exe -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib32" -L"C:/Program Files (x86)/Dev-Cpp/lib" -lalfont -lalleg -m32 
functions.o:functions.cpp:(.bss+0x0): multiple definition of `playButton' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x0): first defined here 
functions.o:functions.cpp:(.bss+0x4): multiple definition of `playAgainButton' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x4): first defined here 
functions.o:functions.cpp:(.bss+0x8): multiple definition of `highsButton' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x8): first defined here 
functions.o:functions.cpp:(.bss+0xc): multiple definition of `creditsButton' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0xc): first defined here 
functions.o:functions.cpp:(.bss+0x10): multiple definition of `quitButton' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x10): first defined here 
functions.o:functions.cpp:(.bss+0x14): multiple definition of `menuButton' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x14): first defined here 
functions.o:functions.cpp:(.bss+0x18): multiple definition of `shipStopped' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x18): first defined here 
functions.o:functions.cpp:(.bss+0x1c): multiple definition of `shipMoving' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x1c): first defined here 
functions.o:functions.cpp:(.bss+0x20): multiple definition of `laserSprite' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x20): first defined here 
functions.o:functions.cpp:(.bss+0x24): multiple definition of `smallAsteroid' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x24): first defined here 
functions.o:functions.cpp:(.bss+0x28): multiple definition of `medAsteroid' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x28): first defined here 
functions.o:functions.cpp:(.bss+0x2c): multiple definition of `largeAsteroid' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x2c): first defined here 
functions.o:functions.cpp:(.bss+0x40): multiple definition of `score' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x40): first defined here 
functions.o:functions.cpp:(.bss+0x68): multiple definition of `numOfScores' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x68): first defined here 
functions.o:functions.cpp:(.bss+0x6c): multiple definition of `points' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x6c): first defined here 
functions.o:functions.cpp:(.bss+0x80): multiple definition of `name' 
asteroidsMain.o:asteroidsMain.cpp:(.bss+0x80): first defined here 
collect2.exe: error: ld returned 1 exit status 

C:\Users\Greg\Documents\Asteroids B\Makefile.win:25: recipe for target 'POPE_Greg_Asteroids.exe' failed 
mingw32-make.exe: *** [POPE_Greg_Asteroids.exe] Error 1 
+2

Это не проблема, но имена, содержащие два последовательных символа подчеркивания ('__ASTEROIDS_H_INCLUDED__') и имена, начинающиеся с символа подчеркивания, за которым следует заглавная буква, зарезервированы для использования реализацией. Не используйте их в своем коде. –

+0

Показать журнал сборки. Нам нужно увидеть хотя бы некоторые из точных сообщений об ошибках. В сообщениях будет четко указано, где и что такое несколько определений. Это, очевидно, жизненно важная информация для этого вопроса. – kaylum

+0

«Я получаю серию« множественных определений », впервые определенных здесь« ошибки »- вы ** читали ** сообщения об ошибках? Я никогда не видел компилятора, который дает такое сообщение об ошибке, не упоминая ** имена ** символов, которые многократно определены, и это большой ключ к решению этой проблемы. Ищите эти имена и ** удаляйте ** код, который не относится к ним, пока у вас не будет самой маленькой программы, с которой вы можете столкнуться, что показывает проблему. Вы можете просто понять, как исправить это самостоятельно. –

ответ

0

Добавить эти файлы в том же проекте.