Houdini日記 | 閑得蛋疼之可視化小甲魚吃魚小游戲

前天晚上睡前突然想起了當初接觸Python時的靈魂導師小甲魚,然后想到了他的一道經典課后題咆耿。

游戲編程:

按以下要求定義一個烏龜類和魚類并嘗試編寫游戲。
假設游戲場景為范圍(x, y)為0<=x<=10凯正,0<=y<=10
游戲生成1只烏龜和10條魚
它們的移動方向均隨機
烏龜的最大移動能力是2(Ta可以隨機選擇1還是2移動)拍埠,魚兒的最大移動能力是1
當移動到場景邊緣芯急,自動向反方向移動
烏龜初始化體力為100(上限)
烏龜每移動一次勺届,體力消耗1
當烏龜和魚坐標重疊,烏龜吃掉魚娶耍,烏龜體力增加20
魚暫不計算體力
當烏龜體力值為0(掛掉)或者魚兒的數量為0游戲結束涮因。

思路分析

首先可以確定的是這種需要過程遞推的方式在solver內進行。

那么在solver之前需要解決:

1.隨機分布

可以把烏龜和魚抽象成兩組點伺绽,用pointWangle在 0-10的范圍內撒點养泡。同時要注意坐標取整問題,可以借助floor()函數奈应。(如果有round()可以四舍五入就好了)

Solver內需要解決:

2.隨機移動

因為結果需要用關鍵幀遞推來實現澜掩,所以隨機移動的隨機seed也可以用當前幀數也就是@Frame茸炒,作為seed宇挫。
rand()返回的隨機數是[0,1] 的浮點值,借助fit01() 適配到 [-1,1] 或者[-2,2] 同時用floor()取整就可以模擬烏龜和魚的移動步長了氏捞。

3.體力值惩妇,移動消耗

可視化的體力值可以用pscale來表現株汉,暫定初始值為1,solver的每一次運算歌殃, pscale -= 0.01乔妈。

4.烏龜吃魚

只要判斷魚的點和烏龜的點坐標是否重合就可以了,如果相同:

  1. 烏龜的體力值pscale += 0.2 氓皱,
    2.魚的點被去除路召,這里用到removepoint() 勃刨。
    如果不相同則繼續(xù)進行下一輪推導。


Ok, let's dive into Houdini!

首先是在空白的集合體內撒點股淡,這里用到pointWrangle身隐。

float seed = chf('random_seed');
for(int i=0; i<10; i++){
    int fishX = floor((rand(i+seed)*10));
    int fishZ = floor((rand(i+134+seed)*10));
    
    vector fishP = set(fishX,0,fishZ);
    addpoint(0, fishP);
}

注:直接創(chuàng)建wrangle并用addpoint()理論上是不會出現點的,因為所有的wrangle都需要輸入端唯灵。
再注:同樣的seed返回的隨機數是相同的贾铝,這里用手動添加seed和增加常量的方法,目的是讓fishX和fishZ的值有所區(qū)別埠帕。

需要將Run Over從point 改為Detail once

同樣的方法創(chuàng)建烏龜的點組忌傻,借助attribute create為烏龜組添加pscale屬性,默認更改為1搞监,同時為小魚組添加一個隨機0.2-0.4的pscale,主要是視覺上比較好看镰矿。


為兩組點定義組名
geometry spreadsheet觀察參數變化

從這里可以發(fā)現琐驴,最后一個永遠都是烏龜,前面的是小魚秤标。那么只要通過npoint()來查找總點數-1 = 烏龜的點序列绝淡。


接下來進入solver開始推導,Solver主要解決三個問題苍姜,

1.魚的移動牢酵,每次在[-1,1]的整數值間選擇;
2.烏龜的移動衙猪,每次在[-2,2]的整數值間隨機選擇馍乙,且伴隨體力消耗-0.01;
3.烏龜吃魚垫释,當烏龜點和小魚點重合時丝格,小魚點被剔除,且烏龜體力 +0.2棵譬;
需要解決一個問題显蝌,魚和烏龜的移動是二維的,如何選定到底是在X軸還是在Z軸移動订咸?這里可以基于當前幀做隨機數曼尊,然后取整返回0或者1,定義一下0代表移動X脏嚷,1代表移動Z骆撇。
同時要注意,rand(@Frame) 返回的值是在[0,1]區(qū)間內的父叙,如果直接floor()取整艾船,獲得1的概率非常小葵腹,顯然不公平。所以這里需要將 [0,1]區(qū)間擴大到[0,2]屿岂,此時再用floor()践宴,返回0和1的概率就相同了。

結構圖

首先是魚的游動問題爷怀,選定fish所在分組阻肩,分別將X軸和Z軸移動作為屬性捆綁到每個點,通過隨機數配合不同的seed來完成隨機篩選运授,這里額外定義了一個@first屬性烤惊,用來控制在X軸或Z軸移動。
然后需要判斷是否存在“碰壁”情況吁朦。如果在0位置且移動數值是-1柒室,則返回0-(-1) ,如果是在9位置且移動數值為1逗宜,則返回9-(1)雄右,在0和9之間,就直接簡單粗暴 P.x + stepX就好了纺讲。

小魚移動代碼如下
i@stepX = floor(fit01(rand(@Frame*(@ptnum+1)+1231235)*2,-1,1));
i@stepZ = floor(fit01(rand(@Frame*(@ptnum+1)+1235)*2,-1,1));
i@first = floor(fit01(rand(@Frame*(@ptnum+1)+12345)*2,0,1));

//first = 0 ---------------> moveX
if(@first == 0){
    i@stepZ =0;
    
    if(@P.x <= 0 && @stepX < 0){
        @P.x -= @stepX;
    }
    if(@P.x >= 9 && @stepX > 0){
        @P.x -= @stepX;
    }  
    if( 0<@P.x<9){
        @P.x += @stepX;
    }
}

//first = 1 ---------------> moveZ
if(@first == 1){
    i@stepX = 0;
    
    if(@P.z <= 0 && @stepZ < 0){
        @P.z -= @stepZ;
    }
    if(@P.z >= 9 && @stepZ > 0){
        @P.z -= @stepZ;
    }  
    if( 0 < @P.z < 9){
        @P.z += @stepZ;
    }
}

同樣的擂仍,烏龜移動的代碼也可以在小魚的基礎上更改,只需要把數值范圍擴大到[-2,2]就好了熬甚,這里記得更改一下隨機seed逢渔,以便減少魚和烏龜移動路徑的重復性。同時不要忘記勾選wrangle針對的烏龜組乡括。(此處更加明白了面向對象編程的重要性)

烏龜移動代碼如下
i@stepX = floor(fit01(rand(@Frame*(@ptnum+1)+123123565)*2,-1,1));
i@stepZ = floor(fit01(rand(@Frame*(@ptnum+1)+123235)*2,-1,1));
i@first = floor(fit01(rand(@Frame*(@ptnum+1)+12234345)*2,0,1));

//first = 0 ---------------> moveX
if(@first == 0){
    i@stepZ =0;
    
    if(@P.x <= 0 && @stepX < 0){
        @P.x -= @stepX;
    }
    if(@P.x >= 9 && @stepX > 0){
        @P.x -= @stepX;
    }  
    if( 0<@P.x<9){
        @P.x += @stepX;
    }
}
//first = 1 ---------------> moveZ
if(@first == 1){
    i@stepX = 0;
    
    if(@P.z <= 0 && @stepZ < 0){
        @P.z -= @stepZ;
    }
    if(@P.z >= 9 && @stepZ > 0){
        @P.z -= @stepZ;
    }  
    if( 0 < @P.z < 9){
        @P.z += @stepZ;
    }
}
//pscale ---------------> -0.01
f@pscale -= 0.01;
注:不要忘記烏龜是有體力值的肃廓!每次移動體力值-0.01。


接下來就是烏龜吃魚的部分了诲泌!

烏龜如果沒吃到魚自然不需要有什么運算亿昏,直接繼續(xù)解算繼續(xù)走就可以了。
如果烏龜吃到了魚档礁,首先烏龜體力值+0.2角钩,然后小魚被從幾何體中剔除。
因為是在烏龜和魚都存在的幾何體層面工作呻澜,分組篩選已經行不通了递礼,但是!之前我們說過烏龜肯定是最后一個點羹幸,所以求得的總點數-1 = 烏龜的點序號脊髓。借助npoints()可以返回當前幾何體的點數。
烏龜吃魚需要用到for循環(huán)栅受,循環(huán)的次數為魚的個數将硝,也就是總點數-1 恭朗。每次移動后用烏龜的坐標和每一條魚的坐標去對比,如果相同則魚被吃掉同時烏龜體力值+0.2依疼。
讀取烏龜和小魚的點坐標痰腮,可以借助point()。


point
借助setpointattrib()來修改烏龜的pscale律罢。
setpointattrib
借助removepoint()來剔除被吃掉的點膀值。
removepoint
注:這兩個函數內的point_num都可以用循環(huán)中的指針i來引導。


結構如下

bite.png

代碼如下

int npt = npoints(0);

vector turtleP = point(0,'P', npt-1);
for( int i=0; i<npt-1; i++){
    if( point(0, 'P', i) == turtleP){
    float npscale = point(0, 'pscale', npt-1) + 0.2;
    setpointattrib(0, 'pscale', npt-1, npscale);
    removepoint(0, i);
    }
}

至此主要程序架構就結束了误辑,通過copy to point 選擇不同的組來進行幾何體復制沧踏,這里用了Houdini自帶的烏賊和海龜玩具。


copytopoint選項注意勾選pack and instance

注:

勾選pack and instance是為了讓幾何體以內存指針形式存在巾钉,從而不需要復制詳細信息轉而以一個點來取代翘狱,也就是之前我們寫入的小魚和烏龜的點。
同時要檢查geometry spreadsheet中點的坐標是否正確砰苍,如果和輸入點的數值有差別潦匈,通常是因為沒有將Pivot Location 改為Origin。

最終完成的烏龜吃魚動圖


如果深入還可以從以下幾點入手:
1.幾何體的移動方向伴隨轉動师骗;
2.幾何體移動從跳動變?yōu)榫€性移動;

有時間再回來迭代吧!先睡了讨惩!

Cheers !

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末辟癌,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子荐捻,更是在濱河造成了極大的恐慌黍少,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件处面,死亡現場離奇詭異厂置,居然都是意外死亡,警方通過查閱死者的電腦和手機魂角,發(fā)現死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門昵济,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人野揪,你說我怎么就攤上這事访忿。” “怎么了斯稳?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵海铆,是天一觀的道長。 經常有香客問我挣惰,道長卧斟,這世上最難降的妖魔是什么殴边? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮珍语,結果婚禮上锤岸,老公的妹妹穿的比我還像新娘。我一直安慰自己廊酣,他們只是感情好能耻,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著亡驰,像睡著了一般晓猛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凡辱,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天戒职,我揣著相機與錄音,去河邊找鬼透乾。 笑死洪燥,一個胖子當著我的面吹牛,可吹牛的內容都是我干的乳乌。 我是一名探鬼主播捧韵,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼汉操!你這毒婦竟也來了再来?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤磷瘤,失蹤者是張志新(化名)和其女友劉穎芒篷,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體采缚,經...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡针炉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了扳抽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片篡帕。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖贸呢,靈堂內的尸體忽然破棺而出赂苗,到底是詐尸還是另有隱情,我是刑警寧澤贮尉,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布拌滋,位于F島的核電站,受9級特大地震影響猜谚,放射性物質發(fā)生泄漏败砂。R本人自食惡果不足惜赌渣,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望昌犹。 院中可真熱鬧坚芜,春花似錦、人聲如沸斜姥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽铸敏。三九已至缚忧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杈笔,已是汗流浹背闪水。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蒙具,地道東北人球榆。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像禁筏,于是被迫代替她去往敵國和親持钉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359