-
Notifications
You must be signed in to change notification settings - Fork 9
Animations
Metro provides an implicit property animation system or key frame animations. This is similar to those familiar with iOS development or those that have used animations within jQuery.
Animations can be defined for Models within Scenes. The animation is defined with the model and the proposed final value of the model property over a given interval of time.
A scene has a number of helper methods (animate and change) that allow you to quickly add animations within your scene.
A scene's ability to register animations is because a Scene includes the model HasAnimations which extends the ClassMethods.
This is an example of animation which fades out (i.e. Setting the alpha property to 0) over 120 ticks of the game:
class HellScene < GameScene
draw :title, model: 'metro::ui::label',
text: 'Welcome To Hell!',
position: "320,240,0",
color: "rgba(255,255,255,1.0)"
animate :title, to: { alpha: 0 }, interval: 120.ticks do
puts "Title is now faded."
end
end
When defining an animation a hash of properties are provided. An important key is to: which defines another hash.
The to hash's keys are the names of properties on the actor. The to hash's values are the final value to set the property.
Any property of the actor can be animated. A property can be model properties but more simply it is any name which matches a getter and setter on the actor. Multiple properties of an actor can also be animated at the same time.
Here we define a scene which will move the hero to a position while rotating them:
class Hero < Metro::Model
property :location
attr_accessor :angle
def after_initialize
@angle = 0
end
# ... a draw method which draws our hero at the location and angle
end
class MovieScene < GameScene
draws :hero
animate :hero, to: { x: 320, y: 240, angle: 180 }, interval: 2.seconds
end
NOTE: The angle attr_accessor is a situation better suited for a property. A getter and setter is used here to illustrate that animations simply require getter and setter methods on the actor's model.
Each animation must provide an interval to perform the animation. Metro provides some additional functionality on Numeric instances to assist with providing more clarity when expressing the interval.
By default the interval, without a suffix, is expressed in game ticks.
Every animation may also be defined with a different easing value. An easing allows you to effect subtly affect the way in which the final result is reached. By default the defined easing is linear.
An animation will by default use a linear easing.
This example we explicitly specify the easing, even though the default is already linear:
class MovieScene < GameScene
draws :hero
animate :hero, to: { x: 320, y: 240, angle: 180 },
interval: 2.seconds, easing: :linear
end
Metro defines 'Ease In' easing.
This example we specify that the animation should be performed with ease in.
class MovieScene < GameScene
draws :hero
animate :hero, to: { x: 320, y: 240, angle: 180 },
interval: 2.seconds, easing: :ease_in
end
Metro allows you define a custom easing. An easing is any class that adheres to the following interface:
class CustomEasing < Metro::Easing
#
# @param [Float] moment the point in time within the interval. For example for
# a 60 tick interval, this would be the values 0, 1, 2, 3, 4, 5, 6, ... 59.
# @param [Float] start the starting value of the property
# @param [Float] change the final value for the property
# @param [Float] interval the total length of the interval
#
# @return [Float] the value at the particular moment of the interval
def self.calculation(moment,start,change,interval)
# this is the exact same as a linear calculation
change * moment / interval + start
end
end
Metro::Easing.register :custom, CustomEasing
An example of using the newly defined custom easing in an animation:
class MovieScene < GameScene
draws :hero
animate :hero, to: { x: 320, y: 240, angle: 180 },
interval: 2.seconds, easing: :custom
end