Spritesheet
When making games, it’s common to have a spritesheet—a single image that contains multiple sprites within it that you slice out and display. Maybe it’s the running animation of your player or a collection of different terrain types. It be be helpful to use spritesheets to group similar images together or reduce the number of files in your game.
Let’s assume we have an image sprites/spritesheet.png
, which is a 16x16 pixel image with four tiles in it. The key part of rendering just one tile as a sprite with DragonRuby GTK is to specify tile_x
, tile_y
, tile_w
, and tile_h
in your sprite Hash:
def tick(args)
args.outputs.sprites << {
path: 'sprites/spritesheet.png',
# this is the good stuff, we render a portion of our image
tile_w: 8,
tile_h: 8,
tile_x: 0,
tile_y: 8,
w: 128, # draw our sprite large!
h: 128,
x: args.grid.w / 2 - 64,
y: 380,
}
end
Here’s an enlarged version of the spritesheet:
What gets drawn:
tile_x
being 0
means start at the left of the sprite, and then tile_y
being 8
says to draw 8 pixels down from the top of the sprite.
Change tile_x
and tile_y
to render different tiles within the spritesheet.
When you specify the w
and h
of the sprite, you can enlarge the slice of the spritesheet we are rendering. Try changing those values too and see what happens.
Tile Map
When working with more complex spritesheets, you may want to define a tilemap which specifies the coordinates and size of a given tile in the spritesheet. We’ll use a Ruby Hash for this. And we’ll animate it by changing the tile every 16 ticks.
def tick(args)
args.state.tile_index ||= 0
# here's our tile map!
tiles = {
0 => { x: 0, y: 0, w: 8, h: 8 },
1 => { x: 8, y: 0, w: 8, h: 8 },
2 => { x: 0, y: 8, w: 8, h: 8 },
3 => { x: 8, y: 8, w: 8, h: 8 },
}
# change the tile every 16 ticks
if args.state.tick_count % 16 == 0
args.state.tile_index += 1
if args.state.tile_index >= 4
args.state.tile_index = 0
end
end
tile = tiles[args.state.tile_index]
args.outputs.sprites << {
path: 'sprites/spritesheet.png',
tile_w: tile.w,
tile_h: tile.h,
tile_x: tile.x,
tile_y: tile.y,
x: args.grid.w / 2 - 64,
y: 380,
w: 128,
h: 128,
}
end
Here’s an example image that coordinates to the index values of the tile map for our spritesheet:
This is one way to animate with DragonRuby GTK, You change the tile from the tile map and then render it. Using a tile map is more flexible because you could have tiles of different sizes within your spritesheet, which can be handy.
It wouldn’t be too much of a stretch to change the keys of our hash to instead be symbols that we could easily reference. Imagine we had a terrain spritesheet:
tiles = {
:grass => { x: 0, y: 0, w: 8, h: 8 },
:mountain => { x: 8, y: 0, w: 8, h: 8 },
:water => { x: 0, y: 8, w: 8, h: 8 },
:forest => { x: 8, y: 8, w: 8, h: 8 },
}
tile = tiles.fetch(:grass)