簡體   English   中英

畫布游戲:我的蛇吃了自己

[英]Canvas Game: My snake eats itself

由於我的其他bug已經解決,我正在為這個bug發布一個新問題。

我做了一個Snake帆布游戲,但是當你同時按下兩個按鈕時,我的蛇往往會吃掉它自己。我不知道如何正確解釋它,但這就是發生的事情:

說我的蛇向左移動,我按下+向右,它會吃掉它自己並引發游戲結束。 當它向右移動時:向下+向左和向下,死亡。 當蛇上下來時,我似乎無法重現這個錯誤。

這是改變方向所涉及的代碼:

bindEvents = ->
    keysToDirections =
        37 : LEFT
        38 : UP
        39 : RIGHT
        40 : DOWN

    $(document).keydown (e) -> 
        key = e.which
        newDirection = keysToDirections[key]

        if newDirection
            setDirection newDirection
            e.preventDefault()

setDirection = (newDirection) ->
    # TODO: there's some bug here; try pressing two buttons at the same time..
    switch Snake.direction
        when UP, DOWN
            allowedDirections = [LEFT, RIGHT]
        when LEFT, RIGHT
            allowedDirections = [UP, DOWN]

    if allowedDirections.indexOf(newDirection) > -1
        Snake.direction = newDirection

我認為編譯的JS有問題,因為我的switch語句在最后一個case中沒有break ; 但是,我嘗試添加else return到咖啡腳本文件,這沒有改變任何東西。 我完全迷失在這里,所以我希望有人能夠找到我出錯的地方。

好像它需要keydown事件正確,但是當你按得太快時它們會被覆蓋。 如果這有道理? 就像..當蛇向右走的時候你會按下,但是在它實際上有機會上升然后它向左移動之前你向左按。 混亂的句子就在那里,我建議你玩一會兒,並嘗試重現這個,如果你像我一樣好奇:(

我不知道如何正確調試這個。當我執行console.log時,游戲循環會向我發送消息。

可以在這里找到現場演示和我的github回購鏈接

提前致謝。

問題是如果你足夠快地按下鍵,它可能在一幀期間多次觸發事件回調。 因此,如果蛇正在下降,它可以向右轉,然后在相同的框架中向上,從而逆轉方向和吃自己。 我會建議兩種方法來解決這個問題:

第一種是在方向改變時設置標志,即:

if allowedDirections.indexOf(newDirection) > -1 and !turnedThisFrame
    Snake.direction = newDirection
    turnedThisFrame = true

然后,在每幀運行的代碼中,將turnedThisFrame設置為false

第二是重寫你如何處理按鍵。 這通常是我采取的方法。 保持按下哪些鍵的地圖(比如keysDown ),並綁定一個將keysDown[e.which] = true為keydown的函數和另一個將keysDown[e.which] = false為keyup的函數。 然后,您可以檢查在每個幀運行的代碼中按下了哪些鍵,並采取相應措施。

以下是我在當前項目中如何實現第二個解決方案的一些細節。 以下代碼出現在我的onload處理程序中:

do ->
  keysDown = []

  $(document).keydown (e) ->
    keysDown.push e.which

  $(document).keyup (e) ->
    keysDown = _.without keysDown, e.which

  window.isPressed = (keyCode) -> keyCode in keysDown

do ->構造用於創建一個函數並立即調用它,這有利於將keysDown保持在處理程序和isPressed閉包中,同時避免污染onload回調的主要范圍。

然后,在我的tick函數的開頭(每幀運行一次並處理游戲邏輯,繪制屏幕等)我會有這樣的事情:

switch Snake.direction
    when UP, DOWN
        allowedDirections = [LEFT, RIGHT]
    when LEFT, RIGHT
        allowedDirections = [UP, DOWN]

for direction in allowedDirections
    if isPressed(directionToKey[direction])
        Snake.direction = newDirection
        break

地圖directionToKey也只是你的對面keysToDirections

請注意,這意味着在allowedDirections首先列出的鍵將具有優先級,即如果您向右並在同一幀中向上和向下按下,則無論先按哪個鍵都會出現向上。

增加了第二種方法的優勢:在菜單屏幕和游戲之間切換時,您不必更改鍵處理程序回調。 你只需要一個不同的tick功能來檢查按下的是什么。

您必須保留蛇實際移動的最后一個方向,並根據該方向確定allowedDirection。 按一個鍵只表示在該方向上移動的意圖,但是當按下該鍵時它實際上並不移動,而是基於游戲的速度,我猜。

我有同樣的問題,但我通過實現隊列解決了它; 每個按鍵設置蛇的方向,並且(新)方向被推到一個數組。 然后,在我實際在游戲循環中移動蛇之前,我檢查我的方向隊列中是否有任何元素。 如果是這樣,我通過Array.shift將其移動一次。 返回值是隊列的第一個元素和我的蛇的新方向。 Array.shift還會從隊列中刪除該元素,這正是我們想要的。 如果幾乎同時按下兩個鍵,則第一個和第二個方向改變存儲在我們的隊列中,我們上面提到的例程通過首先在下一個可用的滴答中應用第一個方向改變然后應用第二個方向改變來處理其余的在此后的下一個刻度。

希望有道理嗎? :-)

你的蛇吃自己顯示你的命中檢測(和命中檢測處理)代碼的問題。 如果你正在擊中蛇,游戲應該結束。 蛇不是蘋果! 沒關系,顯然我錯過了在游戲為你結束部分。

如果您選擇允許像素粒度(我無法看到您的演示,我的工作網絡是半截...),您無法真正使U轉“安全”,就像您可以使用十六進制粒度方法。 不是說你的選擇不好,只是告訴你選擇你的戰斗,有些你無法獲勝。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM