The ugBASIC language provides you with complete
control over the hardware sprites, where available. Hardware
sprites are separate images
which can be automatically overlayed on the home computer's screen.
Since sprites don't interfere with the screen background, they are
perfect for the moving objects required by an arcade game.
Introduction
Basic
Composite
Multiplexed
Redefine
Palette
Coordinates
Other
One of the biggest attractions of the console and
home computer was the ability to produce high quality
games which rival those found on genuine arcade machines.
This can be done using sprites. These can be effortlessly
manoeuvred with the given instructions, so you don't have to
be an expert programmer in order to create your own arcade games.
Hardware sprites are not only fast, but they also take up very little
memory. So they should always be used, if present. The number
of sprites, resolution and number of colors of each sprite vary
by the underlying video chipset used. Normally is around 8 or 32
sprites in a single screen, 16x16 pixel monochrome or
24x21 pixel with a maximum number of three colors.
These features don't seem particularly impressive. But there are
various tricks which can increase both the numbers and sizes of
these sprites beyond recognition.
One solution is to overlap more than one sprite in the very
same video location, in order to have more colors. Another
solution is to reuse each hardware sprite (sprite multiplexing ),
allowing you to apparently display dozens of sprites on the
screen at once. The resolution restriction can be exceeded by
building an object out of several individual sprites.
So you'll be happy to discover that ugBASIC manages the entire
process automatically! Once you've designed your sprites with
any drawing program, you can effortlessly manipulate them with
just a single ugBASIC instruction.
Remember to have a graphic IMAGE
loaded into the program
when trying out the various commands in this guide.
In the examples
folder you will find out
many samples. In order to load an image you can
refer to this guide.
To define an (hardware) SPRITE
you need
to use the SPRITE
function. It takes
an image as parameter and returns a SPRITE
value:
spriteImage = LOAD IMAGE("sprite.png")
sprite = SPRITE(spriteImage)
SPRITE
on various systems follows:
SPRITE MONOCOLOR
)SPRITE MULTICOLOR
)sprite
will
contain an identifier ("handle" in technical jargon) which will
allow it to be used with subsequent instructions. Obviously,
defining a sprite does not mean showing it on screen!
It is necessary to enable (activate) it. So you need to use
the SPRITE
command. This is an example:SPRITE sprite ENABLE AT 50,100 COLOR RED
ENABLE
) a hardware sprite sprite
on the screen at the sprite coordinates 50,100
replacing the actual color with the color RED
.
Note that we must not give the color explicitly, since it is retrieved
automatically by image. Moreover, the coordinates are important and
we will return to the discussion later: just think that
they do not coincide with those of the screen, and therefore a different
reference system must be used.
We said at the beginning that the characteristics of the hardware
sprites are not particularly exciting. On some chipsets it is
necessary to remain monochromatic (color and transparency) to be
able to define a sprite at maximum definition. So, how can we
define a sprite with (say) 3 colors? Simple: overlapping three
sprites! To do this, we simply define three sprites and draw them all
in the same position.
spriteImageColor1 := LOAD IMAGE("sprite_color1.png")
spriteImageColor2 := LOAD IMAGE("sprite_color2.png")
spriteImageColor3 := LOAD IMAGE("sprite_color3.png")
spriteColor1 = SPRITE(spriteImageColor1)
spriteColor2 = SPRITE(spriteImageColor2)
spriteColor3 = SPRITE(spriteImageColor3)
SPRITE spriteColor1 ENABLE AT 100,100
SPRITE spriteColor2 ENABLE AT 100,100
SPRITE spriteColor3 ENABLE AT 100,100
CSPRITE
) starting directly from an image. What happens is that
ugBASIC will separate each individual color component from
the original image, it will generate a separate sprite for each, and then
it "hold them together" when it's time to move them with the SPRITE
command.spriteImageColor := LOAD IMAGE("sprite_color.png")
spriteColor = CSPRITE(spriteImageColor)
SPRITE spriteColor ENABLE AT 100,100
Although the video chipset only provides you with eight actual
sprites, it's possible to use them to display up to 32 different
objects on the screen at once. These objects are known as
multiplexed sprites and are managed entirely by ugBASIC.
Multiplexed sprites can be defined by calling the MSPRITE
function to define them, and using SPRITE
as usual.
Before you can make full use of these sprites you need to
understand some mechanism. Each hardware sprite consists of a
24x21 pixel image, monochromatic (just one color!).
spriteImageMultiplexed := LOAD IMAGE("sprite_multiplexed.png")
spriteMultiplexed = MSPRITE(spriteImageMultiplexed)
SPRITE spriteMultiplexed ENABLE AT 100,100
WAIT VBL
).
But if you are moving a lot of sprites using the SPRITE
command,
the updates will occur before all the sprites have been moved. This
may result in a noticeable jump in your movement patterns. In these
circumstances, you can turn off the automatic updating system with
the DEFINE MSPRITE ASYNC
pragma. Once your sprites have been
successfully moved, you can then slide them smoothly into place with a
call to MSPRITE UPDATE
. This will reposition any sprites
which have moved / enabled / disabled since your last update.
The only problem with multiplexed sprites is that you
never know precisely which hardware sprite is going to be
used in a particular object. This is the main reason
why SPRITE/CSPRITE
and MSPRITE
() cannot
be used together.
Normally the hardware sprites
used in an object will change whenever the object is moved.
Occasionally this can be inconvenient, especially when you
are animating objects such as missiles which need to remain
visible in a wide range of possible sprite combinations.
In these circumstances, it's useful to be able to operate
on the very same sprite, i.e. to change images. In this case,
you can use a slightly different syntax (it depends on the type
of the original sprite, of course!):
sprite = SPRITE(newImage, sprite)
sprite = CSPRITE(newImage, sprite)
sprite = MSPRITE(newImage, sprite)
This redefines immediately the graphical aspect of the sprite.
Note that, in the case of CSPRITE
and MSPRITE
,
the images you need to use to redefine the existing sprites must have
all the same geometric and color characteristics. For example, if you
use a 32x32 pixel frame with 3 colors, you cannot replace it with a
20x20 pixel frame, nor with one with fewer or more than 3 colors.
Even in this case, no checks of any kind are carried out: what happens
is that ugBASIC will seize sprites that are nearby,
therefore giving rise to graphic defects.
The colours required by a hardware sprite (SPRITE
)
are stored in hardware registers, that can be reached in three
ways:
SPRITE COLOR
instruction;POKE
ing values to
registers &HD027
-&HD02F
(c128
c64
c64reu only).CSPRITE
) and the multiplexed
(MSPRITE
)
sprites,
it is not possibile to act directly on the registers, and acting indirectly
is not fully supported. The more convenient way is to use image parsing.
In general, sprites move in a different reference system than that of the drawable
screen. To take these differences into account, without having to write the programs
as many times as there are systems equipped with sprites, a series of constants can
be used:
SCREEN BORDER X
represent the width of the border, i.e. the
first horizontal position (in sprites coordinates) where the sprite can appear;SCREEN BORDER Y
represent the height of the border, i.e. the
first vertical position (in sprites coordinates) where the sprite can appear;SCREEN SPRITE RATIO X
represent, in percentiles, what is the relationship
between the width of the screen and the width that can be used by the sprites.
If the drawable screen is 320 pixels wide but the sprites have a horizontal precision of
only 256 positions (320/256 = 1.25), the value of the SCREEN SPRITE RATIO X
constant will be 125
(125 = 1.25 x 100
)SCREEN SPRITE RATIO Y
represent, in percentiles, what is the relationship
between the height of the screen and the height that can be used by the sprites.
If the drawable screen is 200 pixels wide but the sprites have a vertical precision of
exactly 200 positions (200/200 = 1), the value of the SCREEN SPRITE RATIO Y
constant will be 100
(100 = 1 x 100
)
We already described the SPRITE ... ENABLE
command,
that allows to show a single sprite on the screen. There is
also a variant of that command, SPRITE ENABLE
(also called SPRITE ON
), that allows to enable
all available sprites. On the same side, the SPRITE DISABLE
(also called SPRITE OFF
) command removes one sprite
from the screen.
If you have found a problem, if you think there is a bug or, more
simply, you would like something to be improved, write a topic on the official forum, or open an issue on GitHub.
Thank you!