[成果分享] ad-game-1: 模仿某廣告的簡單小遊戲

[成果分享] ad-game-1: 模仿某廣告的簡單小遊戲

[Project] ad-game-1: A simple game inspired by an ad you familiar with


2022/08/09 08:48:37

前言

相信大家在滑社群軟體、或是看 Youtube 的時候一定看過這樣的遊戲廣告,什麼 99% 的人都過不了這關、或是明明很簡單的算術小遊戲卻被廣告裡的玩家玩得超爛。這些廣告有很大一部分都是出自 Hero Wars 之手。

有關這個遊戲的內容或評價我就不多加評論,但他的廣告數量多到有人開了專門的 Youtube 頻道 來蒐集這些影片。其實這裡面有滿多遊戲感覺真的滿好玩的,但是廣告的遊戲本身(似乎)卻沒把廣告裡的東西做出來。

這次就以 Hero Wars 廣告遊戲 (也就是上面那張圖) 為發想來源,做出了這個小遊戲 相信你一定可以比廣告裡的玩家玩得更好

遊戲內容

連結

遊戲:https://jcxyis.itch.io/ad-game-1
排行榜:https://globalstats.io/leaderboard/62e619e85f5e882eec8b460c

玩法

使用方向鍵或 WASD 移動。
其他我想應該不用介紹了,就想辦法取得高分吧。

截圖

實作相關

其實這個遊戲是為了作為我自用 Unity toolkit 的範本來做開發,因此基本上沒用到任何外部素材,所以才那麼陽春 (絕不是因為懶)

在碰到牆壁上的問題後,是如何進行數學運算?

我在製作這個功能的時候有參考網路上很多人是建議用外部函式庫 (NCalc之類的),但考量到 nuget 包匯進 Unity 不太容易,也可能會有相容性問題而作罷。但後來發現到有個 C# 原生的解法:在System.Data 裡面有 DataTable.Compute,可以 eval 數學式字串。我也意外發現不僅在 Unity 是支援的,在很挑剔的 WebGL 平台也是能用、而且效能表現也還 OK。所以就直接採用了。

public static double DoMath(String expr)
{
expr = expr.Replace("×", "*").Replace("÷", "/");
try
{
var result = Convert.ToDouble(new DataTable().Compute(expr, null));
return result;
}
catch(Exception e)
{
Debug.LogError($"{e.Message}: {expr}");
return 1;
}
}

如何產生這些數學式

隨著玩家的分數的提升,牆上的問題也會越來越難。這裡我利用一個變數 complexity 來決定題目的難易度:

首先我不會管符號後面的數字,我們先關注符號本身,開一個陣列存這些符號。
如果 complexity 為 1,則表示只會有一個運算符號 (e.g. $+2$),運算符號包含了 $+$、$-$、$\times$、$\div$ 以及一個特例 $($。 加減的出現機率為其他符號的約 3 倍。

當出現 $($ 之後,我會在他後面(一個位置)以後、隨便抽個位置放下括號 $)$,也因為如此,上括號 $($ 不會在第一個或是最後出現,這樣不會有 $(+2+3+4)$、$()+2+3+4$ 或是 $+2+3+4()$ 等等的情況出現。

在製作好符號陣列以後,接下來就可以開始填入數字。要考量的點有

  • 符號陣列中,如果下個符號是 $($,則不要填入數字 e.g. $+(+$ 不能添加成 $+3(2+5$
  • $\div$ 後面不能接 0 (這個函式庫不是會報錯,會直接炸掉)

依照這個規則在符號後面隨便生成數字大致就沒問題。

p.s. 原本還想出代數的題目 (e.g. $3x+2$),但考量到遊戲整體難度已經夠高就算了ww

遊戲的平衡性

這個問題我也有在思考,如果有人運氣爆棚開場直接連來好幾個乘法運算,分數差距會很大。所以我在關卡生成邏輯上有動手腳:依照玩家通過的牆壁數決定最高分數增加量,這樣也能確保玩家活到後面分數差距才會拉大,不會有「刷首抽」的事情發生。

當然,沒有「最大分數扣減量」這種東西,撞到 x0 就是 0 😈