2.公主精靈的控制
在第2階段,將創建一個公主角色,支持玩家使用鍵盤上的左、右方向鍵控制公主角色的左、右移動。在“sdgz”項目目中 ,把 version1.jl複製一份並命名爲version2.jl,在第1個版本的基礎上編寫第2 個版本的代碼,具體步驟如下:
(1) 用圖像Actor創建一個公主角色,將其定位在窗口底部居中位置。
princess = Actor(princess_img)
princess.pos=(400, 305)
(2) 在窗口的draw()方法中,調用draw()方法將公主精靈的圖繪製到窗口中。在遊戲處於進行狀態纔會顯示公主精靈,即在 game_state 等於 1 時才繪製公主角色的外觀。
elseif game_state == 1 … draw(princess)
提示:“…”號表示省略掉的部分代碼,下同。
(3) 控制公主角色左、右移動。這裏沒有使用鍵盤事件,而是通過檢測鍵盤按鍵狀態來判斷是否按下左 、右方向鍵。因此需要在窗口的事件循環update()方法中檢測左、右方向鍵的按鍵狀態,並控制公主角色左、右移動。在update()方法中添加如下代碼:
function update(g::Game,dt)
princess_control(g,dt)
end
princess_control是公主角色控制函數,update事件中每幀切換會調用這個函數。princess_control()函數的代碼如下:
#控制公主左右移動 function princess_control(g::Game,dt) global game_state if game_state != 1 return end if g.keyboard.LEFT princess.x -= 400 * dt if princess.left < 0 princess.left = -princess.left end elseif g.keyboard.RIGHT princess.x += 400 * dt if princess.right > WIDTH princess.right += -(2 * (princess.right - WIDTH)) end end end
對上面代碼的說明如下。
①在遊戲處於進行狀態時才能控制公主精靈移動,即如果 game_state 不等於1,就退出這個函數。
②函數 princess_control ()被調用時,自上次被調用以來經過的時間(單位= S)就會被傳遞給參數 dt。假設公主精靈的移動速度爲400 像素/S,那麼它在 princess_control () 函數披調用時的移動速度則爲 400*dt。在向左移動時,princess.x 的值將減去400*dt;在向右移動時 ,princess.x 的值將增加 400*dt。
③公主角色在窗口中移動應該顯示完整的外形。因此princess.left最小值爲0,princess.right最大值是800 。
至此,第 2 個版本的程序編寫完成. 運行程序,就可以用鍵盤上的左、右方向鍵控制公主角色左右移動了。
3.下落物體角色的控制
在第3個階段,將實現從天空中隨機落下雪花、禮物或剪刀。從面向對象的角度看,雪花、禮物和剪刀都可以歸結爲一類物體,即“下落物體類”,原書的做法是從Pyglet的Sprite 類中派生一個下落物體類 FallingObject,並運用該類的實例實現雪花、禮物或剪刀的互相切換。
但是Julia不是傳統意義上的面嚮對象語言,Julia裏沒有class,沒有類的繼承(inheritance),勉強與class能對應上的是struct,且不能派生和繼承,除構造函數外,struct內不能定義其它函數。
1) 創建FallingObject對象
原書中,作者定義了一個名爲 FallingObject的類,繼承自Sprite 類,在類中添加一個屬性 type 和一個用於切換雪花、禮物和剪刀的 change()方法。轉換到Julia,可以寫成如下結構的代碼:
1 mutable struct FallingObject 2 act::Actor 3 type::Int 4 5 function FallingObject() 6 act=Actor(snowflake_img) 7 type=1 8 new(obj,type) 9 end 10 end 11 12 function change(fo::FallingObject) 13 #隨機切換掉落物體的造型 14 n = rand(1:10) 15 if 1 <= n <= 5 16 fo.type = 1 17 fo.act.image = snowflake_img 18 elseif 6 <= n <= 8 19 fo.type = 2 20 fo.act.image = gift_img 21 else 22 fo.type = 3 23 fo.act.image = clipper_img 24 end 25 #將物體定位到窗口上方隨機位置 26 x=rand(100:700) 27 fo.act.pos =x , -100 28 end
筆者原打算按此思路實現下落物體的控制,但是通過研究GameZero的源碼,發現源碼作者對Actor增加了賦予其自定義屬性的能力。由於下落物體本質上是一個Actor,所以我們可以直接這樣定義:
falling_obj =Actor(snowflake_img;pos=(rand(100:700),-100),type=1)
上面代碼中參數snowflake_img是雪花的圖片,pos是位置,其x軸座標爲100-700間的隨機值,第三個參數type就是自定屬性。
這樣一來,代碼將簡潔很多。至於Julia的面向對象編程,筆者將新開貼專題論述。
2) 控制 FallingObject對象
將version2.jl錄複製一份並命名爲version3.jl,在第 2 個版本的基礎上編寫第 3 個版本的代碼。
(1) 在窗口的draw()方法中,繪製出 falling_0bj 對象的外觀。與公主精靈一樣 ,都是在遊戲處於進行狀態時纔會顯示下落物體.
elseif game_state == 1 … draw(falling_obj)
(2) 在窗口的 on_key_down()方法中添加切換下落物體造型的代碼。當在遊戲重新開始時,就調用 Change()方法切換下落物體的造型。
function on_key_down(g, k) global game_state #println(k) if k ==Keys.RETURN #13 if game_state != 1 game_state = 1 change(falling_obj) end end end
另外,事先將Change()方法稍加修改,添加到version3.jl中:
1 function change(fo::Actor) 2 #隨機切換掉落物體的造型 3 n = rand(1:10) 4 if 1 <= n <= 5 5 fo.type = 1 6 fo.image = snowflake_img 7 elseif 6 <= n <= 8 8 fo.type = 2 9 fo.image = gift_img 10 else 11 fo.type = 3 12 fo.image = clipper_img 13 end 14 #將物體定位到窗口上方隨機位置 15 x=rand(100:700) 16 fo.pos =x , -100 17 end
上面的代碼使用隨機數生成掉落物體的造型 ,並將其隨機定位在窗口上方。隨機生成下落物體的算法在本節的編程思路中已經作過介紹。
(1) 控制下落物體向下移動 。在update()方法中添加如下代碼:
function update(g::Game,dt) falling_control(dt) end
函數falling_control()的代碼如下:
1 function falling_control(dt) 2 #禮物精靈的控制''' 3 global game_state 4 if game_state != 1 5 return 6 end 7 8 #控制禮物的落下速度和旋轉速度 9 falling_obj.angle += 60 * dt 10 falling_obj.y += 200 * dt 11 if falling_obj.y >HEIGHT 12 #println("ddd") 13 change(falling_obj) 14 end 15 end
對上面代碼的說明如下。
①在遊戲處於進行狀態時才能控制下落物體的移動,即如果 game_state 不等於 l,就退出這個函數。
②旋轉速度和向下移動速度跟時間有關。下落物體在降落過程中是旋轉的,假設每秒旋轉 60。,就使用 60 *dt 算出 faning_0bj.angle每次的增加量;假設每秒向下移動200 像素,就使用 200 *dt 算出 fa]ling_Obj.y 每次減少的距離。
③當下落物體移動到窗口底部外面的區域時,就將其重新放到窗口的頂部,並隨機切換新的造型,調用 change()方法來實現。
至此,第 3 個版本的程序編寫完成。運行程序,就可以看到在遊戲時會從天空中隨機掉下雪花、禮物或者剪刀。