Game Development Reference
In-Depth Information
A Simpler Solution
One advantage of
Replica Island
is that it does all this stretching and scaling via OpenGL ES,
which is hardware accelerated. So far, we've only discussed how to draw to a
Bitmap
and a
View
via the
Canvas
class, which, on older Android versions, involves slow number-crunching on the
CPU and doesn't involve hardware acceleration on the GPU.
With this in mind, we perform a simple trick by creating a framebuffer in the form of a
Bitmap
instance with our target resolution. This way, we don't have to worry about the actual screen
resolution when we design our graphical assets or render them via code. Instead, we pretend
that the screen resolution is the same on all devices, and all our draw calls target this “virtual�
framebuffer
Bitmap
via a
Canvas
instance. When we're done rendering a frame, we simply draw
this framebuffer
Bitmap
to our
SurfaceView
via a call to the
Canvas.drawBitmap()
method, which
allows us to draw a stretched
Bitmap
.
If we want to use the same technique as
Replica Island
, we need to adjust the size of our
framebuffer on the bigger axis (that is, on the x axis in landscape mode and on the y axis in
portrait mode). We also have to make sure to fill the extra pixels to avoid blank space.
The Implementation
Let's summarize everything in a work plan:
We design all our graphic assets for a fixed target resolution (320×480 in the
ï?®
case of Mr. Nom).
We create a
Bitmap
that is the same size as our target resolution and direct
all our drawing calls to it, effectively working in a fixed-coordinate system.
ï?®
When we are done drawing a frame, we draw our framebuffer
Bitmap
that is
stretched to the
SurfaceView
. On devices with a lower screen resolution, the
image is scaled down; on devices with a higher resolution, it is scaled up.
ï?®
When we do our scaling trick, we make sure that all the UI elements with
ï?®
which the user interacts are big enough for all screen densities. We can do
this in the graphic asset-design phase using the sizes of actual devices in
combination with the previously mentioned formulas.
Now that we know how to handle different screen resolutions and densities, we can explain the
scaleX
and
scaleY
variables we encountered when we implemented the
SingleTouchHandler
and
MultiTouchHandler
in the previous sections.
All of our game code will work with our fixed target resolution (320×480 pixels). If we receive
touch events on a device that has a higher or lower resolution, the x and y coordinates of those
events will be defined in the
View
's coordinate system, but not in our target resolution coordinate
system. Therefore, it is necessary to transform the coordinates from their original system to our
system, which is based on the scaling factors. To do this, we use the following equations:
transformed touch x=real touch x * (target pixels on x axis / real pixels on x axis)
transformed touch y=real touch y * (target pixels on y axis / real pixels on y axis)