Game of Snake Slows Down As Snake Grows???
pharylon
Posts: 5
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.
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