用原生Canvas寫貪吃蛇及問題解決

爲了學習Canvas,寫了這個小遊戲貪吃蛇供本身和你們學習html

 

Github: https://github.com/zhiyishou/Gsnakegit

Play On: http://zhiyishou.github.io/Gsnakegithub

 

遊戲截圖:canvas

 

前言:數組

爲了方便加載轉移,我把整個js都寫在了html裏,爲了方便閱讀,將函數結構在html裏清晰地分開,函數

並在代碼裏有足夠註釋。學習

 

函數結構以下:spa

|----script   
    |----Definations
        |----Global Snake variables
        |----Global Canvas variables
        |----Global Panel variables
        |----Global Stage variables
        |----Global Game status variables
    |----Init Functions
        |----initPanel
        |----initButtons
        |----initStage
        |----initCanvas
        |----initMaps
        |----SnakeNode
        |----initSnake
        |----produceSingle
        |----init
    |----Draw Funcitons
        |----drawScore
        |----drawButton
        |----drawButtons
        |----drawSnake
        |----drawSingle
        |----drawStage
        |----draw
    |----Action Functions
        |----moveSnake
        |----main
    |----Event Functions
        |----KeyDown
        |----getOffsetPosition
        |----determineButton
        |----MouseMove
        |----ClickButton
        |----debounce
        |----bind
        |----Pause
        |----Start
        |----ReStart
        |----Died
    |----ROCK and ROLL
        |----init()
        |----main()

 

 

其中碰到的問題與解決:code

1、鼠標事件問題htm

Canvas 中沒法實現內部事件的添加和刪除,準確的來講,在Canvas就是一張單純的畫布,整個Canvas才能作Dom中的事件操做

若是想在Canvas中實現內部click或mousemove等事件,有兩種方案來實現:

 

一、用四周邊界來肯定:

  • 基於:
    1. 對Canvas綁定事件後,每當有事件發生,則計算當前鼠標相對於Canvas的座標值;
    2. 在每一個要綁定事件的對象中設定其四邊邊距座標,並將其放在一個數組;
  • 觸發:事件發生時則遍歷整個數組,來根據座標來判斷是否在哪個對象的邊界範圍內,來肯定鼠標如今所在的對象。
  • 缺點:這個作的話要求對象只能是形狀規整的直角四邊形,對複雜圖形的處理沒有可實施性。

 

二、使用CanvasAPI中的isPointInPath方法:

  • 基於:
    1. (同上)對Canvas綁定事件後,每當有事件發生,則計算當前鼠標相對於Canvas的座標值;
    2. 將要綁定事件的對象儲存在數組裏;
    3. isPonitInPath或isPointInStroke方法針對context上下文來判斷一個座標值是否在其Path中或上;
  • 觸發:事件發生時則遍歷整個數組,並重繪數組裏的對象,即改變context,每繪製一個對象則context改變一次,當前的context來使用isPointInPath或isPointInStroke方法,將Offset座標傳入,來判斷鼠標是否在其路徑上,肯定如今focus或click的對象。(canvas中的context會在closePath方法後從新設置)
  • 優勢:可實現複雜的圖形事件。

 

2、繪製問題

在我原先的版本中我是將整個對象操做和對象繪製設置成一個Interval來實如今,在後來的編寫中就發現這樣作會很死板,若是想添加或改動一些功能,則要對整個代碼進行修改甚至在這種模型下沒法實現。

最後仍是將繪製和操做分離開來

  • 對繪製設置Interval,如:
setInterval(function(){
     draw();
},1000/60)    //每秒重繪60次
  • 而將繪製對象屬性的改變綁定在事件上,如:

  該遊戲中的Event Functions

原理:對象事件來改變對象的屬性,而繪製則是用對象屬性來繪製,兩個邏輯各司其職,互不干預。

優勢:總體程序邏輯會更清晰,更方便後續功能的新增和修改。

 

 

The End

相關文章
相關標籤/搜索