程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> DX10引擎計劃——子彈,dx10引擎子彈

DX10引擎計劃——子彈,dx10引擎子彈

編輯:C++入門知識

DX10引擎計劃——子彈,dx10引擎子彈


今天把子彈的釋放機制改了一下,設置為碰撞N次或持續一段時間後消亡(自殺)。

難點就是自殺這塊,很難保證自殺後不再“回魂”。

找了很久終於發現了哪個語句在“叫魂”:

這句話就是毛病所在,如果在物體的ActionUpdate內部釋放了自己,那麼下一句 pNew = pNew->pNext就出問題了,指向了一段釋放掉了的空間。所以我做了如下修改:

很經典很老套的方法,但是百試不爽。順利自殺。(這年頭不好混啊,自殺都不容易)

2015/ 03/27

***********************************

終於寫出來了,比預計的晚了一點,一直在修BUG,上圖:

圖片說明:

點鼠標左鍵,就會沿著攝像機視線發射一枚子彈,速度、子彈種類都需要事先設定。我下面貼下代碼。

為了防止子彈數目過多,以及子彈間隔過短,產生粘連(粘連這個問題我現在還沒徹底解決呢),設置一個子彈的冷卻時間,以及子彈的定時回收機制。

我這裡是將子彈統一回收的,不是每個子彈都帶一個定時器(可以帶,那是另一種子彈)。

*********************************************************************

技術相關:

稍微觀察,就明白了,子彈就是一個堆,先入先出(僅限於我選擇的這種,帶定時器的子彈可以是鏈表,任意刪除)。然後子彈占得內存空間不能過大,所以需要一個meshCopy類,我寫了兩個copy類,MeshCopy和MeshCopyNew, 不同之處在於MeshCopyNew會創建一個完全獨立的空間,不受母體影響。MeshCopy則與母體共用一部分內存空間(頂點、貼圖)。母體釋放掉,copy對象必須釋放。這個過程如果寫成任意刪除的模式,好麻煩,感覺得不償失。就把他們整到一起了,整個MeshCopy堆全部是一個整體,就是現在看到的Bullet類,Bullet負責新子彈的添加與刪除,同時子彈有各自獨立的“意識”,執行不同的任務。這樣看起來省事了許多。其實速度也提快了很多。

注意事項:寫堆的時候要注意,內存要釋放干淨。

下面是一部分代碼,只貼這麼多,杜絕懶癌症蔓延。

——————————————————————————————————————————————————

定時發射子彈代碼:

 1 static float t_base_bullet = 0.0f, t_cur_bullet = 0.0f;
 2 
 3     if(GetMouse().GetState() == LKEY_PRESSED)
 4     {
 5         t_cur_bullet = mTimer->getGameTime();
 6         if( (t_cur_bullet - t_base_bullet) >= BULLET_TIME_GAP)
 7         {
 8             gBullet->CreateOneBullet(curScene->GetObjList(), *gCrashList, GetCamera().position(), GetCamera().GetLook());
 9             t_base_bullet = t_cur_bullet;
10         }
11     }


定時回收子彈代碼(與定時發射有些微不同,只是一個小聰明而已,不難理解):

 1 void Bullet::ActionUpdate(float dt)
 2 {
 3     // 定時回收子彈資源
 4     static float t_base_bullet = 0.0f, t_cur_bullet = 0.0f;
 5 
 6     if(!existBullet)
 7     {
 8         // 一個子彈也沒有的時候
 9         t_base_bullet = t_cur_bullet = mTimer->getGameTime();
10         return ;
11     }
12 
13     if(pHead->pNext)
14     {
15         t_cur_bullet = mTimer->getGameTime();
16         if( (t_cur_bullet - t_base_bullet) >= BULLET_LIFE_TIME)
17         {
18             DeleteOneBullet();
19 
20             // 計時
21             t_base_bullet = t_cur_bullet;
22         }
23     }
24 }

 

子彈的增刪,我使用了一點PV操作的知識。
創建子彈代碼:

 1 void Bullet::CreateOneBullet(DemoList& paintList, CrashList& crashList,  D3DXVECTOR3& position, D3DXVECTOR3& speed)    // 創建一個子彈
 2 {
 3     // V操作
 4     // 如果不存在子彈,就設置存在,如果存在,不修改該值
 5     existBullet |= true;
 6 
 7     MeshCopy* pNew = new MeshCopy();
 8     pNew->Copy( *bulletTypeArray[curBulletTypeIndex] );
 9     pNew->SetPosition(position);
10     pNew->SetSpeed(speed * mSpeed);
11     pNew->OpenCrash();
12 
13     pNew->SetMass(1.0f);
14 
15     paintList.AddObj(pNew);
16     crashList.AddObj(pNew);
17 
18     pTail->pContent = pNew;
19 
20     pBulletPoint pP = (pBulletPoint)malloc(sizeof(BulletPoint));
21     pP->pContent = NULL;
22     pP->pNext = NULL;
23 
24     pTail->pNext = pP;
25     pTail = pP;
26 
27 }


刪除子彈代碼

 1 void Bullet::DeleteOneBullet()    // 堆,先進先出刪除
 2 {
 3     if(pHead == pTail)
 4     {
 5         // 堆為空
 6         // P操作
 7         existBullet = false;
 8         return;
 9     }
10 
11     static pBulletPoint pT;
12 
13     pT = pHead->pNext;
14 
15     delete(pHead->pContent);
16     
17     free(pHead);
18     pHead = pT;
19 }

 

————————————————————————————————————————-

好了,本文到此結束吧, 希望對讀者們有用。

 下一階段,添加一下音樂,以及實現說好的《是男人就點100下》!順手再做個CS設計視角的子彈Demo。

 (關於Demo中出現的粘連的BUG,源頭正在查找,如果讀者有什麼發現,希望不吝賜教,謝謝了!orz)

——————————————————————————————-

本章演示Demo下載鏈接(百度網盤,用的次數不多,如果鏈接壞了,希望讀者能及時通知我):

 http://pan.baidu.com/s/18R6iU

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved