Animating sprites inDragonRuby is fairly simple, but it does require putting a couple ideas together.
First, it's best to have a single image with all frames of the animation together, equally spaced apart. I prefer the frames are arranged horizontally from left-to-right, so that is what we will use here.
Here is an example,borrowed from here:
The first frame can be displayed like this:
deftickargsheight=195width=192args.outputs.sprites<<{x:args.grid.center_x-(width/2),y:args.grid.center_y-(height/2),h:height,w:width,source_x:0,source_y:0,source_w:width,source_h:height,path:'sprites/walking.png',}end
source_x
andsource_y
set thebottom left corner of a "tile" or basically a slice of the image. (To use thetop left instead, settile_x
andtile_y
).source_w
andsource_h
set the width and height of the tile. The sprite can be scaled when displayed withw
andh
.
If the frames are laid out horizontally, then all one needs to do is update thesource_x
value (typically by the width of the tile) in order to change the frame.
Here is an illustration for a few frames:
We could accomplish this by using the multiplying the width of the tile by the current tick (modulo the number of frames, so it loops):
deftickargsheight=195width=192num_frames=8source_x=width*(args.tick_count%num_frames)args.outputs.sprites<<{x:args.grid.center_x-(width/2),y:args.grid.center_y-(height/2),h:height,w:width,source_x:source_x,source_y:0,source_w:width,source_h:height,path:'sprites/walking.png',}end
This works... but it's a bit fast for a walk!
This is where DragonRuby helps out. Theframe_index
method will do the calculation of the current frame for us.
frame_index
accepts these arguments:
count
: total number of frames in the animationhold_for
: how many ticks to wait between framesrepeat
: whether or not to loop
frame_index
can be called on any integer, but typically uses the tick number on which the animation started. Below, the code sets this to0
(the first tick). This could instead be when an event happens, based on input, or anything else.
Multiplying thewidth
of the tile by the frame index results in thesource_x
value for the current frame of the animation:
deftickargsheight=195width=192num_frames=8start_tick=0delay=4source_x=width*start_tick.frame_index(count:num_frames,hold_for:delay,repeat:true)args.outputs.sprites<<{x:args.grid.center_x-(width/2),y:args.grid.center_y-(height/2),h:height,w:width,source_x:source_x,source_y:0,source_w:width,source_h:height,path:'sprites/walking.png',}end
And that's it!
But With Ruby Classes
Once a game starts to get moderately complex, I like to arrange behavior into classes. It's also convenient to useattr_gtk
to avoid passingargs
around and to save on some typing (e.g.args.outputs
becomes justoutputs
).
classMyGameattr_gtkdefinitialize(args)@my_sprite=MySprite.new(args.grid.center_x,args.grid.center_y)args.outputs.static_sprites<<@my_spriteenddeftickifinputs.mouse.clickif@my_sprite.running?@my_sprite.stopelse@my_sprite.start(args.state.tick_count)endend@my_sprite.updateendendclassMySpriteattr_spritedefinitializex,y@x=x@y=y@w=192@h=195@source_x=0@source_y=0@source_w=@w@source_h=@h@path='sprites/walking.png'@running=falseend# Set @running to the current tick number# this is so the frame_index can use that as the# start of the animation timing.defstart(tick_count)@running=tick_countenddefstop@running=falseenddefrunning?@runningend# Update source_x based on frame_index# if currently runningdefupdateif@running@source_x=@source_w*@running.frame_index(count:8,hold_for:4,repeat:true)endendenddeftickargs$my_game||=MyGame.new(args)$my_game.args=args$my_game.tickend
This example essentially follows myObject-Oriented Starter approach and moves the logic into a game class and a sprite class.
When the mouse is clicked, the sprite starts moving (using the currenttick_count
as the starting tick). When the mouse is clicked again, the sprite stops.
Source vs. Tile
To use just a piece of an image (for animations or otherwise), there are two options:source_(x|y|h|w)
ortile_(x|y|h|w)
.
These options are nearly identical, exceptsource_y
is bottom left andtile_y
is top left.
Thesource_
options were added in DragonRuby 1.6 and are more consistent with the rest of DragonRuby where the origin is the bottom left. On the other hand, thetile_
options align easier with image editors.
Either option works, depending on what is important to you.
Go!
Now that's really it! Get moving!
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse