遊戲底層邏輯,空間劃分

2021-07-11 16:01:51 字數 3602 閱讀 9276

我們可以預知,該方法在個體總數較小的時候效率較高,一旦個體數突破上百個,就很容易造成極大的cpu開銷,所以此處我們需要研究出另外的索引方案來得到鄰居。

空間劃分的方案主流的有很多,例如四叉樹,八叉樹,bsp樹,四叉樹主要用於資料庫的底層方案,它會將二維的點轉化為一條有規律的曲線;八叉樹是四叉樹的3d版;bsp樹是三維的空間二分;這幾種主流演算法對於我這款遊戲都不合適,此處我們介紹兩個不是很常見的演算法,cell space和geo hash。

我們想象如下的場景:

y君上了計程車

y:「師傅,到xx小區。」

計程車司機:「xx小區在哪兒啊?」

y:」就在電視塔附近。「

很常見的情況,我們注意到,當我們不知道地理位置的時候,我們會查詢「標誌性建築」cell_space_partition(以下簡稱csp)就是引用了這樣一種思路:通過hash(索引)來減少遍歷的難度或者廣度。(筆者最近在思考有沒有可能性直接用一種關聯啟發演算法,來實現這種多對多的劃分邏輯)

這種空間劃分是將二維空間劃分為小方格仔,然後每個小方格存放個體指標的集合,我們在查詢個體鄰居的時候就只需要遍歷小方格裡的個體集合。

#pragma once

#include"baseentity.h"

#include

#include"cocos2d.h"

using

namespace cocos2d;

struct cell

};class cellspacepartition

;cellspacepartition::cellspacepartition(rect spacesize, int cellnumx, int cellnumy) :

_spacerect(spacesize),

_cellnumx(cellnumx),

_cellnumy(cellnumy)

}}void cellspacepartition::addentity(baseentity* entity)

int cellspacepartition::positiontoindex(const vec2 position)const

void cellspacepartition::updateentity(baseentity* entity, vec2 old_position)

}std::vector

cellspacepartition::getneighbors(vec2 position,double radius)

});//end for each

}}//end for

return neighbors;

}

大家可以看到,很簡單的**,此處我們將空間劃分的方格數目固定,當然也可以用固定大小的方格。

在面對運動的個體時,我們需要在物體產生位移的同時更新它的所屬方塊。

如果你開發過基於lbs+的地圖程式,你應該對這個演算法很熟悉了,但是應用在遊戲上還是大姑娘上轎——頭一回!真令人興奮,我們每當做出一小步創新,人類的科技就會有乙個大的進步。

我在此就不班門弄斧介紹這種演算法了,我講一下我的實現。

難點有幾個:

- c++內部對2進製變數的處理比較糟糕

- 我們需要寫乙個base32編碼的方法,而且要盡量高效,一旦該方法不高效,那反而會比空間劃分以前更慢

- 我們需要寫乙個資料庫查詢的like演算法,其實也就是基本模糊查詢,筆者的資料庫知識非常尷尬:),這一塊在找做資料庫的朋友幫忙講解一下

基本步驟:

- 1·為位址結構新增string型別儲存hash值

- 2·傳入乙個地理資訊point(x,y),對其x和y值做如下操作

- 3·將其不斷二分,此處我們使用遞迴方案,屬於左區間值為0或者1,右區間與之相反

- 4·小於設定精度後,結束二分(此處的精度需要根據你的hash字串長度和整個地圖大小來計算)

- 5·我們將x,y值復合,偶數字為x或者y,奇數字為另乙個

- 6·我們這時得到一串二進位製碼,對其進行base32編碼

- 7·得到geohash值

關於base32編碼,就是把二進位制數轉換為32進製數,5位代表乙個32進製數,此處的編碼表為約定版本,詳情見**

關於like方法,由於對效率至關重要,所以筆者不敢妄下定論,大家有好的方案可以m我

class geohash

protected://convert to base32 code

string base32encoding(string);

public:

static

string getindex(vec2);//get geohash code

static

bool like(string,string);

std::vector

getneighbors(vec2, std::vector

);};

char geohash::base32_encode = ;

string geohash::base32encoding(string bitstr)

int refer = 0;

for (int j = 0; j < 5; j++)

outputstr.push_back(base32_encode[refer]);

}if (bitstr.length > count * 5)//push '0' to fill the rest

int refer = 0;

for (int j = 0; j < 5; j++)

outputstr.push_back(base32_encode[refer]);

}return outputstr;

}string geohash::getindex(vec2 po)

return base32encoding(totalbit);

}void geohash::halfdivision(double min, double max, double value,string& bit)

if (between(value, min, (min + max) / 2))

else

}bool geohash::like(string index1,string index2)

}std::vector

geohash::getneighbors(vec2 centre, vector

preselectedentities)

);}

該演算法筆者還沒有進行全面測試,估計在處理靜態物體,超大空間的時候效率會遠遠高於csp,畢竟後者在儲存空間格仔申請的記憶體就會讓處理器**。

這兩種演算法有乙個好處,將額外的計算開銷(csp空間格仔的指標操作,geohash額外的索引計算)平均分配,位置改變是一直進行的,所以cpu的開銷就變成非同步的了。總體來看,總的計算量增加了,然而卻被分配到了實體們每次發生位移時候,計算效率當然大大提高。

劃分字母空間

字串 s 由小寫字母組成。我們要把這個字串劃分為盡可能多的片段,同一字母最多出現在乙個片段中。返回乙個表示每個字串片段的長度的列表。示例 輸入 s ababcbacadefegdehijhklij 輸出 9,7,8 解釋 劃分結果為 ababcbaca defegde hijhklij 每個字母最多...

Z劃分空間

具體數學第一章第二節的問題,knuth寫的 zoj 1652 數論 這題木有思路啊。盜用下別人的分析 分析 典型的遞推題 設f n 表示n個z字型折線至多平面劃分數。現在增加一條邊a,和3n條線都相交,增加3n 1個區域。再增加一條邊b,與a平行,同樣增加3n 1個區域。最後增加一條邊c,與已有的邊...

python底層的邏輯回歸

python底層的邏輯演算法 回歸 回歸是統計學的乙個重要概念,其本意是根據之前的資料 乙個準確的輸出值。邏輯回歸是 機器學習 這門課的第三個演算法,它是目前使用最為廣泛的一種學習演算法,用於解決分類問題。與線性回歸演算法一樣,也是監督學習演算法。諸如 新聞分類 基因序列 市場劃分等的一些根據特徵劃...