By jlnr (dev)
Date 2015-12-24 07:49
Nope, not without additional OpenGL hackery. Or you can use Gosu::clip_to
to render the background again, clipped to the window/door rectangle on a tile, but that's only efficient if the background is very simple (a static image, for example).
It should be easy to generate each tile/cutout combination using RMagick.
It's very doable.
I developed this method for blending different tiles, but the principle can be applied to utilize an alpha mask. It requires you build a class to store pixel data capable of being used as a parameter for Gosu::Image.new();
I called mine Surface because it is used in the same way as sdl's surface class. basicly, it's like this:
class Surface
def initialize(pixels,w,h)
@pixels = pixels
@w = w
@h =h
end
def to_blob
@pixels
end
def to_img
Image::Gosu.new(self, @w, @h)
end
end
#first, ensure the mask and the tile are the same width and height, than use gosu to load the images.
tile = Gosu::Image.new(<tile filename>)
mask = Gosu::Image.new(<mask filename>)
#both gosu::image and our new surface class contain a method .to_blob which returns pixel data as 32 bit strings. Here is a simple method to extract RGBA values from a given blob:
tile_pixel_array = tile.to_blob.unpack('L*').collect{|c| [c].pack('L*').unpack('C*')}
mask_pixel_array = mask.to_blob.unpack('L*').collect{|c| [c].pack('L*').unpack('C*')}
#this is inefficient, what with all this unpacking and re-packing and whatnot. My actual method uses maths but the end result is the same.
#something like this will take the alpha channel of the mask (c[1]) and append it to the rgb of the tile (c[0]):
new_pixels = (tile_pixel_array.zip(mask_pixel_array)).collect{|c| (c[0][0,3] << c[1][3]) }
#you can also add any other color channel as the alpha channel:
new_pixels = (tile_pixel_array.zip(mask_pixel_array)).collect{|c| (c[0,3] << c[1][0]) } #red as alpha mask
new_pixels = (tile_pixel_array.zip(mask_pixel_array)).collect{|c| (c[0,3] << c[1][1]) } #blue as alpha mask
new_pixels = (tile_pixel_array.zip(mask_pixel_array)).collect{|c| (c[0,3] << c[1][2]) } #green as alpha mask
#you then re-pack these into a string, and use it as the blob for a new surface:
composite = Surface.new(new_pixels.flatten.pack('C*'), tile.width, tile.height))
#we can use our Surface class to manipulate these 'blobs' however we want, putting the above code into some custom method and use #to_img to return a new gosu image class.
img = Gosu::Image.new(composite)
or
img = composite.to_img
nothing to it!