Android遊戲之Activity模板

Android遊戲之Activity模板

Android是Linux系統.於其上運行APP都是Linux進程.Android APP沒有main入口函式.所以Android系統啟動APP時以Main Activity作為APP入口點.要理解Android APP運行需理解Activity生命週期.睇上圖左邊從Create到Destroyed完成整個生命週期.

Activity.onCreate():在創建時Activity加載界面並分配資源,如讀取音頻和3D模型.只會在啟動時被調用一次.

Activity.onStart():在onCreate()之後被調用或onRestart()之後調用

Activity.onRestart():用於重置Activity在onStop()之後被調用.

Activity.onResume():用於恢復(總會被調用)Activity在onStart()之後被調用或onPause()之後被調用

Activity.onPause():暫停(總會被調用).當Activity進入後臺時被調用

Activity.onStop():停止.當APP進入後臺時被調用.在onPause()之後調用.

Activity.onDestroy():銷毀.當APP退出時調用.若調用onPause()或onStop()之後onDestroy()將不會被調用.

為讓遊戲結構變得簡單.只需重寫onCreate()、onResume()和onPause()三個函式.下面是用於遊戲開發MainActivity.java模板

public class MainActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

// 初此遊戲資源

super.onCreate(savedInstanceState); //創建Activity時調用

setContentView(R.layout.main); // 把佈局填充給Activity

}

@Override

protected void onResume() {

// 恢復遊戲線程

super.onResume();

}

@Override

protected void onPause() {

// 暫停遊戲線程

super.onPause();

}

}

當你生成MainActivity.java文檔後需要在AndroidManifest.xml文檔中聲明為入口Activity

<activity android:name=”.MainActivity” android:label=”@string/app_name”>

<intent-filter>

<action android:name=”android.intent.action.MAIN” />

<category android:name=”android.intent.category.LAUNCHER” />

</intent-filter>

</activity>

Android Studio啟動Android應用

Android Studio啟動Android應用Debug
Android Studio啟動Android應用Variableh
Android Studio啟動Android應用
Android Studio啟動Android應用ADB
Android Studio啟動Android應用ADB

創建Android應用項目需要在手機上啟動.

  1. 對項目進行編譯工具欄Build/Mak Project
  2. 將手機與電腦連接(USB線)
  3. 設定/更多設定/開發者選項
  4. 啟動『開啟開發人員選項』
  5. 啟動『USB調試』連接USB後啟用偵錯模式
  6. 啟動『USB安裝』允許通過USB安裝應用
  7. 啟動『USB調試』(安全設定)允許通過USB調試修改權限或虛擬觸碰
  8. 編輯配置文檔Run->Edit Configurations->app->General
  9. Module選app
  10. Deploy選Default APK
  11. Launch選Default Activity
  12. Target選USB Device
  13. 在手機上啟動工具欄Run->Run

 

未能正確在手機上調試APP多為ADB(Android Debug Bridge)未正確安裝

  1. 下載Android SDK Platform-Tools(包含EXE)
  2. 系統『Path』變數必須需正確設置. 『%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\tools;』
  3. 下載並正確安裝Google USB Driver.這點很重要很多時就是Android ADB Interface驅動無正確安裝.
  4. 『系統內容->硬體->裝置管理員->ADB Interface』若有嘆號則代表驅動未正確安裝
  5. 下載驅去頁Get the Google USB Driver 最新驅動Download the Google USB driver下載後解壓縮到D:\Android\usb_driver
  6. 最後強制安裝驅動.『系統內容->硬體->裝置管理員->ADB Interface->更新驅動程式->瀏覽電腦上驅動程式軟體(手動尋找並安裝驅動程式軟體)->讓我從電腦上裝置取動程式清單中挑選(此清單會顯示已安裝並且與裝置相容驅動程式軟體,以及與裝置屬￿同類別所有驅動程式軟體)->從磁片安裝->打開(USB drect)->選擇(Android ADB Interface)』

 

若ADB依然未能正確運行可嘗試手動重啟.win+r輸入CMD啟動命令行窗口

1.停止ADB服務

adb kill-server

2.啟動ADB服務

adb start-server

3.查看目前連接Android 設備

adb devices

Android Studio新建Android項目

Android Studio新建Android項目
Android Studio新建Android項目SDK
Android Studio新建Android項目Activity
Android Studio新建Android項目Build

Android Studio新建Project『項目』與Eclipse類似.下面將創建空項目用於遊戲製作.

  1. 啟動Android Studio
  2. 點擊Start a new Android Studio project
  3. Application name應用名使用全小寫如aa
  4. Company domain公司域名如net
  5. Project location工程目錄路徑D:\Android\aa
  6. Package name包名建議使用反向域名語法創建包名.『應用名+域名』以防Java類名衝突.按Edit輸入『bookcard.aa』
  7. 單擊NEXT選擇生成應用設備類型和SDK版本.設備類型有『手機』『平板』『穿戴設備』『電視』『汽車』『物聯網』
  8. 選擇Android SDK最新版本是API-28甘樣只有最新版本Android設備才能運行.而且Android向前(舊版本)兼容.所以你應儘量使用低版本SDK依度選擇API-14 Andorid4.0舊設備已經很難在市面見到.按Help me choose可查看Android各板本市場佔有率
  9. 安卓即時應用程序『Include Android Instant app support』無需勾選
  10. 單擊NEXT選擇模板.這裡選擇Empty Activity不含用戶界面只創建XML佈局
  11. 單擊NEXT生成主Activity文件.『Activity Name』填MainActivity 勾選『Generate Layout File』生成佈局文檔
  12. 『Layout Name』佈局名填main勾選Backwards Compatibility(AppCompat) 『向兼容』
  13. 最後單擊Finish生成Project

Android Studio導入Eclipse項目

Android Studio導入Eclipse項目
Android Studio導入Eclipse項目

雖然Eclipse ADT和Android Studio有不同目錄結構與配置.但可通過其自帶『Import Project』完成工程轉換

  1. 使用『Import Project(Gradle,Eclipse ADT,etc.)』導入Eclipse項目
  2. 選擇Eclipse項目目錄路徑『Select Eclipse or Gradle Project to Import』如G:\Android\aa
  3. 選擇導入目標目錄路徑『Import Destination Directory』如D:\Android\aa
  4. 若目錄不存在則生成『Directory Does Not Exist』
  5. 勾選Replace jars with dependencise,when possible『替換附屬jars』
  6. 勾選Replace library sources with dependencies,when possible『替換附屬Lib文檔』
  7. 勾選Create Gradle-style(camelCase)module names『創建漸變風格模塊名稱』
  8. 如果出現項目無法轉換 如properties Library reference .. could not be found只需要編輯project.properties刪掉無穩到Library即可
  9. 按Finish轉換項目

Android Studio下載與安裝

安裝JAVA
安裝Android Studio
安裝Android Studio
安裝Android Studio
Android Studio下載與安裝Path

以前開發Android遊戲一直使用Eclipse ADT插件進行.因為換左台新電腦覺得是時候轉入『Android Studio』懷抱.只因它是Google親生仔.而且已中止為Eclipse ADT插件和Android Ant編譯系統更新開發.而且Android Studio比起Eclipse啟動速度快很多(因為無需載入所有項目)

安裝JAVA

  1. 首先要下載Java SE(Standard Edition) Development Kit簡稱(JDK) 下載jdk-10.0.1_windows-x64_bin.exe(JDK10只有x64版本)
  2. 單擊開此安裝JDK,勾選『Public JRE』和『Development Tools』、『Source Code』
  3. 安裝路徑選擇默認即可C:\Program Files\Java\jdk-10.0.1\
  4. 為JAVA設定Windows環境路徑.按『Win + Pause Break』鍵打開『系統』/進階系統設定/環境變量/系統變數(S)/
  5. 按『新增』系統變數.『變數名稱』輸入JAVA_HOME『變數值』輸入JAVA安裝路徑『C:\Program Files\Java\jdk-10.0.1\』按『確定』保存
  6. 編輯『Path』系統變數追加『%JAVA_HOME%\bin;』 按『確定』保存

 

安裝Android Studio

  1. 打開下載 Android Studio頁面. Windows有x64安裝版android-studio-ide-173.4819257-windows.exe
  2. 單擊安裝Android Studio 並且確保電腦能連結互聯網.因為安裝過程需要下載所需文檔
  3. 構選Android Virtual Device
  4. 安裝路徑選擇默認即可C:\Program Files\Android\Android Studio
  5. 首次啟動會睇到Complete Installation對話框.因為是全新安裝勾選Do not import settings不導入設置
  6. 第一次啟動時若出現『Unable to access Android SDK add-on list』因為沒有安裝Android SDK.按Cancel後逐安裝
  7. 介面有Intellij和Darcula可選
  8. 勾選Android Virtual Device和Performance(Intel HAXM)HAXM是虛擬引擎加強運行x86 Android虛擬機表現
  9. 最後下載Android SDK完成安裝.要保正常連結com
  10. 為Android Studio設定Windows環境路徑.按『Win + Pause Break』鍵打開『系統』/進階系統設定/環境變量/系統變數(S)/
  11. 按『新增』系統變數.『變數名稱』輸入ANDROID_HOME『變數值』輸入Android SDK安裝路徑如『C:\Android\Sdk』. 按『確定』保存.如果你唔知SDK安裝路徑可同過『FILE->Other Settings->Default Project Structure->Android SDK location』睇到
  12. 編輯『Path』系統變數追加『%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\tools;』 按『確定』保存
  13. 啟動Android Studio
  14. 下載『SDK Tools』按『File->Settings->Android SDK->SDK Tools』
  15. 勾選Android SDK Build-Tools
  16. 勾選Android SDK Platform-Tools
  17. 勾選Android SDK Tools
  18. 勾選Google Play APK Expansion library
  19. 勾選Google Play Licensing library
  20. 勾選Google Play services
  21. 勾選Google USB Driver
  22. 勾選Google WEB Driver
  23. 按Apply自動下載安裝

 

若在手機上調試APP必須正確安裝ADB

  1. 下載Android SDK Platform-Tools
  2. 系統『path』變數必須需正確設置.
  3. 下載並正確安裝Google USB Driver.
  4. adb.exe devices 查看是否正確連接手機

 

 

FPS第一人稱視角射擊遊戲

是時候將之前所學OpenGL/DirectX知識粘合成一完整遊戲.最簡單是『第一人稱視角射擊遊戲』FPS(First-person Shooter). 通過控制『準星』描准『怪物』按滑鼠左鍵發射『飛彈』.若擊中便會『爆炸』並擊殺『怪物』,其實它會在另地在生.若擊中地面則會『爆炸』.按鍵盤上下鍵在山地中前後移動.若近距離接近『怪物』它會另轉面自動走開(AI部分). 所有『怪物』與『飛彈』都是MD2模型.按ESC鍵退出遊戲.下載FPS:

下面所需要文章與代碼:

  1. AI之行走
  2. 準星
  3. 粒子爆炸特效
  4. 邊界球
  5. MD2文檔讀取與解析
  6. WAV音檔分釋與讀取
  7. DirectSound3D
  8. DirectInput之查詢滑鼠
  9. DirectInput之查詢鍵盤
  10. 粒子系統
  11. 廣告牌
  12. 紋理地形
  13. 天幕
  14. 紋理映射

AI之行走

AI之行走

AI也就是『人工智能』在遊戲中實現多數使用『狀態機』.通過定義大量狀態.然後通過條件判斷而切換當前狀態.從而實現對外界作出反應. 當『怪物』它會觀察四周.當你接近它時會另轉面走開.

首先定義下面幾個狀態

#define AI_IDLE       0 // 站立

#define AI_RUN        1 // 奔跑

#define AI_DEATH      3// 死亡

初此AI狀態變量設為站立

int ai = AI_IDLE;

『狀態機』判斷結構

if (ai == AI_IDLE) // 站立

{

}

else

if (ai == AI_RUN)// 奔跑

{

}

else

if (ai == AI_DEATH)// 死亡

{

}

 

站立轉身走開AI代碼

1.首先計算兩者距離

VECTOR3D distance = pos – player.pos;

length = Length_VECTOR3D(&distance);

2.計算『怪物』與『玩加』 矢量之間夾角

Normalize_VECTOR3D(&distance);// 長度歸一

VECTOR3D v;

Init_VECTOR3D(&v, 0, 0, -1);

angle = RAD_TO_DEG(Angle_VECTOR3D(&distance, &v0));// 角度

2.若距離小於10米則會轉身離開

if (length < 10  ){

ai = AI_RUN;// 奔跑

rot.y = (angle – 90) + ((rand() % 90) – 45);// 轉身走開.有45度隨機角度

}

 

OpenGL之準星

OpenGL之準星
準星紋理

射擊遊戲在屏幕中畫有『準星』用於射擊怪獸.因為『準星』固定在屏幕中心.當你移動滑鼠時.相機視角也隨之改變.而當你要移動射擊位置可通過按鍵盤上下鍵

移動滑鼠 響應 角度
左移 相機視角繞Y軸左轉 if (y >= 360.0f) y = 0.0f;
右移 相機視角繞Y軸右轉 if (y <= -360.0f) y = 0.0f;
上移 相機視角繞Z軸右轉 if (z > 60.0f) z = 60.0f;
下移 相機視角繞Z軸左轉 if (z < -60.0f) z = -60.0f;

 

鍵盤鍵 響應 位置與角度
上鍵 位置前移 x = x – (speed * cos(DEG_TO_RAD(y)));

z = z – (speed * sin(DEG_TO_RAD(y)));

下鍵 位置後移
左鍵 相機視角繞Y軸左轉 if (y >= 360.0f) y = 0.0f;
右鍵 相機視角繞Y軸右轉 if (y <= -360.0f) y = 0.0f;

更新相機位置與角度

1.旋轉角度 deltaTime為時間間隔

rot.x = rot.x + dx * 60 *deltaTime;

rot.y = rot.y + dy * 60 *deltaTime;

rot.z = rot.z + dz * 60 *deltaTime;

2.限制視口角度否則會上下搖恍

if ( rot.y >= 360.0f || rot.y <= -360.0f)

player->rot.y = 0.0f;

if (player->rot.z > 60.0f)

player->rot.z = 60.0f;

if (player->rot.z < -60.0f)

player->rot.z = -60.0f;

3.角度轉弧度

float radian = 3.141592654f * player->rot.y / 180.0f;

計算移動速度

4.float speed = dx * 3 *deltaTime;

5.計算位置

pos.x = (float)(pos.x – (speed * cos(radian)));

pos.z = (float)(pos.z – (speed * sin(radian)));

radian = 3.141592654f * rot.z / 180.0f; // 弧度

pos.y = (float)(pos.y – (speed * sin(radian)));

6.UVN相機模型

LookAt_Camera3D();

最後製作準星紋理

  1. 繪製白色準星
  2. 背景色填充為黑色
  3. 模色設為『索引色』256色
  4. 設定透面色為黑色glAlphaFunc(GL_GREATER, 0);

OpenGL之粒子爆炸特效

OpenGL之粒子爆炸特效

遊戲中最常見『爆炸』特效.最常見做法是使用粒子系統模擬『爆炸』.你大約需要:

  1. 黑底白圓位圖『bmp』如上圖
  2. 爆炸特效音頻『wav』
  3. 粒子系統
  4. 廣告牌

其實所有『爆炸』特效都是圓心紋理位圖.只是它使用『廣告牌』技術讓其正對著你即『相機』. 渲染為紅色並讓其隨時間『下墜』『變暗』『縮小』直至消亡.之前模擬『飄雪』特效時使用三級系統.這次我將粒子結構大大簡化.其代碼我都在模擬『爆炸』特效中實現.W

粒子結構體

typedef struct PARTICLE_TYP {

VECTOR3D pos;// 位置

VECTOR3D pos_prev;// 之前位置

VECTOR3D velocity;// 速度與方向

VECTOR3D acceleration;// 加速度

float    energy;// 生命週期(秒)

float size;// 尺寸

float size_delta;//增量

float weight;// 重量

float wdight_delta;// 重量增量

float color[4];// 顏色

float color_delta[4];// 顏色增量

}PARTICLE,*PARTICLE_PTR;

爆炸特效結構體

typedef struct EXPLOSION_TPY {

int          state;//  狀態

PARTICLE_PTR array;// 數組

int          count;// 粒子數量/爆炸量

VECTOR3D     origin;// 原點

VECTOR3D     velocity;// 速度與方向

VECTOR3D     variation;// 速度變量

VECTOR3D     acceleration;// 加速度

float        energy;// 生命週期(秒)

float        size;// 尺寸 5.0f

float        size_variation ;// 尺寸變量 2.0f

float        spread;// 爆炸傳播範圍

float        color[4];// 顏色

VECTOR2D     texture_coord[4];// 紋理座標

}EXPLOSION,*EXPLOSION_PTR;

生成『爆炸』特效函式

count:爆炸量大約1-10即可.

pos:位置

spread: 爆炸傳播範圍 0.1即可

void Build_Explosion(EXPLOSION_PTR explosion,int count,VECTOR3D_PTR pos,float spread){

explosion->state = MODEL3D_STATE_ACTIVE;

explosion->count = count; // 粒子數量

explosion->array = (PARTICLE_PTR)malloc(sizeof(PARTICLE)*count);// 分配空間

explosion->spread = spread;// 傳播

explosion->size           = 5.0f;// 尺寸

explosion->size_variation = 2.0f;// 尺寸變量

explosion->energy = 1.5f + FRAND_RANGE1() / 2.0f;// 生命週期(秒)

Init_VECTOR3D(&explosion->origin, pos->x, pos->y, pos->z);// 源點

Init_VECTOR3D(&explosion->velocity, 0.0f, 2.0f, 0.0f);// 速度

Init_VECTOR3D(&explosion->variation, 4.0f, 4.0f, 4.0f);// 變量

Init_VECTOR3D(&explosion->acceleration, 0.0f, -5.0f, 0.0f);// 加速度

PARTICLE_PTR particle;// 粒子

for (int i = 0; i < count; ++i){

particle = &explosion->array[i];// 粒子

Buid_Explosion(explosion, particle);//生成粒子『爆炸』特效

}

Set_Pos_DirectSound(&explosion_sound3D, pos->x, pos->y, pos->z);// 設置音源位置

Play_DirectSound(&explosion_sound3D, false);//播放音頻數據

}

生成爆炸粒子函式

void Buid_Explosion(EXPLOSION_PTR explosion, PARTICLE_PTR  particle){

// 在發射區隨機位置生成粒子

particle->pos.x = explosion->origin.x + FRAND_RANGE1() * explosion->spread;// 傳播

particle->pos.y = explosion->origin.y + FRAND_RANGE1() * explosion->spread;

particle->pos.z = explosion->origin.z + FRAND_RANGE1() * explosion->spread;

//給粒子隨機速度

particle->velocity.x += FRAND_RANGE1() * explosion->velocity.x;

particle->velocity.y += FRAND_RANGE1() * explosion->velocity.y;

particle->velocity.z += FRAND_RANGE1() * explosion->velocity.z;

// 加速度

particle->acceleration = explosion->acceleration;

// 生命週期

particle->energy = 1.5f + FRAND_RANGE1() / 2.0f;

// 顏色

particle->color[0] = 1.0f;

particle->color[1] = 0.5f + FRAND_RANGE1() * 0.5f;

particle->color[2] = 0.0f;

particle->color[3] = 1.0f;

// 顏色增量

particle->color_delta[0] = 0.0f;

particle->color_delta[1] = -(particle->color[1] / 2.0f) / particle->energy;

particle->color_delta[2] = 0.0f;

particle->color_delta[3] = -1.0f / particle->energy;

// 設置粒子的大小

particle->size = explosion->size + FRAND_RANGE1() * explosion->size_variation;

particle->size_delta = -particle->size / particle->energy;

}

釋放『爆炸』特效函式

void Free_Explosion(EXPLOSION_PTR explosion){

if (explosion->array != NULL)

free(explosion->array);

explosion->state = MODEL3D_STATE_NULL;

memset(explosion, 0, sizeof(EXPLOSION));// 清空

}

更新『爆炸』特效函式

deltaTime:時間間隔

void Update_Explosion(EXPLOSION_PTR explosion, float deltaTime){

PARTICLE_PTR particle;// 粒子

for (int i = 0; i < explosion->count; ){

particle = &explosion->array[i];// 粒子

// 基於時間和速度更新粒子的位置

particle->pos = particle->pos + particle->velocity * deltaTime;

particle->velocity = particle->velocity + particle->acceleration * deltaTime;

particle->energy = particle->energy – deltaTime;

particle->size += particle->size_delta * deltaTime;

particle->color[3] += particle->color_delta[3] * deltaTime;

particle->color[1] += particle->color_delta[1] * deltaTime;

// 將最後一個粒子移動到當前位置,並減少計數.

if (particle->energy <= 0.0)

explosion->array[i] = explosion->array[–explosion->count];

else

++i;

}

if (explosion->count == 0)

Free_Explosion(explosion); // 釋放

}

渲染『爆炸』特效紋理函式

void Render_Explosion2(EXPLOSION_PTR explosion, BILLBOARD_PTR billboard){

float viewMatrix[16];

VECTOR3D right, up, pos;

GLfloat size;

right = billboard->right;

up = billboard->up;

// 壓入當前屬性

glPushAttrib(GL_ALL_ATTRIB_BITS);

glDisable(GL_DEPTH_TEST);

glEnable(GL_BLEND);

glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);

glEnable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, explosion_texture.ID);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glBegin(GL_QUADS);

for (int i = 0; i < explosion->count; ++i){

PARTICLE_PTR particle = &explosion->array[i];// 粒子

size = particle->size / 2;

pos = particle->pos;

glColor4fv(particle->color);

glTexCoord2f(0.0, 0.0); glVertex3fv((pos + (right + up) * -size).M);

glTexCoord2f(1.0, 0.0); glVertex3fv((pos + (right – up) * size).M);

glTexCoord2f(1.0, 1.0); glVertex3fv((pos + (right + up) * size).M);

glTexCoord2f(0.0, 1.0); glVertex3fv((pos + (up – right) * size).M);

}

glEnd();

glDisable(GL_TEXTURE_2D);

glDisable(GL_BLEND);

glEnable(GL_DEPTH_TEST);

glPopAttrib();// 彈出當前屬性

}

OpenGL之曲棍球

OpenGL之曲棍球

『曲棍球』是碰撞算法最好演示,在遊戲中『球臺』寬300長500,並且有四條圍邊,確保『曲棍球』在『球臺』圍邊範圍內移動. 『球臺』會給『曲棍球』帶來『磨擦』後慢慢慢落來並最後停低.而『玩家球』則通過鼠標移動控制.通過與『曲棍球』相碰給『曲棍球』帶來動力.演示程式:下載.我會給出遊戲設計重點,並給出關鍵代碼

1.『冰球』運動核心是碰撞算法.你試想下當『冰球』高速運動時有可能會穿越圍邊(圍邊使用平面定義).所以你需要準確計算碰撞時間.碰撞代碼睇『碰撞時間

2.控制『玩家角色』通過獲取滑鼠標偏移量與位置相加移動『玩家角色』.你需要通過DirectInput獲得滑鼠偏移量. 並且確保不要移出球臺圍邊.若與『冰球』則重新計算返射方向與速度

根據鼠標運動計算速度::Init_VECTOR3D(&player->velocity, diffX, 0, diffY);

計算位置player->position = player->position + player->velocity;

『玩家角色』與『冰球』碰撞使用『邊界球』進行檢測並重新計算返射方向與速度

puck->velocity = Reflection_VECTOR3D(&puck->velocity,&(puck->velocity ^ player->velocity)) + player->velocity*500;

3.設定『球臺』結構與『圍邊平面

typedef struct TABLE_TPY {

TEXTURE   texture;// 球臺紋理

VECTOR3D  position;// 球臺位置

VECTOR3D  corner[4];//球臺角落

PLANE3D    wall[4];// 球臺圍邊平面

float width;// 寬度

float depth;// 深度

float height;// 高度

}TABLE,*TABLE_PTR;

球臺寬300*長500載入紋理Load_File_Texture()綁定紋理Bind_Image_Texture().圍邊使用Init_PLANE3D()定義為平面

4.定義『冰球』結構

typedef struct PUCK_TPY {

VECTOR3D     position;// 位置

VECTOR3D  acceleration;// 加速度

VECTOR3D  velocity;// 速度

float     radius;// 半徑

}PUCK,*PUCK_PTR;

5.定義『玩家角色』結構

typedef struct PLAYER_TPY {

VECTOR3D  position;// 位置

VECTOR3D  velocity;// 速度

float     radius;// 半徑

float     mouseX, mouseY;

}PLAYER,*PLAYER_PTR;