This tutorial begins with a new platformer project. To create a new platformer project, see the Platformer Basics tutorial. In short, the easiest way to get an animated character is to use the new project wizard.
If you started a new project without using the wizard, you would need to create an entity with a sprite and assign a .achx file to the sprite. If you don't have a .achx file prepared already, use these below to give yourself a head start.
Once finished, your project will have a character which is animated and ready to go. The remainder of the tutorials in this series cover how to modify the animations on the player and how to add new animations in response to game logic.
This set of tutorials covers how to write logic to control a platformer animation and to change platformer values according to input (such as a run button and ducking).
This tutorial will create a game similar to Super Mario World. The first begins with a completely empty project and covers the FlatRedBall platformer technology and best practices.
Platformer games (such as Super Mario World) include animated characters which play animations in response to input, physics, and collision with the environment. For example, a game like Super Mario World includes a number of animations:
Idle
Walk
Run
Jump
Duck
Look up
Skid (Trying to turn around when running)
Each of these animations is played in response to logic determining which should play. We can think of each of these animations as having different priority relative to other animations. For example, if the player is pushing the Up direction in Super Mario World, Mario looks upward. This animation has priority over the Idle animation, which plays if the Up is not held. Similarly, the Run animation is played if the player is moving faster than a certain speed, is on the ground, and is holding the run button. If this condition fails, then other animations (such as Walk) perform their logic. The logic to set animations can be performed through standard logic, but FlatRedBall offers a standard animation solution through the AnimationController class. This tutorial explores AnimationLayers and AnimationController which are used to update the Player animations.
By default our Player already has an AnimationController. It doesn't appear in the Player object in the FlatRedBall Editor, but it is generated automatically based on the default settings on the Player. AnimationControllers (both in code and in the FlatRedBall Editor) are containers for AnimationLayers. Each AnimationLayer typically maps to a single animation (or two animations - a left and right facing version). By default, our player has animations for idle, walk, fall (in air, moving downward), and jump (in air, moving upward). We can see these layers by selecting the Player, clicking on the Entity Input Movement tab, and selecting the Animation
Each animation layer plays if its conditions evaluate to true and if the animations below it evaluate to false. Another way to think about this is, entries further down can "overwrite" the current animation if they evaluate to true, with the bottom-most getting the highest priority if it evaluates to true.
Each animation layer defines which animation is played, conditions for playing, and animation speed to play. For example, the CharacterWalk animation plays only if the player has a greater velocity than 1 and if all other animations (CharacterFall and CharacterJump) fail to play.
If we change the Min X Velocity Absolute, we can modify the behavior of the player. For example, if we change the value to 140, the player will only play the walk animation if walking faster than 140 units per second.
While this specific example may not be a practical change to the game, it shows how the logic controls whether an animation is played, and how that logic can cascade up through the layers. The following conditions can be used to control whether an animation plays:
Min X Velocity Absolute - this is the minimum speed that the player must be moving to play the animation. For example, we set the minimum speed to 140 for the CharacterWalk animation, which means the character will only walk if moving faster than 140 units per second. Note that this is Absolute which means the character must be moving either greater than 140 pixels (to the right) or less than -140 pixels (to the left).
Max X Velocity Absolute - this is the maximum speed that the player can move to play the animation. For example, setting the maximum speed to 200 means that if the player is moving faster than 200 units (absolute), then the animation will not play.
Min Y Velocity - the minimum Y velocity (vertical movement) the player must have to play the animation. For example our player has CharacterJump animation which plays only if the velocity is greater than 0.
Max Y Velocity - the maximum Y Velocity (vertical movement) that the player can move to play the animation. If the player is moving faster than this value upward, then animation will no longer play.
Movement Type - this option restricts an animation to whether the player is on the ground, air, or either. For example, this can be used to restrict animations to only play when in the air, such as the CharacterFall and CharacterJump animations.
Movement Name - this option restricts an animation to only play when a particular set of Movement Values are active. This is a dropdown which contains all of the movement values defined in the Movement Values section. This is especially effective if you have logic which is already setting the Movement Values in code - such as allowing a user to run when the run button is held.
Custom Condition - This allows the entry of code (such as a bool variable name) to be checked for whether an animation should be played. See the section below for more information on this property.
The Custom Condition property is the most flexible solution for setting animations. Typically this is used in combination with a bool field or property in the Player object. For example, the Player may have an IsTired property which would return true if the Player's health is below 10% of the max.
This can be used by the animation layer by entering the IsTired variable in the Custom Condition text box.
This produces generated code which checked IsTired in code. The text entered in Custom Condition is directly copied over so you can add any text there which evaluates to true, although the recommended approach is to encapsulate any logic in a property (as shown above) which is then referenced.
The Player contains an .achx file (Animation Chain List XML) which defines all available animations for the Player.
This file can be opened in the Animation Editor to view all animations. To open this file, either:
Double-click the .achx file. The FlatRedBall Editor uses the Windows file association for .achx --or--
Go to the <unzipped FRBDK location>/FRBDK/Xna 4 Tools/AnimationEditor/AnimationEditor.exe
Notice that this .achx file happens to include animations which are not used by the Player - that's okay because not all animations must be used, and a single file can be shared by multiple entities. The FlatRedBall Editor scans this file and provides these animations in the dropdown.
Note that the .achx file contains "Left" and "Right" versions of character animations, but the FlatRedBall Editor only provides the names without Left/Right suffixes. This keeps the Animation Name dropdown smaller and makes it easier to read. This naming convention is encouraged for character animations, and if the Has Left and Right checkbox is checked, then only animations with Left and Right suffixes appear in the dropdown. If animations do not have left and right options, then this option can be unchecked. Then the full name of all animations show up in the dropdown.
The Animation Speed Assignment dropdown provides the animation speed assignment logic. By default, all animations use the ForceTo1 speed, which means the animation plays at the normal speed as defined in the .achx. This dropdown provides a number of options:
ForceTo1 - the Sprite's AnimationSpeed will be forcefully set to 1, so the animation will play at the same speed as defined in the .achx
NoAssignment - the Sprite's AnimationSpeed is left untouched. Previous assignments on the AnimationSpeed (either in custom code or through other animation layers) will remain on the Sprite.
BasedOnVelocityMultiplier - if values are specified, then the Absolute X Velocity Animation Speed Multiplier or Absolute Y Velocity Animation Speed Multiplier values are multiplied by the Player's runtime velocity to determine the speed. For example, if the X Velocity multiplier is set to .1, then the animation speed plays at full speed if the Player is moving at 10 units per second, and plays at 10 times the speed if the Player is moving at 100 Units per second.
BasedOnMaxSpeedRatioMultiplier - if these values are specified, the animation speed will be specified based on the speed of the Player relative to the max speed of the current movement value. For example, the Max Speed on the ground is set to 160 units on the Player. If the MaxSpeedXRatioMultiplier value is set to 1, then the animation plays at full speed when the player moves at max speed. If the MaxSpeedXRatioMultiplier is set to 2, then the animation plays at twice full speed when the player moves at max speed.
For example, the CharacterWalk animation can be set to use BasedOnMaxSpeedRatioMultiplier with a Max Speed X Ratio Mutiplier of 2. This results in the walk animation playing faster based on the movement speed of the player.
Animation layers can be added in the FlatRedBall Editor. New animations layers can be added through the Add button at the bottom of the animation list.
Also, existing animations can be copied with the copy button.
This guide covers all of the options available when defining animation layers. The next tutorial covers changing the platformer movement values.
Now that we have our animations set up, we can work in our platformer values. These values control the way the Player entity moves in response input (such as max speed) and the physics which impact the Player's movement (such as gravity). Our Player entity automatically gets a set of default values which is why we are already able to walk and jump around the level. This tutorial will modify the default values and add additional platformer values for running and ducking.
Before we begin modifying the control values, we'll change the resolution of our game to match the original Super Mario World resolution of 256x224.
In Glue, click the Camera icon
Change the resolution width to 256
Change the resolution height to 224
Change the TextureFilter to Point so that pixels draw without any blurring
Change the Scale so that the game is larger on your screen. A typical 1080 monitor can support the game at 400% Scale.
After making these changes the game should more closely resemble the resolution of the original Super Mario World.
Currently our game has two set of platformer movement values:
Ground
Air
Earlier we added running animations which play when the run button is held. We will be modifying our game so the Player entity can run faster when the run button is held. We will be creating two new set of platformer movement variables for running. We will also be creating a new type of movement for when the player is ducking. Therefore, we'll have three more sets of movement variables:
Running
RunningAir
Ducking
Click the Add Control Values button three times, and name the new control values as listed above.
You should now have five sets of values.
Next we'll modify the values to make the game feel a little more like Super Mario World. We'll be modifying these to get close - this is not intended to be an exact copy. Of course if you want to tune the values to make the game feel different, or if you want to mimic Super Mario World even more closely, feel free to change these values.
Max Speed = 100
Speed Up/Down
Speed Up Time = 0.25
Slow Down Time = 0.15
Jump Speed = 230
Hold to Jump Higher = true (checked)
Max Jump Hold Time = 0.2
Max Speed = 100
Speed Up/Down
Speed Up Time = 0.7
Slow Down Time = 0.7
Jump Speed = 0
Gravity = 900
Max Falling Speed = 260
Max Speed = 150
Speed Up/Down
Speed Up Time = 0.3
Slow Down Time = 0.2
Jump Speed = 250
Hold to Jump Higher = true (checked)
Max Jump Hold Time = 0.25
Max Speed = 150
Speed Up/Down
Speed Up Time = 0.7
Slow Down Time = 0.7
Jump Speed = 0
Gravity = 900
Max Falling Speed = 260
Max Speed = 0
Speed Up/Down
Custom deceleration above max speed = true (checked)
Custom deceleration value = 200
Jump Speed = 230
Hold to Jump Higher = true (checked)
Max Jump Hold Time = .2
Now that we have our platformer movement values created in Glue, we can assign them in code. To switch values, we can change the GroundMovement and AirMovement variables in CustomActivity. We will be looking at the VerticalInput (holding up/down) and the RunInput to decide whether the player should be using the default values, running values, or ducking. To switch between these platformer movement values, modify CustomActivity in Player.cs as shown in the following code snippet:
Now the Player will switch its values according to input, of course, the running animations are not currently being used. Use what was covered in the previous tutorial to see if you can modify the Player's animations to play the running and running jump animations as shown in the following animation.