NaaLaa
Question about snake game - Printable Version

+- NaaLaa (https://www.naalaa.com/forum)
+-- Forum: NaaLaa (https://www.naalaa.com/forum/forum-1.html)
+--- Forum: NaaLaa 7 Questions (https://www.naalaa.com/forum/forum-3.html)
+--- Thread: Question about snake game (/thread-148.html)

Pages: 1 2


RE: Question about snake game - Marcus - 09-19-2024

(08-10-2024, 12:06 PM)aliensoldier Wrote:
(08-08-2024, 02:56 PM)Marcus Wrote:
Code:
'prueba de cola de serpiente

' Marcus: You can remove this, just checking some things.
#dbg

'variables-----------------------
' Marcus: I think list_body should belong to player ================================================
'visible player,list_body
visible player
' ==================================================================================================

set window "serpiente",640,480,false
set redraw off

'player-----------------------------
function Player()
    obj = []
    obj.radius = 14
    obj.x = 320 - obj.radius/2
    obj.y = 240 - obj.radius/2
    obj.speedX = 0
    obj.speedY = 0
    obj.Active = true
    ' Marcus: Putting body list here and a list of recorded head positions =========================
    obj.bodyList = []
    obj.positions = []
    ' ==============================================================================================
   
    ' Marcus: Add one body part to player ==========================================================
    obj.AddBody = function()
        body = Body(0, 0)
        this.bodyList[sizeof(this.bodyList)] = body
        ' Not sure when AddBody might be called, so calling UpdateBody here too.
        this.UpdateBody()
    endfunc
    ' ==============================================================================================
 
    obj.update = function()
        if this.Active = true
            this.move()
            ' Marcus: Reposition body parts ========================================================
            this.UpdateBody()
            ' ======================================================================================
            this.Draw()
        endif
    endfunc
   
    ' Marcus: Set body parts' positions ============================================================
    obj.UpdateBody = function()
        if sizeof(this.bodyList)
            ' We position the body parts one after one, starting with the one closest to the head.
            ' dist is the calculated travel distance between the head and the current body part.
            ' Initiate it to the radius of the head.
            dist = this.radius
            for i = 0 to sizeof(this.bodyList) - 1
                b = this.bodyList[i]
                ' Add radius of body part to dist.
                dist = dist + b.radius
                ' Divide dist by the speed of the snake to convert the traveled distance to an
                ' index in the position list. Use 'min' to make sure it's not outside the list.
                index = min(int(dist/2), sizeof(this.positions) - 1)
                if index >= 0
                    ' Convert single number coordinates to x and y.
                    'b.y = int(this.positions[index]/width(primary))
                    'b.x = int(this.positions[index]%width(primary))
                    b.x = this.positions[index][0]
                    b.y = this.positions[index][1]
                else
                    ' No recorded positions, put at head position.
                    b.x = this.x
                    b.y = this.y
                endif
                ' Add radius of body part to dist.
                dist = dist + b.radius
            next
        endif
    endfunc
    ' ==============================================================================================
 
    obj.Draw = function()
        ' Marcus: Draw body parts ==================================================================
        if sizeof(this.bodyList)
            for i = 0 to sizeof(this.bodyList) - 1  this.bodyList[i].Draw()
        endif
        ' ==========================================================================================

        set color 255,204,0
        draw ellipse this.x,this.y,this.radius,this.radius,true
    endfunc
 
    obj.move = function()
      if keydown(KEY_RIGHT,false)
        this.speedX = 2
        this.speedY = 0
      endif 
      if keydown(KEY_LEFT,false)
        this.speedX = -2
        this.speedY = 0 
      endif
     
        if keydown(KEY_UP,false)
            this.speedX = 0
            this.speedY = -2
        endif
        if keydown(KEY_DOWN,false)
            this.speedX = 0
            this.speedY = 2
        endif
       
        ' Marcus: Save previous position ===========================================================
        if this.speedX or this.speedY
            ' I store the position, x and y, as a single number.
            'insert this.positions, 0, this.y*width(primary) + this.x
            insert this.positions, 0, [this.x, this.y]
            ' Store only 5000 positions for now, might have to increase it depending on how long
            ' the snake can become.
            if sizeof(this.positions) > 5000  free key this.positions, 5000
        endif
        ' ==========================================================================================
     
        this.x = this.x + this.speedX
        this.y = this.y + this.speedY
    endfunc
 
    return obj
endfunc
'end player--------------------------

'body--------------------------------
function Body(x,y)
    obj = []
    obj.radius = 10
    obj.x = x - obj.radius/2
    obj.y = y - obj.radius/2
 
    obj.update = function()
        this.Draw()
    endfunc
 
    obj.Draw = function()
        set color 255,0,204
        draw ellipse this.x,this.y,this.radius,this.radius,true
    endfunc
 
    return obj
endfunc
'end body----------------------------

'iniciar variables-------------------
player = Player()
list_body = []
list_body[sizeof(list_body)] = Body(320,64)
list_body[sizeof(list_body)] = Body(320-32,64)
list_body[sizeof(list_body)] = Body(320-64,64)

while not keydown(KEY_ESCAPE,true)
    set color 0,0,0
    cls
   
    if keydown(KEY_SPACE, true)  player.AddBody()
 
    'actualizar objetos del juego-----------
    player.update()
    if sizeof(list_body)
        for i = 0 to sizeof(list_body)-1
            list_body[i].update()
        next
    endif
    '---------------------------------------
   
    ' Marcus: Some debug output ====================================================================
    set color 255, 255, 255
    set caret 0, 0
    wln "PRESS SPACE BAR TO ADD BODY PARTS"
    wln
    wln "bodyparts: " + sizeof(player.bodyList)
    wln "recorded positions: " + sizeof(player.positions)
    ' ==============================================================================================
     
    fwait 60
    redraw
wend

I've marked my changes with "Marcus" Smile

This solution is probably not very good. The head's position is always recorded into a list, player.positions. Currently I store a maximum of 5000 positions, which covers a snake length of 10,000 pixels (because the speed of the snake is 2). Then I "simply" position the body parts, using the list of recorded positions, in player.UpdateBody.

Press space bar to add body parts.

Edit  But as with the other snake code I posted, this is NOT a very smart solution. It should be enough to store the positions where the player turns, and then use the distance between the head and these points to calculate the positions of the body parts.

Thanks Marcus, I'll see if I understand this better. Smile

Although I don't really want to program the snake game, what I wanted to do is have some planes follow another one. It's in those airplane games where there is a group of planes that move in circles and they all do it together.

Wouldn't it be easier to use something like the polyline library for that?


RE: Question about snake game - johnno56 - 09-19-2024

I am going to offer my 2 cents for what it is worth... lol

I am not very technical but I will try... Firstly, polyline would probably look nicer...lol Secondly: To place a sprite the program basically needs a pair of co-ordinates (x,y)... Correct me if I am wrong... Ployline needs a pair of co-ordinates for 'each' line. (x and y for each end of the line) Therefore, producing a square, would need 4 pairs... whereas a sprite needs only two. Visually, either method would move and look the same, but my guess would be that polyline may need to crunch more numbers... Now, if you want your space ship to explode like it does in Asteroids, then polyline is the way to go... Moo ha ha ha...