2013-03-20 12 views
14

Trenowałem używać zorientowane obiektowo programowanie w C++, ale wciąż otrzymuję ten błąd:błąd krytyczny LNK1169: jeden lub więcej mnożyć zdefiniowane symbole występujące w programowaniu gier

1>main.obj : error LNK2005: "int WIDTH" ([email protected]@3HA) already defined in GameObject.obj 
1>main.obj : error LNK2005: "int HEIGHT" ([email protected]@3HA) already defined in GameObject.obj 
1>Spaceship.obj : error LNK2005: "int WIDTH" ([email protected]@3HA) already defined in GameObject.obj 
1>Spaceship.obj : error LNK2005: "int HEIGHT" ([email protected]@3HA) already defined in GameObject.obj 
1>C:\Users\ted\documents\visual studio 2010\Projects\fullSpace\Debug\fullSpace.exe : fatal error LNK1169: one or more multiply defined symbols found 

Jednak mnie wydaje się, że cały kod jest napisany poprawnie, a dwa int są wymienione tylko w nagłówku Global i wszystkie obiekty wydają się odpowiednio dziedziczyć. Jednak, jak powiedziałem, jestem początkującym w OOP, więc naprawdę potrzebuję opinii: Warto również wspomnieć, że używam allegro 5 do stworzenia side shootera.

ten kod:

(główny):

#include <allegro5/allegro.h> 
#include <allegro5/allegro_image.h> 
#include <allegro5/allegro_primitives.h> 
#include <allegro5/allegro_font.h> 
#include <allegro5\allegro_ttf.h> 
#include <allegro5\allegro_audio.h> 
#include <allegro5\allegro_acodec.h> 

#include <list> 


#include "GameObject.h" 
#include "Spaceship.h" 
#include "Globals.h" 



//controls 

bool keys[] = {false, false, false, false, false}; 
enum KEYS{UP, DOWN, LEFT, RIGHT, SPACE}; 

//globals 
Spaceship *ship; 

std::list <GameObject *> objects; 
std::list <GameObject *>::iterator iter; 
std::list <GameObject *>::iterator iter2; 



//prototypes 



//main function 
int main(int argc, char **argv) 
{ 
    //shell variables 
    bool done = false; 
    bool render = false; 

    float gameTime = 0; 
    int frames = 0; 
    int gameFPS = 0; 

    //project variables 

    ship = new Spaceship(); 


    ALLEGRO_BITMAP *shipImage = NULL; 
    ALLEGRO_BITMAP *cometImage= NULL; 
    ALLEGRO_BITMAP *explImage = NULL; 
    ALLEGRO_BITMAP *bgImage = NULL; 
    ALLEGRO_BITMAP *mgImage = NULL; 
    ALLEGRO_BITMAP *plImage = NULL; 
    ALLEGRO_BITMAP *mgImage2 = NULL; 
    ALLEGRO_BITMAP *fgImage = NULL; 
    ALLEGRO_BITMAP *titleImage= NULL; 
    ALLEGRO_BITMAP *lostImage = NULL; 


    //allegro variables 
    ALLEGRO_DISPLAY *display = NULL; 
    ALLEGRO_EVENT_QUEUE *event_queue = NULL; 
    ALLEGRO_TIMER *timer; 
    ALLEGRO_FONT *font18; 



    //initiate variables 
    if(!al_init()) 
     return -1; 

    display = al_create_display(WIDTH, HEIGHT); 
    if(!display) 
    return -1; 

    //addon installation 

    al_install_keyboard(); 
    al_init_image_addon(); 
    al_init_font_addon(); 
    al_init_ttf_addon(); 
    al_init_primitives_addon(); 
    al_install_audio(); 
    al_init_acodec_addon(); 

    //project init 

    font18 = al_load_font("arial.ttf", 18, 0); 
    al_reserve_samples(15); 




    bgImage = al_load_bitmap("layer1.png"); 
    mgImage = al_load_bitmap("layer2.png"); 
    plImage = al_load_bitmap("starMG.png"); 
    mgImage2 = al_load_bitmap("layer3.png"); 
    fgImage = al_load_bitmap("layer4.png"); 




    shipImage = al_load_bitmap("spaceship.png"); 
    al_convert_mask_to_alpha(shipImage, al_map_rgb(255, 0, 255)); 



    cometImage = al_load_bitmap("asteroid-1-96.png"); 
    explImage = al_load_bitmap("explosion_3_40_128.png"); 

    titleImage = al_load_bitmap("Shooter_Title.png"); 
    lostImage = al_load_bitmap("Shooter_Lose.png"); 



    //object init 
    ship->init(shipImage); 


    //iter list 
    objects.push_back(ship); 


    srand(time(NULL)); 

    //timer init and startup 

    event_queue = al_create_event_queue(); 
    timer = al_create_timer(1.0/60); 

    al_register_event_source(event_queue, al_get_timer_event_source(timer)); 
    al_register_event_source(event_queue, al_get_keyboard_event_source()); 

    al_start_timer(timer); 
    gameTime = al_current_time(); 

    while(!done) 
    { 
     ALLEGRO_EVENT ev; 
     al_wait_for_event(event_queue, &ev); 

     //input 
     if(ev.type == ALLEGRO_EVENT_KEY_DOWN) 
     { 
      switch(ev.keyboard.keycode) 
      { 
      case ALLEGRO_KEY_ESCAPE: 
       done = true; 
       break; 
      case ALLEGRO_KEY_LEFT: 
       keys[LEFT] = true; 
       break; 
      case ALLEGRO_KEY_RIGHT: 
       keys[RIGHT] = true; 
       break; 
      case ALLEGRO_KEY_UP: 
       keys[UP] = true; 
       break; 
      case ALLEGRO_KEY_DOWN: 
       keys[DOWN] = true; 
       break; 
      case ALLEGRO_KEY_SPACE: 
       keys[SPACE] = true; 
       break; 


      } 
     } else if(ev.type == ALLEGRO_EVENT_KEY_UP) 
     { 
      switch(ev.keyboard.keycode) 
      { 
      case ALLEGRO_KEY_ESCAPE: 
       done = true; 
       break; 
      case ALLEGRO_KEY_LEFT: 
       keys[LEFT] = false; 
       break; 
      case ALLEGRO_KEY_RIGHT: 
       keys[RIGHT] = false; 
       break; 
      case ALLEGRO_KEY_UP: 
       keys[UP] = false; 
       break; 
      case ALLEGRO_KEY_DOWN: 
       keys[DOWN] = false; 
       break; 
      case ALLEGRO_KEY_SPACE: 
       keys[SPACE] = false; 
       break; 
      } 
     } 



     else if (ev.type == ALLEGRO_EVENT_TIMER) 
     { 
      render = true; 

      //fps 
      frames++; 
      if(al_current_time() - gameTime >= 1) 
      { 
       gameTime = al_current_time(); 
       gameFPS = frames; 
       frames = 0; 
      } 

      //shipUpdate 

      if(keys[UP]) 
       ship ->moveUp(); 
      else if(keys[DOWN]) 
       ship ->moveDown(); 
      else 
       ship->resetAnim(1); 

      if(keys[LEFT]) 
       ship ->moveLeft(); 
      else if(keys[RIGHT]) 
       ship -> moveRight(); 
      else 
       ship ->resetAnim(0); 

     } 
     //render 

      if(render && al_is_event_queue_empty(event_queue)) 
      { 
       render = false; 

       //begin render 
       for(iter = objects.begin(); iter != objects.end(); ++iter) 
        (*iter)->render(); 




       //Flip Buffers 
       al_flip_display(); 
       al_clear_to_color(al_map_rgb(0,0,0)); 
      } 
     } 

       //destroy objects 



     //visual objects 
    al_destroy_bitmap(cometImage); 
    for(iter = objects.begin(); iter != objects.end(); ++iter) 
     (*iter)->destroy(shipImage); 
     iter = objects.erase(iter); 

    al_destroy_bitmap(explImage); 
    al_destroy_bitmap(bgImage); 
    al_destroy_bitmap(mgImage); 
    al_destroy_bitmap(fgImage); 
    al_destroy_bitmap(titleImage); 
    al_destroy_bitmap(lostImage); 

     //audio objects 
    /* 
    al_destroy_sample(shot); 
    al_destroy_sample(boom); 
    al_destroy_sample(song); 
    al_destroy_sample_instance(songInstance); 
    */ 


     //shell objects 
    al_destroy_font(font18); 
    al_destroy_timer(timer); 
    al_destroy_event_queue(event_queue); 
    al_destroy_display(display); 

    return 0; 
} 

(Globals.h)

#pragma once 

int WIDTH = 1024; 
int HEIGHT = 800; 

enum ID{PLAYER, ENEMY, BULLET, BORDER, MISC}; 
enum STATES{TITLE, PLAYING, LOST}; 

(GameObject.h)

#pragma once 


#include "Globals.h" 
#include <iostream> 

#include <allegro5/allegro5.h> 

#include <allegro5/allegro_primitives.h> 



class GameObject 
{ 
private: 
    int ID; 
    bool alive; 
    bool collidable; 

protected: 
    float x; 
    float y; 

    float velX; 
    float velY; 

    int dirX; 
    int dirY; 

    int boundX; 
    int boundY; 

    int maxFrame; 
    int curFrame; 
    int frameCount; 
    int frameDelay; 
    int frameWidth; 
    int frameHeight; 
    int animationColumns; 
    int animationDirection; 

    ALLEGRO_BITMAP *image; 

public: 
    GameObject(); 
    void virtual destroy(ALLEGRO_BITMAP *image); 

    void init(float x, float y, float velX, float velY, int dirX, int dirY, int boundX, int boundY); 
    void virtual update(); 
    void virtual render(); 

    float getX() {return x;} 
    float getY() {return y;} 

    void setX(float x) {GameObject::x = x;} 
    void setY(float y) {GameObject::y = y;} 

    int getBoundX() {return boundX;} 
    int getBoundY() {return boundY;} 

    int getID() {return ID;} 
    void setID(int ID) {GameObject::ID = ID;} 

    bool getAlive() {return alive;} 
    void setAlive(bool alive) {GameObject::alive = alive;} 

    bool getCollidable() {return collidable;} 
    void setCollidable(bool collidable) {GameObject::collidable = collidable;} 

    bool checkCollisions(GameObject *otherObject); 
    void virtual collided(int objectID); 
    bool collidableCheck(); 
}; 

(GameObject.cpp):

#include "GameObject.h" 

GameObject::GameObject() 
{ 
    x = 0; 
    y = 0; 

    velX = 0; 
    velY = 0; 

    dirX = 0; 
    dirY = 0; 

    boundX = 0; 
    boundY = 0; 

    maxFrame = 0; 
    curFrame = 0; 
    frameCount = 0; 
    frameDelay = 0; 
    frameWidth = 0; 
    frameHeight = 0; 
    animationColumns = 0; 
    animationDirection = 0; 

    image = NULL; 

    alive = true; 
    collidable = true; 

} 

void GameObject::destroy(ALLEGRO_BITMAP *image) 
{ 
    if(image != NULL) 
     al_destroy_bitmap(image); 

} 
void GameObject::init(float x, float y, float velX, float velY, int dirX, int dirY, int boundX, int boundY) 
{ 
    GameObject::x = x; 
    GameObject::y = y; 

    GameObject::velX = velX; 
    GameObject::velY = velY; 

    GameObject::dirX = dirX; 
    GameObject::dirY = dirY; 

    GameObject::boundX = boundX; 
    GameObject::boundY = boundY; 

} 

void GameObject::update() 
{ 
    x += velX*dirX; 
    y += velY*dirY; 
} 

void GameObject::render() 
{ 

} 

bool GameObject::checkCollisions(GameObject *otherObject) 
{ 
    float oX = otherObject->getX(); 
    float oY = otherObject->getY(); 

    int obX = otherObject->getBoundX(); 
    int obY = otherObject->getBoundY(); 

    if(x + boundX > oX - obX && 
     x - boundX < oX + obX && 
     y + boundY > oY - obY && 
     y - boundY < oY + obY 
     ) 
     return true; 
    else 
     return false; 
} 

void GameObject::collided(int objectID) 
{ 

} 
bool GameObject::collidableCheck() 
{ 
    return alive && collidable; 
} 

(SpaceShip.h):

#pragma once 

#include "GameObject.h" 

class Spaceship : public GameObject 
{ 
private : 
    int lives; 
    int score; 
    int animationRow; 

public : 
    Spaceship(); 

    void destroy(ALLEGRO_BITMAP *image); 

    void init(ALLEGRO_BITMAP *image = NULL); 

    void update(); 
    void render(); 

    void moveUp(); 
    void moveDown(); 
    void moveLeft(); 
    void moveRight(); 

    void resetAnim(int pos); 

    int getLives(){return lives;} 

    int getScore() {return score;} 

    void looseLife() {lives--;} 
    void addPoint() {score++;} 

    void collide(int objectID); 



}; 

(SpaceShip.cpp):

#include "Spaceship.h" 

    Spaceship::Spaceship() 
    {} 

    void Spaceship::destroy(ALLEGRO_BITMAP *image) 
    { 
     GameObject::destroy(image); 
    } 
    void Spaceship::init(ALLEGRO_BITMAP *image) 
    { 
     GameObject::init(20, 200, 6, 6, 0, 0, 10, 12); 

     setID(PLAYER); 
     setAlive(true); 

     lives = 3; 
     score = 0; 

     maxFrame = 3; 
     curFrame = 0; 
     frameWidth = 46; 
     frameHeight = 41; 
     animationColumns = 3; 
     animationDirection = 1; 

     animationRow = 1; 

     if(image != NULL) 
     { 
      Spaceship::image = image; 
     } 
    } 

    void Spaceship::update() 
    { 
     GameObject::update(); 
     if(x < 0) 
      x=0; 
     else if (x > WIDTH) 
      x = WIDTH; 
     if(y < 0) 
      y = 0; 
     else if (y > HEIGHT) 
      y = HEIGHT; 
    } 
    void Spaceship::render() 
    { 
     GameObject::render(); 

     int fx = (curFrame % animationColumns) *frameWidth; 
     int fy = animationRow *frameHeight; 

     al_draw_bitmap_region(image, fx, fy, frameWidth, frameHeight, 
      x - frameWidth /2, y - frameHeight /2, 0); 

    } 

    void Spaceship::moveUp() 
    { 
     animationRow = 0; 
     dirY = -1; 

    } 
    void Spaceship::moveDown() 
    { 
     animationRow = 2; 
     dirY = 1; 
    } 
    void Spaceship::moveLeft() 
    { 
     curFrame = 2; 
     dirX = -1; 
    } 
    void Spaceship::moveRight() 
    { 
     curFrame = 1; 
     dirX = 1; 
    } 

    void Spaceship::resetAnim(int pos) 
    { 
     if(pos == 1) 
     { 
      animationRow = 1; 
      dirY = 0; 
     } 
     else 
     { 
      curFrame = 0; 
      dirX = 0; 
     } 
    } 

    void Spaceship::collide(int objectID) 
    { 
     if(objectID == ENEMY) 
      lives--; 

    } 
+0

możliwe duplikat [Błąd LNK1169 na globalnym const char \ *] (http://stackoverflow.com/questions/13772206/error-lnk1169-on-global-const-char) –

Odpowiedz

40

Dwa int zmienne są zdefiniowanew pliku nagłówka. Oznacza to, że każdy plik źródłowy zawierający nagłówek będzie zawierał definicję (uwzględnienie nagłówka jest czysto tekstowe). Oczywiście prowadzi to do błędów wielu definicji.

Masz kilka opcji, aby to naprawić.

  1. Bądź zmienne static (static int WIDTH = 1024;). Będą nadal istnieć w każdym pliku źródłowym, ale ich definicje nie będą widoczne poza plikiem źródłowym.

  2. kolei ich definicje w deklaracji za pomocą extern (extern int WIDTH;) i umieścić definicję w jeden pliku źródłowego: int WIDTH = 1024;.

  3. Prawdopodobnie najlepsza opcja: dokonaj zmiennych const (const int WIDTH = 1024;). To czyni je static niejawnie, a także pozwala na ich stosowanie jako stałe w czasie kompilacji, dzięki czemu kompilator do korzystania z ich wartości bezpośrednio zamiast kodu wydawanie go odczytać z zmienna itd

+3

+1 za udzielenie wielu rozwiązań. –

+0

Dziękuję bardzo, ale teraz mam nowy błąd, ciągle otrzymuję "fullSpace.exe": Załadowany "C: \ Windows \ SysWOW64 \ dwmapi.dll", Nie można znaleźć lub otworzyć pliku PDB dla setek. Dll, może ponownie pomagasz? – Ted

+0

@ user2189708 To jest inne pytanie. Najpierw wyszukaj. –

5

nie można umieścić definicje zmiennych w plikach nagłówkowych, gdyż będzie wtedy częścią ze wszystkich plików źródłowych do nagłówka.

Ma na celu ochronę przed wieloma włączeniami w tym samym pliku źródłowym, a nie przed wieloma włączeniami w wielu plikach źródłowych.

Można zadeklarować zmienne jak extern w pliku nagłówka, a następnie określić je w jednym pliku źródłowym. Lub można zadeklarować zmienne jako const w pliku nagłówkowym, a następnie kompilator i linker będzie nim zarządzać.

0
const int WIDTH = 1024; 
const int HEIGHT = 800; 
+1

Tak, to jest problem, ale dlaczego? –

+0

spróbuj wyszukać "jedną regułę definicji" – AnatolyS

+0

naprawiono., Działa., Dziękuję – Ted