As soon as you start drawing more than one thing on the screen, you have to consider which will be rendered in front of the other. It makes no sense for the background (which typically covers the entire screen) to be rendered in front of the player and enemies, or for things to be rendered behind the background.
Gosu uses a 3D rendering interface to render 2D images. Because of this, it has easy access to Z-ordering, or putting images in front of or behind each other. In a 3D scene, this Z-ordering would determine how far "into" the screen objects are. It's the same in a 2D scene except there's no perspective, images rendered at a Z-layer far "into" the screen are the same size as images rendered at a "closer" Z-layer. Likewise, images rendered at a Z-layer far "into" the screen will be rendered as if they are "behind" images at a closer Z-layer.
We've seen Z-ordering in this article series before. When we created a window, we rendered the background at Z-layer 0. Later when we loaded an image, we rendered that image on Z-layer 1. If we rendered both at once, since the image has a higher Z-layer, it would be rendered in front of the background. The higher the Z-layer, the closer to the screen the image is. The lower the Z-layer, the farther away it is.
The following program will render two rectangles. These rectangles are overlapping and rendered at Z-layers 0 and 1. When the space bar is pressed (more on input in a later article), the Z-order will be reversed and the opposite rectangle will be displayed in front.
#!/usr/bin/env ruby require 'rubygems' require 'gosu' class MyWindow < Gosu::Window def initialize super(640, 480, false) @order = [0, 1] end def draw c1 = Gosu::Color.new(255, 0, 0, 255) c2 = Gosu::Color.new(255, 255, 0, 0) draw_quad( 100, 100, c1, 200, 100, c1, 100, 200, c1, 200, 200, c1, @order ) draw_quad( 150, 150, c2, 250, 150, c2, 150, 250, c2, 250, 250, c2, @order ) end def button_down(id) @order.reverse! end end MyWindow.new.show
Magic Numbers are Bad
Up until now, we've been hard-coding Z-layer numbers into the program. This is not a good practice. What is "Z-layer 0?" It could be anything, it's best to have names for your Z-layers.
One very common idiom you see in Gosu programs is a Z-order module. In this module, there are a number of constants that represent the Z-layers used in the game. These are assigned to integers by assigning a range (converted to an array) to the list of constants. Those listed first in the module will be rendered behind those listed later in the module.
While it's generally a bad idea to have single-letter module names (especially in the global namespace), since the Z-ordering module will be referred to quite often, I've named it simply Z. If this is a problem, you can name it something like ZOrder.
module Z Background, Player = (1..100).to_a end
Now, whenever you need to refer to one of these layers (when drawing an image, for example), you simply need to use the constants Z::Background or Z::Player.
This article is part of a series. Read more articles about Rapid Game Prototyping in Ruby