game.go 3.1 KB

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