我從來不是一個浪漫的人。每次想到要求婚,腦中浮現的都是那些繽紛、夢幻的場景,但我清楚自己做不到。即便如此,我還是希望能給她一個特別、難忘、只屬於我們的回憶。
幸好,我向來點子很多,加上會寫程式,於是我萌生了一個有點瘋狂的想法,那就乾脆做一款遊戲,讓她在冒險闖關的過程中,逐步發現這個最重要的驚喜:一場為她準備的求婚。
我們都熱愛海洋,也熱愛潛水,所以主題很快就確定下來:一場「海底探險」。 而真正困難的,反而是遊戲機制的設計。我必須在「技術可行」和「不會無聊」之間找到平衡。有時候腦洞一開,會想到很多龐大卻難以實現的玩法,但我不能耗費大量的時間慢慢研究,因為求婚,可是不能拖太久的。
從寫網站到做遊戲,對我來說就像是一場冒險。這篇文章想和大家聊聊,我在遊戲開發過程中遇到的挑戰,以及那些讓我成長的經驗。
最終決定的玩法是在海底潛水時,藉由跟NPC或物品互動逐步取得線索,最終尋得寶箱裡的寶藏。
雖然是使用 Three.js
開發3D遊戲,但我簡化了角色的操控,玩家使用上下左右即可遊玩,不需要用滑鼠移動視角,就像在玩2D遊戲一樣。我在場景中央放置了巨大的珊瑚礁岩,而角色透過左右鍵將會應用三角函數圍繞著珊瑚礁移動。
接下來把NPC及遊戲道具放置好,遊戲的雛形就差不多了。
接下來我做了一個簡易的任務系統來處理玩家跟NPC間的對話以及事件觸發,也同時處理了與道具互動的邏輯,當玩家移動到NPC或道具的交互範圍內按下空白鍵,就會出現相應的對話。
將Three.js與前端框架結合的好處就是能夠方便的刻出UI,譬如說任務系統要使用的對話框與物品欄,而玩家已搜集的道具也可以存在store中方便其他地方判斷。
上面任務系統的介紹中有提到『NPC的交互範圍』,這邊我使用 THREE.Box3 為每個NPC都定義了一個bounding box,並使用 intersectsBox
去偵測玩家是否觸碰到bounding box,當觸碰到時畫面上會出現可以互動的提示。
這邊值得一提的是我使用了 ECS (Entity Component System) 的概念來實作碰撞系統,我將每個需要判定碰撞的物體(Entity)賦予了boundingBox的屬性(Component),並在CollisionSystem中以data oriented的方式於每個update中檢測物體間的碰撞。 這麼一來當我們物體很多時也不需要一一處理碰撞的邏輯,只要幫他們加上boundingBox就輕鬆解決了。
當基礎遊戲流程都完成後我開始想辦法替遊戲增添一些可看性,我決定在某些任務結束後播放CG動畫。
CG動畫有很多好處,除了可以製作更高品質的畫面外,遊戲內實時渲染的動畫勢必會帶來更多複雜的code,並且影響到效能。乍聽之下非常完美,然而這對我來說卻是另一個坑:我根本不會做動畫!也因此我加緊腳步的去學了如何使用Blender。
最終我總共製作了4個場景的CG動畫。完成後我對CG動畫帶來的效果蠻滿意的,雖然以我的技術無法製作出更細緻的動畫,但在播放動畫的瞬間還是給了我一種:『啊!我完成任務了』的感覺。
在遊戲開發中3D模型也是非常重要的一環,我曾經也試著自己學習建模,但依然停留在初學階段,隨著AI技術的興起,我開始嘗試用AI生成我想要的3D模型,產出的結果雖稱不上完美,但對我來說卻也夠用了,而我也得以把更多時間分配給開發遊戲本身。
這邊我列出我有使用過的AI tools:
像當初我就有使用Meshy AI直接生成出帶有骨骼及預設走路動畫的模型:
不過這些AI工具的迭代都太快了,我已經無法以當初接觸時的功能來介紹他們,現在看來這些工具都已經變得更加強大,因此我也推薦有興趣的朋友直接去他們網站玩玩看,基本上他們都有提供免費的額度可以試用。
另外這邊也必須推一下Mixamo,這是個針對人型3D模型的免費動作庫,當我們生成3D模型後可以上傳到mixamo輕易的套用許多動作並導出使用,我專案中的游泳動作就是靠它完成的。
耶嘿!最後順利的求婚成功啦~不然也不會有這篇文章了XD
這些技術挑戰和小巧思,對專業的遊戲開發者來說可能只是日常,但對我而言卻是一種全新的創作方式,我不是在做一款商業遊戲,而是在打造一段我們的回憶。
最後shout out to 鱈魚的酷酷元件,感謝他做的按鈕讓我的求婚多了點惡搞的元素。