Elm Guide stumbling blocks

Agreed that the random bounce exercise is a big jump in difficulty from the others! :scream:

In particular, it’s hard because it requires tapping into a lot of other parts of Elm, not just random generators. It might make sense to either add a label to it saying it’s a much harder exercise or remove it altogether in favor of something else.

Below is a discussion on how to solve it, starting with the simplest solution and building up to more complex. I’ve linked a full implementation in Ellie for each iteration. For easy reference, I’m listing them all here at the top as well:

  1. All the faces at once (text)
  2. All the faces at once (SVG)
  3. Faces over time (text)
  4. Faces over time (SVG)
  5. Moving faces over time

Technically counts?

Executable example

The simplest approach is to just generate a randomly sized list of die rolls and print out that list. It’s not exactly what the exercise asks for, but it gets at the spirit of what the exercise is asking for. It’s also solely focused on random generators so it’s actually exercising the skill learned in this section.

Key lesson: Random.andThen allows you to chain dependent random rolls. First you roll to know how many bounces there will be, then you roll an n-element long list of random die rolls.

dieRoll : Random.Generator Int
dieRoll =
    Random.int 1 6

bounceCount : Random.Generator Int
bounceCount =
    Random.int 1 10

randomBounces : Random.Generator (List Int)
randomBounces =
    bounceCount
        |> Random.andThen (\number -> Random.list number dieRoll)

Add some visuals

Executable example

The exercise seems to assume that you’re building on the earlier ones where you added a visual representation of the die face. Let’s use that to display n die faces, one for each bounce rather than just showing a list of numbers.

I used the elm/svg package but if you wanted to be fancy you might want to look at ianmackenzie/elm-geometry and the associated ianmackenzie/elm-geometry-svg.

Key lesson: Elm has both first and third-party packages to draw graphics to the screen

Faces over time

Executable example (text)
Executable example (svg)

Displaying all the bounces at once isn’t really what the exercise is asking for. We’d like to show them all in sequence over time. In order to do that we’ll need to subscribe to the clock. Time and subscriptions are explained in the next chapter of the guide. It might make sense to call that out in the exercise description :thinking:.

While the model is in the Bouncing state, I trigger a NewBounce message every 750 milliseconds. In the update I handle that message by popping the head off the list of bounces.

Key lesson: Elm allows you to subscribe to the clock, sending your update a message of your choice every n time interval.

subscriptions : Model -> Sub Msg
subscriptions model =
    case model of
        Initial ->
            Sub.none

        Bouncing _ _ ->
            Time.every 750 (\_ -> NewBounce)

        Final _ ->
            Sub.none

Random positions

Executable example

It’s cool that we’re showing a bunch of different die faces over time but they aren’t moving. So far, each roll has been represented by an integer. We could use a fancier data structure to capture both a value and a position for each die roll.

type alias Position =
    { x : Int
    , y : Int
    }

type alias Die =
    { position : Position
    , value : Int
    }

Then we create some new random generators to generate these more complex types:

dieValue : Random.Generator Int
dieValue =
    Random.int 1 6

randomPosition : Random.Generator Position
randomPosition =
    Random.map2 Position (Random.int 0 200) (Random.int 0 200)

dieRoll : Random.Generator Die
dieRoll =
    Random.map2 Die randomPosition dieValue

We use some SVG transforms in the view render the die at its position.

Key lesson: Try to model the problem without randomness first. Here, we need to render a die to an arbitrary position so we added that to our data modeling. Once we have that, we can figure out what generators are necessary to make those positions random.

Going further

This is OK but you’d like it to feel more alive. Have some rotations! Move smoothly between different points! Bounce realistically according to natural laws!

You’ve now gone beyond randomness and firmly entered the realms of computer graphics, animation, and physics simulation. The #gamedev channel on the elm-lang Slack would be a good place to ask questions on these topics. Good luck!

9 Likes