第三章 WINDOWS 電玩程式
3.6 電玩程式
3.6.3 程式碼
3.6.3.1 飛機射擊遊戲的程式碼
3.6.3.1.1 input.h
//所有的使用者鍵盤輸入都定義在這,遊戲中需要判別這一些值
#ifndef __input_h__
#define __input_h__
/********************************************************************/
/*這是個定義使用者收入哪一些按鍵的結構 */
/********************************************************************/
struct inputstruct {
int fire;//使用者按了 ENTER 鍵 fire=1,使用者放開 ENTER 鍵 fire=0 int bomb;//使用者按了 B 鍵 bomb=1,使用者放開 B 鍵 bomb=0 int left;//使用者按了左鍵 left=1,使用者放開左鍵 left=0
int right;//使用者按了右鍵 right=1,使用者放開右鍵 right=0 int up;//使用者按了上鍵 up=1,使用者放開上鍵 up=0
int down;//使用者按了下鍵 down=1,使用者放開下鍵 down=0 int pause;//使用者按了 P 鍵 pause=1,使用者放開 P 鍵 pause=0
int space;//使用者按了 SPACE 鍵 space=1,使用者放開 SPACE 鍵 space=0 int decrease_game_speed;//使用者按了 D 鍵 decrease_game_speed=1,使用者放 開 D 鍵 decrease_game_speed=0
int increase_game_speed;//使用者按了 I 鍵 increase_game_speed=1,使用者放 開 I 鍵 increase_game_speed=0
};
#endif
3.6.2.1.2 myplane.h
//一些遊戲中要用到的類別的定義和函式的宣告
#ifndef __myplane_h__
#define __myplane_h__
#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <ddraw.h>
#define man_controlled 0
#define straight 1
#define move_to_enemy 2
/********************************************************************/
/*class moveobject 定義著遊戲中會動的物件(如子彈,敵機,飛彈等等...) */
/*的基本資料 */
/********************************************************************/
class moveobject {
public:
BOOL alive;//TRUE for alive,FALSE for dead
BOOL movable;//TRUE for it can move,FALSE for it can not move
int mode_of_flying;//這個物件飛行的方式
//0 表示由人控制 man_controlled //1 表示直線飛行 stright
//2 表示朝敵人方向飛行 move_to_enemy
int belongto;//表示這個移動物件是屬於哪一方的
//0 for player side,1 for 電腦控制的敵方,2 for 電腦控 制的中立
double xpos;//此物件的圖片的最左上角的點在螢幕中的 x 位置
double ypos;//此物件的圖片的最左上角的點在螢幕中的 y 位置
double angle;//此物件移動時的角度
double speed;//此物件移動時的速度
double x_speed;//此物件的 x 軸速度 double y_speed;//此物件的 y 軸速度
int x;//此物件的圖片的最左上角的 x 座標所在的圖檔的
int y;// 此物件的圖片的最左上角的 y 座標所在的圖檔的
int width;//此物件的圖片的寬度
int longth;//此物件的圖片的長度
LPDIRECTDRAWSURFACE lpDDoffscrean;//此物件的圖片所在的緩
衝顯示頁
moveobject(BOOL p_alive,BOOL p_movable,int p_mode_of_flying,double p_xpos,double p_ypos,double p_angle,
double p_speed,int p_x,int p_y,int
p_width,int p_longth,
LPDIRECTDRAWSURFACE p_lpDDoffscrean);//建構子 ~moveobject();//解構子
virtual void movable_object_control(struct object_draw_list *b,moveobject
*a,object_draw_list **c);//這個函示負責移動物件本身 };
/********************************************************************/
/*一個把 moveobject 物件串成 linking_list 的結構 */
/********************************************************************/
struct object_draw_list {
class moveobject *m_object;
struct object_draw_list *former;//前一個物件的指標 struct object_draw_list *next;//後一個物件的指標 };
/********************************************************************/
/*這個 sparkle 類別定義了飛機爆炸後的火花 */
/********************************************************************/
class sparkle:public moveobject {
protected:
int cycle;//這個 sparkle 的生命週期,當 cycle 為 0 時 sparkle 消失 public:
sparkle(BOOL p_alive,BOOL p_movable,int p_mode_of_flying,double p_xpos,double p_ypos,double p_angle,
double p_speed,int p_x,int p_y,int p_width,int p_longth,
LPDIRECTDRAWSURFACE p_lpDDoffscrean)
:moveobject(p_alive,p_movable,p_mode_of_flying,p_xpos,p_ypos,p_angle,
p_speed,p_x,p_y,p_width,p_longth,p_lpDDoffscrean)
{
cycle=0;
}//建構子 ~sparkle() {
}//解構子
void movable_object_control(struct object_draw_list *b,moveobject
*a,object_draw_list **c);//這個函式移動物件本身,參數 b 是物件 a 所在的串列結構 的頭的指標,而 c 是 b 的子標。
};
/********************************************************************/
/*這個類別定義了玩家的飛機 */
/********************************************************************/
class player_side_plane:public moveobject {
public:
UINT score;//玩家的分數 int powerlevel;//玩家的等級
int maxpowerlevel;//玩家的等級上限 int bombstock;//玩家的炸彈儲存量
int counter_to_next_powerlevel;//目前的所吃的 powerup box 總數除以 10 的餘數 int max_of_counter_to_next_powerlevel;//內定值為 10
BOOL protected_mode;//如果是 TRUE 的話玩家是無敵的 UINT protected_mode_start_time;
/********************************************************************/
/*class player_side_plane 的建構子 */
/*input BOOL p_aliveÎTRUE 表示這個物件是活的,FALSE 表示這個物件是 */
/*死的 */
/*input BOOL p_moveableÎTRUE 表示這個物件是可移動的,FALSE 表示這 */
/*這個物件是不可移動的 */
/*input int p_mode_of_flyingÎ0 表示由人控制 man_controlled */
/* 1 表示直線飛行 stright */
/* 2 表示朝敵人方向飛行 move_to_enemy */
/*input double p_xposÎ這個物件在螢幕中 x 的位置 */
/*input double p_yposÎ這個物件在螢幕中 y 的位置 */
/*input double p_angelÎ這個物件移動的角度 */
/*input double p_speedÎ這個物件移動的速度 */
/*input double p_xÎ這個物件的圖片在圖檔中 x 的位置 */
/*input double p_yÎ這個物件的圖片在圖檔中 y 的位置 */
/*input double p_widthÎ這個物件的圖片的寬度 */
/*input double p_longthÎ這個物件的圖片的長度 */
/*input LPDIRECTDRAWSURFACE p_lpDDoffscreanÎ這個物件的圖片要存入*/
/*顯示頁 */
/*input int p_powerlevelÎ這個物件的 powerlevel */
/*input int p_bombstock Î這個物件的炸彈存量 */
/*input BOOL p_protected_modeÎTRUE 表示無敵,FALSE 表示會死 */
/*input UINT p_protected_mode_start_timeÎ無敵模式的起始時間 */
/*沒有輸出直 */
/********************************************************************/
player_side_plane(BOOL p_alive,BOOL p_movable,int p_mode_of_flying,double p_xpos,double p_ypos,double p_angle, double p_speed,int p_x,int p_y,int p_width,int p_longth,
LPDIRECTDRAWSURFACE p_lpDDoffscrean,int p_powerlevel,int p_bombstock,BOOL p_protected_mode
,UINT p_protected_mode_start_time)
:moveobject(p_alive,p_movable,p_mode_of_flying,p_xpos,p_ypos,p_angle,
p_speed,p_x,p_y,p_width,p_longth,p_lpDDoffscrean) {
score=0;
powerlevel=p_powerlevel;
maxpowerlevel=6;
bombstock=p_bombstock;
protected_mode=p_protected_mode;
protected_mode_start_time=p_protected_mode_start_time;
counter_to_next_powerlevel=0;
max_of_counter_to_next_powerlevel=10;
}//建構子
/********************************************************************/
/* class player_side_plane 的解構子 */
/*沒有輸入值 */
/*沒有輸出值 */
/********************************************************************/
~player_side_plane() { }//解構子 };
/********************************************************************/
/* class guided_missile:public 這個類別定義了追蹤飛彈 */
/********************************************************************/
class guided_missile:public moveobject {
public:
moveobject *a_target;//追蹤飛彈的目標
object_draw_list **ptr_of_a_targets_list;//追蹤飛彈的目標所在的串列結構的頭 的指標
object_draw_list *targets_list; //追蹤飛彈的目標所在的串列結構的頭
/********************************************************************/
/*class player_side_plane 的建構子 */
/*input BOOL p_aliveÎTRUE 表示這個物件是活的,FALSE 表示這個物件是 */
/*死的 */
/*input BOOL p_moveableÎTRUE 表示這個物件是可移動的,FALSE 表示這 */
/*這個物件是不可移動的 */
/*input int p_mode_of_flyingÎ0 表示由人控制 man_controlled */
/* 1 表示直線飛行 stright */
/* 2 表示朝敵人方向飛行 move_to_enemy */
/*input double p_xposÎ這個物件在螢幕中 x 的位置 */
/*input double p_yposÎ這個物件在螢幕中 y 的位置 */
/*input double p_angelÎ這個物件移動的角度 */
/*input double p_speedÎ這個物件移動的速度 */
/*input double p_xÎ這個物件的圖片在圖檔中 x 的位置 */
/*input double p_yÎ這個物件的圖片在圖檔中 y 的位置 */
/*input double p_widthÎ這個物件的圖片的寬度 */
/*input double p_longthÎ這個物件的圖片的長度 */
/*input LPDIRECTDRAWSURFACE p_lpDDoffscreanÎ這個物件的圖片要存入*/
/* input object_draw_list **p_targets_list Î這個物件所要加入的串列的指標 */
/*的指標 */
/*沒有輸出值 */
/********************************************************************/
guided_missile(BOOL p_alive,BOOL p_movable,int p_mode_of_flying,double p_xpos,double p_ypos,object_draw_list **p_targets_list,
double p_speed,int p_x,int p_y,int p_width,int p_longth,
LPDIRECTDRAWSURFACE p_lpDDoffscrean,double p_angle);//建構子
/********************************************************************/
/* class guided_missile 的解構子 */
/*沒有輸入值 */
/*沒有輸出值 */
/********************************************************************/
~guided_missile();
void movable_object_control(struct object_draw_list *b,moveobject
*a,object_draw_list **c);//這個函示負責移動物件本身 };
/*void moveobject_init(struct moveobject *a,BOOL alive,BOOL movable,int xpos,
int ypos,int x_speed,
int y_speed,int x,int y,int width,int longth,
LPDIRECTDRAWSURFACE lpDDoffscrean);*/
BOOL add_object_into_object_draw_list(object_draw_list *a,moveobject
*b,object_draw_list **c);//這個函是把物件 b 加入到它所該加入到的串列 a 當中,而 c 是 a 的指標
//void movable_object_control(object_draw_list *b,moveobject *a,object_draw_list
**c);
void object_draw_list_control(object_draw_list *a,object_draw_list **b);//這個函式會 控制串列 a 中所有物件該做的動作而 b 是 a 的指標
sparkle *checkhit(object_draw_list *attacker,object_draw_list
*defender,object_draw_list **c,object_draw_list **d
,LPDIRECTDRAWSURFACE lpDDoffscrean);
//這個函式串列 attacker 中是否有某些物件跟串列 defender 中的否些物件相撞,如
果 attacker 串列中的 A 物件和 defender 串列中的 B 物件相撞,則把 A 物件由 attacker 串列中刪除,同時也把 B 物件由 defender 串列中刪除,且傳回一個指向 sparkle 的 指標。但是如果 attacker 串列和 defender 串列當中沒有任何物件相撞則這個函式傳 回 NULL
#endif
3.6.2.1.3 myplane.cpp
這是遊戲中要用到的函式
#include "myplane.h"
//這個函示負責初始化一個會移動的物件,類別 moveobject 的建構子
/********************************************************************/
/*class moveobject 的建構子 */
/* */
/*input BOOL p_aliveÎTRUE 表示這個物件是活的,FALSE 表示這個物件是 */
/*死的 */
/*input BOOL p_moveableÎTRUE 表示這個物件是可移動的,FALSE 表示這 */
/*這個物件是不可移動的 */
/*input int p_mode_of_flyingÎ0 表示由人控制 man_controlled */
/* 1 表示直線飛行 stright */
/* 2 表示朝敵人方向飛行 move_to_enemy */
/*input double p_xposÎ這個物件在螢幕中 x 的位置 */
/*input double p_yposÎ這個物件在螢幕中 y 的位置 */
/*input double p_angelÎ這個物件移動的角度 */
/*input double p_speedÎ這個物件移動的速度 */
/*input double p_xÎ這個物件的圖片在圖檔中 x 的位置 */
/*input double p_yÎ這個物件的圖片在圖檔中 y 的位置 */
/*input double p_widthÎ這個物件的圖片的寬度 */
/*input double p_longthÎ這個物件的圖片的長度 */
/*input LPDIRECTDRAWSURFACE p_lpDDoffscreanÎ這個物件的圖片要存入*/
/********************************************************************/
moveobject::moveobject(BOOL p_alive,BOOL p_movable,int p_mode_of_flying,double p_xpos,
double p_ypos,double p_angle,double p_speed,
int p_x,int p_y,int p_width,int p_longth,
LPDIRECTDRAWSURFACE p_lpDDoffscrean) {
//把外面傳進來的參數用來初始化物件的各個成員 alive=p_alive;//alive 用來表示物件是否還存在
movable=p_movable;//用來表示這個物件是可移動的 mode_of_flying=p_mode_of_flying;//物件飛行的模式
xpos=p_xpos;//物件圖片的最左上角的點在螢幕中的 X 位址
ypos=p_ypos; //物件圖片的最左上角的點在螢幕中的 Y 位址
speed=p_speed;//物件移動的速度
x_speed=(double)(p_speed*cos(p_angle*6.28/360));//speed 在 x 軸上的 分量
y_speed=(double)(0-(p_speed*sin(p_angle*6.28/360))); //speed 在 Y 軸 上的分量
/*if(x_speed==0&&((p_angle>0&&p_angle<90)||(p_angle>90&&p_angle<180)||
(p_angle>-180&&p_angle<-90)||(p_angle>-90&&p_angle<0))) {
x_speed=1;
}
if(y_speed==0&&((p_angle>0&&p_angle<90)||(p_angle>90&&p_angle<180)||
(p_angle>-180&&p_angle<-90)||(p_angle>-90&&p_angle<0))) {
if(p_angle>0&&p_angle<180) {
y_speed=-1;
}
if(p_angle<0&&p_angle>-180) {
y_speed=1;
} }*/
x=p_x;
y=p_y;
width=p_width;//物件圖片的寬度 longth=p_longth;//物件圖片的長度
lpDDoffscrean=p_lpDDoffscrean;//物件圖片所儲存於的後顯示頁 }
//解構子
/********************************************************************/
/*class moveobject 的解構子 */
/* */
/*沒有輸入值 */
/*沒有輸出值 */
/********************************************************************/
moveobject::~moveobject() {
}
//guided_missile 的建構子
/********************************************************************/
/*class player_side_plane 的建構子 */
/*input BOOL p_aliveÎTRUE 表示這個物件是活的,FALSE 表示這個物件是 */
/*死的 */
/* */
/*input BOOL p_moveableÎTRUE 表示這個物件是可移動的,FALSE 表示這 */
/*這個物件是不可移動的 */
/*input int p_mode_of_flyingÎ0 表示由人控制 man_controlled */
/* 1 表示直線飛行 stright */
/* 2 表示朝敵人方向飛行 move_to_enemy */
/*input double p_xposÎ這個物件在螢幕中 x 的位置 */
/*input double p_yposÎ這個物件在螢幕中 y 的位置 */
/*input double p_angelÎ這個物件移動的角度 */
/*input double p_speedÎ這個物件移動的速度 */
/*input double p_xÎ這個物件的圖片在圖檔中 x 的位置 */
/*input double p_yÎ這個物件的圖片在圖檔中 y 的位置 */
/*input double p_widthÎ這個物件的圖片的寬度 */
/*input double p_longthÎ這個物件的圖片的長度 */
/*input LPDIRECTDRAWSURFACE p_lpDDoffscreanÎ這個物件的圖片要存入*/
/* input object_draw_list **p_targets_list Î這個物件所要加入的串列的指標 */
/*的指標 */
/*沒有輸出值 */
/********************************************************************/
guided_missile::guided_missile(BOOL p_alive,BOOL p_movable,int
p_mode_of_flying,double p_xpos,double p_ypos,object_draw_list **p_targets_list, double p_speed,int p_x,int p_y,int p_width,int p_longth,
LPDIRECTDRAWSURFACE p_lpDDoffscrean,double p_angle)
:moveobject(p_alive,p_movable,p_mode_of_flyin g,p_xpos,p_ypos,p_angle,
p_speed,p_x,p_y,p_width,p_longth,p_lpDDoffscrean)
{
object_draw_list *temp_1=*p_targets_list;//p_targets_list 是 guided_missile 物件攻 擊的目標物件所在的串列結構
targets_list=*p_targets_list;
ptr_of_a_targets_list=p_targets_list;
a_target=NULL;
if(targets_list!=NULL)//如果不是完全沒有 guided_missile 攻擊的目標 {
int amount=0,index=0,i=0;
while(temp_1!=NULL)//這個 while loop 計算出 guided_missile 的目標串列裡 面共有多少個目標物件,並把計算的結果存於 amount 中
{
amount++;
temp_1=temp_1->next;
}
index=rand()%amount;//給 index 指定一個由(0~amount-1)的值 temp_1=targets_list;
while(i<=index-1) {
temp_1=temp_1->next;
i++;
}
a_target=temp_1->m_object;//此時 a_target 就是一個指向 guided_missile 的攻 擊目標物件的指標
}
if(a_target!=NULL)//如果 a_target!=NULL 那就把 guided_misssile 的攻擊方向改 向指向其所攻擊的目標
{
angle=(360/6.28)*atan2(-(a_target->ypos-(ypos)),a_target->xpos-xpos);
x_speed=(double)(p_speed*cos(angle*6.28/360));
y_speed=(double)(0-(p_speed*sin(angle*6.28/360)));
} }
//guided_missile 的解構子
/********************************************************************/
/*class guided_missile 的解構子 */
/* */
/*沒有輸入值 */
/*沒有輸出值 */
/********************************************************************/
guided_missile::~guided_missile() {
free(targets_list);
free(a_target);
}
//add_object_into_object_draw_list 這個函式把會動的物件鏈結成串 //(廢話 @@" 好像由函式的名子就看得出來)
//把物件 b 加入 a 串列中,c 是 a 的指標
/********************************************************************/
/*這個函式是把物件 b 加入串列 a 中 */
/* */
/*input object_draw_list *aÎ一個串列的頭的指標 */
/*input moveobject *b Î一個物件的指標 */
/*input object_draw_list **c Îc 是 a 只標 */
/*output TRUE 表示加入成功,FALSE 表示加入失敗 */
/********************************************************************/
BOOL add_object_into_object_draw_list(object_draw_list *a,moveobject
*b,object_draw_list **c) {
object_draw_list *temp=NULL;
if(b!=NULL)//如果不檢查 b 是否為 NULL 的話,當 b 是 NULL 時程式執行就會 有錯
if(b!=NULL)//如果不檢查 b 是否為 NULL 的話,當 b 是 NULL 時程式執行就會 有錯