2014-03-06 46 views
4

我想使用SFML庫在C++中圍繞屏幕移動一個字符。 每次做一個項目我都會得到相同的LNK 2001錯誤。LNK 2001未解決C++ SFML

請向我解釋我做錯了什麼,如何解決它。我仍然是初學者,所以如果你有任何關於修復錯誤或編寫代碼的建議,我很樂意。

Main.cpp的:

#include "Game.cpp" 
#include "Game.h" 

int main() 
{ 
    Game Game; 

    Game.GameRun(); 
} 

Game.h:

#pragma once 

#include <SFML\Window.hpp> 
#include "Character.h" 

class Game 
{ 
public: 
    void GameRun(); 
    void UpdateGame(Character player); 
    void Controls(int sourceX, int sourceY, Character player); 
}; 

Character.h:

#pragma once 

#include <SFML\Graphics.hpp> 
#include <SFML\System.hpp> 
#include <SFML\Window.hpp> 
#include "Game.h" 

class Character 
{ 
public: 
    enum Direction {Down, Left, Right, Up}; 

    int characterX; 
    int characterY; 

    sf::Texture txt_character; 
    sf::Sprite spr_character; 
}; 

Game.cpp:

#include "Game.h" 
#include "Character.h" 

#include <iostream> 

inline void Game::GameRun() 
{ 
    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML test"); 

    Character player; 

    player.characterX = 1; 
    player.characterY = Character::Down; 

    player.txt_character.loadFromFile("character sprite sheet.png"); 
    player.spr_character.setTexture(player.txt_character); 

    while(window.isOpen()) 
    { 
     Game::UpdateGame(player); 
    } 
} 

inline void Game::UpdateGame(Character player) 
{ 
    sf::Event event; 
    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML test"); 

    while (window.pollEvent(event)) 
    { 
     if (event.type == sf::Event::Closed) 
     window.close(); 
    } 
    Game::Controls(player.characterX, player.characterY, player); 

    player.spr_character.setTextureRect(sf::IntRect(player.characterX * 32, player.characterY * 32, 32, 32)); 

    window.draw(player.spr_character); 
    window.display(); 
    window.clear(); 
} 

inline void Game::Controls(int sourceX, int sourceY, Character player) 
{ 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) 
    { 
     sourceY = Character::Up; 
     sourceX++; 
     if (sourceX * 32 >= player.txt_character.getSize().x) 
      sourceX = 0; 
     player.spr_character.move(0, -2); 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) 
    { 
     sourceY = Character::Down; 
     sourceX++; 
     if (sourceX * 32 >= player.txt_character.getSize().x) 
      sourceX = 0; 
     player.spr_character.move(0, 2); 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) 
    { 
     sourceY = Character::Left; 
     sourceX++; 
     if (sourceX * 32 >= player.txt_character.getSize().x) 
      sourceX = 0; 
     player.spr_character.move(-2, 0); 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) 
    { 
     sourceY = Character::Right; 
     sourceX++; 
     if (sourceX * 32 >= player.txt_character.getSize().x) 
      sourceX = 0; 
     player.spr_character.move(2, 0); 
    } 
} 

錯誤:

1> main.obj:錯誤LNK2001:解析外部符號? 「市民:靜態INT字:: characterY」(characterY @字符@@ 2HA)

1> main.obj:錯誤LNK2001:解析外部符號? 「公共:靜態INT字符:: characterX」(characterX @字符@@ 2HA)

1> C:\用戶\ SONY \ Documents \ Visual Studio 2010 \ Pr ojects \自上而下游戲\調試\下的Game.exe:致命錯誤LNK1120:2周無法解析的外部

感謝:d

編輯:FYI我有沒有類的代碼,它是可以正常使用,這只是一個大在main.cpp中

編輯的代碼塊:鏈接到文件夾的程序:https://www.dropbox.com/s/3yyjti8zwu019s7/Top%20Down%20Game%20With%20Classes.rar

+0

什麼被賦予了錯誤? LNK 2001意味着未解決的符號,它應該給你的那個符號的名字。 –

+3

您正在#main.cpp中包含'Game.cpp'。不要這樣做! – 2014-03-06 21:42:36

+1

您的'Character'類與這些錯誤不匹配。錯誤表示它們被聲明爲「靜態」,但是你的代碼另有說明。 –

回答

2

編輯2014年3月8日:我想你的來源。刪除Main.cpp文件中的#include "Game.cpp"Game.cpp文件中的inline關鍵字。

背後的邏輯無法正常工作,所以我將其固定爲最小值,以便在修正編譯(鏈接)錯誤後立即生效。你應該嘗試我的代碼,看看它是否有用。

一點解釋第一

通過傳遞值的選手對象(當你有void someMethod(Character player)如)發送對象的副本的方法。所以當你對玩家對象進行更改時,這些更改僅針對副本而不是實際玩家。我改變了你的代碼,所以它發送了一個指針(void someMethod(Character * player)。該方法接收到一個指向實際播放器對象的指針,並且對該對象所作的更改反映在實際播放器對象上。 (有些人可能會說這是過度殺毒或太危險)。

這可能是代替:

  • 參考void someMethod(Character& player)
  • 或返回值Character someMethod(Character player)
  • 或兩個Character someMethod(const Character& player)
  • 混合或一個成員變量(在頭文件中定義)

另一件事是你保持sf :: Texture值你的角色類。 sf :: Texture實際上是「沉重的」對象,所以它們不應該被值傳遞並且應該保持爲指針。你可以做的最好的事情(並且我沒有在你的代碼中完成)是從Character類中完全移除sf :: Texture,並且只保留已經擁有sf :: Texture的sf :: Sprite(in一個優化的方式,所以你不打擾它)。

下面的代碼

Main.cpp的

#include "Game.h" 

int main() 
{ 
    Game Game; 

    Game.GameRun(); 
} 

Game.h

#ifndef GAME_H_ 
#define GAME_H_ 

//#include <SFML/Window.hpp> /* you don't need this */ 
#include <SFML/Graphics/RenderWindow.hpp> 


// forward declaration, this prevents recursive/circular dependencies. 
// only works with pointer or referenced type. 
class Character; 

class Game 
{ 
public: 
    void GameRun(); 

    // I change the param to pointer to Character for logic reasons. 
    // You were doing changes on a Character COPY of the player, 
    // which was deleted when leaving the scope of the functions. 
    void UpdateGame(Character * player); 
    void Controls(Character * player); 
private: 
    // I added this here, so you can create the window in the 
    // GameRun and UpdateGame methods where needed. 
    sf::RenderWindow window; 
}; 

#endif 

Game.cpp

#include "Game.h" 
#include "Character.h" 

#include <SFML/Window/Event.hpp> /* you only need this */ 

#include <iostream> 

void Game::GameRun() 
{ 
    // I moved the window creation here because you were 
    // creating a new window each update which made the windows 
    // flickers each frame, making it impossible to close properly. 
    window.create(sf::VideoMode(800, 600), "SFML test"); 

    Character * player = new Character(); 

    player->characterX = 1; 
    player->characterY = Character::Down; 

    // if the file isn't available, this will prevent further problems. 
    if (player->txt_character.loadFromFile("character.png")) 
    { 
     player->spr_character.setTexture(player->txt_character); 
    } 

    while (window.isOpen()) 
    { 
     Game::UpdateGame(player); 
    } 
} 

void Game::UpdateGame(Character * player) 
{ 
    sf::Event event; 


    while (window.pollEvent(event)) 
    { 
     if (event.type == sf::Event::Closed){ 

      window.close(); 

     } 
    } 
    Controls(player); 

// player.spr_character.setTextureRect(
//   sf::IntRect(player.characterX * 32, player.characterY * 32, 32, 
//     32)); 

    window.clear(); 
    window.draw(player->spr_character); 
    window.display(); 

} 

// You were already sending the player so I removed the other 
// params and used the player instead. 
void Game::Controls(Character * player) 
{ 
    int sourceX = player->characterX; 

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) 
    { 
     player->characterY = Character::Up; 
     sourceX++; 
     if (sourceX * 32 >= player->txt_character.getSize().x) 
      sourceX = 0; 
     player->spr_character.move(0, -2); 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) 
    { 
     player->characterY = Character::Down; 
     sourceX++; 
     if (sourceX * 32 >= player->txt_character.getSize().x) 
      sourceX = 0; 
     player->spr_character.move(0, 2); 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) 
    { 
     player->characterY = Character::Left; 
     sourceX++; 
     if (sourceX * 32 >= player->txt_character.getSize().x) 
      sourceX = 0; 
     player->spr_character.move(-2, 0); 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) 
    { 
     player->characterY = Character::Right; 
     sourceX++; 
     if (sourceX * 32 >= player->txt_character.getSize().x) 
      sourceX = 0; 
     player->spr_character.move(2, 0); 
    } 
    player->characterX = sourceX; 
} 

Character.h

#ifndef CHARACTER_H_ 
#define CHARACTER_H_ 

//#include <SFML\Graphics.hpp> 
//#include <SFML\System.hpp> 
//#include <SFML\Window.hpp> 
//#include "Game.h" 
#include <SFML/Graphics/Sprite.hpp> /* Don't include more than you need */ 
#include <SFML/Graphics/Texture.hpp> 

class Character 
{ 
public: 
    enum Direction {Down, Left, Right, Up}; 

    int characterX; 
    int characterY; 

    sf::Texture txt_character; // Don't keep the texture value, it's really heavy. 
    sf::Sprite spr_character; 
}; 

#endif 

一般C++信息

+1

嘿,我得到了同樣的錯誤,實際上我得到了一個額外的錯誤:錯誤LNK2005:「public:void __thiscall Game :: GameRun(void)」(GameRun @ Game @@ QAEXXZ)已經在Game.obj中定義了,你也可以更簡單地解釋你做了什麼?畢竟是一個初學者:D – mkdewidar

+0

對於錯誤,你有「包含在項目中」的源文件嗎?我認爲當您不包含這些文件時,MS Visual Studio可能會抱怨。 (要添加它們,請在解決方案資源管理器中右鍵單擊它們,如果它們完全不存在,請單擊解決方案資源管理器中的「顯示所有文件」按鈕)。對於額外的解釋,我會嘗試更新我的答案。 –

+1

我沒有點擊顯示所有,並意識到精靈表沒有「包含在項目中」。錯誤仍然存​​在,但...由於某些原因,將函數更改爲在game.cpp中內聯會導致「已定義」錯誤消失。 – mkdewidar