2015-01-01 72 views
0

我正在編寫街機遊戲pong,以便在大學介紹C++項目。遊戲有一種遊戲者練習模式,在這種模式下,球只是從屏幕的另一側反彈,而雙人模式則使用w和s鍵來進行球員1的槳運動,上下鍵則用於球員2的運動。我原本是在一堂課中編寫遊戲,但經過與我的講師的諮詢後,他建議使用三個班來構建遊戲,以獲得額外的價值。從基類創建派生類的實例(使用FLTK構建GUI的C++)

Fl_Window 
^ 
| 
Game Interface 
^   ^
|   | 
One Player Two Player 

我的講師發給我的圖可以在上面看到。

我有一個遊戲界面類,其中包含兩種遊戲模式(例如畫球,屏幕頂部和底部的碰撞以及移動玩家1的槳)共用的方法,以及兩個其他類的一個玩家和兩個玩家包含特定於該模式的方法(例如,移動播放器2的槳板,評分系統和繪圖播放器2的槳板)的模式。

最初,我創建了一個遊戲界面類的實例,並運行了一個初始化遊戲菜單功能,該功能創建了一個可選擇遊戲模式的菜單。當選擇任一模式時,遊戲接口類中的一個功能將擦除菜單窗口小部件,繪製玩家1的球拍,抽出球並以恆定速度隨機發送球。

我希望發生的事情是創建正確的遊戲模式類的實例,並從該類內運行另一個特定的初始化函數(一個玩家或兩個玩家)。

我也希望能夠從任何遊戲模式返回主菜單並能夠選擇其他模式。

這是我第一次使用C++大型項目,因此原諒我對整體概念理解不足!

如何以及在哪裏創建特定遊戲模式類的這些實例?在基本的遊戲界面類或主?

我intialise遊戲菜單是這樣的:

//Main Function 
int main() 
{ 
GameInterface MyInterface(GameInterface::WindowSizeX, 
GameInterface::WindowSizeY, "PONG"); 
MyInterface . InitialiseMenu();                

return Fl::run();                   
} 

它運行功能:

void GameInterface :: InitialiseMenu() 
{ 
begin(); 

MenuTitle = new Fl_Box (400, 50, 100, 50, "Welcome to PONG"); 
MenuTitle -> labelcolor (FL_WHITE); 
MenuTitle -> labelsize (MenuTitleTextSize); 
MenuTitle -> box (FL_NO_BOX); 
MenuTitle -> show(); 

TwoPlayerMode = new Fl_Button (400, 300, 150, 50, "Two Player Mode"); 
TwoPlayerMode -> callback(TwoPlayerMode_cb, this); 
TwoPlayerMode -> show(); 

show(); 
} 

(注:我目前只是試圖獲得2個球員類與合作遊戲界面,然後我嘗試並獲得所有三個類的工作)

使用的回調函數是:

//Define two player mode button call back function 
void GameInterface :: TwoPlayerMode_cb(Fl_Widget* w,void* data) 
{ 
((GameInterface*) data) -> TwoPlayerMode_cb_i(w); 
} 

void GameInterface :: TwoPlayerMode_cb_i(Fl_Widget* w) 
{ 
TwoPlayerMode -> hide(); 
MenuTitle -> hide(); 
InitialiseGameObjects(); 

} 

的INITIALISE遊戲對象的功能是:

//Define initialise game objects 
void GameInterface :: InitialiseGameObjects() 
{ 
Fl::add_timeout(0.01, GameInterfaceUpdate_cb, this); 

begin(); 

Ball = new Fl_Box (400, 300, 10, 10); 
Ball -> box(FL_FLAT_BOX); 
Ball -> color (FL_WHITE); 
Ball -> show();  

Player1Paddle = new Fl_Box(0, 300, PaddleSizeX, PaddleSizeY); 
Player1Paddle -> box(FL_FLAT_BOX); 
Player1Paddle -> color(FL_WHITE); 
Player1Paddle -> show(); 

InitialBallDirectionGenerator(); 

BallVelocityX = InitialBallDirectionX * InitialBallSpeed; 


BallVelocityY = InitialBallDirectionY * InitialBallSpeed; 

//TwoPlayerModeInitialise_i(); 

end(); 

} 

在那裏它讀取// TwoPlayerModeInitialise_i點();我希望運行兩個玩家類中包含的方法,以初始化兩個玩家遊戲模式所需的其他對象,函數等。我認爲我需要在這一點上創建這個類的實例?然後,我希望來自這兩個班級的方法來控制遊戲(例如,玩家1的槳板運動來自遊戲界面課程,並且玩家2的槳板運動來自兩個玩家模式類別)。

我的班是由這樣的:

//Game Interface Class 
class GameInterface : public Fl_Window 
{ 
//Defining Public Members 
public:             
GameInterface(int width, int height, const char* title=0) : Fl_Window(width, height, title)  
{ 
color(FL_BLACK);                   
show();                     
} 
... 
}; 

&

class TwoPlayerMode : public GameInterface 
{ 
... 
}; 

任何幫助將不勝感激,因爲我真的被困在下一步去哪裏! 謝謝。

回答

0

我建議將公共函數GameInterface getBaseClass() { return *this; }添加到GameInterface中,然後當它在子類的實例上調用時,它應該返回主基類。

然後,你可以做一個構造函數在一個或兩個球員,需要一個GameInterface併發送了一行:

OnePlayer(GameInterface base) : GameInterface(base) { 
    //here you could call any additional init functions 
} 

編輯:當我測試它的作品的一個抽象的例子

class Base { 
protected: 
    int x; 

public: 
    Base(int x) : x(x) {} 
    Base getBaseClass() { return *this; } 
    virtual int getX() { 
     return x + 1; 
    } 
}; 

class Derived : public Base { 
public: 
    Derived(Base b) : Base(b) {} 

    Base getBaseClass() { 

    } 

    int getX() { 
     return x; 
    } 
}; 

int main() { 
    Base t(6); 
    Derived d(t); 
    std::cout << d.getX() << '\n'; //6 

    Base y = d.getBaseClass(); 
    std::cout << y.getX() << '\n'; //7 
} 
+0

感謝您的幫助,但我還是不明白以下幾點: 1)爲了使用它的方法,我必須創建一個類的實例嗎? 2)如果是這樣,我將如何以及在哪裏爲子類創建此實例? –

+0

1.如果它們是靜態的,它們可以在沒有實例的情況下運行,但這些不是。請注意,構造函數是一個異常,因爲它返回新的對象。 2.當你想要轉換時,子類將被做出,因爲他們做出了選擇。以玩家1爲例,它將是OnePlayer gamedata(gameinterface); – Eadword

+0

我試圖按照你的建議創建子類的實例,但是我看起來根本無法調用它的方法,爲什麼有這樣的困難從派生的基類中創建派生類的實例從Fl_Window? –

0

您應該設計遊戲模式,以便初始化陣列中的玩家。在單人模式下,陣列中只有一個Player對象。在雙人遊戲模式下,它有2個。這樣,兩個類中的許多功能可以相同。

任何想要在派生類中重寫的函數都應該在基類中聲明爲虛擬的,以允許它是多態的。記得在基類中聲明析構函數也是虛擬的!

您應該使用一個指向GameInterface對象,因爲指針是多態的,然後可以爲遊戲模式......

// create a pointer to a GameInterface object 
GameInterface *game; 

// start one player mode 
game = new OnePlayer(); 
game->run(); 

// before you change the game mode delete the current game 
delete game; 

// start two player mode 
game = new TwoPlayer(); 
game->run(); 

你可以在菜單中創建一個圍繞一流的包裝,如果你不想在主體中有任何代碼。然後,只需創建主菜單對象並運行它:

int main() 
{ 
// assuming default constructor exists, create the menu 
GameSelectMenu menu; 

// run the menu 
menu.run(); 

return 0; 
} 

菜單類本身就拿着GameInterface指針,這將是負責切換遊戲模式時,內存管理。您可以創建運行不同模式的函數,以將GameInterface *指定爲OnePlayer或TwoPlayer對象。這也將是在您創建的實際菜單中的用戶界面,使用戶可以真正改變遊戲模式......

//.. Within run() function of menu class 

std::string input; 
std::cout << "choose a game (enter 'a' or 'b'): " 
std::cin>> input; 

// check input for errors 
... 

// run a mode depending on input 
if (input == "a") startOnePlayer(); 
else if (input == "b") startTwoPlayer(); 

// remember to delete the GameInterface object when you have finished with it if it has been initialised 
if (game != NULL) delete game; 

... 
相關問題