塊,路點按坡度以及靜態物件自動生成,主要思想是參考了火炬之光的作法,看起來效果還不錯,載圖留念:
posted @
2014-08-20 17:03 flipcode 閱讀(181) |
評論 (0) |
編輯 收藏
unigine多線程處理系統:
一。 更新系統:
主線程World::update_multiple()中:
1. 清空update_threads[]中每一個thread的所有結點
2. 處理所有node,將node.frame==engine.frame + 1的結點均衡地分配給update_threads[](即每個updatethread盡量擁有數量相同的node, 以便線程處理時間平衡), 同時設置分配后的node.frame=engine.frame(防止更新重入時再次加入此結點)
3. 接著通過update_shader->runSync(size);函數同步更新上述加入的所有結點:
遍歷所有存有node的update_threads[],將它們與cpu工作線程關聯(這樣他們的線程run時會轉調轉回調用world中的update_threads[id].update(ifps);, 而update_threads[id]能遍歷所有加入的node->update()函數同時重置node.frame=engine.frame + 1;
最后等待線程同步執行完所有更新再返回.
【注意】上述第3點的runSync()中對應cpu工作線程數為實際cpu-1個,當cpu為1個時就不用線程而是直接運行完所有結點更新,而如果是
有超過一個cpu的則本地和cpu線程同時進行更新工作。雖然在主線程中同步等待完成,但這樣如果有多核則能并發同時處理。
另外還有異步runAsync()函數,分別在PathFind和Physics的更新函數中調用。這個runAsync()函數功能和runSync()差不多,只是它的工作線程為實際cpu個數,然后將任務均衡交給各線程處理,并且不會同步等待完成就返回了。所以是異步并發的。
二。渲染系統:
1.收集可視surfaces(scene intersection):
在RenderRenderer::render_world()中調用scene::getIntersection(bound_frustum,occluder,exclude)中:
a. render world occluders得到所有被occluders排除的nodes;
b. 判斷node是否被occluder所排除(exclude),沒有則add visible nodes.
c. objects_shader->runSync(RENDER_SCENE_NUM_THREADS);同步等待8線程并發處理所有沒被occulude排除的
visible node將它置為visible并將它們在bound_frustum中的surface(submesh)加入surfaces中.
c. 在update_intersection()函數中遍歷各線程所加入的surfaces[iThread].size, 將其按材質是否透明收集
到opacity_surfaces和transparent_surfaces中。
2. 反射渲染(render reflections):
render reflections中遍歷opacity_surfaces和transparent_surfaces處理收集reflection_2d_surfaces和 reflection_cube_surfaces.并進行反射渲染.
3. update scene:
分別UpdateSurface了opacity_surfaces和transparent_surfaces兩種surface,
內部好像只是針對OpctitySurfacefade state和tessellation state設置了對應的材質,并將surface鏈接起來遍歷調用
它們的create(),而create()內部只調用了create(ObjectSurface *surface), 這個好像只有skinmesh重載進行了處理。
4. sort scene:
按照type、mask、center.x順序分別對Lights、defferredLights、forwardLights進行排序
按照material、resource順序對opacity_surfaces進行排序
按照order、sequence、distance、blending順序對transparent_surfaces進行了排序。
在scene->optimize()中將opacity_surfaces和transparent_surfaces統一收集到optimized_surfaces中,然后讓 opacity_surfaces和transparent_surfaces重新指向對應的optimized_surfaces中元素。(這是為了讓surface更緊湊達到優化效果?)
5. deferred textures:
a. 先得到
deferred->depth_texture、
deferred->color_texture、
deferred->normal_texture、
deferred->parallax_texture、
deferred->texturerender
b. render deferred surfaces:
render_deferred_surfaces(scene->getOpacitySurfaces(),0)
render_deferred_surfaces(scene-getTransparentSurfaces(),0)
6. occlusion queries:
這個是使用dx9的硬件查詢進行occulsion的culling.
http://frustum.org/
http://www.humus.name/index.php?page=3D
https://www.assembla.com/code/scavenger/subversion/nodes/692/Scavenger
http://www.hmrengine.com/blog/?cat=5
posted @
2014-03-21 16:01 flipcode 閱讀(331) |
評論 (0) |
編輯 收藏
秦坦之旅的模型顯示, 上個女主角祼模:

還有招喚出來的死靈:

通過pixwin分析模擬出來的對應的shader:
uniform matrix wvp;
uniform texture BaseTexture;
uniform texture BumpTexture;
sampler t = sampler_state
{
Texture = <BaseTexture>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
};
sampler b = sampler_state
{
Texture = <BumpTexture>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
};
static const int MAX_MATRICES = 48;
float4x4 g_boneMatrices[MAX_MATRICES] : WORLDMATRIXARRAY;
struct VS_IN
{
float4 pos : POSITION;
float2 tex : TEXCOORD0;
float3 Normal : NORMAL;
float4 BlendIndices : BLENDINDICES;
float4 BlendWeights : BLENDWEIGHT;
};
struct VS_OUT
{
float4 pos : POSITION;
float2 tex : TEXCOORD0;
};
//----------------------------------------------------------------------
VS_OUT VS( VS_IN vsIn )
{
VS_OUT vsOut;
int indices[4] = (int[4])vsIn.BlendIndices;
indices[0] = vsIn.BlendIndices.z*255;//vsIn.BlendIndices[2]*255;
indices[1] = vsIn.BlendIndices.y*255;//vsIn.BlendIndices[1]*255;
indices[2] = vsIn.BlendIndices.x*255;//vsIn.BlendIndices[0]*255;
indices[3] = vsIn.BlendIndices.w*255;//vsIn.BlendIndices[3]*255;
float weights[4] = (float[4])vsIn.BlendWeights;
float4 pos = 0.0f;
float4 bonepos = vsIn.pos;
bonepos.w = 1;
for ( int i = 0; i < 4; i++ )
{
pos += mul( bonepos, g_boneMatrices[indices[i]]) * weights[i];
}
vsOut.pos = mul( pos, wvp );
vsOut.tex = vsIn.tex;
return vsOut;
}
struct PS_OUT
{
float4 color : COLOR;
};
//----------------------------------------------------------------------
PS_OUT PS( VS_OUT psIn )
{
PS_OUT psOut;
psOut.color = tex2D(t, psIn.tex);
//psOut.color = float4(1,1,1,1);
return psOut;
}
//----------------------------------------------------------------------
technique RenderMsh
{
pass P0
{
VertexShader = compile vs_2_0 VS();
PixelShader = compile ps_2_0 PS();
}
}
posted @
2013-12-27 17:58 flipcode 閱讀(363) |
評論 (0) |
編輯 收藏
支持幾十公里的大地圖編輯,可以隨意用筆刷在周邊刷出新的patch地塊,不用的任意patch也可直接刪除,
該地形非常適合作超大地圖的arpg, 也測試了一些角色ai,包括dota原型,上圖:

posted @
2013-12-27 17:51 flipcode 閱讀(239) |
評論 (0) |
編輯 收藏
rts游戲warringstates的AI管理
創建時間:2013年4月7日(星期天) 上午10:37 | 分類:
AI
| 字數:1834 |
發送到我的Qzone |
另存為... |
打印 | 添加到日歷
warringstates的aiplayer中有幾個管理器每幀更新:
1. build_mgr(工程部)
2. exploration_mgr(探索部)
3. army_mgr(軍工部)
4. unit_mgr(人力部)
5. resource_mgr(資源部)
每個管理器相當于一個部門,它每幀會更新處理兩個事情:a. 請求列表(request)處理; b.工作(job)列表處理;c.job的響應事件(觸發式:
job提交的請求得到滿足時觸發回來)
每個部門更新時在job中處理自己要做的事情(這是b.步驟),發現需要其它部門的幫助時,則向其它部門發出請求, 其它部門會把請求收入隊列,
然后更新時檢查是否可以滿足對應的請求(這是在a.步驟),是則立即給響應,否則按排工作組員(job)去完成; 完成后再給對應請求部門(這里直接是請求者(job)發出響應 (這是c.步驟)
例如:
1. aiplayer的更新中發現人口太多,房屋不夠則向build_mgr發出一個增加住房的請求,build_mgr收到后找到消耗金錢少的但住人多的
戶型并產生一個AIBuildJob讓組員去完成.
2. AIBuildJob的更新中發現要建造這樣的戶型所需的資源當前不夠(缺少木村),于是他向resource_mgr(資源管理器)MakeRequest申請
所需要的資源。
3. resource_mgr的更新中:
a. 從請求列表中取出該請求,產生對應的AIHarvestJob放入jobs列表中。
b. 接著遍歷更新jobs取出該AIHarvestJob更新
c. AIHarvestJob的更新發現該采集job還沒有對應農民,于是它向unit_mgr請求對應類型的農民。
4. unit_mgr的更新中:
從請求列表中取出該請求, 發現當前mAvailableUnits中有符合的已產生的農民,于時立即響應給對應的請求者AIHarvestJob
AIHarvestJob把對應的農民登錄到mHarvesters中.(說明:如果沒有的話則產生一個AITrainJob,在AITrainJob的處理中會看是否有對應unitype的工廠,
沒有則向build_mgr發出請求,有則向資源請求對應的單位所需要的資源,等資源管理器更新時發現請求滿足并響應回來時則開始向對應的工廠發出
eCOMMAND_TYPE_Train指令,之后就會跑到GameBuilding的Train工作流程)
5. resource_mgr的更新中:
遍歷更新jobs取出該AIHarvestJob進行更新,該AIHarvestJob遍歷mHarvesters取得那個農民,向他發出eCOMMAND_TYPE_Harvest
指令。
6. object_mgr的更新中:
遍歷所有單位進行更新,輪到那個農民更新時,它think函數中發現當前指令是eCOMMAND_TYPE_Harvest,于是它開始了Harvest的
工作流程:判斷背包中木材是否滿了,是則回城(搜索路徑),否則尋找木材資源(搜索路徑),到達后卸載/收割資源.
這樣當木材足夠時在resource_mgr的更新中,發現對應的木材資源請求足夠時就會移除該請求并向
對應的AIBuildJob發出響應說明木材已收集夠了; AIBuildJob收到后接著會向unit_mgr請求一名建筑工人。
(插入說明: 向unit_mgr請求所得的工人都是出租方式的,時間到了會收回并按請求級別優先級重新分配給其它需要他的請求)
由于之前收割的農民租期到了,而且那個木材收割的request已被移除(因此沒再請求分配農民)。
所以unit_mgr會把當前這個農民重新分配為建筑工人,向對應AIBuildJob發出響應。AIBuildJob收到后開始在主城附近有塊空地
并向建筑工人發出eCOMMAND_TYPE_Build指令讓其開始建造的工作流程.
其它軍工部的更新會判斷當前是否需要軍隊,并向人力部請求對應的兵,人力部又會看是否有這樣的兵,沒有的話則判斷對應產生
這樣兵種的兵工廠是否存在,不存在的話又會向工程部發出請求對應的兵工廠,工程部收到后又會判斷是否有足夠資源,沒有的話
又會向資源部要求對應的資源,資源部又會向人力請求對應的農民來采集資源,等等,如此類似的相關循環。。。
posted @
2013-04-07 11:34 flipcode 閱讀(429) |
評論 (0) |
編輯 收藏
raven的ai處理:
先據評估項(函數)進行評估選出當前最優一項,據此項產生對應的新行為處理對象(先清除之前的所有行為),調用它的process()來處理.
具體如下:
一。行為評估項:
每個bot有一個brain(即Goal_Think類),在brain中有一個評估列表m_Evaluators;
raven中主要是有4種需要評估的行為:
1.拿藥包
2.探索
3.攻擊
4.拿武器
具體如下:
double HealthBias = RandInRange(LowRangeOfBias, HighRangeOfBias);
double ShotgunBias = RandInRange(LowRangeOfBias, HighRangeOfBias);
double RocketLauncherBias = RandInRange(LowRangeOfBias, HighRangeOfBias);
double RailgunBias = RandInRange(LowRangeOfBias, HighRangeOfBias);
double ExploreBias = RandInRange(LowRangeOfBias, HighRangeOfBias);
double AttackBias = RandInRange(LowRangeOfBias, HighRangeOfBias);
//create the evaluator objects
m_Evaluators.push_back(new GetHealthGoal_Evaluator(HealthBias));
m_Evaluators.push_back(new ExploreGoal_Evaluator(ExploreBias));
m_Evaluators.push_back(new AttackTargetGoal_Evaluator(AttackBias));
m_Evaluators.push_back(new GetWeaponGoal_Evaluator(ShotgunBias,
type_shotgun));
m_Evaluators.push_back(new GetWeaponGoal_Evaluator(RailgunBias,
type_rail_gun));
m_Evaluators.push_back(new GetWeaponGoal_Evaluator(RocketLauncherBias,
type_rocket_launcher));
上述評估項目主要派生了一個 CalculateDesirability(), 以便bot在更新時遍歷該評估表,
調用它們的CalculateDesirability()選出最優先的行為項,并調用它的SetGoal(m_pOwnerBot)方法;
對應被選中的評估項的SetGoal函數內容:
void AttackTargetGoal_Evaluator::SetGoal(Raven_Bot* pBot)
{
pBot->GetBrain()->AddGoal_AttackTarget();
}
void ExploreGoal_Evaluator::SetGoal(Raven_Bot* pBot)
{
pBot->GetBrain()->AddGoal_Explore();
}
void GetHealthGoal_Evaluator::SetGoal(Raven_Bot* pBot)
{
pBot->GetBrain()->AddGoal_GetItem(type_health);
}
void GetWeaponGoal_Evaluator::SetGoal(Raven_Bot* pBot)
{
pBot->GetBrain()->AddGoal_GetItem(m_iWeaponType);
}
二。行為處理類:
在上述SetGoal對應具體函數中所調用的brain方法具體產生的行為如下:
void Goal_Think::AddGoal_Explore()
{
if (notPresent(goal_explore))
{
RemoveAllSubgoals();
AddSubgoal( new Goal_Explore(m_pOwner));
}
}
void Goal_Think::AddGoal_GetItem(unsigned int ItemType)
{
if (notPresent(ItemTypeToGoalType(ItemType)))
{
RemoveAllSubgoals();
AddSubgoal( new Goal_GetItem(m_pOwner, ItemType));
}
}
void Goal_Think::AddGoal_AttackTarget()
{
if (notPresent(goal_attack_target))
{
RemoveAllSubgoals();
AddSubgoal( new Goal_AttackTarget(m_pOwner));
}
}
當bot更新時會調用brain的process,從而調用到對應的subgoal中的Process()函數
注意:
每個goal在處理時還可以產生它自己的子goal。因為有時候在處理一個goal時需要等完成
另一個子goal后才能處理。 即狀態管理使用了樹結構.
posted @
2013-04-07 11:08 flipcode 閱讀(261) |
評論 (0) |
編輯 收藏
關于預測樹:
同事做了個demo,演示了這個預測樹。感覺復雜的ai可能評分有點難(比如說團隊合作之類的游戲,當然棋類游戲的話可以很容易使用這種方式).
主要用了兩個表: 評估表和評分表
每次預測時先產生一個根結點(帶當前局面S(Situation)),并開始處理根結點
1.
依賴于全局評估表根據當前局面S產生可能的決策D(decision)(它有自己的局面S,在決策處理時進行刷新);
2.
遍歷決策D列表模擬每一個決策的前瞻處理(并刷新當前決策下的局面S);
在每一個決定處理完后又回到第1.步產生可能的新的決策列表以及對應的局面(模擬有深度限制),
當模擬深度結束時使用全局評分表對每個決策的新局面進行評分。把評分累積到父結點。
最后選擇評分最高的決策作為下一步行動。(決策翻譯成命令并發送)
posted @
2012-09-24 17:29 flipcode 閱讀(311) |
評論 (0) |
編輯 收藏
關于全屏
1。 假全屏(如:成吉思汗、11的EF):
用API:ChangeDisplaySettings( &dm, CDS_FULLSCREEN );來設置
2. 對話框全屏(如:起凡早期的三國爭霸):
有限制,設備緩沖必須是discard交換并且是lockable的;
顏色跟gdi兼容;
設備不能開反鋸齒;
3. flip獨占全屏(如war3、LOL):
這種方式最快,但是顯示不出輸入法的選字框。
所以必須自繪輸入框(使用ime處理)
理論上第2種對話框是介于1和3的一種折中的解決方案,但是2的限制也有點大,主要是不能開反鋸齒,性能和3比差別不是很大。
但是目前出現一個嚴重問題,在一些可進行cpu和gpu切換的筆記本中(目前發現A卡的3000-5000系列),當切換到高性能時第2種
對話框全屏方式的游戲(必須開HARDWARE頂點,軟件頂點不受影響)會嚴重地卡幀,相當地卡!原因可能是這系列卡的驅動并未能
很好地處理這種全屏模式(開啟d3d debug可以看到BitBlt or StretchBlt failed in Present之類的報錯)
如果你的游戲以前也用第2種方式,那么現在你得照顧下這些交火切換之類的本本了。。。
posted @
2012-09-24 15:11 flipcode 閱讀(230) |
評論 (0) |
編輯 收藏
行為樹的理解:
傳統的AI習慣用FSM來管理狀態規則,一個管理類對多個狀態類進行管理。
FSM可以通過轉換狀態來處理(如:泰坦之旅),
也可以讓狀態并行處理(如:mythos). 另外為了處理某種狀態下的某種子行為,派生出了
分層狀態機(mythos通過棧來實現分層)。
FSM為了處理并行以及分層,在處理上讓人感覺不是非常清晰。而行為樹天生就是分層的,每一層又是并行的
通過條件以及控制結點可以清晰地使用圖形化來控制各種分支行為。
個人覺得搞行為樹就像是在搞流程圖
一般的行為樹都會有控制結點、條件結點、動作結點。
用控制結點根據不同的條件結點讓程序按不同的控制結點分支進行運行,當某些條件結點成立觸發相應的動作結點。
為了控制分支,控制結點有選擇、序列、并行等方式控制。同時還有一些用于裝飾的如循環、結果取反等之類的特殊結點。
光暈2、LOL等游戲用了行為樹。
可以參考:
行為樹
http://aigamedev.com/premium/tutorial/second-generation-behavior-trees/
行為樹
http://aigamedev.com/premium/interview/league-of-legends/
posted @
2012-09-24 14:46 flipcode 閱讀(949) |
評論 (0) |
編輯 收藏
著名游戲引擎公司GARAGEGAMES聯合全球一流大學MIT麻省理工大學,聯合推出Torque 3d engine永久免費版本.
今年9月.著名游戲引擎公司www.GarageGames.com與國際一流大學MIT(麻省理工大學)共同推出全球最具有權威的游戲開發相關技術標準及課程.
此消息發布一周內,包括EA,暴雪,微軟,UBI等多家公司隨即表示加盟.現在全球最大標準及技術查詢教學在線中心正在建立..
.(詳細:http://services.garagegames.com/)
可到此下載:
https://github.com/GarageGames/Torque3D
posted @
2012-09-24 13:36 flipcode 閱讀(433) |
評論 (0) |
編輯 收藏