Skip to content

Rendering End of Game

Ryan Neufeld edited this page Jul 9, 2013 · 6 revisions

To follow along with this section, start with tag v2.1.10.

In this section we finish the game by rendering the updated wait screen. If you play a game now, it will end but you will not see the winner or the high scores list.

Recording the end of a game

Rendering the end of a game is a great demonstration of the purpose of recording. Games take time to play. Imagine that it takes 2 minutes to play a single game. That is two minutes until you would be able to see that the winner and high score part of the wait screen is rendering properly. To really see that it is working properly you would need to play at least 2 games. Now you are up to 4 minutes. What if there was a limit of 10 on the number of high scores that would be displayed. Would you like to have to play 10 games to confirm that it renders correctly?

With the combination of the Data UI and recording you can make games finish quickly and you can record multiple games. When playing a recording you can speed through the deltas and at any speed you like to get the point that is interesting.

Once an application gets to a certain level of complexity, being able to record and playback deltas becomes a huge benefit. This application is very simple and it has already reached the required level of complexity to make recording a huge time saver.

So, before you start making change to the renderer, create a new recording by starting a game and entering a score of 300. Play another game and enter a score of 500. You should then see that the high score list contains two high scores. After at least two games, save this recording as "End of Game" and use it to test the new rendering code. This will take a fraction of the time that it would take to play multiple games.

Slice the new Wait template

Add an entry in the tutorial-client-templates map which will extract the high-score template.

(defmacro tutorial-client-templates
  []
  {:tutorial-client-page (dtfn (tnodes "game.html" "tutorial") #{:id})
   :login-page (tfn (tnodes "login.html" "login"))
   :wait-page (dtfn (tnodes "wait.html" "wait" [[:#players] [:#high-scores]]) #{:id})
   :player (tfn (tnodes "wait.html" "player"))
   :high-score (tfn (tnodes "wait.html" "high-score"))})

Remember to restart. I know, we need to fix this.

Rendering the end of a game

In the namespace, tutorial-client.rendering update the renderer by adding the following two functions to render the winner and the high scores.

(defn render-winner [renderer [_ path _ v] _]
  (templates/update-t renderer [:wait]
                      {:winner (str (:player v) " wins with a score of " (:score v))}))

(defn render-high-scores [renderer [_ path _ v] _]
  (let [t (:high-score templates)
        high-scores (apply str
                           (map (fn [{:keys [player score]}]
                                  (t {:player-name player :player-score score})) v))]
    (templates/update-t renderer [:wait]
                        {:high-scores high-scores})))

The high score list is never changed in place so it works fine as a static template. Each time the wait screen is displayed the complete list will be rendered in the correct order.

Finally, add these functions to the render-config.

[:value [:wait :winner] render-winner]
[:value [:wait :high-scores] render-high-scores]

That is it! The game is complete. It starts. It ends. The world is a better place.

Next steps

You may have noticed, especially if you are using Safari or Firefox, that the game can be a bit jerky. If you haven't noticed this then let a bunch of circles accumulate then pop them as fast as you can. The game in the other browser that is on the receiving end of the flood of resulting messages will grind to a halt while it tries to process all the new messages.

In the next section, you will see how pedestal-app has a very elegant solution to this problem which allows for all dataflow processing to happen on separate thread.

The tag for this section is v2.1.11.

Home | Parallel Processing

Clone this wiki locally