Advertisement
Guest User

Untitled

a guest
Feb 24th, 2017
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.62 KB | None | 0 0
  1. import scalanative.native._
  2. import SDL._
  3. import SDLExtra._
  4.  
  5. @extern
  6. @link("SDL2")
  7. object SDL {
  8. type Window = CStruct0
  9. type Renderer = CStruct0
  10.  
  11. def SDL_Init(flags: UInt): Unit = extern
  12. def SDL_CreateWindow(title: CString,
  13. x: CInt,
  14. y: CInt,
  15. w: Int,
  16. h: Int,
  17. flags: UInt): Ptr[Window] = extern
  18. def SDL_Delay(ms: UInt): Unit = extern
  19. def SDL_CreateRenderer(win: Ptr[Window],
  20. index: CInt,
  21. flags: UInt): Ptr[Renderer] = extern
  22.  
  23. type _56 = Nat.Digit[Nat._5, Nat._6]
  24. type Event = CStruct2[UInt, CArray[Byte, _56]]
  25.  
  26. def SDL_PollEvent(event: Ptr[Event]): CInt = extern
  27.  
  28. type Rect = CStruct4[CInt, CInt, CInt, CInt]
  29.  
  30. def SDL_RenderClear(renderer: Ptr[Renderer]): Unit = extern
  31. def SDL_SetRenderDrawColor(renderer: Ptr[Renderer],
  32. r: UByte,
  33. g: UByte,
  34. b: UByte,
  35. a: UByte): Unit = extern
  36. def SDL_RenderFillRect(renderer: Ptr[Renderer], rect: Ptr[Rect]): Unit =
  37. extern
  38. def SDL_RenderPresent(renderer: Ptr[Renderer]): Unit = extern
  39.  
  40. type KeyboardEvent =
  41. CStruct8[UInt, UInt, UInt, UByte, UByte, UByte, UByte, Keysym]
  42. type Keysym = CStruct4[Scancode, Keycode, UShort, UInt]
  43. type Scancode = Int
  44. type Keycode = Int
  45. }
  46.  
  47. object SDLExtra {
  48. val INIT_VIDEO = 0x00000020.toUInt
  49. val WINDOW_SHOWN = 0x00000004.toUInt
  50. val VSYNC = 0x00000004.toUInt
  51.  
  52. implicit class EventOps(val self: Ptr[Event]) extends AnyVal {
  53. def type_ = !(self._1)
  54. }
  55.  
  56. val QUIT_EVENT = 0x100.toUInt
  57.  
  58. implicit class RectOps(val self: Ptr[Rect]) extends AnyVal {
  59. def init(x: Int, y: Int, w: Int, h: Int): Ptr[Rect] = {
  60. !(self._1) = x
  61. !(self._2) = y
  62. !(self._3) = w
  63. !(self._4) = h
  64. self
  65. }
  66. }
  67.  
  68. val KEY_DOWN = 0x300.toUInt
  69. val KEY_UP = (0x300 + 1).toUInt
  70. val RIGHT_KEY = 1073741903
  71. val LEFT_KEY = 1073741904
  72. val DOWN_KEY = 1073741905
  73. val UP_KEY = 1073741906
  74.  
  75. implicit class KeyboardEventOps(val self: Ptr[KeyboardEvent])
  76. extends AnyVal {
  77. def keycode: Keycode = !(self._8._2)
  78. }
  79. }
  80.  
  81. final case class Point(x: Int, y: Int) {
  82. def -(other: Point) = Point(this.x - other.x, this.y - other.y)
  83. def +(other: Point) = Point(this.x - other.x, this.y - other.y)
  84. }
  85.  
  86. object Snake extends App {
  87. var window: Ptr[Window] = _
  88. var renderer: Ptr[Renderer] = _
  89. var snake: List[Point] = _
  90. var pressed = collection.mutable.Set.empty[Keycode]
  91. var over = false
  92. var apple = Point(0, 0)
  93. var rand = new java.util.Random
  94.  
  95. val title = c"Snake"
  96. val width = 800
  97. val height = 800
  98. val Up = Point(0, 1)
  99. val Down = Point(0, -1)
  100. val Left = Point(1, 0)
  101. val Right = Point(-1, 0)
  102.  
  103. def newApple(): Point = {
  104. var pos = Point(0, 0)
  105. do {
  106. pos = Point(rand.nextInt(40), rand.nextInt(40))
  107. } while (snake.exists(_ == pos))
  108. pos
  109. }
  110.  
  111. def drawColor(r: UByte, g: UByte, b: UByte): Unit =
  112. SDL_SetRenderDrawColor(renderer, r, g, b, 0.toUByte)
  113. def drawClear(): Unit =
  114. SDL_RenderClear(renderer)
  115. def drawPresent(): Unit =
  116. SDL_RenderPresent(renderer)
  117. def drawSquare(point: Point) = {
  118. val rect = stackalloc[Rect].init(point.x * 20, point.y * 20, 20, 20)
  119. SDL_RenderFillRect(renderer, rect)
  120. }
  121. def drawSnake(): Unit = {
  122. val head :: tail = snake
  123. drawColor(100.toUByte, 200.toUByte, 100.toUByte)
  124. drawSquare(head)
  125. drawColor(0.toUByte, 150.toUByte, 0.toUByte)
  126. tail.foreach(drawSquare)
  127. }
  128. def drawApple(): Unit = {
  129. drawColor(150.toUByte, 0.toUByte, 0.toUByte)
  130. drawSquare(apple)
  131. }
  132.  
  133. def onDraw(): Unit = {
  134. drawColor(0.toUByte, 0.toUByte, 0.toUByte)
  135. drawClear()
  136. drawSnake()
  137. drawApple()
  138. drawPresent()
  139. }
  140.  
  141. def gameOver(): Unit = {
  142. over = true
  143. println(s"Game is over, your score is: " + snake.length)
  144. }
  145.  
  146. def move(newPos: Point) =
  147. if (!over) {
  148. if (newPos.x < 0 || newPos.y < 0 || newPos.x > 39 || newPos.y > 39) {
  149. println("out of bounds")
  150. gameOver()
  151. } else if (snake.exists(_ == newPos)) {
  152. println("hit itself")
  153. gameOver()
  154. } else if (apple == newPos) {
  155. snake = newPos :: snake
  156. apple = newApple()
  157. } else {
  158. snake = newPos :: snake.init
  159. }
  160. }
  161.  
  162. def onIdle(): Unit = {
  163. val head :: second :: rest = snake
  164. val direction = second - head
  165. val userDirection =
  166. if (pressed.contains(UP_KEY)) Up
  167. else if (pressed.contains(DOWN_KEY)) Down
  168. else if (pressed.contains(LEFT_KEY)) Left
  169. else if (pressed.contains(RIGHT_KEY)) Right
  170. else direction
  171. move(head + userDirection)
  172. }
  173.  
  174. def init(): Unit = {
  175. rand.setSeed(java.lang.System.nanoTime)
  176. SDL_Init(INIT_VIDEO)
  177. window = SDL_CreateWindow(title, 0, 0, width, height, WINDOW_SHOWN)
  178. renderer = SDL_CreateRenderer(window, -1, VSYNC)
  179. snake = Point(10, 10) :: Point(9, 10) :: Point(8, 10) :: Point(7, 10) :: Nil
  180. apple = newApple()
  181. }
  182.  
  183. def delay(ms: UInt): Unit =
  184. SDL_Delay(ms)
  185.  
  186. def loop(): Unit = {
  187. val event = stackalloc[Event]
  188. while (true) {
  189. while (SDL_PollEvent(event) != 0) {
  190. event.type_ match {
  191. case QUIT_EVENT =>
  192. return
  193. case KEY_DOWN =>
  194. pressed += event.cast[Ptr[KeyboardEvent]].keycode
  195. case KEY_UP =>
  196. pressed -= event.cast[Ptr[KeyboardEvent]].keycode
  197. case _ =>
  198. ()
  199. }
  200. }
  201. onDraw()
  202. onIdle()
  203. delay((1000 / 12).toUInt)
  204. }
  205. }
  206.  
  207. init()
  208. loop()
  209. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement