天天看點

《HTML5 Canvas開發詳解》——1.9 第二個示例:猜字母

本節書摘來自異步社群《html5 canvas開發詳解》一書中的第1章,第1.9節,作者: 【美】steve fulton , jeff fulton 更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

現在來快速看一下另一個廣泛提及的 “hello world!”類型的應用程式示例——“猜字母”遊戲。本章通過這個示例來說明用javascript編寫canvas程式比用canvas api多了哪些工作量。

如圖1-4所示的遊戲當中,玩家要做的是猜出計算機從字母表中随即抽取的字母。遊戲會記錄玩家已經猜了多少次,列出已經猜過的字母,并且告訴玩家是需要往哪個方向猜(往z方向猜還是往a方向猜)。

《HTML5 Canvas開發詳解》——1.9 第二個示例:猜字母

1.9.1 遊戲如何工作

這個遊戲的基本結構與“hello world!”的設定相同,canvasapp()是主函數,所有其他函數都定義為局部函數。這裡使用drawscreen()函數在畫布上顯示文本。不過,本示例中也包括了其他一些函數,後面的章節會繼續描述。

1.9.2 “猜字母”遊戲的變量

這裡是遊戲中将要用到的所有變量的清單,它們都在canvasapp()中定義并初始化,是以它們的作用域都被限定在本地定義的封裝函數内。

guesses:這個變量儲存玩家按鍵的次數,次數越少說明他玩得越好。

message:這個變量用來向玩家提示遊戲的玩法。

letters:這個數組儲存字母表中的每一個字母,一方面用來随機挑選一個遊戲的秘密字母,另一方面也用來計算字母在字母表中的相對位置。

today:這個變量儲存目前日期,僅用于在螢幕上顯示,并無其他目的。

lettertoguess:這個變量儲存目前被猜的遊戲秘密字母。

higherorlower:這個變量存儲文本 “higher”或“lower”,具體取決于最後一次猜的字母與秘密字母的位置關系。如果秘密字母離“a”更近,程式給出“l- ower”提示,如果離“z”更近,則給出“higher”提示。

lettersguessed:這個數組儲存玩家已經猜過的字母集合。程式将把這些字母顯示在螢幕上,提示玩家他已經猜過什麼字母。

gameover:這個變量在玩家獲勝前都設為false,程式能通過它知道何時在螢幕上顯示“you win”資訊,玩家赢了之後就不用再猜了。

代碼如下所示。

1.9.3 initgame()函數

initgame()函數為玩家初始化遊戲。以下是兩段重要的代碼。第一段代碼從字母數組中找出一個随機字母,然後将其儲存在lettertoguess變量中。

第二段代碼為dom的window對象添加了一個事件監聽器,以“監聽”鍵盤的keyup事件。當某個鍵被按下時,将調用eventkeypressed事件處理函數檢測按下的字母。

以下是函數的全部代碼。

1.9.4 eventkeypressed()函數

當玩家按下一個鍵時将調用此函數,這個函數包含了遊戲中的大部分操作。javascript中的每個事件處理函數都會傳遞event對象。該對象中包含發生事件的相關資訊,這裡使用e參數表示該對象。

首先檢測gameover變量是否為false,如果是false,則繼續檢測玩家按下的是哪個鍵。以下代碼實作了該功能。第一行代碼從事件中獲得按鍵值,并将其轉換為一個字母表中的字母,用于與lettertoguess中存儲的字母進行比較。

下一行代碼将這個字母轉換為小寫字母,如果玩家不小心打開大寫鎖定鍵也可以檢測大寫字母。

接下來增加guesses變量的計數,用于顯示猜測次數。然後使用array.push()方法将字母添加到lettersguessed數組。

現在檢測遊戲的目前狀态并給玩家回報。首先,測試letterpressed與lettertoguess是否相同,如果相同玩家就赢了。

如果玩家沒赢,程式需要分别獲得lettertoguess以及letterpressed在數組letters中的索引。下面将用這些數值計算是應該顯示“higher”還是應該顯示“lower”,或者顯示“that is not a letter.”(這不是一個字母)。為此,這裡使用數組的indexof()方法獲得每個字母的對應索引。由于數組是按字母順序排列的,是以判斷顯示哪條資訊就非常容易。

現在來進行檢測。首先,如果guessindex小于0,意味着indexof()傳回了-1,也就是說按鍵不是一個字母,那麼就顯示一條錯誤資訊。

剩下的測試就簡單了。如果guessindex大于letterindex就把higherorlower文本設為 “lower”。反之,若guessindex小于letterindex就把higherorlower文本設為 “higher”。

最後,調用drawscreen()在螢幕上進行繪制。

1.9.5 drawscreen()函數

下面開始編寫drawscreen()函數。之前已經學習過其中的大部分代碼了——代碼幾乎與“hello world!”中的代碼相同。例如,這裡使用canvas文本api在螢幕上繪制多個變量。僅需要設定一次context.textbaseline = 'top'就可以對所有顯示的文本生效,還可以使用context.fillstyle改變顔色,并且可以使用ontext.font改變字型。

這裡最有趣的事就是顯示lettersguessed數組的内容。在畫布上,數組将顯示為一組用逗号分隔的字元串,例如:

為了輸出這個字元串,隻需使用lettersguessed數組的tostring()方法,即可以使用逗号間隔的方式列印出玩家猜到的數組。

接下來還需檢測gameover變量。如果結果為真,程式在螢幕上使用大字号(40px)顯示文本“you got it!”(你勝利了),這樣使用者就知道自己獲勝了。

以下是函數的完整代碼。

1.9.6 導出canvas到圖像

之前,本章簡要讨論了canvas對象的todataurl()屬性。這裡将使用這個屬性讓使用者能夠随時建立一個遊戲畫面的圖像。這就像基于canvas制作的遊戲中的螢幕捕捉功能。

此處需要在html頁面上建立一個按鈕,使用者單擊就可以獲得螢幕捕捉的圖像。下面将這個按鈕添加到< form > 中,然後賦予其編号createimagedata。

在init()函數中,通過document對象的getelementbyid()方法獲得了這個表單元素的參考。然後使用createimagedatapressed()方法為按鈕的“單擊”事件設定一個事件處理器。

在canvasapp()函數中,定義createimagedatapressed()函數作為事件處理器,這個函數調用window.open(),并将canvas.todataurl()方法的傳回數值傳送給視窗,由于這個資料表單是一個有效的png,圖像會在一個新視窗中顯示。

1.9.7 最終的遊戲代碼

例1-4顯示了猜字母遊戲的完整代碼

繼續閱讀