game.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package main
  2. import (
  3. "log"
  4. "time"
  5. "github.com/gdamore/tcell/v2"
  6. )
  7. const (
  8. Left = iota
  9. Right
  10. Up
  11. Down
  12. )
  13. func initilize() (tcell.Screen, tcell.Style, error) {
  14. style := tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset)
  15. var err error
  16. screen, err := tcell.NewScreen()
  17. if err != nil {
  18. log.Println("Error creating screen: ", err)
  19. }
  20. err = screen.Init()
  21. if err != nil {
  22. log.Fatalln("Error initializing screen: ", err)
  23. }
  24. return screen, style, err
  25. }
  26. func quit(screen tcell.Screen) {
  27. maybePanic := recover()
  28. screen.Fini()
  29. if maybePanic != nil {
  30. panic(maybePanic)
  31. }
  32. }
  33. func gameDirector(screen tcell.Screen, style tcell.Style, keypresses chan int, gamestate chan int) {
  34. // Destined to die, even before I was born.
  35. defer quit(screen)
  36. var score int = 0
  37. var scoreCounter int = 1
  38. // Board size
  39. var screenx = 80
  40. var screeny = 24
  41. // Have snake start at the center of the board
  42. var snakex int = (screenx / 2) - 1
  43. var snakey int = (screeny / 2) - 1
  44. // Last direction we went in
  45. var lastpress int = 1
  46. var snake Snake = initSnake(&snakex, &snakey)
  47. var apple Apple = placeApple(&snake)
  48. for {
  49. // Take input or sleep
  50. select {
  51. case press := <-keypresses:
  52. snakeDirection(press, &snake)
  53. lastpress = press
  54. case <-time.After(500 * time.Millisecond):
  55. snakeDirection(lastpress, &snake)
  56. }
  57. if snake.head.x == apple.x && snake.head.y == apple.y {
  58. apple = placeApple(&snake)
  59. score += scoreCounter
  60. scoreCounter++
  61. snake.length = 3 + score
  62. }
  63. // Call it quits once the snake hits the border.
  64. if snake.head.x == 0 || snake.head.x == screenx-1 {
  65. close(gamestate)
  66. return
  67. } else if snake.head.y == 0 || snake.head.y == screeny-1 {
  68. close(gamestate)
  69. return
  70. }
  71. // Check if head intersects with any parts of the body
  72. if hitsTail(&snake, snake.head.x, snake.head.y) {
  73. close(gamestate)
  74. return
  75. }
  76. // Clean the screen
  77. screen.Clear()
  78. // Draw the screen
  79. drawBox(screen, style, 0, 0, screenx-1, screeny-1)
  80. drawCoords(screen, style, &snake)
  81. drawApple(screen, style, &apple)
  82. drawSnake(screen, style, &snake)
  83. drawScore(screen, style, score)
  84. // Draw the screen
  85. screen.Show()
  86. }
  87. }
  88. func keyboardProcessor(screen tcell.Screen, keypresses chan int, gamestate chan int) {
  89. defer close(keypresses)
  90. for {
  91. // Poll for an event
  92. ev := screen.PollEvent()
  93. // Fetch the type, and check if any other actions are required.
  94. switch ev := ev.(type) {
  95. //case *tcell.EventResize:
  96. // x, y := screen.Size()
  97. // drawBox(screen, 0, 0, x-1, y-1, style)
  98. // updateScore(screen, style, snakex)
  99. // screen.Sync()
  100. case *tcell.EventKey:
  101. if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC {
  102. return
  103. } else if ev.Rune() == 'q' || ev.Rune() == 'Q' {
  104. return
  105. } else if ev.Key() == tcell.KeyCtrlL {
  106. screen.Sync()
  107. } else if ev.Rune() == 'C' || ev.Rune() == 'c' {
  108. screen.Clear()
  109. } else if ev.Key() == tcell.KeyLeft {
  110. keypresses <- Left
  111. } else if ev.Key() == tcell.KeyRight {
  112. keypresses <- Right
  113. } else if ev.Key() == tcell.KeyDown {
  114. keypresses <- Down
  115. } else if ev.Key() == tcell.KeyUp {
  116. keypresses <- Up
  117. }
  118. }
  119. // This function needs to know if the game is over.
  120. select {
  121. case <-time.After(10 * time.Millisecond):
  122. case _, ok := <-gamestate:
  123. if !ok {
  124. return
  125. }
  126. }
  127. }
  128. }