229
14
2DMagic
Daniel Higgins
Lunchtime Studios, LLC
Magician street performers don’t require a big stage, scantily clothed assistants,
or saw boxes to amaze an audience. They are extraordinary in their ability to en-
tertain with a coin or a deck of cards. Many modern-day game developers are
like street performers and do amazing things on a smaller stage. They often work
on mobile platforms and in small groups instead of giant teams. Small budgets
and limited time are no excuses for developers producing subpar products, how-
ever. Limited resources means that these teams must stretch what little they have
in order to produce magic on screen.
The magic described in this chapter is simple, powerful, and requires only a
small amount of graphics knowledge, such as how to construct and render a quad
[Porter and Duff 1984]. This isn’t an introduction to graphics programming, and
it isn’t about using shaders or the latest API from DirectX or OpenGL. Instead,
it’s a collection of easy-to-implement graphical tricks for skilled (non-graphics
specialist) programmers. In this article, we first explore very basic concepts that
are central to graphics programming, such as vertices, colors, opacity, and texture
coordinates, as well as creative ways to use them in two dimensions. Next, we
examine how to combine these building blocks into a powerful and complex
structure that allows for incredible 2D effects (with source code included on the
website). Finally, we conclude by conjuring our own magic and demonstrating
some simple examples of this structure in action.
14.1ToolsoftheTrade
When a magician develops a new trick featuring a prop, he must first examine
the prop’s properties. Take a coin for example. It’s small, round, light, and stur-
dy. It easily hides in the palm of our hand and is the right size to roll across our
230 14.2DMagic
fingers. Once we have a good understanding of the coin’s properties, we can de-
velop tricks that suit its potential. Likewise in graphics, our props are vertices.
Knowing what composes a vertex gives us clues about how to develop tricks that
harness its powers.
In its most basic form, a vertex is a point with properties that are used while
rendering. It’s graphics information for a drawing location somewhere on (or off)
the screen. In 2D, it’s most commonly used as one of four points that make up a
quad (two triangles sharing an edge) and is generally used in the rendering of text
or an image. A vertex contains position, color, opacity, and often texture coordi-
nates. Let’s examine each property in detail.
14.2Position
A vertex’s position determines where it is rendered on the screen. Location on its
own may not seem interesting, but when combined with the other vertices of a
quad, we open up a window for scale, motion, and perspective effects.
ScaleEffects
Imagine a boat race game where we want to display a countdown prior to the
start of a race. Displaying the count involves starting each number small, then
increasing its size over the course of one second. We accomplish this by altering
the position of each vertex in a quad relative to the others in such a way that the
screen space becomes larger. Consider dressing this up with some acceleration
modifications that affect how fast it scales. Does it overshoot its destination scale
and have to snap back, producing a wobbling jelly-like effect? Perhaps it starts
quickly and eases into its destination scale, like a car pulling into a parking spot.
Regardless of what acceleration modifier you choose, don’t choose linear
acceleration—how boring! Adding unique scaling techniques, such as the smooth
step shown in Figure 14.1, adds character to a game. Smooth step is just a simpli-
fication of a Hermite spline [Pipenbrinck 1998] but produces elegant results with
little CPU usage. Other functions to consider when modifying percentages are
sine, cosine, power, square, and cube. Once you determine a scaling acceleration
theme, develop a cohesive style by using it throughout the user interface (UI).
MotionEffects
Motion effects, such as sliding or bouncing a quad across the screen, are
achieved by applying a physics force to a quad (and eventually each vertex). We
are not limited to maintaining a flat border in 2D space. That is, the y coordinate
14.2Position
for
o
b
e t
h
or f
l
the
r
posi
t
also
ren
d
Per
s
A b
i
wit
h
this
Fi
gu
its
pi
toge
t
Fi
g
u
r
o
ur top-left v
e
h
e same. We
l
ip them upsi
d
r
ange
0,2π
o
t
ion of each
o
store the n
d
ering.
s
pectiveEf
i
g advantage
h
the lighting
problem, ho
w
u
re 14.2. (a) T
h
i
xels. (c) Squ
a
t
her.
r
e 14.1. The s
m
e
rtex and the
can just as e
a
d
e down. W
e
o
n the quad.
W
o
f its four ve
r
ew orientati
o
f
ects
3D has over
rendered int
o
w
eve
r
—whil
e
h
e original im
a
a
shing the vert
i
0
m
ooth-step fun
y
coordinate
a
sily alter th
e
e
accomplish
W
hen the ori
e
r
tices to be re
o
n in a tra
n
2D is lighti
n
o
the art dur
i
e
we cannot
c
a
ge. (b) A sh
a
i
ces to build
p
1
0
0
smoothstep x
n
ction remaps t
h
for our top-r
i
e
orientation
o
this by stori
n
e
ntation cha
n
lative to its
n
n
sform matri
x
n
g. In the 2D
i
ng producti
o
change the l
i
a
dow generate
d
p
erspective. (d
)
1
2
32xx
t
he range [0,1]
.
i
ght vertex d
o
o
f our object
s
n
g an orienta
t
n
ges, the qua
d
n
ew orientati
o
x
that is ap
p
world, we’r
e
o
n. We shoul
d
i
ghting in th
e
d
by darkenin
g
)
The final im
a
.
o
not have to
s
, spin them,
t
ion value in
d
updates the
o
n. We could
p
lied before
e
often stuck
d
n’t bemoan
e
art, we can
g
and blurring
a
ges rendered
231
232 14.2DMagic
enhance it at run time. A perfect example of this is using shadows with our 2D
objects. Consider what happens in Figure 14.2. Here we take a rendering of one
of our characters, darken it, blur it, and squash its vertices, projecting it down to
create a slightly angled shadow. The result is an almost magical, subtle effect that
provides depth to our game world visuals.
14.3ColorandOpacity
Tinting and opacity are the primary responsibilities of a vertex’s color. Normally,
vertices are rendered with a white coloring (no tint), and the color’s alpha value
is used to indicate the transparency of a quad’s corner. That’s just the tip of the
iceberg, though, as color is one of the most valuable tools for taking our 2D
games to the next level, especially for UI design.
ColoredUIModel
Optimization isn’t just for frame rates; its principles should be applied to a com-
pany’s development processes. With that in mind, look to vertex coloring as a
means for small, budget-conscious teams to reduce art pipelines, promote reuse
of textures, and develop consistency in UI design.
Traditionally, UI art is built in third-party tools and rendered verbatim to the
screen. When it’s time to render, each vertex is rendered white (no visible
change) and may use its alpha value as the vertex’s transparency. This has the
advantage that artists know what the outcome will be, but it does not promote art
reuse and requires third-party tools if color changes are needed. What if we want
to reuse much of our game’s art, save memory, or want our UI to adapt to the
player’s preferences? We need to look at our UI rendering differently than we
have in the past and move to the colored UI model.
The colored UI model involves building reusable pieces of UI in grayscale,
focusing on making them as white as possible, with darkened areas to indicate
shadow and depth, then coloring these pieces when rendering. This allows for
UIs to quickly change their color and opacity based on run-time data or be initial-
ized from data files during load. Consider looking into luminance format textures
for more performance improvements.
Black and white is all about predictability. Render a colorful texture to a
green-colored quad, and the result is predictably a modulation of source texel and
destination color but is likely not the programmer’s intended result. If, however,
our UI is black and white, we know that the ending colors will all be shades of
the original colors we applied through the vertex. The catch with this is that we
14.3ColorandOpacity 233
are changing only the purely white areas of the original texture to our desired
color, and all other final display colors are darker depending on the shade of gray
in the original texture.
The most common example of white art and vertex coloring is text rendering.
When rendering a string that uses a font where each character has been preren-
dered in white onto a transparent background, we have the ability to color text
dynamically. To accomplish this, we look up a character’s texture coordinates,
choose the color for each character, and then render it on a quad of that color.
Our result? Characters from the same font file are shown on screen but colored
differently, with no extra texture memory required. We now extend this reuse to
our entire UI.
Imagine building a sports game where each team has a light and dark color.
Our designer wants to connect our gamers with the identity of their team through
the use of team colors. We could build a uniquely colored UI for each team, but
that takes a lot of effort and resources. Instead, artists design a black and white
UI, with the knowledge that some UI pieces will use the light team colors and
other areas will use the dark team colors. Now we have one art set instead of
many, resulting in a savings in memory, art development time, and likely load
time as well.
This isn’t to say an image of a person somersaulting off a building should be
in black and white and tinted when rendered. Use white art and tint it when there
is an asset that can be reused if colored differently. Often, buttons, frames, bor-
ders, scroll bars, tab controls, and other basic UI components are easily colored
to fit into different scenes.
OpacitySeparatefromColor
Gone are the days when it was acceptable to have UI objects jarringly pop on and
off the screen. Modern games fade objects or provide some other type of smooth
transition. These transitions (and indeed all transparency) are achieved by modi-
fying the alpha component of a vertex’s color. A value of one means the vertex is
fully opaque. A value of zero means the vertex is completely invisible.
Opacity is closely related to color due to the effect of a color’s alpha value on
transparency. It’s arguable that opacity is unnecessary since alpha is transparen-
cy. Why store opacity then? The problem is that temporary effects, like fades,
pollute the true value of a color’s alpha. It’s safer to apply opacity during render-
ing (
finalAlpha = alpha * opacity) and preserve the true state of a vertex’s
color. We can optimize this a bit by not storing opacity per vertex and opt for
storing it on a quad instead, since most opacity effects (like fade) don’t need to
affect vertices individually.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset