Quick and dirty sprite glueing

By Greg Goltsov

During the development of one of my small games for a coursework, Guilds and Dragons, I was really trying to create that nice isometric, slightly pixelated feel of old-school RPGs (Baldur's Gate, Planescape: Torment, Arcanum etc.). The fact that I was developing for PlayStation 2 on Linux kit meant that the game was going to be in glorious 640x512 resolution. The only problem was — I had absolutely no time to draw anything and I am not really an artist.

Thankfully, it was possible to find enough absolutely awesome sprites, thanks to places like Spriter's Resource and others. However, the best source of sprites that fitted my game perfectly was Reiner's tilesets. Absolutely great selection of monsters, characters, awesome 8-directional animation and other things. One problem, though, — everything was created in Blender and then output (via scripts) in a very specific way — one file per direction per frame. Meaning this

when we really wanted this

to produce this animation

Now, of course, for games we really want a nice, simple spritesheet. And we want it for all the characters, in all orientations doing all the possible actions (in my case it was around 2200 separate image files). This kind of makes it completely impossible to do it manually (as I tried in the beginning, but it got tedious very quickly).

So, mixing a bit of desperation, Ruby and the black wizardry of ImageMagick's gem (installation of ImageMagick is left as an exercise for the reader, although I seem to remember Homebrew's formula was working perfectly last time I tried it), the the following simple script was born.

# Usage:
# Place the script in the directory with all the images, tweak `prefix` and `output` and just run it.

require 'rubygems'
require 'RMagick'
include Magick

Image_dims = 96
prefix = 'swordskel attack'
output = 'p_dying'
output_fname = output + '_big.bmp'
# If the animation has too many frames, take every even one
#nums = %w( 0 2 3 5 6 7 9 11 )
# Otherwise, just use the simple progression
nums = (0..7).to_a.map(&:to_s)
dirs = %w( n ne e se s sw w nw )

Canvas = Image.new( 768, 768 ) { self.background_color = "black" }
puts 'Starting the script'

def draw_image( dir, num, image )
  offset = 0
  Canvas.store_pixels( num * Image_dims,
                       dir * Image_dims,
                       Image_dims,
                       Image_dims,
                       image.get_pixels(offset,offset,Image_dims,Image_dims) )
end

dirs.each_index do |dir|
  puts "For dir #{dirs[dir]}..."
  nums.each do |num|
    n = (num.to_i < 10) ? '0'+num : num
    image_name = "#{prefix} #{dirs[dir]}00#{n.to_s}.bmp"
    puts "Trying to push file \"#{image_name}\" to the ImageList"
    draw_image( dir, nums.rindex(num), (Image.read(image_name))[0] )
  end
end

#Canvas.display
Canvas.write( output_fname )

exit

Now, this is the version I used several years ago when I needed it and only now am releasing it — this means that it is given "as-is", and is not particularly friendly just now (I was quite new to Ruby back then). If someone becomes interested in this, I'll update it to be a bit nicer.