4. 碰撞檢測 、得分及生命
在第 4 個階段,利用GameZero的碰撞檢測功能,使公主角色能夠接到雪花 、禮物或剪刀。 在“sdgz”項目目錄中 ,把 version3.jl錄複製一份並命名爲version4.jl,在第 3 個版本的基礎上編寫第 4 個版本的代碼。
1) 碰撞檢測
檢測公主角色與下落物體是否碰撞。在GameZero裏碰撞檢測很簡單,只需調用碰撞檢測函數即可,碰撞檢測函數在本節的“編程思路”中有具體詳解。
collide(princess, falling_obj)
2) 顯示得分和愛心寶石
切換到源文件“version4.jl”的編輯窗口中,準備編寫代碼。
創建一個顯示愛心寶石的角色,放在窗口的左上角位置(50,100)。
heart = Actor(heart1_img)
heart.pos=(50, 100)
創建一個文本標籤用來顯示得分情況,文本的字體顏色爲黑色,字體爲“moonhouse”,位置爲(300,12)。
score_label = TextActor("Hello World", "moonhouse";color=Int[0,0,0,0])
score_label.pos=(300,12)
在窗口的draw()方法中添加顯示文本標籤和愛心寶石圖像的代碼。
elseif game_state == 1 … draw(score_label) if 1 <= heart_num <= 3 draw(heart) end else game_state == 2 … draw(score_label)
注意:變量 heart_num 需要用 global關鍵字來聲明爲全局變量。
3) 更新得分和愛心寶
在 falling_control(dt) 函數中應用碰撞檢測功能 ,並更新得分和愛心寶石的變化情況,具體步驟如下:
(1) 通過碰撞檢測函數檢測公主與下落物體是否碰撞,如果公主碰到雪花加10 分,碰到禮物加 50 分,碰到剪刀則扣掉一顆愛心寶石。碰撞之後還要播放一個 pop 音效,以及切換下落物體的造型。
1 if collide(princess.position, falling_obj) 2 if falling_obj.type == 1 3 score += 10 4 elseif falling_obj.type == 2 5 score += 50 6 elseif falling_obj.type == 3 7 heart_num -= 1 8 end 9 10 #音效 11 play_sound(pop_sound) 12 13 #切換下落物體造型 14 change(falling_obj) 15 end
注意: 變量 heart_num 和 score 需要用 global 關鍵字聲明爲全局 變量。
(2) 將玩家得分更新到文本標籤中
由於TextActor不能動態更換文字,只能重新定義一個新的TextActor對象,不斷更替舊對象,來達到更新得分的效果:
#更新得分
score_label = TextActor(string(score),"moonhouse";color=Int[0,0,0,0])
score_label.pos=(300,12)
注意在draw()事件函數中一定要clear()。
(3) 根據變量 heart_num的值更新愛心寶石圖像,或者heart_num 小於 0 時就讓遊戲進人結束狀態。
#更新生命愛心 if heart_num < 0 game_state = 2 elseif heart_num == 1 heart.image = heart1_img elseif heart_num == 2 heart.image = heart2_img elseif heart_num == 3 heart.image = heart3_img end
4) 按回車鍵開始遊戲時,讓程序使用預設值
在窗口的 on_key_down()方法中加入下面的代碼,將 score 設爲 0、heart_num 設爲 3。
if game_state != 1 … score = 0 heart_num = 3 end
注意: 變量 heart_num 和 score 需要用 global 關鍵字來聲明爲全局 變量。
5) 從窗口的 on_key_down()方法中刪除如下測試代碼:
#用於測試遊戲結束的情況
if k == Keys.SPACE
game_state = 2
end
至此,第 4 個版本的程序編寫完成。運行程序,然後對下面的功能進行測試。
①玩家控制公主精靈左右移動,如果接到雪花和禮物就能獲取得分,如果碰到 剪刀就會扣掉愛心寶石。②當愛心寶石被用光,再碰到剪刀,就會進人遊戲結束狀態。
如果程序未能實現上述功能,請認真檢查自己編寫的代碼,或者對照本文資源包中提供的源代碼進行檢查。
5. 其他控制
在第 5 個階段,爲遊戲增加倒計時和循環播放背景音樂的功能。在“sdgz”項目目錄中,把 version4.jl文件制一份並命名爲version5.jl,在第4個版本的基礎上編寫第5個版本的代碼。
1) 實現倒計時功功能
切換到源文件“version5.jl”的編輯窗口,準備編寫代碼。
創建一個文本標籤用於顯示倒計時時間,文本的字體顏色爲黑色,字體爲“moonhouse”,位置爲(430,12)。
timer_label=TextActor("00:00", "moonhouse";color=Int[0,0,0,255])
timer_label.pos=(430,12)
在窗口的draw()方法中添加繪製文本標籤 timer_label 的代碼,在遊戲處於進行狀態和結束狀態時都顯示倒計時的文本標籤。
elseif game_state == 1 … draw(timer_label) else game_state == 2 … draw(timer_label) end
在窗口的on_key_down()方法中設定變量 timer_value 初始值爲 300。
if game_state != 1 … timer_value=300 end
注意: 變量 timer_value 需要用 global關鍵字來聲明爲全局變量。
爲了使變量 timer_value 的值不斷減少,添加函數others_control(dt),代碼如下:
1 function others_control(dt) 2 #其他控制:倒計時、循環播放背景音樂''' 3 global game_state, timer_value,timer_label,isPlaying 4 5 #倒計時 6 if game_state == 1 7 timer_value -= 1 * dt 8 if timer_value <= 0 9 timer_value = 0 10 game_state = 2 11 end 12 timer_label=TextActor(@sprintf("%02d:%02d", div(timer_value,60), timer_value % 60),"moonhouse";font_size=16,color=Int[0,0,0,255]) 13 timer_label.pos=(420,15) 14 end 15 #循環播放背景音樂 16 if game_state == 1 17 if !isPlaying 18 play_music(music) 19 isPlaying=true 20 end 21 end 22 23 end
注意代碼中使用了@sprintf標籤,它是用來實現參數字符串的效果。所以,需要引入Printf庫,在代碼中加入:using Printf。
當遊戲處於進行狀態時,以秒爲單位進行倒計時,變量 timer_value 的值每秒減少量爲 1 *dt。 當變量 timer_value 的值小於等於 0 時 ,則遊戲結束。
上面代碼中還增加了循環播放背景音樂的代碼,注意isPlaying變量,用來判斷音樂是否已在播放。初始值是false。
在update()方法中調用,並傳入時間參數。
function update(g::Game,dt)
…
others_control(dt)
end
至此,第5個版本的程序編寫完成。運行程序,然後對倒計時和循環播放背景音樂的功能進行測試。
經過 5 個版本的迭代,一個簡單的“公主迎聖誕”小遊戲終於完成了。