In the first installment (Angry Rationals Part I) we set out the structure for a multi-level game inspired by Angry Birds. Today we will flesh things out a bit by adding some more compelling game play to our first level.

Level 1 of our game challenges the player to set the initial position of a rational projectile (1/2) so its path along a parabola causes it to crash into the game’s first irrational villan (**π**). The level will have several effects:

- The projectile should leave a trace of its path as it flies across the screen.
- If hit, the villan should change color to provide feedback to the player.
- If hit, the villan should tip over to provide a degree of satisfaction to the player (and the rational).

Additional effects, such as sound would be nice but we will save those for a future installment.

The first effect can be achieved using * Line* and

*to generate the points. The points come from the trigger variable*

**Table***t*, the single user set parameter

*p1*and the function for a parabola

*f[t_] := 1 – t^2*. Despite its name, Line can generate smooth curves provided the collection of points are finely spaced.

` f[t_] := 1 - t^2;`

path = Table[{t1 + p1, f[t1]}, {t1, TSTART + p1, t + p1, PathIncr}];

The second effect requires a means to detect collisions. ** EuclideanDistance** does the trick as long as we define a collision as an intersection of two points within a reasonable delta.

` collision[p1_, p2_] := EuclideanDistance[p1, p2] < COLLIDETHRS;`

The game and sprites are implemented in terms of Mathematica’s 2D ** Graphics** primitives. I already mentioned Line and I also use

**and**

*Text***. The third effect, tipping over the Pi is done using**

*Style***Rotate**.

The remainder of the code is game state logic. In particular, when using **Manipulate**, remember that the body of the **Manipulate** is continuously being evaluated. This means that you must arrange for state variables to always represent the current state of play. For example, we have a state variable called success that is updated using the following logic.

success = success || collision[{t + p1, f[t]}, {PiX, PiY}];

success = success && t > TSTART;

This keeps the value of success **False** until a collision is detected and then keeps the value of success **True** until the trigger variable *t* is reset to *TSTART*.

The complete code for level 1 follows.

DynamicModule[{success = False}, With[{LMARGIN = 50, RMARGIN = 50, BMARGIN = 50, TMARGIN = 50, TSTART = -1, TEND = 1, COLLIDETHRS = 0.05, PiX = 0.85, PiY = 0.35, PiSZ = 48, ratSZ = 28, PathIncr = 0.05, PlRngPad = 0.25, PlotRng = {{-1, 1}, {0, 1}}}, Manipulate[ DynamicModule[{f, pi, collision, path}, f[t_] := 1 - t^2; path = Table[{t1 + p1, f[t1]}, {t1, TSTART + p1, t + p1, PathIncr}]; collision[p1_, p2_] := EuclideanDistance[p1, p2] < COLLIDETHRS; success = success || collision[{t + p1, f[t]}, {PiX, PiY}]; success = success && t > TSTART; pi = If[success, Rotate[Text[ Style[\[Pi], Bold, Pink, PiSZ], {PiX, PiY}], -30 Degree], Text[Style[\[Pi], Bold, Green, PiSZ], {PiX, PiY}]]; Graphics[ { Text[Style[1/2, Bold, Red, ratSZ], {t + p1, f[t]}], pi, Line[path] }, PlotRange -> PlotRng, PlotRangePadding -> PlRngPad, ImagePadding -> None] ], {p1, -0.1, 0.1}, {t, TSTART, TEND, Trigger}, FrameMargins -> {{LMARGIN, RMARGIN}, {BMARGIN, TMARGIN}} ]]]

Here is level 1 to try out by itself as a CDF. I needed to alter the structure because it seems Wolfram does not allow CDF’s containing **DynamaicModule** or **With**, which is a shame. This explains why Part 1 would not work.

Lou can download the entire game, integrated into the framework from Part 1. In the next installment I’ll add more levels, sound and make the whole game it a bit more polished.