ugBASIC User Manual

Sprites

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

Introduction

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.

Basic commands

Available on (hardware, software):
c128 c64 c64reu coleco msx1 sc3000 sg1000

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)




The size of a sprite is the one given by the underlying hardware: so, no adaption is done but a simple "cropping" of the original image to the hardware limits. In other words, if your image is 32x32 pixel large and the underlying hardware sprite is 24x21 pixel, the image will be "cropped" to that size.

The limits of SPRITE on various systems follows:
  • c128 c64 c64reu
    • 8 sprites of 24x21 pixel with one color (SPRITE MONOCOLOR)
    • 8 sprites of 12x21 pixel with three colors (SPRITE MULTICOLOR)
  • coleco msx1 sc3000 sg1000
    • 32 sprites of 16x16 pixel with one color


Anyway, from this moment on, the variable 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




This command will display (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.

Composite sprites

Available on (hardware, software):
c128 c64 c64reu coleco msx1 sc3000 sg1000

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




Of course, doing it by hand can be tedious. For this reason the ugBASIC language allows you to define a composite sprite (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

Both traditional hardware sprites and composite hardware sprites have the same video chipset limitation, in terms of number of sprites and resolution.

Multiplexed sprites

Available on (hardware, software):
c128 c64 c64reu

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!).



graphics courtesy of gaymoo


Unlike hardware sprites where images are cropped, the size of a multiplexed sprite is taken directly from the image data, and it is rounded to the underlying hardware size (so a 32x32 monochromatic image as above will be converted into 4 hardware sprites of 24x21 pixels). So, if the hardware sprites cannot be resized, a part of the area inside these sprites is wasted, and that you need more than one sprite to represent a large image.




As the composite sprite described above, since each hardware sprite can draw just one color, you need a sprite for each color, too.

Finally, once the hardware sprite has been drawed on the screen, its image can be recycled, by using another sprite image, and so on. In this way we can have many virtual sprites.

So a multiplexed sprite is a composition of composite sprite where each element of the composition is done by using a virtual sprite that, in turns, use a real (hardware) sprite.

Confused? Don't worry!

The ugBASIC language takes care of all the technical and complicated part, leaving you with simple to use instructions, very similar to the previous ones:

spriteImageMultiplexed := LOAD IMAGE("sprite_multiplexed.png")
spriteMultiplexed = MSPRITE(spriteImageMultiplexed)
SPRITE spriteMultiplexed ENABLE AT 100,100

Due to the way multiplexed sprites are produced, there is the restriction that you can't have more than eight multiplexed sprites on a single line. In practice the system is complicated by the need to produce sprites which are larger than the 24 pixel maximum or that have more than one color. The ugBASIC generates these objects by automatically positioning several multiplexed sprites "side by side" and "overlapped".

So, the maximum of eight hardware sprites therefore imposes a strict limit to the number of such objects you can display on a horizontal line. The total width of the objects must not exceed:
  • 24*8=192 pixels (for monochrome sprites)
  • 16*4=96 pixels (for two colors sprites)
  • 16*2=48 pixels (for four colors sprites)
  • 16*1=24 pixels (for eight colors sprites)

If you try to ignore this limitation, you won't get an error message, but your multiplexed sprite will not be displayed on the screen. So it's vital to ensure that the above restriction is respected.

Normally, whenever you move a sprite, its position is updated automatically during the next vertical blank period (see 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.

Redefining sprites

Available on (hardware, software):
c128 c64 c64reu coleco msx1 sc3000 sg1000

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.

Sprite palette

Available on (hardware, software):
c128 c64 c64reu

The colours required by a hardware sprite (SPRITE) are stored in hardware registers, that can be reached in three ways:

  • implied, by parsing any image;
  • indirectly, using the SPRITE COLOR instruction;
  • directly, POKEing values to registers &HD027-&HD02F (c128 c64 c64reu only).
For the composite (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.

Coordinates

Available on (hardware, software):
c128 c64 c64reu

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)

Other topics

Available on (hardware, software):
c128 c64 c64reu coleco msx1 sc3000 sg1000

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.


Any problem?

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!