發表文章

千字文射擊 BreakShoot

圖片
[ GitHub ][ Play ] 兒子小學低年級時,學校要求他們背弟子規,所以我想如果他們也能學習千字文應該很不錯。千字文總共一千個字,每個字都不同,是古代的兒童課本。學習千字文可以了解古代社會的規範、歷史常識和禮節禮儀等。平常只要有機會我就會想辨法引導他們去讀讀千字文,這也是製作這個小遊戲的用意。 動態點陣字標題 遊戲的標題是由'BREAKSHOOT'這幾個字元構成,每一個字元的畫素又以千字文裡的一個中文字取代。進入標題畫面時,可以看到有約1秒鐘的動畫,每一個點陣字的中文字畫素隨機打散至畫面四周,然後再飛入重組。 點陣字的畫素取得是先透過Graphics.GenCanvas生成一個大小9x18的虛擬畫布,然後每次從'BREAKSHOOT'裡面取出一個個字元出來,以Graphics.DrawText畫到這個畫布上。之後再以Graphics.GetPixel取出畫布上的每個點,如果不是0就生一個中文字出來。 點陣字的動畫則是把上面的步驟裡生出來的中文字由 STGE 腳本來控制移動。為了實現這個功能,新增了一條API:Stge.LoadScript,可以在Runtime建立新的腳本。整個動作結合起來,如下面程式所示: local function LoadStgeCharScript(c, W, H, script_name, ch) Graphics.FillRect(c, 0, 0, W, H, 0) Graphics.DrawText(c, 0, 0, ch, 1) local script = 'script ' .. script_name for x= 0, W-1 do for y= 0, H-1 do local p = Graphics.GetPixel(c, x, y) if (0 ~= p) then script = script .. string.format(' fire(title_char,$1+%d,$2+%d)', CW * x, CH * y) end end end script = script .. ' end' Stge.LoadScript(s

Escape from Planet Delta by Russell Wallace 文字冒險遊戲

Escape from Planet Delta是以OASYS系統製作的文字冒險遊戲,OASIS是一個用於製作文字冒險遊戲的物件導向的系統。最早Escape是在1980年代中期在Commodore64上以The Quill製作的,在1991年時移植至OASYS系統。Escape發佈於public domain,可以任意複制和散佈source和可執行檔。 OASYS是Object-Oriented Adventure System的縮寫,它的作者是Russell Wallace,在1992年於comp.binaries.ibm.pc發佈的,並且可以在各大FTP站取得。下載的zip包包含一個說明文件檔、二個範例(其中一個是escape)、反組譯器、編譯器及解譯器的C的source、以及MS-DOS的反組譯器、編譯器及解譯器的可執行檔。原始的zip包裡的source缺少include檔不過不難移植到非MS-DOS的平台。 [ Play ] / [ Github ] 1. 編譯程式碼及執行 OASYS製作的遊戲是先以OASYS程式語言撰寫好程式碼後,再以oac編譯器編譯為物件碼,再透過oai解譯器執行。 1.1 OAC 首先你需要使用一個文字編輯器編輯你的遊戲原始碼,一般附屬檔名為s,例如test.s。接著使用oac編譯器把你的遊戲原始碼編譯為物件碼。 請執行以下命令編譯原始碼 oac test.s 或者省略附屬檔名 oac test 編譯成功的話會輸出同檔名的物件檔,不包含附屬檔名。如編譯test.s成功後,產生名為test的物件檔。 編譯過程如果有任何錯誤,則會輸出錯誤訊息。請再根據錯誤訊息,修正程式錯誤,並再重複以上的編譯命令及修正錯誤的流程,直到成功編譯出物件檔。 1.2 OAI 編譯成功的物件檔,可透過oai解譯器執行。 請執行以下命令執行物件檔 oai test 載入並成功啟動遊戲的話,可以看的遊戲輸出的訊息,以及接受文字命令的輸入提示符號。透過文字命令進行遊戲,quit離開。 2. OASYS程式語言 Language 底下介紹基本的OASYS程式語言語法規則,更詳細的說明請參數OASYS說明文件。 2.1 大小寫 Case 雖然底下的範例都是以大寫字母作示範,但OASYS程式語言不區分大小寫英文字母。 2.2 空白字元 Spaces 空白字元包含space、

無限隨機地圖生成 Wang Tiles

圖片
Wang Tiles ---------------- 在研究關於可用於地圖生成的 波函數坍縮 演算法(Wave Function Collapse,底下簡寫WFC)的時候,又看到關於 王式磚 的資料(Wang Tiles,底下簡寫WT)。跟WFC比起來,WT比較容易理解和實作,所以我就先根據WT的原理實作了一個無限隨機地圖生成的測試。 關於WT,這個 網站 有詳細的介紹,同時也有許多tilesets可以用來作為測試資源。WT是數學家發明的遊戲,主要概念是邊緣匹配的tile連通拚接。每一個矩形tile有4個邊和4個角,所以有2種拼法,一種是邊匹配的拼法,一種是角匹配的拼法。 邊匹配 2Edge --------------------- 以邊匹配的拼法為例,每一個矩形tile的4個邊裡面,每個邊如果用0或1表示不同顏色,則總共有2x2x2x2共16種不同的tile。如下圖,生成tilemap時,如果一個tileA的上方的tileB的下邊是1,則tileA的上邊必須也是1,才能連通。同理,右方的tileC的左邊是1的話tileA的右邊也要是1,等等。整個tilemap的每一個tile都符合這個規則,就是一個符合WT的tilemap。 生成隨機tilemap的方式不只一種,一個簡單的方法是從左到右從上到下,一個一個tile生成。每一個新tile生成時,針對它的上方及左方2個己生成的tile的邊建立連通狀態(上方tile的下邊是1則新tile的上邊也需為1,左方tile的右邊為1則新tile的左邊也需為1),而新tile的右方及下方的邊則隨機選擇0或1。 如下圖,針對tileX的4個邊依序上右下左以2進制編碼為1,2,4,8,這樣在生成tilemap時可以使用bit運算操作方便判斷。 這樣16種tile的編號也同時是它的編碼。如tile0表示4個邊都是0,tile8表示左邊是1其餘3邊是0,tile13表示上左下邊是1右邊是0,等等。底下是生成邊匹配的tilemap的虛擬碼。 void gen2EdgeWangTilesmap(cx, cy) {   foreach tile i of tilemap {     tile = 0;     if (tilemap[upper] & 4) {           // Match upper edge.      

Good Game Editor HTML5 porting (resource browser)

圖片
斷斷續續製作了一個HTML5版本的Good Game Editor,一方面是作為測試及學習web相關技術,一方面也是利用這個過程持續對good作點改良。雖然目的是想作一個HTML5版的編輯器,但實際上目前只作到resource browser,可以在web browser開啟good package作資源檢視。目前大部份的功能還是原來的C++ code直接以emscripten編譯成javascript,再加上少部份javascript,最後利用w3.css作排版。 < 試試 > 點擊連結會列出網站上good/uploads目錄下的所有good package,可以再點擊package的play來試玩或者是edit開啟編輯器(res browser)。 目前編輯器大致可以檢視所有類型的資源,包含聲音(audio)、貼圖(texture)、精靈(sprite)、地圖(tilemap)、關卡(level)、腳本(script)及粒子腳本(particle)。 如下圖,為點擊herobye.zip這個package的Edit時顯示的第一個畫面。 編輯器畫面主要分為3個部份。左側依據不同類型資源,列出所有資源列表。右側是屬性顯示區,顯示選取的物件屬性資料。中間區域為編輯區,依據選取的不同類型物件作不同顯示。 下圖是選取了聲音(audio)類型的資源,編輯區顯示標準的播放聲音介面。 下圖是選取了貼圖(texture)類型的資源。 如下圖是選取了精靈(sprite)類型的資源,編輯區顯示此精靈每個frame的資訊及在上方播放精靈動畫。而右側屬性區也會顯示此精靈使用的貼圖物件。 下圖是選取的地圖(tilemap)類型的資源,編輯區顯示己編輯的tilemap,右側屬性區也會顯示目前地圖使用的貼圖。 下圖為選取關卡(level)類型的資源,編輯區顯示關卡內容,右側屬性區上方顯示關卡內物件的階層圖。點擊階層圖上的子物件時,右側屬性區下方會再顯示選取子物件的屬性資訊。 下圖為選取腳本(script)類型的資源。 下圖為選取粒子腳本(particle)類型資源。編輯區有二個分頁,左分頁Source同腳本一樣顯示script內容。右分頁Test為粒子執行preview畫面,同時右側屬性區上方也會列出所有可測試的particle script名稱,點擊時立即執行作preview。

867的HTML5移植

圖片
[ PLAY ] 這個遊戲是較早期的作品,所以使用的技術是以當時自己較熟悉的 Win32 相關技術製作。遊戲核心部份一開始就己分離出來,但還不是100%跨平台。畫面部份是以Win32 GDI呈現,以及透過Windows視窗機制處理輸入。本次目標是將遊戲移植到 HTML5 ,主要的工作有三個部份。 將遊戲核心Gameplay確實作到跨平台。 將畫圖及輸入部份抽離作到跨平台。 將遊戲移植為HTML5可以在Browser上執行。 第一部份己幾乎完成了,只需再作點小修改就能達成。主要的移植工作在於第二和第三部份,以下是這部份工作的重點記錄。 抽離繪圖層 因為867和Win32 GDI緊密結合,一時無法輕易的將繪圖層抽離出來。萬事起頭難,可以先從最簡單的改良開始,一次一小步逐步重整。首先增加一個Renderer類別,只包含一個很大略的一個render函數。而render函數的實作,是根據當前遊戲狀態透過renderTitle和renderGame二個函數實作遊戲的全部繪圖。 class Renderer { public: void render(const Game &game, CDCHandle& dc) { switch (game.iStage) { case Game::STAGE_TITLE: renderTitle(dc); break; case Game::STAGE_GAME: renderGame(dc, Game::MENU_NONE); break; case Game::STAGE_MENU: renderGame(dc, Game::MENU_GAME); break; case Game::STAGE_DIE: renderGame(dc, Game::MENU_NONE); break; case Game::STAGE_OVER: renderGame(dc, Game::MENU_OVER); break; case Game::STAGE_WIN: renderGame(dc, Game::MENU_NONE);

耐心烏龜 Patience

圖片
有一次去看診的時候,因為等了好久等到有點快失去耐性,看完診花了不少時間。在回家的路上有感而發,想說不知道有沒有什麼可以訓練或培養耐性的方法。如果沒有的話,或者我自己可以作個APP來達到這個目的,最後就作了這個APP。 < 玩 玩 > < Android > 一開始想到的不是烏龜,而是主畫面是一個泡泡。這個泡泡會愈來愈大,但很容易就破掉。比如不小心點了畫面、程式進入背景、有來電或收到訊息通知等等,都會讓泡泡破掉。程式的目的就是想辨法讓泡泡持續變大,也就是你愈有耐心的保護它,就愈成功。可能可以顯示一個存活時間,用來表示耐心度。 後來一邊考慮程式內容時,一邊把泡泡改成了烏龜。同時考慮到,如果這隻烏龜很容易就死掉,要用這種方式來訓練耐心似乎很難,甚至會有反效果。考慮到一次性的遊戲方式,以存活度來評價耐心度有難度,改變為養成性質的作法。現在不會死掉了,存活時間是累計制的。這樣子應該會比較容易讓人持續的去作這作事,長期下來應該就能提高點耐心吧。 改成養成性質的作法後,其它的設計就能對應調整。首先除了存活度(存活時間)之外,再加上一個等級。這個等級的定義,只是簡單的每次烏龜從左走到右就升級一次。等級每升一級,烏龜就長大1個pixel。同時等級也對應烏龜移動速度,LV10表示每10秒烏龜走1個pixel。以上是核心功能,其它還設計了幾個裝飾畫面的功能。如上方背景日夜變化、月相變化及顯示12星座等。 以下作重點說明。 背景連續山脈圖 背景的山是先建好一個div元素,以CSS設定背景水平重複。   // CSS.   #mountains {     background-repeat:repeat-x;     background-position:bottom;     text-align:     right;font-size:48px;   }   // HTML.   <div style="mountains">   </div> 重複的圖片則以一記憶體canvas畫了一個山型emoji後產生。 var mountains = document.getElementById('mountains'); var url = getCharImgUrl(32, '⛰️');