41 lines
1.7 KiB
Scala
41 lines
1.7 KiB
Scala
package snake
|
|
|
|
/** A thing to draw. The picture is plain data; drawing it is somebody else's job (m07). */
|
|
enum Shape:
|
|
case Rect(x: Int, y: Int, w: Int, h: Int, color: String)
|
|
case Text(x: Int, y: Int, text: String, color: String, size: Int, align: String)
|
|
|
|
/** A picture: shapes drawn in order. */
|
|
type Scene = List[Shape]
|
|
|
|
/** m06 view: the picture is plain data (a list of shapes); drawing it is somebody else's job (m07). */
|
|
object View:
|
|
|
|
val CELL: Int = 20
|
|
|
|
private def rect(x: Int, y: Int, w: Int, h: Int, color: String): Shape = Shape.Rect(x, y, w, h, color)
|
|
|
|
private def text(x: Int, y: Int, str: String, size: Int, align: String): Shape =
|
|
Shape.Text(x, y, str, "#ffffff", size, align)
|
|
|
|
// One cell, inset by 1px so neighbouring segments show a gap.
|
|
private def cell(p: Point, color: String): Shape = rect(p.x * CELL + 1, p.y * CELL + 1, CELL - 2, CELL - 2, color)
|
|
|
|
private def overlay(state: GameState): Scene =
|
|
val cx = state.width * CELL / 2
|
|
val cy = state.height * CELL / 2
|
|
def banner(title: String, hint: String): Scene =
|
|
List(text(cx, cy, title, 32, "center"), text(cx, cy + 30, hint, 16, "center"))
|
|
state.status match
|
|
case Status.Paused => banner("Paused", "Press Space to resume")
|
|
case Status.GameOver => banner("Game Over", "Press R to restart")
|
|
case Status.Won => banner("You Win!", "Press R to restart")
|
|
case Status.Playing => Nil
|
|
|
|
def view(state: GameState): Scene =
|
|
List(rect(0, 0, state.width * CELL, state.height * CELL, "#111111")) ++
|
|
state.apple.map(cell(_, "#e53935")).toList ++
|
|
state.snake.zipWithIndex.map((p, i) => cell(p, if i == 0 then "#7cb342" else "#43a047")) ++
|
|
List(text(6, 18, s"Score: ${state.score}", 16, "left")) ++
|
|
overlay(state)
|