Shop OBEX P1 Docs P2 Docs Learn Events
Game of Snake Slows Down As Snake Grows??? — Parallax Forums

Game of Snake Slows Down As Snake Grows???

pharylonpharylon Posts: 5
edited 2013-06-23 05:13 in Propeller 1
So, another forum member, __red__, had a class for a few of us at the Hackerspace in Charlotte to work with Propellers. We build these name badges that have an embedded 7 x 8 LED grid, and could print our name across them. Pretty cool, right?

So, I figured, this is basically a "low res" display, but I could run something like Snake on it. So, I did. However, I noticed the game starting to slow down as the snake got bigger. I was kind of surprised at that, but figured, eh, I'll just increase the clock speed. So I turned it up to 80 MHz, but while that mostly solved the problem, I found that once the Snake gets really big - like, takes up half the screen big - it's still slowing down the game. Now, we're talking about a 7x8 grid of LEDs. We're talking about tracking, at most, 56 points, and that's if the snake was the size of the entire game. It shouldn't be lagging. But it is. And as this is my first Spin program, I'm guessing I'm missing something. Here's the code, and thanks in advance.

Also, I'm thinking that the GameTick method would be the main culprit, but I dunno.
CON
  _clkmode=xtal1+pll16x         'Run at 16x5 = 80mhz!
  _xinfreq=5_000_000            'We are using a 5Mhz Crystal 


GameSpeedMultiplier = 5   
StartingPixels = 4
XBounds = 7
YBounds = 6
S2Pin = 17
S3Pin = 18
S4Pin = 19


OBJ
rr: "RealRandom.spin"
printer: "LedPrinter"


VAR
byte SnakePixelsX[56]
byte SnakePixelsY[56]
byte CurrentLength
long DrawStack[20]
long MoveStack[20]
long InputStack[20]
long NumberArray[10]
long ScoreArray[5]
byte GraphicsCogID
byte CurrentDirection  ' 0 is up, 1 is right, 2 is down, 3 is left.
long Seed
byte FruitX
byte FruitY
byte FruitExists
byte GameOver
byte TurnQueued
byte ButtonPressed
byte GameState
long Score
long FruitValue
byte LongMessage[4000] 


PUB Main
cognew(Input, @InputStack)
cognew(OpeningDisplay, @DrawStack)  
repeat while GameState == 0
  waitcnt(clkfreq/5 + cnt)
  waitcnt(clkfreq + cnt)    
initializeSnake
cognew(Graphics, @DrawStack)


GenerateFruit 
repeat while GameOver == 0
  GameTick
waitcnt(clkfreq * 2 + cnt)
COGSTOP(GraphicsCogID)
EndGame




pri Input
repeat
  if ina[S2Pin] == 0 AND TurnQueued == 0 AND ButtonPressed == 0 
    TurnQueued := 1 
    TurnCounterClockwise
    waitcnt(clkfreq/10 + cnt)
    WatchForButtonRelease(S2PIN)
  elseif ina[S4Pin] == 0 AND TurnQueued == 0 AND ButtonPressed == 0
    TurnQueued := 1
    TurnClockwise
    waitcnt(clkfreq/10 + cnt)
    WatchForButtonRelease(S4PIN)
  elseif ina[S3Pin] == 0
    COGSTOP(GraphicsCogID)
    GameState := 1
    


pri WatchForButtonRelease (PIN) | i
repeat while i < 4
  if ina[PIN] == 1
    i++
  else
    i := 0
ButtonPressed := 0  
  
pri TurnCounterClockwise
  if CurrentDirection == 0
    CurrentDirection := 3
  else
    CurrentDirection -= 1


pri TurnClockwise
  if CurrentDirection == 3
    CurrentDirection := 0
  else
    CurrentDirection += 1


pri GameTick | collision,i
waitcnt(clkfreq/GameSpeedMultiplier + cnt)
collision := DetectFruitCollision
if collision == 1
  eatFruit
repeat i from CurrentLength -1 to 1
  SnakePixelsX[CurrentLength - 1] := SnakePixelsX[0]
  SnakePixelsY[CurrentLength - 1] := SnakePixelsY[0]
if CurrentDirection == 0
  SnakePixelsY[0] += 1
elseif CurrentDirection == 1
  SnakePixelsX[0] -= 1
elseif CurrentDirection == 2
  SnakePixelsY[0] -= 1
else
  SnakePixelsX[0] += 1
DetectOutOfBounds
DetectSelfCollision
if FruitExists == 1
  FruitValue -= 1
TurnQueued := 0




pri DetectSelfCollision | i,n
repeat i from 0 to CurrentLength - 1
  repeat n from 0 to CurrentLength - 1
    ifnot i == n
      if SnakePixelsX[i] == SnakePixelsX[n] AND SnakePixelsY[i] == SnakePixelsY[n]
        FruitX := SnakePixelsX[i]
        FruitY := SnakePixelsY[i]
        FruitExists := 1
        GameOver := 1 


pri DetectOutOfBounds | i
repeat i from 0 to CurrentLength - 1
  if SnakePixelsX[i] > XBounds OR SnakePixelsY[i] > YBounds
    GameOver := 1
    FruitX := SnakePixelsX[i+1]
    FruitY := SnakePixelsY[i+1]
  elseif SnakePixelsX[i] < 0 OR SnakePixelsY[i] < 0
    GameOver := 1
    FruitX := SnakePixelsX[i+1]
    FruitY := SnakePixelsY[i+1]
    
PRI OpeningDisplay
GraphicsCogID := COGID
  repeat while GameState == 0
    Printer.Print(string("PRESS S3 TO START"))
      
pri eatFruit
FruitExists := 0
SnakePixelsX[currentLength] := SnakePixelsX[CurrentLength - 1]
SnakePixelsY[currentLength] := SnakePixelsY[CurrentLength - 1]
CurrentLength++
Score += FruitValue
GenerateFruit 


  
pri clearScreen
dira[20..27] := 0




pri Graphics | i,Counter
GraphicsCogID := COGID
repeat
  if GameOver == 0
    repeat i from 0 to CurrentLength - 1
      lightPixel(SnakePixelsX[i], SnakePixelsY[i])
  elseif GameOver == 1
     repeat i from 1 to CurrentLength - 1
      if SnakePixelsX[i] <> FruitX OR SnakePixelsY[i] <> FruitY
        lightPixel(SnakePixelsX[i], SnakePixelsY[i])
  if FruitExists == 1 AND Counter > 50
    lightPixel(FruitX, FruitY)
    Counter := 0
  Counter++
    
  


pri GenerateFruit | collision
collision := 1
repeat while collision == 1
  fruitX := Roll(0, 7)
  fruitY := Roll(0, 6)
  collision := DetectFruitCollision
FruitExists := 1
FruitValue := 100
  


pri DetectFruitCollision | collision, i
repeat i from 0 to CurrentLength - 1
  if FruitX == SnakePixelsX[i] AND FruitY == SnakePixelsY[i]
    collision := 1
return collision




pri Roll(minValue, maxValue) : returnValue
returnValue := ||(Seed?//256)
repeat while returnValue < minValue OR returnValue > maxValue
  returnValue := ||(Seed?//256)
return returnValue




pri lightPixel(X, Y)
dira[20..27] := 0
dira[X + 20] := 1
outa[X + 20] := 0
if X > Y
  dira[Y + 20] := 1
  outa[Y + 20] := 1
else
  dira[Y + 21] := 1
  outa[Y + 21] := 1


pri EndGame | ScoreText,ScoreNumAsText,i
COGNEW(DrawX, @DrawStack)
waitcnt(clkfreq + cnt) 
COGSTOP(GraphicsCogID)


if Score > 999 
  ScoreArray[0] :=  (Score - (Score // 1000)) / 1000
  Score -= ScoreArray[0] * 1000
if Score > 99
  ScoreArray[1] :=  (Score - (Score // 100)) / 100
  Score -= ScoreArray[1] * 100
if Score > 9
  ScoreArray[2] :=  (Score - (Score // 10)) / 10
  Score -= ScoreArray[2] * 10
if Score > 0  
  ScoreArray[3] :=  Score


ScoreText := string("SCORE ")


repeat i from 0 to 3
  ScoreNumAsText := NumberArray[ScoreArray[i]]
  bytemove(ScoreText+strsize(ScoreText),ScoreNumAsText,strsize(ScoreNumAsText)+1)


repeat
  Printer.Print(ScoreText)


pri DrawX | i
GraphicsCogID := COGID
repeat
  repeat i from 0 to 7
    lightPixel(i, i)
    lightPixel(i, XBounds - (i + 1)) 


Pri initializeSnake
CurrentDirection := 1
CurrentLength := 4
SnakePixelsX[0] := 4
SnakePixelsY[0] := 3
SnakePixelsX[1] := 5
SnakePixelsY[1] := 3
SnakePixelsX[2] := 6
SnakePixelsY[2] := 3
SnakePixelsX[3] := 7
SnakePixelsY[3] := 3
NumberArray[0] := string("0")
NumberArray[1] := string("1")
NumberArray[2] := string("2")
NumberArray[3] := string("3")
NumberArray[4] := string("4")
NumberArray[5] := string("5")
NumberArray[6] := string("6")
NumberArray[7] := string("7")
NumberArray[8] := string("8")
NumberArray[9] := string("9")
rr.Start
Seed := rr.Random
rr.Stop
dira[S2Pin] := 0
dira[S3Pin] := 0
dira[S4Pin] := 0
Sign In or Register to comment.