26 lines
1.3 KiB
Scala
26 lines
1.3 KiB
Scala
package snake
|
|
|
|
/** m09 app: the whole game wired together as values: streams of actions in, a stream of drawings out. */
|
|
object App:
|
|
|
|
val TICK_MS: Long = 150
|
|
val FRAME_MS: Long = 25
|
|
|
|
// Everything that can happen to the game: a Tick every TICK_MS, and an action for each bound key.
|
|
lazy val classicActions: Stream[Action] =
|
|
Stream.interval(TICK_MS).map(_ => Action.Tick).merge(Stream.keyDowns.filterMap(Input.keyToAction))
|
|
|
|
// m10: a Frame every FRAME_MS instead of a Tick; the game itself decides (movesEvery) which frames take a step.
|
|
lazy val speedActions: Stream[Action] =
|
|
Stream.interval(FRAME_MS).map(_ => Action.Frame).merge(Stream.keyDowns.filterMap(Input.keyToAction))
|
|
|
|
// Actions folded into game states. startWith puts the initial state first so it is drawn right away.
|
|
def states(seed: Long, actions: Stream[Action]): Stream[GameState] =
|
|
actions.scan(Spawn.newGame(seed))(Game.update).startWith(Spawn.newGame(seed))
|
|
|
|
def render(state: GameState): IO[Unit] = IO.drawScene(View.view(state))
|
|
|
|
// The whole program as a value: get a seed, then turn the stream of states into a stream of drawings.
|
|
// Nothing runs here; Runtime interprets it.
|
|
lazy val main: IO[Stream[IO[Unit]]] = IO.randomSeed.map(seed => states(seed, speedActions).map(render))
|