Spikey Bird: Creating a Flappy Bird Mod in the Wolfram Language
An earlier version of this post appeared on Wolfram Community, where the creation of a game interface earned the author a staff pick from the forum moderators. Be sure to head over to Wolfram Community and check out other innovative uses of the Wolfram Language!
If you like video games and you’re interested in designing them, you should know that the Wolfram Language is great at making dynamic interfaces. I’ve taken a simple game, reproduced it and modded it with ease. Yes, it’s true—interactive games are yet another avenue for creative people to use the versatile Wolfram Language to fulfill their electronic visions.
The game I’m using for this demonstration is Flappy Bird, a well-known mobile game with a simple yet captivating interactive element that has helped many people kill a lot of time. The goal of the game is to navigate a series of pipes, where each successful pass adds a point to your score. The challenge is that the character, the bird, is not so easy to control. Gravity is constantly pulling it down. You “flap” to boost yourself upward by repeatedly tapping the screen, but you must accurately time your flaps to navigate the narrow gaps between pipes.
So follow along and see what kind of graphical gaming mayhem is possible in just a few short lines of code!
Creating Spikey
I’m going to make Spikey Bird by implementing the gameplay features of Flappy Bird. Our character is going to be Spikey:
✕
spikey = RemoveBackground[ ImageCrop[ Rasterize[Style["\[MathematicaIcon]", FontSize -> 200], ImageResolution -> 700]]]; spikey = ImageResize[spikey, ImageDimensions[spikey]/40] |
Considering the season, let’s make Spikey festive:
✕
santaHat = ImageCrop[RemoveBackground[\!\(\*GraphicsBox[ TagBox[RasterBox[CompressedData["CUSTOMIMAGEDATA"], {{0, 2338}, {2200, 0}}, {0, 255},ColorFunction->RGBColor], BoxForm`ImageTag[ "Byte", ColorSpace -> "RGB", Interleaving -> True], Selectable->False],DefaultBaseStyle->"ImageGraphics", ImageSize->{29., Automatic},ImageSizeRaw->{2200, 2338}, PlotRange->{{0, 2200}, {0, 2338}}]\)]]; spikey = ImageCompose[ ImagePad[spikey, {{0, 0}, {0, 7}}, RGBColor[1, 1, 1, 0]], ImageResize[santaHat, ImageDimensions[santaHat]/46]] |
Game Plan
The gameplay is going to make heavy use of Dynamic within a Graphics expression. Going into all details of how Dynamic works is beyond the scope of this blog, but you can learn more about it watching this great video and reading the extensive documentation.
I’m going to purposely put the most dynamic expressions into an infinite loop. Each update to the dynamic expression is going to take only a fraction of a second—the faster, the better.
The rest of this post is organized around the game’s main mechanic elements:
- Gravity
- Player input (controls)
- Creating objects with automatic movement
- Hit detection
- Scoring
- Sprite animations, sounds and other aesthetics
Designing Gravity
Gravity acts to accelerate an object downward. An acceleration is just a change in velocity per time step, and velocity is just a change in position per time step. One method for modeling gravity is to have velocity update before the position updates:
✕
SetAttributes[updateSpikeyPosition, HoldFirst]; updateSpikeyPosition[{pos_, vel_}, gravity_, ups_] := ( vel += gravity/ups/ups; pos += vel/ups; pos) |
The rate that Dynamic can update—the “updates per second,” or UPS for short—is analogous to frames per second in modern video games. This sets a timescale that is included to slow down the apparent movement; two factors are used in acceleration (distance per second per second) and one factor in velocity (position per second).
The use of HoldFirst allows external variables, provided in the first argument, to update their definitions from within the function:
✕
posExample = velExample = 10; data = Table[ updateSpikeyPosition[{posExample, velExample}, -1, 1], {i, 25}]; ListPlot[data, AxesLabel -> {"Time Step", "Height"}, PlotMarkers -> {"\[MathematicaIcon]", 20}, PlotStyle -> Red] |
This example has the UPS set to 1. For the given parameters, it took 20 time steps to have the position return to 0. In practice, I set the UPS to be about 30, but this depends on the speed of your CPU.
Player Input
A “flap” is modeled by instantly changing the velocity opposite to gravity. Let’s set this action to the keyboard’s Ctrl key. Because this key controls Spikey’s movement, I put it inside Spikey’s movement code. If I put it somewhere else, like within some other Dynamic expression, you might perceive a slight lag when pressing the key.
It would be cheating if repeated flapping was applied by holding down the key. Thus, an instance of Switch is used to track that the key was pressed only once.
Lastly, I don’t want Spikey to leave the game world, so I include upper and lower bounds to its movement. Changes to updateSpikeyPosition are highlighted:
✕
SetAttributes[updateSpikeyPosition, HoldFirst]; updateSpikeyPosition[{pos_, vel_, previousKeyState_}, keyState_, boost_, gravity_, ups_] := ( Switch[{previousKeyState, keyState}, {False, True}, vel = boost; pos += vel/ups; previousKeyState = True, {True, False}, previousKeyState = False]; vel += gravity/ups/ups; pos += vel/ups; Which[ pos < 0, vel = pos = 0, pos > 14, pos = 14; vel = 0]; pos) |
I can create a set of controls that can modify gameplay even while you play. I separate the controls into different groups, such as the controls that affect Spikey:
✕
SetAttributes[playerEffects, HoldAll]; playerEffects[hPos_, kick_] := Panel[ Grid[{ {"Flap Speed", LabeledSlider[Dynamic[kick], {-5, 5}]}, {"Hor. Position", LabeledSlider[Dynamic[hPos], {0, 20}]}}, Alignment -> Left], "Player"] |
And a set of controls that affects the whole game environment:
✕
SetAttributes[environmentEffects, HoldAll]; environmentEffects[ups_, gravity_, worldEdge_, imageSize_] := Panel[ Grid[{ {"UPS Factor", LabeledSlider[Dynamic[ups], {1, 60}]}, {"Gravity", LabeledSlider[Dynamic[gravity], {-50, 50}]}, {"Right Edge", LabeledSlider[Dynamic[worldEdge], {10, 20}]}, {"Image Size", LabeledSlider[Dynamic[imageSize], {100, 500}]}}, Alignment -> Left], "Environment"] |
Spikey is not a graphics primitive, so I use Inset in order to insert it into the Graphics expression. The key here is to use at least the four-argument syntax for Inset so you can specify the size in the fourth argument. Otherwise, the inset object’s size does not scale with the image size of the graphics.
Putting the pieces together in an instance of DynamicModule yields our first basic interface and keeps the variables locally scoped. You can play around with different combinations of gameplay factors, even while the disk is in motion:
✕
DynamicModule[{vPos = 10, hPos = 3, vel = 0, ups = 30, gravity = -30, kick = 2, previousKeyState = False, worldEdge = 10, imageSize = 200}, Grid[{{ Graphics[ Inset[spikey, {Dynamic[hPos], Dynamic[ updateSpikeyPosition[{vPos, vel, previousKeyState}, CurrentValue["ControlKey"], kick, gravity, ups]]}, Center, 1.2], Frame -> True, PlotRange -> {{0, Dynamic[worldEdge]}, {0, 14}}, ImageSize -> Dynamic[imageSize] ], Grid[{ {playerEffects[hPos, kick]}, {environmentEffects[ups, gravity, worldEdge, imageSize]} }, Alignment -> {Left, Top}]}}], SaveDefinitions -> True ] |
Obstacle Movement
Obstacles in Spikey Bird consist of pipes, i.e. rectangles. I’m going to use vertices instead of the Rectangle primitive in anticipation of how I’ll implement hit detection:
✕
pipeVertices[hPos_, vPos_, pWidth_, pGap_] := { {{hPos, 0}, {hPos, vPos}, {pWidth + hPos, vPos}, {pWidth + hPos, 0}}, {{hPos, vPos + pGap}, {hPos, 14}, {pWidth + hPos, 14}, {pWidth + hPos, vPos + pGap}}} |
The function allows for flexible creation of a pair of obstacles with a fixed size and gap:
✕
Manipulate[ Graphics[Polygon[pipeVertices[hPos, vPos, pWidth, pGap]], PlotRange -> {{0, 10}, {0, 14}}, Frame -> True], {{hPos, 5, "Horizontal Position"}, 0, 10}, {{vPos, 5, "Vertical Position"}, 0, 14 - pGap}, {{pWidth, 1, "Pipe Width"}, 1, 3}, {{pGap, 1, "Gap Width"}, 1, 4}, SaveDefinitions -> True] |
I use pipeVertices for each update in order to also allow the pipe gap and other factors to dynamically change even while the game is active. The horizontal and vertical positions are extracted from the previous instance of the blocks using the Part function, but only the horizontal position is updated.
I won’t create new objects every time they leave the plot range. Instead, I reuse the object but reset its position if it goes offscreen:
✕
SetAttributes[updateBlockPairPosition, HoldFirst]; updateBlockPairPosition[{vertices_}, speed_, ups_, pipeWidth_, pipeGap_, worldEdge_] := ( vertices = pipeVertices[vertices[[1, 1, 1]] + speed/ups, vertices[[-1, -1, -1]] - pipeGap, pipeWidth, pipeGap]; Which[ Max[vertices[[All, All, 1]]] < 0 && speed < 0, vertices = pipeVertices[worldEdge, RandomReal[{2, 11}], pipeWidth, pipeGap], Min[vertices[[All, All, 1]]] > worldEdge && speed > 0, vertices = pipeVertices[-pipeWidth, RandomReal[{2, 11}], pipeWidth, pipeGap] ]; vertices) |
Let’s add more gameplay controls for the obstacles:
✕
SetAttributes[obstacleEffects, HoldAll]; obstacleEffects[scrollSpeed_, pipeWidth_, pipeGap_] := Panel[ Grid[{ {"Scroll Speed", LabeledSlider[Dynamic[scrollSpeed], {-5, 5}]}, {"Pipe Width", LabeledSlider[Dynamic[pipeWidth], {0.5, 4}]}, {"Pipe Gap", LabeledSlider[Dynamic[pipeGap], {1, 6}]}}, Alignment -> Left], "Obstacles"] |
Let’s also include some fun buttons. One resets the blocks, which is needed if you change the size of the playing area. One inverts gravity. And one pauses the game by temporarily setting all movement variables to zero:
✕
SetAttributes[buttonEffects, HoldAll]; buttonEffects[velocity_, kick_, gravity_, scrollSpeed_, obstacle1_, obstacle2_, pipeWidth_, pipeGap_, worldEdge_] := DynamicModule[{previousMovement, pauseToggle = False, gravityToggle = False}, Grid[{ {Button["Pause", If[pauseToggle, pauseToggle = False; {gravity, scrollSpeed, kick, velocity} = previousMovement , pauseToggle = True; previousMovement = {gravity, scrollSpeed, kick, velocity}; gravity = scrollSpeed = kick = velocity = 0]], Button["Reset Block Spacing", If[scrollSpeed < 0, obstacle1 = pipeVertices[worldEdge, RandomReal[{2, 11}], pipeWidth, pipeGap]; obstacle2 = pipeVertices[3/2 worldEdge, RandomReal[{2, 11}], pipeWidth, pipeGap]; , obstacle1 = pipeVertices[-pipeWidth, RandomReal[{2, 11}], pipeWidth, pipeGap]; obstacle2 = pipeVertices[-worldEdge/2 - pipeWidth, RandomReal[{2, 11}], pipeWidth, pipeGap];]], Button["Invert Gravity", gravity = -gravity; velocity = 0; kick = -kick]} }, Alignment -> Left] ] |
Now I have something that looks like a simplified version of Flappy Bird. First I create two pairs of pipes that are roughly equally spaced along the horizontal direction, but off of the right side of the visible plot range. There’s no hit detection yet, so you can change with the parameters to adjust the difficulty without frustration.
✕
DynamicModule[{vPos = 10, hPos = 3, vel = 0, ups = 30, gravity = -50, kick = 2, scrollSpeed = -1.6, pipeWidth = 2, pipeGap = 3.25, previousKeyState = False, obstacle1, obstacle2, worldEdge = 12, imageSize = 200}, obstacle1 = pipeVertices[worldEdge, RandomReal[{2, 11}], pipeWidth, pipeGap]; obstacle2 = pipeVertices[3/2 worldEdge, RandomReal[{2, 11}], pipeWidth, pipeGap]; Grid[{{ Framed[Graphics[{ Inset[ spikey, {Dynamic[hPos], Dynamic[updateSpikeyPosition[{vPos, vel, previousKeyState}, CurrentValue["ControlKey"], kick, gravity, ups]]}, Center, 1.2], Polygon[ Dynamic[updateBlockPairPosition[{obstacle1}, scrollSpeed, ups, pipeWidth, pipeGap, worldEdge]]], Polygon[ Dynamic[updateBlockPairPosition[{obstacle2}, scrollSpeed, ups, pipeWidth, pipeGap, worldEdge]]] }, Frame -> False, PlotRange -> {{0, Dynamic[worldEdge]}, {0, 14}}, ImageSize -> Dynamic[imageSize] ], FrameMargins -> -1], Grid[{ {buttonEffects[vel, kick, gravity, scrollSpeed, obstacle1, obstacle2, pipeWidth, pipeGap, worldEdge]}, {environmentEffects[ups, gravity, worldEdge, imageSize]}, {playerEffects[hPos, kick]}, {obstacleEffects[scrollSpeed, pipeWidth, pipeGap]} }, Spacings -> {1, 1}, Alignment -> {Left, Top}]}}], SaveDefinitions -> True] |
Hit Detection
There are many ways to implement hit detection. I’ll implement a perimeter of points around each object and track how close Spikey gets to each point. This allows us to use more interesting polygons later with minimal effort.
Let’s add points to our existing polygons. I’ll take a walk around the polygon, so let’s add the starting point to the end of our perimeter:
✕
originalPolyPoints = pipeVertices[5, 5, 2, 2][[1]]; cyclic = Append[originalPolyPoints, First[originalPolyPoints]] |
Now accumulate the distances between the vertices in the walk around the polygon, including zero at the start:
✕
accumulatedDistance = Prepend[Accumulate[Norm /@ Differences[cyclic]], 0.] |
Linearly interpolate the x and y coordinates. This creates a function for our walk around the perimeter:
✕
intX = Interpolation[ Transpose[{accumulatedDistance, cyclic[[All, 1]]}], InterpolationOrder -> 1]; intY = Interpolation[ Transpose[{accumulatedDistance, cyclic[[All, 2]]}], InterpolationOrder -> 1]; |
Our walk consists of a number of steps with equal spacing. The spacing between the chosen points is small enough that Spikey can’t squeeze through two adjacent points. Before I start the interpolated walk, I join the original vertex distances to the equally spaced ones:
✕
spacing = 0.8; steps = Union[Range[0, Last[accumulatedDistance], spacing], Most[accumulatedDistance]]; newPts = Transpose[{intX[steps], intY[steps]}] |
I put all of these steps into a function:
✕
generatePerimeterPoints[originalPoints_, spacing_] := Module[{cyclic, accumulatedDistance, intX, intY, steps}, cyclic = Append[originalPoints, First[originalPoints]]; accumulatedDistance = Prepend[Accumulate[Norm /@ Differences[cyclic]], 0.]; intX = Interpolation[ Transpose[{accumulatedDistance, cyclic[[All, 1]]}], InterpolationOrder -> 1]; intY = Interpolation[ Transpose[{accumulatedDistance, cyclic[[All, 2]]}], InterpolationOrder -> 1]; steps = Union[Range[0, Last[accumulatedDistance], spacing], Most[accumulatedDistance]]; Transpose[{intX[steps], intY[steps]}] ] |
Spikey hits a pipe if it gets within a minimal distance to any of the points:
✕
hit[position_, obstaclePoints_, dist_] := Min[Norm /@ Transpose[Transpose[obstaclePoints] - position]] < dist || position[[2]] > 13.5 || position[[2]] < 0.5 |
Here's a visualization of this effect in action. A detected hit colors the circle red:
✕
DynamicModule[{pos = {1, 1}}, Grid[{{ Graphics[{Point[newPts], Dynamic[If[hit[pos, newPts, 0.5], Red, Green]], Thick, Circle[Dynamic[pos], 0.5]}, ImageSize -> Small, PlotRange -> {{0, 10}, {-0.1, 6}}, Frame -> True, Axes -> False, AspectRatio -> Automatic], Slider2D[Dynamic[pos], {{0.5, 0.4}, {9, 5.5}}]}}], SaveDefinitions -> True ] |
Scoring
Let's reward the player with a point. Every time a pair of blocks passes the player, I add a point to the score. I also set a flag to False to indicate that I should not score a second time until the block resets:
✕
SetAttributes[scoreFunction, HoldFirst]; scoreFunction[{score_, scoreFlag_}, hPos_, worldEdge_, speed_, obstacle_] := ( If[scoreFlag && (Max[obstacle[[All, All, 1]]] < hPos && speed < 0 || Min[obstacle[[All, All, 1]]] > hPos && speed > 0), score++; scoreFlag = False]; If[ Max[obstacle[[All, All, 1]]] < 0 && speed < 0 || Min[obstacle[[All, All, 1]]] > worldEdge && speed > 0, scoreFlag = True]; ) |
Now let's add the scoring feature and hit detection to our game. The game objects get extra vertices by mapping generatePerimeterPoints over the pipe vertices, but updateBlockPairPosition only outputs the original vertices. This allows easier application of textures.
Scoring is added by including scoreFunction. Changes to updateBlockPairPosition are highlighted:
✕
SetAttributes[updateBlockPairPosition, HoldFirst]; updateBlockPairPosition[{vertices_, score_, scoreFlag_}, hPos_, speed_, ups_, pipeWidth_, pipeGap_, worldEdge_] := Module[{originalVertices}, originalVertices = pipeVertices[vertices[[1, 1, 1]] + speed/ups, vertices[[-1, -1, -1]] - pipeGap, pipeWidth, pipeGap]; vertices = generatePerimeterPoints[#, 0.5] & /@ originalVertices; scoreFunction[{score, scoreFlag}, hPos, worldEdge, speed, vertices]; Which[ Max[vertices[[All, All, 1]]] < 0 && speed < 0, originalVertices = pipeVertices[worldEdge, RandomReal[{2, 11}], pipeWidth, pipeGap]; vertices = generatePerimeterPoints[#, 0.5] & /@ originalVertices; , Min[vertices[[All, All, 1]]] > worldEdge && speed > 0, originalVertices = pipeVertices[-pipeWidth, RandomReal[{2, 11}], pipeWidth, pipeGap]; vertices = generatePerimeterPoints[#, 0.5] & /@ originalVertices; ]; originalVertices] |
Let's add a button to reset the game with the current settings so I don't have to reevaluate the function every time:
✕
SetAttributes[resetButton, HoldFirst]; resetButton[{score_, velocity_, kick_, gravity_, scrollSpeed_, obstacle1_, obstacle2_}, startingValues_, pipeWidth_, pipeGap_, worldEdge_] := Button["Reset Game", {gravity, velocity, kick, scrollSpeed} = startingValues; score = 0; If[scrollSpeed < 0, obstacle1 = pipeVertices[worldEdge, RandomReal[{2, 11}], pipeWidth, pipeGap]; obstacle2 = pipeVertices[3/2 worldEdge, RandomReal[{2, 11}], pipeWidth, pipeGap]; , obstacle1 = pipeVertices[-pipeWidth, RandomReal[{2, 11}], pipeWidth, pipeGap]; obstacle2 = pipeVertices[-worldEdge/2 - pipeWidth, RandomReal[{2, 11}], pipeWidth, pipeGap];]] |
Let's add a button to toggle the hit detection so it's only on when I'm ready for it:
✕
SetAttributes[hitEffects, HoldAll]; hitEffects[hitToggle_] := Button["Hit Detection", If[hitToggle, hitToggle = False, hitToggle = True], Appearance -> Dynamic[If[hitToggle, "Pressed", Automatic]]] |
Putting It All Together
In addition to the hit detection and scoring, some finishing touches include styling the objects and the background. Changes to the interface are highlighted:
✕
DynamicModule[{vPos = 10, hPos = 3, vel = 0, ups = 30, gravity = -50, kick = 2, scrollSpeed = -1.6, pipeWidth = 2, pipeGap = 3.25, previousKeyState = False, obstacle1, obstacle2, worldEdge = 14.5, imageSize = 500, hitToggle = True, score = 0, canScore1 = True, canScore2 = True, startingValues}, obstacle1 = generatePerimeterPoints[#, 0.5] & /@ pipeVertices[worldEdge, RandomReal[{2, 11}], pipeWidth, pipeGap]; obstacle2 = generatePerimeterPoints[#, 0.5] & /@ pipeVertices[3/2 worldEdge, RandomReal[{2, 11}], pipeWidth, pipeGap]; startingValues = {gravity, vel, kick, scrollSpeed}; Grid[{{ Framed[Graphics[{ Inset[spikey, {Dynamic[hPos], Dynamic[ If[hitToggle, If[hit[{hPos, vPos}, Flatten[Join[obstacle1, obstacle2], 1], 0.5], If[gravity != 0 || vel != 0 || kick != 0 || scrollSpeed != 0, startingValues = {gravity, vel, kick, scrollSpeed}]; gravity = vel = kick = scrollSpeed = 0]]; updateSpikeyPosition[{vPos, vel, previousKeyState}, CurrentValue["ControlKey"], kick, gravity, ups] ]}, Center, 1.2], {EdgeForm[Black], Texture[{{{1, 0, 0}, {1, 1, 1}, {1, 1, 1}}}], Polygon[ Dynamic[updateBlockPairPosition[{obstacle1, score, canScore1}, hPos, scrollSpeed, ups, pipeWidth, pipeGap, worldEdge]], VertexTextureCoordinates -> 3 {{0, 0}, {1, 1}, {2, 0}, {1, -1}}]}, {EdgeForm[Black], Texture[{{{1, 0, 0}, {1, 1, 1}, {1, 1, 1}}}], Polygon[ Dynamic[updateBlockPairPosition[{obstacle2, score, canScore2}, hPos, scrollSpeed, ups, pipeWidth, pipeGap, worldEdge]], VertexTextureCoordinates -> 3 {{0, 0}, {1, 1}, {2, 0}, {1, -1}}]}, Text[Style[Dynamic[score], 30], Scaled[{0.5, 0.8}], Center], }, Frame -> False, PlotRange -> {{0, Dynamic[worldEdge]}, {0, 14}}, ImageSize -> Dynamic[imageSize], Background -> Darker[Green] ], FrameMargins -> -1], Grid[{ {buttonEffects[{vel, kick, gravity, scrollSpeed, obstacle1, obstacle2}, pipeWidth, pipeGap, worldEdge]}, {hitEffects[hitToggle]}, {resetButton[{score, vel, kick, gravity, scrollSpeed, obstacle1, obstacle2}, startingValues, pipeWidth, pipeGap, worldEdge]}, {environmentEffects[ups, gravity, worldEdge, imageSize]}, {playerEffects[hPos, kick]}, {obstacleEffects[scrollSpeed, pipeWidth, pipeGap]}}, Alignment -> Left]} }, Spacings -> {1, 1}, Alignment -> {Left, Top}], SaveDefinitions -> True ] |
Final Thoughts
With just a couple hundred unique lines of code, I was able to implement Spikey Bird using the Wolfram Language. Not only that, all of the gameplay parameters were left open to change while you play, kind of like not-so-hidden developers' tools. If you got rid of the developers' tools, then the code would be considerably shorter!
Here are some suggestions you can try on your own:
- Play the game using only the "Invert Gravity" button.
- Modify the blocks to fall from the top of the screen to the bottom (similar to classic "flight" games).
- Change the obstacles to randomly generated polygons instead of rectangles, and add more of them!
- Add sound effects in appropriate places using EmitSound.
Bonus Suggestion 1: Using Sprites Instead of Primitives
I'm not an artist, but the Wolfram Language makes it simple to include bitmap graphics. For example, I can screen capture images from the internet and import them. Like I did with Spikey, it's often sufficient to just use ImageCrop and RemoveBackground, then use Inset to include it in a graphics expression. It's important to keep the image size small, though, or updates to the image can take time to render for each update. The polygons will still be needed for hit detection, but the images sit on top of them:
✕
pipe = \!\(\*GraphicsBox[ TagBox[RasterBox[CompressedData[" 1:eJzt2PtXVOUex3Hy9EM/nv8gxBS8zMQtHEVrZSUXgWD27LkPCswAQwYyjKio iAh2EQFL8waoLS075ik1j6aC4qVlUamlxdLQ8oqJdlmVlsinZ++ZYBbiSTh2 qrU+P7zZz3evxcxrDcOe/czgzAJ99qCgoKCiB8QPfcaMxz2ejFnSP8Ug5xe5 c/JdzoR8ryvH5dFl/kOcdN8XFDRKHO8XFbYcD8pZtma2FD4Bldulm5u/d+Ji 52Icu16KuouW7hrabVh6OhWeJg0WtyZg5TkjivdHwLNXg6K92oHVpMX0Aw8j 57Xh0M8aDNerYeo588IhMMwNgVwZDNkReUsenYxn/r1jfOH7n9BLL7300ksv vfTSSy+99NJLL7300ksvvfTSSy+99NJLL7300ksvvfTSSy+99NJLL7300ksv vfTSSy+99NJLL7300ksvvfTSSy+99NJLL7300ksvvfTSSy+99NJLL7300ksv vfTSSy+99NJLL7300ksvvfTSSy+99NJLL7300ksvvfTSSy+99NJLL7300ksv vfTSSy+99NJLL7300ksvvfTSSy+99NJLL7300ksvvfTSSy+99NJLL7300ksv vfTSSy+99NJLL7300ksvvfTSSy+99NJLL7300ksvvfTSSy+99NJLL7300ksv vfTSSy+99NJLL7300ksvvfTSSy+99NJLL7300ksvvfTSSy+99NJLL71/V+87 vbwXLN01XAzwfv7new3CW9HLu1o4f6teeF9u6/GuOCu8zX++9807eS/5vY29 vGJWnmNANQrvfuHd4PeuC1PPqd7Su/R+5/f+JLznLd3VXwjwfkbvPfGe+4t7 twnvt728/urPC+8XwrvH7/1KePdFqLPyHANqj/A29/LuoZdeev9qXoleehXv B58OylnaMFf1bpVubrrmxIVfqnD0h1KsOmvpru6cDS+dEt7dGlSdSMDyL4V3 b4Q6K88xoHYL7z7hXS+8M4V3bZh6zlzpvz+rCPBu/s9jhYePDfIcaQ3KXfGq V/Eu3CndfOu6C1dQi89ulaHhsrW7tV/bsexsKoqaR6HmiwSsumTCjEPh6uzd rxlYzRoUv6dF7hth0M8ORvaGUPWc+YUQGOYPhvz8g5DTI1Tv1G27ozwfnQjK 394U7qyoXi1FPtE1uz61s+5IOlpay7DreBGqD8rd1Rwy4bmmFExdH4Hyd+Ox 6ICEaRsfwbMbIgfe+kgUbIyCc4kW+vxQZFZr1HOmmcNh8IRBnhEK2RRzS9Yl deUuXzc1f0fzSLt+MuSYiTDEJMKoS4BpbCLMIuVoHJNwW7IuXhS4vjcZRouj P2VtiPH3iHJM7DRETcBk9/Sd1mQ79I+O65Js0dCbI5Em0vuTzFGQLFEwWKJ7 1tZodVaz3uOEQbb1zMpativFdOpjYm85XEVvW5PSYdLr4HhpGLKWjBB/m5Fw 1IT6qg2FtWoILItCxDwM9pqhMC8a/IdlXBis/o8pa9Pz4v27INh3jSgf0ik9 NhoOp3eLKc6OZz3xWH5exuGrM3HkmzlYcdqIV07LWHnGhLmHxqK4MVI9V30i CZ5dWhTu0vwh2aqGwlgegmk7NGJPN8J3jSgTlQ7tlB7t8RbMSET9NSs+vVGG Uzcr1b17XbsVa8Q1ofzDWJQcjPLt58+kiuuPdkB5e637ylYtvAtC1Guze5Pi Fa/xfOGd18tbnIi6KxYc/bEUrTcWiL2wFauV7xzEHnN+SyxmHYhSz73c9jS8 Yl87kIp6rfvqN69HXJvd//odb4dFfKbNRevPPm+daE27HfM/HNftXdqWql7f +5vXX+C6r3zeIepnSZ54faXSu/GWq7b6QO/B/807PcD738zK/7OxQvE+LLwj 6f2/enX00nub1/g39h79aQ4+F17lu16lte0OlH80HiWHotV5WVsaipvD+9++ cOHsmX2+8Nty1A6DqfIheBvDkfem8M67k3cSGq7ZcOJ6GU7+XIGVF0xqqy9Z MOd9nbgn16pz7alkFDSO6HeeplEoFCnrwsaR6nfIfWV+MQT6ecEofFeD3I3D kVYS7Lt/CHz/xtvhLnwKNWcmYU9HPlp+mIUtV3KxtSMX267moeGkhJXHk9V5 08UMvHIssV8tO5aA8pbxaspc9fGTKP0gFmV9VLAxGnlro1B2eBy8O6NhXzIU JrGX893v+L2J6V2T3WPgfW8Uqk5OwuZvsnEJi3EZ1Wpfo0ZU659967vtCpao j/V6RyZev5oh5hocvjETqy5bxP7KgQZxPxXYmg4lG9ZdTUdtWxK8B7VIXzpM 7D0fEveTY+BwTX/bFGeCPC4WDlsssqY8gamuRMzOM9yzStwS3M54NWX25KQg O2sicrLi7tBE5DrjkDV5AmzmsZCTdJDidJ1p2tGwZ07b7sguajenToE5zdVl ejoLxpRMGFKm3LnkfiZ+R3lM9XHFLKdkwCTWv5uwmFOdsOidsBpcneYUBzJK Ftb9ChNPXgY= "], {{0, 361}, {44, 0}}, {0, 255}, ColorFunction->RGBColor],BoxForm`ImageTag[ "Byte", ColorSpace -> "RGB", Interleaving -> True, MetaInformation -> Association[ "Exif" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com", "DateTime" -> DateObject[{2017, 7, 25, 9, 33, 57.}, "Instant", "Gregorian", -6.]], "Comments" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com", "Creation Time" -> DateObject[{2017, 7, 25, 9, 33, 57.}, "Instant", "Gregorian", -6.]]]],Selectable->False], DefaultBaseStyle->"ImageGraphics",ImageSizeRaw->{44, 361}, PlotRange->{{0, 44}, {0, 361}}]\); city = \!\(\*GraphicsBox[ TagBox[RasterBox[CompressedData[" 1:eJztvXmcXMd1HgouopLYT8/x8vvlOY4UP8mOo8SyndgveXl2ItmyZFmOFsuS Zck/J5a1ccNGgFhIgAABEDt3EvtKggRAEPsymAEGy2w9a+9796zds+8ACYAD oN756lZ1V9+5t/v2TDdmwLl/fGjMTN9bVV+d89WpqlP3/uaP5vz1Tx+cNWvW U/+M/vnrf1z0pfnz/3HJd36Jfvju7Kce/dnsn/z4a7MX/ORnP5n/X3/0EP1y FeGLD8ya9TB9zq1qsmHDho0ZhXk1rlmPlVZMeT1s2LBh417D1j8bNmzMVNj6 Z8OGjZkKW/9s2LAxU2Hrnw0bNmYqbP2zYcPGTIWtfzZs2JipsPXPhg0bMxW2 /tmwYWOmwtY/GzZszFTY+mfDho2ZClv/bNiwMVNh658NGzZmKmz9s2HDxkyF rX82bNiYqbD1z4YNGzMVtv7ZsGFjpsLWPxs2bMxU2Ppnw0bR8MC86qaH88RD 06DeMwa2/tmwURzMqWya9VhF46zHrlrH4/T9OdOg7jMFtv7ZsFEwPDBPw4Ok YQ8srXV+6nW/5x9eD3h+JPBPWfCPb9Dna37P1xY5nA/TvR7CfXC/uRqmum0f S9j6Z8NGYTCb4r0nCbPp/z+nWO5Fj/tbPbejrO+ONfTfjbLkrejN1U2uRx6r SN8PceRUt+3jClv/bNgoDJbUOn95eb3r15c3OP8N/f/Xt4U8P+sei46RBt4g jOXAR72E5EfRa6/63H/8TJ3z15fXO/814ddFPDjl7fs4YpL69yDhoTzx4FS3 2cZ9h3xtDLgXc0ZZ1icpTnvwXNL/dvvN6M3Yh5Hr8Q8jN1tvRKBpLF+03Igw XB/7IPIB7neoxffK4xWND82rbvqkUuZU98nHApPRv3n5oDr9/6lus437C3r7 sWJn96xehPlV2lz1ck/g5AiLsb7b0Tv9mNNOQPt6xXxZXH9nlO53osP33hMV jbPmV9/b9s0E5KN/87Q12Yeovx+ZU9n00HstvmXO4XBp3UDoXP1gqDQb8B18 90irf9kc7T6PyPtNNQc2phUeUOzioYU1TZ8q7QocaxwiGxoMnbdkZ0Ph0u0h 7588Wdn4EGlGys4KYW/YkyCte2hVk+sXa/pDR6nMMl7uYKi8+UbkJmnXXZrL ckxE+yTEPe7gftEPw111WvvKwMOV3uAxmh9/SviRPZ+aTH9a1D/syT9RoeFJ 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 n2zn74fwpM7omftkXPhkLEP/VH/LyH824c9K/su4eir8mcV/WnzlSOmh1Ht5 9ql48V+cx398rBlUxzdN//l5oRF5RrqGlXdqa3o4H4e8mXPtXvLXNPDzyTbt /BCeh6WP/wqV/yyfB+oe1GJkOSeQ8Z+zKPFfNBX/ga/AUDoGQ5muQZEvO5zm D2foYW/ITYXNnG0fD5wdwpqBFv/FU/GfzH8uL0D+s4z/UCenEkNI/jD2t9yD +K9JF/81qPHfkGbztb11fM9sF9nO8VY/P+uotzGcG0UcfYjHf+FU/GeW/3x5 AvnP6fhP17+KfwSUeKig8V/Cxf1NH/819af5cwufPJ9wpTg+J/jR83WM5h+H mnXxXx75z5ct5D9L/UOcJ8/KZfBnEv+l9n/1639YL08WP//lsNn6nzJe8udv JLX1Z7l+gO+1jKbfT9sszviDR5zxP22w/ldhdP6tcyL5zznioXuw/idzbszG S9iQtv8W521oU947K/mKiudH4LzVIbF/ruqfWf6zMX/m+pda/0sanKebwvW/ s7r1P9j72Q4H24t5W1B7X6/+Pccto1rOG56DBn7k+l9FHvnPcr8xW/zXlKN/ 1XioGPsfsLGM9T+hByp/pfQdfBc2hudvpJ4ZodgY6sefH5Z6fkSm/hUq/1m/ /jc+niz+/m+nOG+N57gXev+3tDOdfyDXT6Oib3yDdalnCzXwfJ8qdqq9YZz+ YV0BZwkl1xj7UValkv9cxXNVa3LkPxdm/xe2KZ/jaVX/rO4PpvMP4tr7esUz rfyD2ppIJGNsTecPSf3Ds67wN/SLHPNre2uy8ndP9n/Jtvj7kG+Yv79iovu/ sHecv5X6J9/Xi9gVNibXPWT+Ae6p7n+gDbAbcFTTm+4PtBM8eYU9o70Xu7T3 5hV7/7ebYhLtGbvZ340ykf1f+JnUP/m+3ojgxz+Ufu6akf9K/ZP+Jn09F38t OfY/JrL/W6j8P/5OgRFzjk3jPwP9058XOm/CH94fUJrM3O8x0z95ZjLXmTH5 nYnk/xk9D9RI/7jNjXiyvu/Dav6fFf1rFb6JPr2isxe9/pmdR4ya8BceuUf5 f6qdZbGvQuof6lUn8of0+fd6/bN6LlHlbaL6Z2n/d9hj+V0f4+K/CeifOl8t sxC/xBQe9NwY8TfR/L9c+sfXIzozz3+gfy925al/FqHqH9ZR8KwwtX+R316m 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 YQn9flXgZfZe/H3+fe26ozQvred6tjuk6SCeIyv1D+/wxN8w/rZQ2SXtXvGO 7zC3yz1h5FMeY4eb3+M4Aq0Pb6Gy1meUvVRA+3kDW+M5yNa7zlL7j7EjLYfY sdYS3nacE9PWgxxsa7CExqrTVAa1seV99mZ0N2+DUdu09q1nb0R2Uf3fZwco Bt0SPEhj9VFqh/bcvHcxPlLda0iDEjr9U8ffNiXWqeq8xI7ENY6PN5+gexxm ywObs3C8nq0Lvsa5OETYGT7EtoUO0fh7guKUM8Ql2nKEbY/uNb0HsNi3nr0Y 3kp6foS9Q23ZGjrI9kSO8DEdtqidf6vhMXd8RMtxwLl2xHHQP9le9JWR/mXP p6b4rNsp+tfH3o+fIjs5Rhwc47Ef6qXv30xsYHuiBzhfmo29Tzpazs9m7IsE +RoJYlnj8/u1PN7Fugl0ci/OUvL3IZ6ncfkQ5xX9u4P405er2hjqtza4hbg/ zHZFDvPrjrYcpXitgpfj42tc9aSxJezN4LvE7WFuu2/H38m7f9E31T2X+dmG kg4PjeNR8tEg3+u1YmNe0uejcfLHuMYxfHND6E222JTjDWxZYBPbT3Ho+2RL bwZOUJx4mm0kwMZe9Z3kbXknfpCtDGbXg5WkB+/GwesRin8Oc5+52nWRc+Md wHm4mvT5txFtvbS2T54zcPD2Yl7zbtwr9uyvUj+9n1MPng1uYgtqV43Tv3T8 FxgX//kHXSzxQQN9J0SxQYLaW8KeIA2fXU26SjHD3No1bEXbRrYquYmtShig cxNb0bqJzXGs4d/HdYinNnvKyS47yNabqS6t7GhrZFz8V9/nptiugZV1hPh3 8N294Tb6m4c95aB71oh7Vq5hz4TXs9WdJnUQeNq5lseD86gOGBve8O+isYLG jev1fOzAnHV10ys0VjxPYzrVk+67yLOOrTZrGwFlLvKu49+dW72WuFnF490Q f4eYk8YHilmp7vU9GGPdqfEZ76HuEvGNROeojw1cD7O3I4fYoxiHHS/wts2r e4GtbM9eh2WxDYJfLWZAPDKP+JlPmFuj8f60e515P4n7LA1uEG15gY/hS+s2 MU9/JWunOLvtWiOPtzHXl3uXrTzXtY7/DbEJ2ou+wnup9PpXYhL/NQ3UcRur 6/FQ/7ZT/7qp3puozquV/t2Qs38XNK3ldZ9DdX+CYsXnGt4im22j+W+U/ARz Le39lGr8V9uP9+w2sgDi3S7EgPVsfzTG45rlDXvZk9UUQ1Rr913oysFf1yb2 TIjiOMHfE8TfEuLPS+MHYqMW4i1Bc5X9kQMUaz/P7WUi/TuXz3FW07hdwjo/ cLKyBM45trKz7VGyITefZ0j966Q5hJGN1XRe5naR8iECyshm6ys7NrH5dZpN zq3W5gwAbAy2Bt7RlhVtm8x5Smp6wG27WvK0ip1tO8njtpZrDdzWWsie1LN3 /Kwk/a3jOs2xEhhj22gsCNL8pI6daL/EFjqInxx6sLpzM2ngav6eqZ2E2l5t Lf1Kl4vsNsjKRZ4s1vwwFz7WQvFloox+f4bGxHI+f1zrOcwWkx0scW/gWOoh Paf2Pt9hjpXU3iWeDalrFpMfrvO8z171VrFXvFdJC69SXFnJ9Qf74qcp1kQ8 WJK4xC51nqa/XaRYpoJ/9xVfFc0FStnTtdDydWyxk+7p2sCei23MWgfgmQCV 7dLqsNC5jr0U3EZcnmNlybPsIqEkcYqt9r1KOrleqyd991my51z3XRbaqNWD rnmauHne+zKNUafILs9RzHyZt+9sWyNz9vqZr09ba8a66ZXkBXYlkcZl4rqy s5zG8j1km6RXDVrblnpzc7yieZPCr4aF9etpnFhPPGmfS9zr2fOJLPehvy2P btI4IixyrWfPeV5kp9tPED/niKuz1KYzrKHviniPWT1z9DhZdXc990XMr9He Fz0V7L2WSr5+WC2ej+QT639VSj51Pf1N29sr5zZ2tKWU+riKbfaWsmfcL/L6 8jbl3b/UH661bKUH68+V7HX/JfZW/DQ72HKG5jNVYv1Pe0fy5e7L7GLnWYrJ zlL8fppi9zMUC1ymelTQPG4b8baWLWoUthDIYQsm/J0S/IG7S50lbEtkN9nf 2lTbeP+2G9xP+d1z6F9x38Uc69m7zYfZ5c5z3D82uq+yAzQ3a+yheX+vl7UO eQgu0rlL3K4ybCxZTvH1UbaQ7AKQ9X0unp1j1PEZryxfs7GniRtuYwJPk82t aN2Y1c4y9MCl+cxb8QPsEtnQBfLDUuKpsruM6wHWCN0DDo6rXReIxzPUzovk U5UUN14kDk5TrP0+W1SXWw9WJTeTjaymMbGZ4s5m1tinrYtDV4G4spfZQmMi YphVTa9yXUfb5leR7nnXcy3NZYu57GSxh+5Xs4775hzSbKwpx0cbOBBfQP9f 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 7slxlr3Oxe6v7OVPpq9z17sYZds2/vGw8fV1XxyHDfVfYutq/wd73fdX7HDP P7HDvWkc6vkR/3wz8A3+HaPr19d/kW1s+FP2Vsffs/d6f5y+nu71Xt+P2b62 H/AyspW9LfztcdeibOBVz9fMyya86PwKe7fzf9N16vU/4mXvav6u6XWyTrua v8e/q5aNz3e6/hfd+88Ny95Qp9X7Ve/XUhylOdPavTX0LdN6o2xgX/sPxrUb 7Xgr8fec02ycoU8y2qz01+u+r2flbHPjl9mB5D/oONPqvaf1+1k5w313RL9j 0F//xA52/yN72f1V+q5R2RrfL7u+yr9nxBnuu87w2nR/7Wn5vnF/UXs2Nf2Z beO2jZva+OyLn8/AHMKTZf+ePVryW2xpzX9h25J/m4EdXX/HdvX8kK1o/BP2 ROnvjLt29oXPs8dLf5t/vhz7Btve+f3Utfj/7t6/57+fW/4fspa9sum/0/f/ Ln2tKHtn9w/YM47/hz1RZlT2v2ePn/9tNv/yF9gbbd/JKHuHKHtD8Ku8DH3Z AO6J69f6v8zLUuuNNm9JfJctrPiDcdfzelPZj1G9F1f9Idua+N44zlD2KtcX Ter9ec7lE6X/jm2OfJ3qqi/779lrrd9m8y79RxPOPs85W1b/3zLarPYX/mba X9TmuRf/I3ut+VuG/bU58peGfM3mZf8Ob/dq95d09f5b6qsfUr99ny2q+s+G nGn99Vts4dXfZ1s6vmvI2Vrfl3kZ48oWnKHu6FOj/nqz/TvsqSu/Z9xfto3b Nk5YcPn3MvBU+e+ylQ1/wjaH/pK9Sn24i+opsTP5d2y978/Z6qb/wZZW/xF7 6tIXMq+lnxdX/iHbFPgL9iJdv63je3TdD/i1u7t+yF6h++HaFfV/PK5cef0a 15d42a9TPeW1u7p+wLbTvV5w/ylbRdcvrvzPbMElfb2/wJ6p/i9sc/Br7KUw 8Ut+p16P+qDs5bX/77hrJdZ5v0zX/yV7s/U7VF95LdlE29/wej1P/vD01T8w KPt32XN1/x8v4+Xo/2Q7Fc6ADf6v8LKfJV8z4mzR1f/ENvq/ytu9tf27GZy9 Hv8mXftF6pM/Zgsv/75hf4ETXPta7JsZbd6R+D5b5/kyL3sJ2ey4somzJVV/ xDlD3Xck/jaj7Jcjf8Wvfa7uvxnyBaz1/Bm/9o2Wv2a7lbLRjheIs1Xk44sq /pMhZ+gLXPsSlQPbUjnbFPwLXvYyx3816K8vsIVXfp9t8H2F9xf6R/YX6v1G y7fZGucXtf66Ytxfto3bNg78/zWwbBA= "], {{0, 131}, {320, 0}}, {0, 255}, ColorFunction->RGBColor],BoxForm`ImageTag[ "Byte", ColorSpace -> "RGB", Interleaving -> True, MetaInformation -> Association[ "Exif" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com", "DateTime" -> DateObject[{2017, 7, 25, 9, 37, 51.}, "Instant", "Gregorian", -6.]], "Comments" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com", "Creation Time" -> DateObject[{2017, 7, 25, 9, 37, 51.}, "Instant", "Gregorian", -6.]]]],Selectable->False], DefaultBaseStyle->"ImageGraphics",ImageSizeRaw->{320, 131}, PlotRange->{{0, 320}, {0, 131}}]\); ground = \!\(\*GraphicsBox[ TagBox[RasterBox[CompressedData[" 1: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 x2z77CSnPN4gWrPDVR11q9j+Kla3lO2saqGLeI0jVA66jexqVYTuPsvznLiB OTPjbsaVHvWEJwWHvKw1zeQC7qZwQVrD/ZGkzLqa3yU9ZxRypZXcL8IyyZPL 0GyTFykmxvTNdevX3b+1fpZNU1WJOJr1UnXX/fKaDPaq5rqZlNxet5Ldqlqs q2Vjzz/TOjJmoWOPJndRr5if/9xDqflW7qi4IpyUFr2UpNz7Qp70K7dIiJIc uU7xT+Sq3k4Lzp9XDToSoE8c0PYEv138kP1RNUC3u9IMXVRf6tRsJ9UXuhns AJUtVW+DKlL3OzuU7y3OY9pPm5O2p1PGspt5VdxTNZvlhYpMIVEK/1OSJO6x IEtbuFXCEsmVu6tJlg8oBsbuuhQzZMHkn5Pt203lR4l7GX8Vp0v5iyTlNSlL 4kLjGMsuUU3WSex6frFYwIye+iClpL3rkilXIoeVaK7KOxVHhENSGPe+aURe TPJUMErbuR3Cr9JoTtD4yt8rniy5eaWv23tBR1N1Hbx5VlxMSb7TGdiu9Oyz /iJJ2eg4qSx089hw1Q+6LLaUN4q92d8CuaQP7NIXMhfTBz/VnJZPKk4JKZSk tqlLX+zbKprb0l4uWdgrBXJ9NdZyVcXC5eK11h7h0xsc8evcj+8qTmV4lYcu le2u+ko3+zV90kvVShfFBlDyI2w3VR1dILvPf7z+qM3AeWfPFvavHX9HPqPI ptGZydXUPJAOVST5wJSkhua+dJA7IhyWpnNfamrLWdyOuCUFE7yahMce9+7e kbcRlYxK5a5Loru01kW/pm+7qsyobhNVw3SHWHdVD916dqcqTCez+VFzT7N9 68c/lNMoSYoUxVXX3JP2cy/P5YfSYe6MkCpFczeEi9JqLkGYXTZSEZdP1nXo wDNiEOOnctMdZh1VbXRzX5OkvHt/VPXX7WSnqb7XnWSf80WiPds48s6pGb1D aO58rrgtXJE2cM+E69QVWFWwqvz9VQXdgm75t+1BE6l/OnLjhdNSe266UCg5 c1uET+UgTicw8hzaL7zkG9yYyLbZ6532K9uLs5i+/E7xM7YL/6tYn7Xkl4sl TGVakFXYW8pvRT1TqpwkZjAX/HpqY60PhtfJeNJ9bNzZAjuvBcIjyYtzFfZL n3C+piTlKoXzUmfuN6GR7MfFCVXk7zmdpkPhWsX7MWNye/Rrr1qqq2ZTi58q nmf68fvE5pUmKcvwjGF4QazO3lCOEBOZhnwQjWCQ37PDn1urpw87Yui8cnnx NW+Pa4Kr/BvXU9go1eTKazJBOCN1MOXpwG0S6sv+XJhwWxrAtY2fWdjMu96C kvOTBmn8P048Y5ukbCuqGQ8+WWQrSVJKSZZRElt+pfgeW51XiblMHV4pnmV2 +HXVTrSeGvSNYWPHD5b9mDdmuK0mTq6tsBME6aFXeTX+GKMcqR11dW35R26O 8EQazj3U9C1MVuxetP1S1BCfwIKkU3aTlJe0lswYPlvs8Rc1KUvC8vFiNbYG ZTjHPFf+JB5jbvtN0R60vjU5OXlju5TFn11pMOw7zTHZQWElLJZuev1PNf7I EyfUksdwGqGBPI6bo8mVvRXeSxyu2riVTBmV+l2HTso12nvW4/nzojNrxa8Q n1cyOiWm0anKNuTDxELmhtJd3M94Kc9rLZh+AfaJNdveW7DnQtPBY2kW96ea rJLuef0sZEt2L41RtHBXGspto77157pqlsrvK3yXd8lv55E4bW96887Wyq3a QuuxfKbowLK8hu7110ka8xHiLSZfOZxWiXnK37XuTBXVz7rN7OOYi7mf9Z+o 0coDFB2EddIjr7FCpsRWJClL1ZZTC7ekwaa+nUpzMFC+yB2O+1yK8nINszze rPv7ysWUZByNTje2rBNqVpqkvGKt+SX0uaxvDzGi0pJm3w2lj5jECHMW5Hj3 maE5SaPTTlgrlXiNETIkpiLJOFOfTBMkyYnbKjSVA2i3GigncLOpeydxC2cG nLzQ6yvlFu1961H8UbEj245fI9b6yySlTEt+kfiUKaSa7KPKDKPK2NMVrlnb zfrs1DzHYsFZPskNprfKRtxIIU1qzWFVwary5qsKugXd8q/dg2i8eO6EUEJv Zf7CaulrzjZuaMExT8OK2/nenp3iPAsSPVfN6p61vnc7PoR6KZt/KoaxSfwd cRK7m88Tv3/JPfw1cRSZL45hd/CXxKFsiaqNfrON5N8scZ+tRpWnG2gTMzP1 xLWeGXE3CyK98oWP5VhuA42aF7373ZMCuLI8Kk5L+nET4rYX2HhFrTiYb+15 Me5ewWyvq1ENzzzsu0lVqHO1WcLrRCf2FP9cDH1Fkt2mJPv4AnEsvRXniC7s bVVT/XybZ/7WiXrbnqowXWsbbWinY191s1sxKv+6h43GW77CLafdoT+dm+5I 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 SyJHJ+7E/zpxlycpH8Ef+W2iGftM2UXcwzwmVzI7/R4fHmP9xZzxOc595sUX FI72PhfXRprnNUHYL1mYumh4RZ5EoYHsz1nT7CviHDUxspE7S9n03KfqEZkX HNYoPxHbM0/5jjo9u4l/SLN4Mo3gq/durckkylOP9xCTmSa8p3iUqe439fB2 q+kzh55M6PVIY194TFFD8JD2e40WtktfmJKU7VOy9A23W6gmf899oRkuH+F6 U//f5W5o6hQeUPwwZ3NObJ9gmrnt2Ay+rm4Ou5svpTWkbE981cpT7iQ6Z1mx Lfjx4lmmBc+JJ5nbk4Yc3my1J3TOsYndmmlGyke5HsI86amXu7Cedsbyc2VZ EgW3Qbgj/UC7dn+aWV01kbQmfBHfobBAcSrml9z3+serbus8bWL4U+IANpWv p4tgp/FpdLr0oyTWlXZLK36SmM/U5weKB5h+fqsP17D+elpRWpZ9W2G6dM1r spBO86g/dW/NipPCSupqb9PJbhj3QGgv7+ScNGr5NndXY114SLF6QdULGYNS /Z/ow20H8nFiXTaLb6pbwM6gd6celY5OWRfZsB3pTeY+c0dpKa5mrvq11wZa fzfFJWV9+8Dl1vmdPH4Xusi7uLZChHTDK1I4KTlRn5S9Rfwi3KJZ9kBwkjdT n8yWf+eOamoXqhVfLg65nDa03eQRye+3+5QfK55gLvFf6QR2Nn9adK50BgXS 2Nmxg+lsXoctVNpQkkHU84XWG/w/T7xlu27x9Cs+wzSabNlT0UD4QUr3iqAk PU2j482tEW6S12gFmMN11kyUb3C3NVaFqxStl0XlFQ7/Nkht2NjRQH07nrlF K8l2NobPFftXuuaU68GvExuxT5WONIOmK/drzZgMvq3uNjtyofPF7YO/iB9W WKi4G9dX2uAVTCNlX5Gk7P3KkzPQyTeWa6GZ8J9VJRerClaVP60qG+ndZgz3 THCVL3BfaybLxVyWpmFhKPYgdMu/ag9SRcpZbZ2qqfdlig4WETtPXu8VN/li 8sp2V5VW4gJmMX9RdKdUB2iMJvJ7Ke2LzqL9y4ntwE8WbzL5Kgf9DptvZ7Q6 cb5HnTndctg+w2evyw5wPrCk39X33OZq0uWRiuFCvNSAEpadtf2EfRLDNdBw 8jlu2rJ9eY+G9589M7uuc2LE4sxgh+MRAZnxDvWmfpDq1CFJ2ZhmShx/VfyG qnSQKvPnJKG8QezOevMbxC/YWipn3U72eBh7vGb3dnNm5Azso488m7XJ6cfY 65dWDlmmyZUnKMpOTPW5ecIZaTAXIGhprt0U2tFOenH51/k/egTOuZrzU59x 9IbfxmGBuiizpWOP4HRD504PlN7ir8xCPlscZvp/ntu/IkkQ9bM9zTItqaZU LdmRIT2OZndJme2cY95nYWRB1iSnUwvWXvhgcB/NVPkzxThhj9SKRjBL6s+F CgapG7dXqCGHcXXjuhTM8dwdHX4m0MUtonlmA4fj6smnFjj6Tz+fHtF5I18g KuiOB6hnptH86kLdu48658UkAZShHTuHzguD2bo0szYx94Mt0kfbu87+NXuN syZSytrqdG/e1+c7DjwrWMu/crOEI5IjN1vIpLPbDPrswK2nNfAHrqbQUTJ4 Fc7dcvZm/8AIl8zWDrL6u1O7HPeErDrKdL3BO+jW0cq2lla2UOrq7q9IUj5q 8/kz4lD2Gp3+FjKfB3kaunQsjnTJPuqUEdkiu5Fz1Nzos8v6q+m+NrTOXJO+ 49RCBr3PRNJJoY9prg2lhDrq8xPzR58/N3BbxNjMUQ4H1apToY5M2K1jZ7qp VLt03W0c+CjxCRPBH6NT0p+T+JkqtsiU5IKykxjLjJvSI6Vz+36Rs7JqOH01 e0J2H+c50YozP7iMittZ8JFXltBUXsJNE1KkrhVjFCYcp8pcFRrRWXvzQuXF osE5EfGZyx2WqAeccnVsMaNPxs89tvrn6pW2X9GUvsTMpjnSh+67j+77cpL9 9E0UjU5/tjrvLh5k1gTuTOLtYuk6uxzHz9ZlL3UumtPytL7PguU3rzl6tNB8 L1/lJlC3WHExQrY0oCKVJFjJG7mGi70vmw1NVnc4pXIcpv76VHPHcTPPnCjq GRf4Q9IIu/f4H8REJobuNeAVc7m8SrPpX/uyn/PfidnMPf+BiXrbUzPjThb2 2j47L/um88PZw3OeORcv3Ze3Yvg3mvnyV4qRQgKtxvNpBrnSWfuAxHKf0Iny Kldn6dCroW51I4Ozknt/pD6SmelgF3Hw5AOsKlhVKlaVTcJD6ScuL66JtM7L f57FuSkDXGadP/XEsZ/6cWYdR+xB6JZ/0x40PuB3fdu2fn7iYYW1UrlWO5Sp y38lnmcG8N+LrVkH3osy9+YV1DMv6sR7i83Z8fwMWpOvKG9qDzI7A24nzmyr X3DmQoPB38W7FY73Pi7clvZwU4UZ1D+fCoz00Mta6E5vg18L9lIVrijuWYHW q47mM/k+Fx+bcKnq0KzASUnN2nXyCz1cz3qmcpvWl8lX1qK37kGUpNVrkozk A2h8bfju9N5o7f+d/plN/NxTZ/P7d4xfUejifUm4Iu3lFgrLpFFcM8FaelCR pI3QWarK3YurIaV5pQvnpR20O3xCu8PEqdVSd3RIn9Tk8BqreOU+rZLJUV7X rmR601t3C7bMz//jf+fx5v2o5wfwI2k0J/Hz6Pct5xzJqdNniaZF4V5FHc0j 6TK3nfamMO5zoa30yMtK6PafJNWFT6QLdKKZIzlzpcuMeUXujaZ3Sw/rvHLS 80PjrJYq92uDGYMyS7uYceFHiOasI2V4VU3KdeN9qK/G8dPEgexJZbF2PiNG +GS2dzgkOMgHOAsNIzdW6ISj0hLOTOgkPfOyFLpK1SlJF6ka96HwlVTkZSP0 kWpxcSuW5wd7rgp3OX6j+8NJFocPWPHKBO1IZosyWzuDauIpNjPdsXmlNXHl x4htqM9niq6sQPX8huHDf844070m3fGB11DNWLmvIo3WmV84K6pDNeqQsgwW pjwfC62lm15m1DOlXl8LLaR7XjXV205mO/T0Czxsbf2tMlrbg5mt3KudyLTj B4j12T78N+KXpsq8KslAfjR1tS/17SB2B1VSxViEfHA0ssvSFV0KIjxHa5bK XooCOqHs4joKzrT6taLKPK+ozGfUww+83hfMJclrlbCcTruHZn+Xvdx5l1/R YcHaQTlB+yUTpVyldWXM+S40v5ypM1tUWpPynFP4ueJwVqmM0fZhPIO8DIM6 piy9nBc3fJMmTV6reCzkSQZuoKCQWtIYtTeNUTepBveFYEOdU1NoKuVSki3S Mm5PzPUz9fp/zncSHzJP/Tpo82gGxWs96ZxoJd6nbvle/Ipq8uoZ5Ey91IKd wIfTXBaVZ7VxzKTJwcnO7SJj4y/fHPJQ83lhde8bNJdTudGCP73RfSHYSo+p b8tmkJlgJz3xKo1rKGV6raeT+ApOs2Dz+XOD0vy/1c+xneN35jBPSXZpf8Cq glWlYlXpKAykmTVixQ/5PT2FGc0zrvZop7opXmUf+3XVytiD0C3/qj1IN3lk ykO7o3wz/SNmteqEPpP1Ui3UR7EDVWp9MDtIFakPIWfpp7+kq2q2PpRVqjbr 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 N/vHSf4wkq7WxHT9Nn8jSbmR3lPoKf55n5RbVuFPKqr9d5NEewdRj/2Tu784 g8K9VeEftVzoHUEd+Kbj8kffzvUOoXn3z6tRniTMNBMX0Fxo9Ubd8mKSed50 PDXNwYav6ECsKlhVXl5VJtOqMs1UW+xB6JZ/3x7UfL9iZZEjhBBCCCF8V9Y5 f37jmkEQQgghhPBdeeP0jA2x/SGEEEII4btyyPlPEq14CCGEEEL4rqxz+f7Z MUshhBBCCOG7MufSqlz7xRBCCCGE8F154dKx3BkQQgghhPCdeelSbu5iCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGE EEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgj/l/r/ABBW hlw= "], {{0, 158}, {400, 0}}, {0, 65535},ColorFunction->RGBColor], BoxForm`ImageTag[ "Bit16", ColorSpace -> "RGB", Interleaving -> True, MetaInformation -> Association[ "Exif" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com", "DateTime" -> DateObject[{2017, 7, 25, 9, 51, 31.}, "Instant", "Gregorian", -6.]], "Comments" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com", "Creation Time" -> DateObject[{2017, 7, 25, 9, 51, 31.}, "Instant", "Gregorian", -6.]]]],Selectable->False], DefaultBaseStyle->"ImageGraphics",ImageSizeRaw->{400, 158}, PlotRange->{{0, 400}, {0, 158}}]\); |
You can even restyle your images using ImageRestyle:
✕
artStyles = {\!\(\*GraphicsBox[ TagBox[RasterBox[CompressedData["CUSTOMIMAGEDATA"], {{0, 150}, {150, 0}}, {0., 1.}, ColorFunction->RGBColor],BoxForm`ImageTag[ "Real", ColorSpace -> "RGB", Interleaving -> True], Selectable->False],DefaultBaseStyle->"ImageGraphics", ImageSizeRaw->{150, 150}, PlotRange->{{0, 150}, {0, 150}}]\), \!\(\*GraphicsBox[ TagBox[RasterBox[CompressedData["CUSTOMIMAGEDATA"], {{0, 300}, {480, 0}}, {0, 255},ColorFunction->RGBColor],BoxForm`ImageTag[ "Byte", ColorSpace -> "RGB", ImageResolution -> {72, 72}, Interleaving -> True, MetaInformation -> Association[ "Exif" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com"]]],Selectable->False], DefaultBaseStyle->"ImageGraphics",ImageSizeRaw->{480, 300}, PlotRange->{{0, 480}, {0, 300}}]\), \!\(\*GraphicsBox[ TagBox[RasterBox[CompressedData["CUSTOMIMAGEDATA"], {{0, 276}, {400, 0}}, {0, 255},ColorFunction->RGBColor],BoxForm`ImageTag[ "Byte", ColorSpace -> ColorProfileData[CompressedData[ "CUSTOMIMAGEDATA"], "RGB", "XYZ"], ImageResolution -> {300, 300}, Interleaving -> True, MetaInformation -> Association[ "Exif" -> Association[ "Orientation" -> Association[ "CameraTopOrientation" -> Top, "Mirrored" -> False], "XResolution" -> 300, "YResolution" -> 300, "ResolutionUnit" -> "inch", "Software" -> "Created with the Wolfram Language : \ www.wolfram.com", "DateTime" -> DateObject[{2017, 3, 9, 11, 56, 18.}, "Instant", "Gregorian", 2.], "PixelXDimension" -> 750, "PixelYDimension" -> 519]]],Selectable->False], DefaultBaseStyle->"ImageGraphics",ImageSizeRaw->{400, 276}, PlotRange->{{0, 400}, {0, 276}}]\), \!\(\*GraphicsBox[ TagBox[RasterBox[CompressedData["CUSTOMIMAGEDATA"], {{0, 250}, {400, 0}}, {0, 255}, ColorFunction->RGBColor],BoxForm`ImageTag[ "Byte", ColorSpace -> "RGB", ImageResolution -> {72, 72}, Interleaving -> True, MetaInformation -> Association[ "Exif" -> Association[ "Orientation" -> Association[ "CameraTopOrientation" -> Top, "Mirrored" -> False], "XResolution" -> 72, "YResolution" -> 72, "ResolutionUnit" -> "inch", "Software" -> "Created with the Wolfram Language : \ www.wolfram.com", "DateTime" -> DateObject[{2017, 5, 30, 17, 18, 42.}, "Instant", "Gregorian", 2.], "ExifVersion" -> "2.21", "ComponentsConfiguration" -> "Y", "FlashpixVersion" -> "1.00", "ColorSpace" -> "RGBColor", "PixelXDimension" -> 1024, "PixelYDimension" -> 640, "SceneCaptureType" -> "Standard"]]],Selectable->False], DefaultBaseStyle->"ImageGraphics",ImageSizeRaw->{400, 250}, PlotRange->{{0, 400}, {0, 250}}]\)}; |
✕
cityStyles = Prepend[SetAlphaChannel[ImageRestyle[city, #], AlphaChannel[city]] & /@ artStyles, city]; |
✕
groundStyles = Prepend[ImageRestyle[ground, #] & /@ artStyles, ground]; |
✕
groundStyles = Prepend[ImageRestyle[ground, #] & /@ artStyles, ground]; |
✕
domColors = {RGBColor[ 0.44313725490196076`, 0.7725490196078432, 0.8117647058823529], GrayLevel[0.9], RGBColor[ 0.8257116158191437, 0.7624872802598549, 0.6834260771904932], RGBColor[ 0.9275118744483869, 0.8953480709038453, 0.7543210863558273], RGBColor[ 0.2386547585427879, 0.4876022587659778, 0.7371873300590905]}; |
✕
styleControl = Thread[Range[5] -> Prepend[artStyles, Image[ConstantArray[1, {150, 150}]]]]; |
Here's an example of what the game could look like with a little more effort:
✕
Manipulate[ Graphics[{ Inset[cityStyles[[art]], {-5, 2}, Scaled[{0, 0}], 10], Inset[spikey, {-2, 9}, Center, 1.2], Inset[ImageReflect[pipeStyles[[art]], Top], {x0, height}, Scaled[{0, 1}], pWidth], Inset[pipeStyles[[art]], {x0, height + pGap}, Scaled[{0, 0}], pWidth], If[draw, {FaceForm[None], EdgeForm[Red], Polygon[pipeVertices[x0, height, pWidth, pGap]]}, {}], Inset[groundStyles[[art]], {-5, 2.3}, Scaled[{0, 1}], 10]}, PlotRange -> {{-5, 5}, {0, 14}}, Background -> domColors[[art]], PlotRangeClipping -> True], {{x0, 1.08, "Hor. Position"}, -5, 5}, {{pWidth, 1.745, "Pipe Width"}, 1, 4}, {{height, 7.62, "Gap Position"}, 0, 12}, {{pGap, 2.248, "Gap Width"}, 1, 3}, {{draw, False, "Draw Hit Box"}, {True, False}}, {{art, 1, "Art Styles"}, styleControl}, SaveDefinitions -> True] |
Bonus Suggestion 2: Animation
Animation can add another polished element to your game, but it will use the CPU continuously:
✕
animationFrames = {\!\(\*GraphicsBox[ TagBox[RasterBox[CompressedData[" 1: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 JWH9 "], {{0, 29}, {38, 0}}, {0, 255},ColorFunction->RGBColor], BoxForm`ImageTag[ "Byte", ColorSpace -> "RGB", Interleaving -> True, MetaInformation -> Association[ "Exif" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com"], "Comments" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com", "Creation Time" -> DateObject[{2017, 7, 25, 9, 27, 5.}, "Instant", "Gregorian", -6.]]]],Selectable->False], DefaultBaseStyle->"ImageGraphics",ImageSizeRaw->{38, 29}, PlotRange->{{0, 38}, {0, 29}}]\), \!\(\*GraphicsBox[ TagBox[RasterBox[CompressedData[" 1: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 "], {{0, 29}, {39, 0}}, {0, 255},ColorFunction->RGBColor], BoxForm`ImageTag[ "Byte", ColorSpace -> "RGB", Interleaving -> True, MetaInformation -> Association[ "Exif" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com"], "Comments" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com", "Creation Time" -> DateObject[{2017, 7, 25, 9, 27, 5.}, "Instant", "Gregorian", -6.]]]],Selectable->False], DefaultBaseStyle->"ImageGraphics",ImageSizeRaw->{39, 29}, PlotRange->{{0, 39}, {0, 29}}]\), \!\(\*GraphicsBox[ TagBox[RasterBox[CompressedData[" 1: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 "], {{0, 30}, {41, 0}}, {0, 255},ColorFunction->RGBColor],BoxForm`ImageTag[ "Byte", ColorSpace -> "RGB", Interleaving -> True, MetaInformation -> Association[ "Exif" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com"], "Comments" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com", "Creation Time" -> DateObject[{2017, 7, 25, 9, 27, 5.}, "Instant", "Gregorian", -6.]]]],Selectable->False], DefaultBaseStyle->"ImageGraphics",ImageSizeRaw->{41, 30}, PlotRange->{{0, 41}, {0, 30}}]\), \!\(\*GraphicsBox[ TagBox[RasterBox[CompressedData[" 1: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 "], {{0, 29}, {39, 0}}, {0, 255},ColorFunction->RGBColor], BoxForm`ImageTag[ "Byte", ColorSpace -> "RGB", Interleaving -> True, MetaInformation -> Association[ "Exif" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com"], "Comments" -> Association[ "Software" -> "Created with the Wolfram Language : \ www.wolfram.com", "Creation Time" -> DateObject[{2017, 7, 25, 9, 27, 5.}, "Instant", "Gregorian", -6.]]]],Selectable->False], DefaultBaseStyle->"ImageGraphics",ImageSizeRaw->{39, 29}, PlotRange->{{0, 39}, {0, 29}}]\)}; ListAnimate[animationFrames, AnimationRate -> 2] |
The ground is unique in that the image never changes. To create the illusion of continuous movement, you can reset its position at a certain point, exactly like I do with the obstacles:
✕
SetAttributes[updateGroundPosition, HoldFirst]; updateGroundPosition[{groundPos_}, groundResetValue_, vel_, ups_] := ( groundPos += vel/ups; If[groundPos < -groundResetValue, groundPos = 0]; groundPos) |
For continuously updating sprites, like the bird, the Clock function is often sufficient to cycle through the animation frames at a fixed rate:
✕
DynamicModule[{vPos = 10, hPos = 3, vel = 0, ups = 30, gravity = -50, kick = 2, previousKeyState = False, worldEdge = 10, imageSize = 250, groundPos = 0, groundResetValue = 0.71}, Framed[Graphics[{ Inset[city, {0, -0.6}, Scaled[{0, 0}], 10], Inset[Dynamic[animationFrames[[Clock[{1, 4, 1}, 0.5]]]], {hPos, Dynamic[ updateSpikeyPosition[{vPos, vel, previousKeyState}, CurrentValue["ControlKey"], kick, gravity, ups] ]}, Center, 1.2], Inset[ ground, {Dynamic[ updateGroundPosition[{groundPos}, groundResetValue, -0.7, ups]], -0.3}, Scaled[{0, 1}], 12] }, PlotRange -> {{0, worldEdge}, {-2, 12}}, ImageSize -> imageSize, Background -> RGBColor[0.44313725490196076`, 0.7725490196078432, 0.8117647058823529] ], FrameMargins -> -1], SaveDefinitions -> True ] |
The worst case is noncontinuous movement, such as movement that is triggered by pressing a button. I still want the dynamic expression to update as fast as possible such that our position updates like normal, but I don't want the animation frames to cycle at the same rate. I tend to use an instance of Mod to introduce a delay into the update of the frame index:
✕
DynamicModule[{animationCounter = 0, animationDelay = 10, frameCounter = 1}, Dynamic[ If[CurrentValue["ControlKey"], animationCounter++; If[Mod[animationCounter, animationDelay] == 0, animationCounter = 0; frameCounter++]; If[frameCounter == 5, frameCounter = 1]]; animationFrames[[frameCounter]] ], SaveDefinitions -> True ] |
If you'd like to play around with the code you read about today, you can download this post as a Wolfram Notebook.
When will the application be on i tunes?
Hello, and thanks for your question! Unfortunately, there are no plans for releasing on iTunes.
Fun game