Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Justin
Justin

Posted on • Edited on

     

DragonRuby: Basic Sprite Animation

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:

Animation frames of a walking adventurer

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
Enter fullscreen modeExit fullscreen mode

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.

Single frame of adventurer

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:

Frame index illustration

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
Enter fullscreen modeExit fullscreen mode

This works... but it's a bit fast for a walk!

Very fast 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 animation
  • hold_for: how many ticks to wait between frames
  • repeat: 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
Enter fullscreen modeExit fullscreen mode

Slower walk

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
Enter fullscreen modeExit fullscreen mode

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)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

I work on Brakeman (security tool for Ruby on Rails) and do other stuff too.
  • Location
    San Francisco Bay Area
  • Education
    UCLA, Seattle University
  • Joined

More fromJustin

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp