glbasic snake game I was working on...


monstercameron

Well-Known Member
Joined
Oct 19, 2010
Messages
1,001
Website
www.thinkteletronics.com
I save the coords of every movement to 2 arrays, then use those values to display the tail. somewhere along it crashes and glbasic complains about the array bounds...

How would I draw as many segments as the snakeLength variable dictates without having a separate line for each segment in drawStuff?

https://www.youtube.com/embed/Z4g-sCYKpl0?feature=oembed

also it is framerate dependent, any ideas how to seperate the two?

Code:
// --------------------------------- //
// Project: snake
// Start: Saturday, November 03, 2012
// IDE Version: 10.283


// FREE-VERSION:
// Need Premium for Features:
// 3D Graphics
// Network Commands
// INLINE C/C+++ code

// SETCURRENTDIR("Media") // go to media files



//main loop
WHILE TRUE
    //initial loading
    IF isLoaded = 0
        GOSUB loadStuff
    ENDIF
    GOSUB logicStuff
    GOSUB drawStuff
    SHOWSCREEN
WEND



SUB loadStuff:
    GLOBAL windowWidth = 640
    GLOBAL windowHeight = 480
    GLOBAL windowFullscreen = 0
    SETSCREEN windowWidth,windowHeight,windowFullscreen
    
    GLOBAL snakePosiY = 200
    GLOBAL snakePosiX = 100
    GLOBAL snakePosiYStart = 200
    GLOBAL snakePosiXStart = 100
    GLOBAL snakePosiYLast = 200
    GLOBAL snakePosiXLast = 100
    GLOBAL snakeLenght = 1
    GLOBAL snakeDirection = 2    //1=up 2=right 3=down 4=left
    GLOBAL snakeSpeed = 3 //by tens from 1-10 speed
    GLOBAL userScore = 0
    
    GLOBAL goalIsWaiting = 0
    
    GLOBAL keyPressed = 0
    
    GLOBAL isLoaded = 0
    GLOBAL isLoaded = isLoaded + 1
    
    GLOBAL checkInsideX = 0
    GLOBAL checkInsideY = 0
    
    GLOBAL snakeTailXArray[]
    GLOBAL snakeTailYArray[]
    
    GLOBAL snakeTailX = 1
    GLOBAL snakeTailXElem = 1
    
    GLOBAL snakeTailY = 2
    GLOBAL snakeTailYElem = 1
    
    DIM snakeTailXArray[100][500]
    DIM snakeTailYArray[100][500]
    
    
    GLOBAL looper =11
    GLOBAL looperLenght = 10
ENDSUB

FUNCTION posCatcher: lastPosX, lastPosY
    snakeTailX = snakeTailX + 1
    snakeTailY = snakeTailY + 1
    
    snakeTailXArray[snakeTailX][snakeTailXElem] = lastPosX
    snakeTailYArray[snakeTailY][snakeTailYElem] = lastPosY
    
    IF snakeTailX > looperLenght -10 THEN snakeTailX = 1
    IF snakeTailY > looperLenght -10 THEN snakeTailY = 1
ENDFUNCTION

SUB logicStuff:

    //to change direction
    IF snakeDirection = 1
        snakePosiY = snakePosiY - snakeSpeed
    
    ELSEIF snakeDirection = 2
        snakePosiX = snakePosiX + snakeSpeed
    
    ELSEIF snakeDirection = 3
        snakePosiY = snakePosiY + snakeSpeed
    
    ELSEIF snakeDirection = 4
        snakePosiX = snakePosiX - snakeSpeed
    
    ENDIF
    
    //manages the keyboard inputs to change direction    
    IF KEY(200) = 1
        IF keyPressed = 3
        keyPressed = 3
        ELSE
        keyPressed = 1
        ENDIF
    
    ELSEIF KEY(208) = 1
        IF keyPressed = 1
        keyPressed = 1
        ELSE
        keyPressed = 3
        ENDIF
    
    ELSEIF KEY(205) = 1
        IF keyPressed = 4
        keyPressed = 4
        ELSE
        keyPressed = 2
        ENDIF
    
    ELSEIF KEY(203) = 1
        IF keyPressed = 2
        keyPressed = 2
        ELSE
        keyPressed = 4
        ENDIF
    
    ELSE    
        //keyPressed = 0
    
    ENDIF
    
    
    //assigns keypress to numeric value in snakeDirection
    IF keyPressed = 1
        snakeDirection = 1
    
    ELSEIF keyPressed = 2
        snakeDirection = 2
    
    ELSEIF keyPressed = 3
        snakeDirection = 3
    
    ELSEIF keyPressed = 4
        snakeDirection = 4
    ENDIF
    
    
    //check for collision with goal to add to score and lenght
    IF snakePosiX > goalPosiX AND snakePosiX < goalPosiX + goalSize OR snakePosiX + 10 > goalPosiX AND snakePosiX + 10 < goalPosiX + goalSize
        checkInsideX = 1
    
        IF  snakePosiY > goalPosiY AND snakePosiY < goalPosiY + goalSize OR snakePosiY + 10 > goalPosiY AND snakePosiY + 10 < goalPosiY + goalSize
            checkInsideY = 1
        ELSE
            checkInsideY = 0
        ENDIF
    
    ELSE
        checkInsideX = 0
    ENDIF
    
    IF checkInsideX = 1 AND checkInsideY = 1
        userScore = userScore + 1
        snakeLenght = snakeLenght + 1
    
        looperLenght = looperLenght + 4
        IF looperLenght > 490 THEN looperLenght = 490
        GOSUB goalPlotter
    ENDIF
    
    //stores the values of the current position in any direction to the arrays
    ////////////////////////////////////////////////////////////////////////////
    //maybe this could work
    //IF snakeDirection > 0 and snakeDirection < 5
    //    posCatcher(snakePosiX,snakePosiY)
    ////////////////////////////////////////////////////////////////////////////
    IF snakeDirection = 2
        posCatcher(snakePosiX,snakePosiY)
        //DRAWRECT snakePosiXLast , snakePosiYLast, snakePosiX - snakePosiXLast, 10, RGB(0, 0, 255) // blue
    
    ELSEIF snakeDirection = 1
        posCatcher(snakePosiX,snakePosiY)
        //DRAWRECT snakePosiXLast, snakePosiYLast, 10, snakePosiY -snakePosiYLast, RGB(0, 0, 255) // blue
    
    ELSEIF snakeDirection = 4
        posCatcher(snakePosiX,snakePosiY)
        //DRAWRECT snakePosiXLast, snakePosiYLast, snakePosiX - snakePosiXLast, 10, RGB(0, 0, 255) // blue
    
    ELSEIF snakeDirection = 3
        posCatcher(snakePosiX,snakePosiY)
        //DRAWRECT snakePosiXLast, snakePosiYLast, 10, snakePosiY -snakePosiYLast, RGB(0, 0, 255) // blue
    ENDIF
    
    //?
    IF snakePosiXLast = snakePosiX - (snakeLenght * 10)
        snakePosiXLast = snakePosiXLast + snakeSpeed
    
    ELSEIF snakePosiXLast = snakePosiX + (snakeLenght * 10 + 10)
        snakePosiXLast = snakePosiXLast - snakeSpeed
    
    ELSEIF snakePosiYLast = snakePosiY + (snakeLenght * 10 + 10)
        snakePosiYLast = snakePosiYLast - snakeSpeed
    
    ELSEIF snakePosiYLast = snakePosiY - (snakeLenght * 10)
        snakePosiYLast = snakePosiYLast + snakeSpeed
    ENDIF
    
    //allowing the snake to warp to the opposite side of the screen
    IF snakePosiX > windowWidth
        snakePosiX = 0
    
    ELSEIF snakePosiX < windowWidth - windowWidth
        snakePosiX = windowWidth
    
    ELSEIF snakePosiY > windowHeight
        snakePosiY = 0
    
    ELSEIF snakePosiY < windowHeight - windowHeight
        snakePosiY = windowHeight
    ENDIF
ENDSUB


SUB goalPlotter:
    //plots random color and pos of goal
    GLOBAL goalPosiX = (RND(300)+20)
    GLOBAL goalPosiY = (RND(300)+20)
    GLOBAL goalSize = (RND(30)+10)
    GLOBAL goalColorR = RND(255)
    GLOBAL goalColorG = RND(255)
    GLOBAL goalColorB = RND(255)
    //GLOBAL goalPosiX = 0
    //GLOBAL goalPosiY = 0
ENDSUB

SUB traceRoute:
    //GLOBAL TRcurrentPosiX
    //GLOBAL TRcurrentPosiY
    //IF

ENDSUB

SUB drawStuff:
    //draws debug text.
    PRINT "isLoaded ("+ isLoaded + ")",10,5
    PRINT "snakeDirection ("+ snakeDirection + ")",10,25
    PRINT "checkInsideX ("+ checkInsideX + ")" + "     checkInsideY ("+ checkInsideY + ")" ,10,65
    PRINT "userScore ("+ userScore + ")",10,85
    PRINT "snakeLenght ("+ snakeLenght + ")",10,105
    PRINT "keyPressed ("+ keyPressed + ")",10,125
    PRINT "looper ("+ looper + ")",10,145
    PRINT "snakeTailX ("+ snakeTailX + ")" + "snakeTailY ("+ snakeTailY + ")" ,10,165
    
    //draw snake goal
    DRAWRECT goalPosiX, goalPosiY, goalSize, goalSize, RGB(goalColorR, goalColorG, goalColorB) // random color
    
    //draw snake head
    DRAWRECT snakePosiX, snakePosiY, 10, 10, RGB(255, 255, 255) // white
    
    //snakeTail[snakeTailX][snakeTailXElem] = lastPosX
    //snakeTail[snakeTailY][snakeTailYElem] = lastPosY
    
    
    //draw snake tail by looping through the values in the arrays...need better solution
    //looper = looper - 3
    //IF looper < 10 THEN looper = looperLenght - 10
    
    looper = 1
    
    //DRAWRECT snakeTailXArray[looper-1][snakeTailXElem], snakeTailYArray[looper-1][snakeTailYElem], 10, 10, RGB(255, 0, 0) // red
    
    FOR i = 1 TO snakeLenght STEP looper
    
        DRAWRECT snakeTailXArray[looper+1][snakeTailXElem], snakeTailYArray[looper+1][snakeTailYElem], 10, 10, RGB(255, 0, 0) // red
    
    NEXT

ENDSUB
 
Last edited by a moderator:
I'll have a proper look at the code later, but a quick glimpse would indicate that there's a lot of trimming you could do.

eg


userScore = userScore + 1

Could be simply written as


INC userScore
You could also reduce the key testing routine to


IF KEY(200) THEN SnakeDirection=1
IF KEY(208) THEN SnakeDirection=3
... etc

or


SnakeDirection=0
IF KEY(200) AND SnakeDirection=0 THEN SnakeDirection=1
 
IF KEY(208) AND SnakeDirection=0 THEN SnakeDirection=3
...

Also in your FOR/NEXT loop

FOR i = 1 TO snakeLenght STEP looper

You don't need the "STEP looper" bit as you're only ever increasing by one in each count. If the count was more or less than one then it would be necessary.

The array going out of bounds is surprising as they are very large - I'll see what's happening later. :)
 
Last edited by a moderator:
Here's a very simple piece of code that I think you should be able to understand and build on. It's a fairly complete game of snake, but doesn't check for collisions with it's own body or walls.

This code is OpenSource - do what you like with it without restrictions.

[EDIT] Public Domain. Open Source. FREE. I don't give a shit. Just use it if you want in any way you want.

Code:
// --------------------------------- //
// Project: snake
// Start: Sunday, May 26, 2013
// IDE Version: 10.283


// SETCURRENTDIR("Media") // go to media files

GLOBAL body_x%[], body_y%[], length%=1, fruit_x%, fruit_y%, speed%, dir%, score%
 
// Maximise snake size (100 segments)
DIM body_x[100]
DIM body_y[100]

// Head position
body_x[0]=10
body_y[0]=10

// Tail position
body_x[1]=9
body_y[1]=10

// Create fruit at random position
fruit_x=RND(39)
fruit_y=RND(29)

WHILE TRUE
 
 // Set snake direction
 IF KEY(200) THEN dir=4
 IF KEY(205) THEN dir=1
 IF KEY(208) THEN dir=2
 IF KEY(203) THEN dir=3
 
 // Move snake in selected direction
 IF dir>0 AND speed=0
   
    // Eat fruit
    IF body_x[0]=fruit_x AND body_y[0]=fruit_y
     INC score
     fruit_x=RND(39)
     fruit_y=RND(29)
     INC length
    ENDIF
 
    // Ensure that all segments follow the segment before it (or head)
    FOR n=length TO 1 STEP -1
     body_x[n]=body_x[n-1]
     body_y[n]=body_y[n-1]
    NEXT
   
    // Move head segment
    IF dir=1 THEN INC body_x[0]
    IF dir=2 THEN INC body_y[0]
    IF dir=3 THEN DEC body_x[0]
    IF dir=4 THEN DEC body_y[0]

 ENDIF

 // Draw fruit
 DRAWRECT fruit_x*16,fruit_y*16,16,16,RGB(RND(255),RND(255),RND(255))

 // Draw head
 DRAWRECT body_x[0]*16,body_y[0]*16,16,16,RGB(255,0,0)
 
 // Draw body segments
 FOR n=1 TO length
  DRAWRECT body_x[n]*16,body_y[n]*16,15,15,RGB(0,255,0)
 NEXT

 DEC speed
 
 // Limit snake movement speed (higher values=slower movement)
 IF speed<0 THEN speed=5

 PRINT "DIR "+dir,10,10
 
 PRINT "SPD "+speed,10,30

 PRINT "LEN "+length,10,50

 PRINT "SCORE "+score,10,70

 SHOWSCREEN
 
WEND
 
Last edited by a moderator:
I don't care. I also don't care for licenses, so public domain then -

no-copyright.png


http://creativecommons.org/publicdomain/mark/1.0/

Help people with a bit of code and STILL get fecking OS/PD? questions. I fucking hate this bullshit. I stated clearly that I don't care what users do with it. I've edited the code post to reflect this.
 
Last edited by a moderator:
thanks for the replies, gonna study the code you provided...

...I feel so ashamed of myself after compiling your code...

I will just use your code as a base, my original code had it where you couldn't go the opposite direction, like left then right.
 
Last edited by a moderator:
i know it's not a big improvement but here is the modified game so far...

working on menus, scoring and so forth...

Code:
// --------------------------------- //
// Project: snake-iprice
// Start: Monday, May 27, 2013
// IDE Version: 10.202


// FREE-VERSION:
// Need Premium for Features:
// 3D Graphics
// Network Commands
// INLINE C/C+++ code

// SETCURRENTDIR("Media") // go to media files
// --------------------------------- //
// Project: snake
// Start: Sunday, May 26, 2013
// IDE Version: 10.283


// SETCURRENTDIR("Media") // go to media files



WHILE TRUE
    IF started% = 0 THEN GOSUB loadVars
    GOSUB gameINPUT
    GOSUB draw
    SHOWSCREEN
WEND




SUB loadVars:

    GLOBAL windowWidth = 640
    GLOBAL windowHeight = 480
    GLOBAL windowFullscreen = 0
    SETSCREEN windowWidth,windowHeight,windowFullscreen
    LIMITFPS 60
    ALLOWESCAPE FALSE
    
GLOBAL started%,body_x%[], body_y%[], length%=1, fruit_x%, fruit_y%, speed%, dir%, score%, keyPressed%, gameState%, menu_x%, menu_y%, menuOption%[], option%    

// Maximise snake size (100 segments)
DIM body_x[100]
DIM body_y[100]

// Head position
body_x[0]=10
body_y[0]=10

// Tail position
body_x[1]=9
body_y[1]=10

// Create fruit at random position
fruit_x=RND(39)
fruit_y=RND(29)

//gameState% switches between game screens 1=mainmenu, 2=gamescreen, 3=paused, 4=end/scorescreen
gameState=1

//toggles between menu options
DIM menuOption[4]
menuOption[0]=50
menuOption[1]=90
menuOption[2]=120
menuOption[3]=50
option=0

//theis var means that it is already loaded, set to 0 to reset game
started% = 1
ENDSUB





SUB gameINPUT:


IF gameState= 1
 //y position of the menu highlight
 menu_x=100
 
 //directions keys
 IF KEY(200) THEN INC option
 IF KEY(205) THEN INC option
 IF KEY(208) THEN DEC option
 IF KEY(203) THEN DEC option
 
 //enter keys
 IF KEY(28) AND option = 0 THEN gameState = 2
 IF KEY(28) AND option = 2 THEN END
 //IF KEY(28) AND option = 1 THEN gameState = 2 //adjusts speed/difficulty
 
 //highlights menuoption
 menu_y=menuOption[option]
 
 //infinite scroll list
 IF option > 2 THEN option = 0
 IF option < 0 THEN option = 2
ENDIF


IF gameState= 2
//manages the keyboard inputs to change direction    
    IF KEY(200) = 1
        IF keyPressed = 3
        keyPressed = 3
        ELSE
        keyPressed = 1
        ENDIF
    
    ELSEIF KEY(208) = 1
        IF keyPressed = 1
        keyPressed = 1
        ELSE
        keyPressed = 3
        ENDIF
    
    ELSEIF KEY(205) = 1
        IF keyPressed = 4
        keyPressed = 4
        ELSE
        keyPressed = 2
        ENDIF
    
    ELSEIF KEY(203) = 1
        IF keyPressed = 2
        keyPressed = 2
        ELSE
        keyPressed = 4
        ENDIF
        
    ELSEIF KEY(01) = 1
        gameState = 3
        
    ENDIF
 
    //assigns keypress to numeric value in snakeDirection
    IF keyPressed = 1
        dir = 4    
    ELSEIF keyPressed = 2
        dir = 1   
    ELSEIF keyPressed = 3
        dir = 2    
    ELSEIF keyPressed = 4
        dir = 3
    ENDIF
    
     //allowing the snake to warp to the opposite side of the screen
    IF body_x[0] > windowWidth/16
        body_x[0] = 0
    
    ELSEIF body_x[0] < windowWidth - windowWidth
        body_x[0] = windowWidth/16
    
    ELSEIF body_y[0] > windowHeight/16
        body_y[0] = 0
    
    ELSEIF body_y[0] < windowHeight - windowHeight
        body_y[0] = windowHeight/16
    ENDIF
    
    //check collision between head and body of snake
    FOR n=1 TO length
        IF body_x[0] = body_x[n] AND body_y[0] = body_y[n]
            length = 0
        ENDIF
     NEXT
    

 // Move snake in selected direction
 IF dir>0 AND speed=0

    // Eat fruit
    IF body_x[0]=fruit_x AND body_y[0]=fruit_y
     INC score
     fruit_x=RND(39)
     fruit_y=RND(29)
     INC length
    ENDIF

    // Ensure that all segments follow the segment before it (or head)
    FOR n=length TO 1 STEP -1
     body_x[n]=body_x[n-1]
     body_y[n]=body_y[n-1]
    NEXT

    // Move head segment
    IF dir=1 THEN INC body_x[0]
    IF dir=2 THEN INC body_y[0]
    IF dir=3 THEN DEC body_x[0]
    IF dir=4 THEN DEC body_y[0]

 ENDIF
 
ENDIF


IF gameState= 3
    IF KEY(28) = 1
        gameState = 2
    ELSEIF KEY(16) = 1
        END
    ENDIF
ENDIF


IF gameState= 4

ENDIF
 
 
ENDSUB




SUB draw:

IF gameState= 1
 //main menu
 DRAWRECT menu_x,menu_y,16,16,RGB(255,0,0)
 
 PRINT "PLAY ",100,50

 PRINT "SPEED ",100,90

 PRINT "QUIT ",100,130
 
ENDIF

IF gameState= 2
 // Draw fruit
 DRAWRECT fruit_x*16,fruit_y*16,16,16,RGB(RND(255),RND(255),RND(255))

 // Draw head
 DRAWRECT body_x[0]*16,body_y[0]*16,16,16,RGB(255,0,0)

 // Draw body segments
 FOR n=1 TO length
  DRAWRECT body_x[n]*16,body_y[n]*16,15,15,RGB(0,255,0)
 NEXT

 DEC speed
 
 // Limit snake movement speed (higher values=slower movement)
 IF speed<0 THEN speed=5

 PRINT "DIR "+dir,10,10

 PRINT "SPD "+speed,10,30

 PRINT "LEN "+length,10,50

 PRINT "SCORE "+score,10,70

 PRINT "x|y pos: "+body_x[0]+" "+body_y[0],10,90

ENDIF

IF gameState= 3

 //left,right|up,down|wide|high
 //p
 DRAWRECT 1,1,50,16,RGB(255,0,0)
 DRAWRECT 1,1,16,100,RGB(255,0,0)
 DRAWRECT 1,50,50,16,RGB(255,0,0)
 DRAWRECT 50,1,16,50,RGB(255,0,0)
 //a
 DRAWRECT 70,40,16,50,RGB(0,255,100)
 DRAWRECT 70,80,50,16,RGB(0,255,75)
 DRAWRECT 100,40,16,60,RGB(0,255,50)
 DRAWRECT 70,40,40,16,RGB(0,255,25)
 //u
 DRAWRECT 130,40,16,50,RGB(255,0,0)
 DRAWRECT 130,80,50,16,RGB(255,0,0)
 DRAWRECT 160,40,16,60,RGB(255,0,0)
 //s
 DRAWRECT 190,10,40,16,RGB(255,0,0)
 DRAWRECT 190,10,16,40,RGB(255,0,0)
 DRAWRECT 190,50,40,16,RGB(255,0,0)
 DRAWRECT 220,50,16,40,RGB(255,0,0)
 DRAWRECT 190,80,40,16,RGB(255,0,0)
 //e
 DRAWRECT 250,40,50,16,RGB(255,0,0)
 DRAWRECT 250,60,50,16,RGB(255,0,0)
 DRAWRECT 250,80,50,16,RGB(255,0,0)
 DRAWRECT 250,40,16,40,RGB(255,0,0)
 DRAWRECT 280,40,16,16,RGB(255,0,0)
 
 PRINT "Press Enter To Continue",200,200
 PRINT "Press Q To Quit!",200,250
 
 
ENDIF

IF gameState= 4
ENDIF


ENDSUB
 
Last edited by a moderator:
Back
Top