B4J Question Snake Game

PatrikCavina

Active Member
Licensed User
Longtime User
Hi to everyone, i'm trying to do a simple version of snake. Problem that i met is add another part of snake when it eat a dot.
Code Module call an array of Block class, that rappresent single block of snake
B4X:
Sub Process_Globals
    Private fx As JFX
    Type MatrixPosition(x As Int, y As Int)
    Type RealPosition(x As Double, y As Double)
  
    Private fd As Food
    Private blck() As Block
  
    Private Timer As Timer
    Private keyboardListener As Reflector

    Private direction As String
  
    Private score As Int
  
    Private mBase As Pane
    Private cvs As Canvas
End Sub

Public Sub Initialize(Speed As Long)
    mBase = Main.GameBase
    cvs.Initialize("Cvs")
    mBase.AddNode(cvs,0,0,mBase.Width,mBase.Height)
    Timer.Initialize("Timer",Speed)
    Dim blk(Main.MatrixDimension*Main.MatrixDimension) As Block
    blck = blk
    blck(0).Initialize(cvs)
    fd.Initialize

    keyboardListener.Target = mBase
    keyboardListener.AddEventHandler("Direction_KeyPressed", "javafx.scene.input.KeyEvent.ANY")

    StartGame
End Sub

Public Sub StartGame
    direction = ""
    cvs.ClearRect(0,0,cvs.Width,cvs.Height)
    blck(0).SetInCenter
    score = 0
    cvs.RequestFocus
    fd.ProduceFood
End Sub

Private Sub Timer_Tick
    For i = 0 To blck.Length-1
        If Not(blck(i).IsInitialized) Then
            Exit
        End If
        blck(i).Movement(direction)
        If fd.foodPosition.x = blck(0).blockPosition.x And fd.foodPosition.y = blck(0).blockPosition.y Then
            Eat
            blck(i+1).Initialize(cvs)
            blck(i+1).SetBlock(blck(i).rBlockPosition)
        End If
    Next
End Sub

Private Sub Eat
    fd.RemoveFood
    fd.ProduceFood
    score = score + 1
End Sub

'Risponde alla domanda: "Il giocatore ha perso?"
Public Sub LoseClause As Boolean
    If blck(0).blockPosition.x < 0 Or blck(0).blockPosition.x >= Main.MatrixDimension Or blck(0).blockPosition.y < 0 Or blck(0).blockPosition.y >= Main.MatrixDimension Then
        Timer.Enabled = False
        Log("Lose")
        If fx.Msgbox2(Null,"Ricominciare?","Loser","Si","Cancel","No",fx.MSGBOX_CONFIRMATION) = fx.DialogResponse.POSITIVE Then
            fd.RemoveFood
            StartGame
        Else
            ExitApplication
        End If
        Return True
    End If
    Return False
End Sub

Private Sub Direction_KeyPressed_Event(e As Event)
    Timer.Enabled = True 'Il timer parte appena un bottone di movimento viene spinto
    Dim KE As Reflector
    KE.Target = e 'e is a KeyEvent instance
    Dim KeyCode As String = KE.RunMethod("getCode")
    Dim EventType As String = KE.RunMethod("getEventType")
    Select EventType
        Case "KEY_PRESSED"
            If KeyCode = "UP" Or KeyCode = "DOWN" Or KeyCode = "LEFT" Or KeyCode = "RIGHT" Then
                direction = KeyCode
            End If
    End Select
    e.Consume
End Sub

Block Class:
B4X:
Sub Class_Globals
    Private fx As JFX

    Private cvs As Canvas
    Private gridUnits As Int
    Private blockDimension As Double
  
    Public blockPosition As MatrixPosition 'Posizione della testa di snake all'interno della matrice
    Public rBlockPosition As RealPosition
    Public stackMovements As List
    Private direction As String
End Sub

Public Sub Initialize(base As Canvas)
    cvs = base
    stackMovements.Initialize
    gridUnits = Main.MatrixDimension
    rBlockPosition.Initialize
    blockDimension = cvs.Width/gridUnits
End Sub

Public Sub SetInCenter
    rBlockPosition.x = cvs.Width/2-blockDimension/2
    rBlockPosition.y = cvs.Height/2-blockDimension/2
    cvs.DrawRect(rBlockPosition.x,rBlockPosition.y,blockDimension,blockDimension,fx.Colors.Black,True,0)
    PositionInMatrix
End Sub

Public Sub SetBlock(position As RealPosition)
    rBlockPosition = position
    cvs.DrawRect(rBlockPosition.x,rBlockPosition.y,blockDimension,blockDimension,fx.Colors.Black,True,0)
    PositionInMatrix
End Sub

Public Sub Movement(mvmnt As String)
    Remove(rBlockPosition)
    stackMovements.Add(mvmnt)
    If stackMovements.Size > 0 Then
        direction = stackMovements.Get(0)
        stackMovements.RemoveAt(0)
    End If
    Select direction
        Case "UP"
            rBlockPosition.y = rBlockPosition.y - blockDimension
        Case "DOWN"
            rBlockPosition.y = rBlockPosition.y + blockDimension
        Case "LEFT"
            rBlockPosition.x = rBlockPosition.x - blockDimension
        Case "RIGHT"
            rBlockPosition.x = rBlockPosition.x + blockDimension
    End Select
    PositionInMatrix
    Snake.LoseClause
    Move(rBlockPosition)
End Sub

Private Sub Move(rP As RealPosition)
    cvs.DrawRect(rP.x,rP.y,blockDimension,blockDimension,fx.Colors.Black,True,0)
    Main.matrix(blockPosition.x,blockPosition.y) = False
End Sub
Public Sub Remove(rp As RealPosition)
    cvs.ClearRect(rp.x,rp.y,blockDimension,blockDimension)
    Main.matrix(blockPosition.x,blockPosition.y) = True
End Sub

Private Sub PositionInMatrix
    blockPosition = CalculatePosition.PositionInCell(rBlockPosition)
End Sub

In this way, when snake eat a dot its speed increase.
I can't understand my mistake
 

PatrikCavina

Active Member
Licensed User
Longtime User
Yes i know the existence of that library. But i want study the problem from the bottom even if this is a simple game . I don't know if i explain
 
Upvote 0
Top