從零開始自製遊戲引擎 IV

這幾天要麼刷題,要麼寫引擎,要麼寫文章,都沒怎麼說好玩的事,這期我來講講我開發引擎過程中遇到的二三事吧。

比較雜亂,想到哪寫到哪,主要娛樂向。

第一件事

第二件事

鑒於第三篇文章被建議修改的原因,我已經刪除。

第三件事

下文涉及比較複雜的Kotlin語言特性。

那就是我終於體會到了什麼叫「對一種技術上癮到走火入魔」的感受。曾經看到知乎上一個問題叫「玩C++模板元編程到走火入魔是怎樣的體驗?」,看到了許多我這個不會寫工程C++的弱渣看不懂的代碼。我只知道,那滿屏的template就是這些吸毒者的罪惡之源。

真愛生命,遠離模板。而且OI有句古話,「有了STL,媽媽再也不用擔心我TLE了!」,畢竟STL裡面有些本身可以O(1)的演算法經常為了內存上的優化而做成了O(n)的,Java的范型集合庫也有這個問題,這多半就是那天我在一張圖片裡面廣搜搜半天出不來結果的原因(長跪不起)。

那麼我是又是玩什麼走火入魔了呢?使用Kotlin+anko開發過Android的人,應該對這個東西不陌生吧:

async() { // Access network or database, or some bad stuff #(滑稽) uiThread { // Display data }}

著名的async代碼塊,再也不需要那糟糕的AsyncTask了。而我也實現了這麼一個代碼塊:

inline fun <T> T.async(crossinline block: T.() -> Unit): T { Thread({ block.invoke(this) }).start() return this}

然後你在你的代碼裡面可以直接調用(這也是寒冰引擎截圖功能的正確使用方式):

async() { ImageIO.write(getScreenCut().image, "png", File("截屏" + cnt++ + ".png"));}

然後我發現這太好玩了,於是專門在utils包下弄了個叫kotlin的包,裡面專門放這種東西。因為extension只有在Kotlin中使用才會體現出它的方便,所以這些東西只支持Kotlin。

inline fun <T> T.loop(block: T.() -> Unit): T { while (true) block.invoke(this)}inline fun <T> T.loop(count: Int, block: T.(Int) -> Unit): T { for (index in 0..count - 1) block.invoke(this, index) return this}inline fun <T> T.loopIf(condition: () -> Boolean, block: T.() -> Unit): T { while (true) if (condition.invoke()) block.invoke(this)}inline fun <T> T.forceRun(block: T.() -> Unit): T { try { block.invoke(this) } catch (e: Throwable) { } return this}inline fun <T> T.forceGet(default: Any, block: T.() -> Any) = try { block.invoke(this) } catch (e: Throwable) { default }/** * if theres exception, it will exit */inline fun <T> T.forceLoop(block: T.() -> Unit) = forceRun { loop(block) }fun <T> T.pause(length: Int) = pause(length.toLong())fun <T> T.pause(length: Double) = pause(length.toLong())fun <T> T.pause(length: Long): T { Thread.sleep(length) return this}

沒錯,壓行的習慣是OI撿來的。

然後你們曾經在第二章看到過的那一段刷新主線程的代碼,已經發生了翻天覆地的變化:

// Original 原來的樣子while (true) if (!paused && !stopped) { try { onRefresh() } catch (ignored: Exception) { } timeListeners.forEach { it.check() } panel.repaint() Thread.sleep((1000.0 / refreshPerSecond).toLong())}// Current 魔改版loopIf({ !paused && !stopped && refresh.ended()}) { forceRun { onRefresh() } timeListeners.forEach { it.check() } panel.repaint()}

資料庫讀寫、音頻播放什麼的全部都被我下了毒。。。

第四件事

那就是我發現了發文章的時間對文章的贊同數是有影響的。

第一篇文章我是在晚上發的,當天晚上就來了60多個贊同。第二天早上我就把第二章發了,結果到現在也只有13個。第三篇是當天中文發的(間隔時間也太短了吧。。),效果接近。

估計是因為晚上大家都在線,我一發文章,你們在時間線裡面就看得到。所以我決定在晚上發這篇文章。嘿嘿。

說實話贊同數對於寫文章的人來說是一種莫大的鼓勵啊!

第五件事

我一直對Java的性能很不自信,以為Java卡,Java慢,反正就是垃圾語言。所以我一開始給引擎固定的刷新率是40fps(我提供了API修改這個值),然後整個畫面看起來有點卡,不過還行,起碼看得過去。然後後來在和凱凱(3A)聊天時,提到了fps這個東西。

凱凱是元火引擎的作者,元火是個C++引擎。我發現fps原來都是幾百上千的,於是也想試試,看看Java(Kotlin)引擎性能怎麼樣。

然後我把這個調到了1000fps,發現毫無卡頓,如絲般順滑。。我當時就被這個流暢的畫面驚艷到了,Java的渲染也沒那麼糟糕嘛。看來無論什麼事都得試試才行啊。

說實話我對Java的負面印象全是C++吧吧務團隊給我留下的,我曾經以Java廚的身份被他們集體吊打,並且被打為「可見Java廚並不知道Java是什麼,就廚了」,當時給我留下了很深的陰影(特大霧),讓我再一次意識到自身的弱小。。

重拾自信!

第六件事

上期已經說過了,在commit message裡面寫fuck JRuby,被JRuby的開發者之一上門查水表,看到郵件嚇得我一身冷汗。這件事告訴我們不能在commit message裡面亂寫東西。不過人家還幫我解決了疑惑,讓我受寵若驚。

另外,總感覺JRuby的人在盯著我。。

第七件事

讀者們,這玩意掛在GitHub上,求各位客官給個star,或者把release弄下來寫點小遊戲唄。

隨時歡迎各種pull request,各種issue,一定看得到!五天寫了6k+行代碼,刪了2k+行代碼,還是在我是壓行狂魔的基礎上,我寫這個一直樂在其中。但是沒人用就很尷尬了,我的wiki寫的挺詳(la)細(ji),最多遺漏一兩個剛更新的API。我的README也寫的很誘(wei)人(suo),但是就是沒人用啊,唉。。。。

順帶一提

寒冰引擎的截圖略扯淡,雖然畫面很流暢,但是截圖出來的效果是這樣的:

謎之錯位。更神奇的是,那個我吹了很多次的65行Flappy bird,我加了幾行代碼,讓它在你死的時候截圖,效果出來是這樣的:

這個bird的力氣真大,柱子都被你撞動了。當時看到圖的時候真是戳笑點,哈哈。

轉載自我的博客,原文鏈接:ice1000.github.io/2016/


推薦閱讀:

為什麼 Qt Creator 的編譯如此之慢?
如何學習程序語言比如C#之類?
如何學習開源代碼?有什麼好的書籍可以引導初學者學習?
編程是否該作為基礎教育的一部分?

TAG:游戏引擎 | 编程 | Kotlin |