2013-03-20 3 views
14

Я тренировался использовать объектно-ориентированное программирование на C++, но я получаю эту ошибку:фатальные LNK1169 ошибки: один или несколько умножить определенные символы, найденных в программировании игр

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 

Однако мне кажется, что весь код написан правильно, и два ints упоминаются только в заголовке Global, и все объекты, похоже, правильно наследуются. Однако, как я только что сказал, я новичок в ООП, поэтому мне действительно нужно мнение: Также стоит упомянуть, что я использую allegro 5 для создания побочного шутера.

Это код:

(основной):

#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

возможно дубликат [ошибка LNK1169 на глобальном const char \ *] (http://stackoverflow.com/questions/13772206/error-lnk1169-on-global-const-char) –

ответ

40

Две int переменные определены в файле заголовка. Это означает, что каждый исходный файл, включающий заголовок, будет содержать свое определение (включение заголовка чисто текстовое). Разумеется, это приводит к многочисленным ошибкам определения.

У вас есть несколько вариантов исправить это.

  1. Сделать переменные static (static int WIDTH = 1024;). Они все равно будут существовать в каждом исходном файле, но их определения не будут видны вне исходного файла.

  2. Превратите свои определения в декларациях, используя extern (extern int WIDTH;) и поместить определение в один исходный файл: int WIDTH = 1024;.

  3. Возможно, лучший вариант: сделать переменные const (const int WIDTH = 1024;). Это делает их static неявно, а также позволяет использовать их в качестве константы времени компиляции, что позволяет компилятору использовать их значение непосредственно вместо выдачи кода, чтобы прочитать его с переменной и т.д.

+3

+1 за предоставление нескольких решений. –

+0

Большое спасибо, но теперь у меня есть новая ошибка, я продолжаю получать «fullSpace.exe»: загружен «C: \ Windows \ SysWOW64 \ dwmapi.dll», не удается найти или открыть файл PDB для сотен DLL. вы снова поможете? – Ted

+0

@ user2189708 Это другой вопрос. Сначала выполните поиск. –

5

Вы не можете поместить определения переменных в файлах заголовков, так как это будет являться частью из всего исходного файла вы включаете заголовок.

#pragma once предназначен для защиты от нескольких включений в одном исходном файле, а не от нескольких включений в нескольких исходных файлах.

Вы можете объявить переменные как extern в файле заголовка, а затем определить их в одном исходном файле. Или вы можете объявить переменные как const в файле заголовка, а затем компилятор и компоновщик будут управлять им.

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

Да, это проблема, но почему? –

+0

попытайтесь найти «одно правило определения» – AnatolyS

+0

исправлено., Он работает., Спасибо – Ted

 Смежные вопросы

  • Нет связанных вопросов^_^