標(biāo)題所指的糞扣並非變數(shù)、函式命名問(wèn)題,而是效能爛掉。
這篇沒(méi)有改過(guò)的程式碼可以抄。
在 RPG Maker MV 中,地圖上出現(xiàn)的其他物件被稱為 event (事件) ,而判斷 event 與一 event 是否產(chǎn)生碰撞,流程是這樣的:
每個(gè) event 在每幀都會(huì)呼叫一次自己的 update 函式。
每個(gè) event 都要自己移動(dòng)的前一刻判斷。
一個(gè) event 要詢問(wèn)所有的 event 。詢問(wèn)該 event 是否在指定的座標(biāo)且無(wú)法被穿透。
指定的座標(biāo)且無(wú)法被穿透被寫成這樣:
版本:
update 流程:
往某個(gè)方向走:
確認(rèn)可走:
對(duì)個(gè)別 event 確認(rèn)碰撞:
取得候選 event :
發(fā)現(xiàn)問(wèn)題了?如果同一幀中所有 event 同時(shí)要移動(dòng),有 10 個(gè) event 時(shí)會(huì)呼叫上面的函式 10 * 10 = 100 次; 100 個(gè)則是 100 * 100 = 10000 次; 1000 個(gè)則是 1000 * 1000 = 1000000 次,呼叫次數(shù)呈現(xiàn) event 數(shù)量的平方。
那麼可以怎麼改進(jìn)呢?能不能只看有機(jī)會(huì)撞到的 event 就好了?比方說(shuō)只看在某 x,y 座標(biāo)的 event ,並透過(guò) O(1) 存取的方式得到他們:
1. 在所有 event 呼叫自己的 update 之前,重新建表:位置 -> 存放在該位置的 event 的陣列。不計(jì) Garbage Collection (垃圾回收)的時(shí)間時(shí),時(shí)間花費(fèi)與 event 數(shù)量呈線性。
2. 假裝 event 鮮少重疊。
3. 檢查碰撞時(shí)將座標(biāo)代入表中,得到寥寥無(wú)幾的 event 。
4. 每個(gè) event 只檢查寥寥無(wú)幾的 event ,當(dāng) O(1) 。
5. 把 1. 與 4. 的時(shí)間花費(fèi)均攤到每個(gè) event 的 update 上,使得時(shí)間複雜度與沒(méi)檢查碰撞相同。
6. 若有兩個(gè) event 同時(shí)移動(dòng)到同一格,就給他移,管他的。或是移動(dòng)後更新一下表格。
Q1: 為什麼寫晶晶體?
A1: 並非所有人都熟悉 RPG Maker MV 的翻譯,此舉是為避免因 RPG Maker MV 的翻譯造成語(yǔ)句上理解的歧義。當(dāng)中途變成使用另一個(gè)語(yǔ)言時(shí),你會(huì)很清楚知道那是關(guān)鍵字,而不會(huì)拿原詞彙的意思解讀。如果以上理由說(shuō)服不了你,你可以試著把英文的部分換回去中文,會(huì)有多難以理解到底是取原意思,還是那是關(guān)鍵字。
Q2: 我建表了,還是卡,為什麼?
A2: 因?yàn)檫@部分只是冰山一角。
這篇沒(méi)有改過(guò)的程式碼可以抄。
在 RPG Maker MV 中,地圖上出現(xiàn)的其他物件被稱為 event (事件) ,而判斷 event 與一 event 是否產(chǎn)生碰撞,流程是這樣的:
每個(gè) event 在每幀都會(huì)呼叫一次自己的 update 函式。
每個(gè) event 都要自己移動(dòng)的前一刻判斷。
一個(gè) event 要詢問(wèn)所有的 event 。詢問(wèn)該 event 是否在指定的座標(biāo)且無(wú)法被穿透。
指定的座標(biāo)且無(wú)法被穿透被寫成這樣:
Game_CharacterBase.prototype.posNt = function(x, y) { // No through return this.pos(x, y) && !this.isThrough(); }; |
版本:
update 流程:
往某個(gè)方向走:
確認(rèn)可走:
對(duì)個(gè)別 event 確認(rèn)碰撞:
取得候選 event :
發(fā)現(xiàn)問(wèn)題了?如果同一幀中所有 event 同時(shí)要移動(dòng),有 10 個(gè) event 時(shí)會(huì)呼叫上面的函式 10 * 10 = 100 次; 100 個(gè)則是 100 * 100 = 10000 次; 1000 個(gè)則是 1000 * 1000 = 1000000 次,呼叫次數(shù)呈現(xiàn) event 數(shù)量的平方。
那麼可以怎麼改進(jìn)呢?能不能只看有機(jī)會(huì)撞到的 event 就好了?比方說(shuō)只看在某 x,y 座標(biāo)的 event ,並透過(guò) O(1) 存取的方式得到他們:
1. 在所有 event 呼叫自己的 update 之前,重新建表:位置 -> 存放在該位置的 event 的陣列。不計(jì) Garbage Collection (垃圾回收)的時(shí)間時(shí),時(shí)間花費(fèi)與 event 數(shù)量呈線性。
2. 假裝 event 鮮少重疊。
3. 檢查碰撞時(shí)將座標(biāo)代入表中,得到寥寥無(wú)幾的 event 。
4. 每個(gè) event 只檢查寥寥無(wú)幾的 event ,當(dāng) O(1) 。
5. 把 1. 與 4. 的時(shí)間花費(fèi)均攤到每個(gè) event 的 update 上,使得時(shí)間複雜度與沒(méi)檢查碰撞相同。
6. 若有兩個(gè) event 同時(shí)移動(dòng)到同一格,就給他移,管他的。或是移動(dòng)後更新一下表格。
Q1: 為什麼寫晶晶體?
A1: 並非所有人都熟悉 RPG Maker MV 的翻譯,此舉是為避免因 RPG Maker MV 的翻譯造成語(yǔ)句上理解的歧義。當(dāng)中途變成使用另一個(gè)語(yǔ)言時(shí),你會(huì)很清楚知道那是關(guān)鍵字,而不會(huì)拿原詞彙的意思解讀。如果以上理由說(shuō)服不了你,你可以試著把英文的部分換回去中文,會(huì)有多難以理解到底是取原意思,還是那是關(guān)鍵字。
Q2: 我建表了,還是卡,為什麼?
A2: 因?yàn)檫@部分只是冰山一角。