Sprites

From Open Surge Wiki
Revision as of 04:34, 19 January 2021 by Alexandre (Talk | contribs) (Modifying the battery sprite The Right Way™)

Jump to: navigation, search

Introduction

All objects with an animation are referred to as sprites. Consider a picture sheet with all the frames needed to be displayed in an animation. In Open Surge, a sprite is composed by two things:

  • A picture sheet (also known as spritesheet), usually in the .png format. These files are placed in the images/ folder.
  • A .spr file, which is a text file telling the engine how to display the sprite. These files are placed in the sprites/ folder and they can be opened with any simple text editor like Notepad.

All picture sheets have a transparent color. They differ between games, but Open Surge uses magenta (RGB 255,0,255) as transparent. Since Open Surge 0.5.0, RGBA 0,0,0,0 can also be used as transparent.

How to create and modify sprites

The battery sprite

We'll learn by example. Consider the following spritesheet:

Collectibles by svgmovement

Batteries are used as collectible elements in the game.

Let's see how Open Surge reads data from your images so that it can be displayed in-game. We will look at the corresponding sprite file (.spr) included with the game.

...

// Collectible
sprite "Collectible"
{
    source_file     "images/collectibles.png"
    source_rect     0 0 304 16
    frame_size      16 16
    hot_spot        8 12

    // spinning
    animation 0
    {
        repeat      TRUE
        fps         16
        data        0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
    }

    // disappearing
    animation 1
    {
        repeat      FALSE
        fps         8
        data        16 17 18
    }
}

...

In the above file, there are several things you will notice:

  • There are lines that begin with //. These lines are there merely for your convenience and are ignored by the engine.
  • sprite "Collectible": This is what this definition is called. You must make sure that no two sprites have the same name.
  • source_file: This is where the image you are reading from is located. The engine assumes that images are located somewhere in the game directory folder, so you do not need to specify the full file path. Instead, you just have to specify where the images are located in the game folder.
  • source_rect: The first two numbers give the X and Y coordinate, respectively, of the top left corner of the image you are defining. The second two numbers, width and height, respectively, give how big of a rectangle it would take to completely enclose every frame of the animation. These numbers are given in pixels. You can get them with an image editor such as GIMP.
  • frame_size: Defines the size of each frame of your animation. In this example, the size of the source rectangle is 304 by 16 pixels, but each piece of the animation is only 16 by 16 pixels.
  • hot_spot: Every object in the engine has a X and a Y position in the screen, but is this spot its top-left corner? Or maybe its center? This is the place which the engine will use to determine the x and y position of your object. It also is the place where the level editor grabs your object when you select it. There are different reasons for placing hotspots in different places, however it is mostly a matter of preference. The hot spot also performs an important role in objects that are flipped or rotated in the game.
  • animation <NUMBER>: These are the animations your object can perform. Assuming that your object has N animations, <NUMBER> must vary from 0 to N-1. For example, if you're creating an object with five animations, you would need to specify animation 0, animation 1, ... and animation 4. There are three different things that animations need to be fully defined:
    • repeat: this tells the engine if you want it to keep doing the animation as long as it is the selected one. In this case, while the collectible is standing still it will continuously spin because repeat is set to TRUE in animation 0. However, when the active animation changes to 1 (when a player touches it), it will play the animation only one time before disappearing.
    • fps: This defines how fast the engine will cycle through your frames. In this case it plays 16 frames every second for animation 0 and 8 frames per second for animation 1. The higher the fps, the faster the animation.
    • data: This defines which frame you want to play at any particular moment. In this case it plays frames 0-7 and then repeats under animation 0, and plays frames 8-10 and doesn't repeat under animation 1.

Note: you may also define different values of hot_spot in different animation blocks, but that is optional.

Modifying the battery sprite

Now that we've examined a sprite file and determined what each of the components do, we'll modify it so that we replace the batteries in the game with our collectibles.

Warning: Changing sprite files makes a major change to the game. Make sure to backup your sprite files before you change them, so if something goes wrong, you will be able to restore the original functionality to the game. Read below for a better way to do it.

images/my_collectibles.png (design by lunarrush)

We'll now edit sprites/items/collectibles.spr and modify the Collectible sprite:

...

// Collectible
sprite "Collectible"
{
   source_file     "images/my_collectibles.png"
   source_rect     1 1 176 16
   frame_size      16 16
   hot_spot        8 12
   
   // idle
   animation 0
   {
       repeat      TRUE
       fps         16
       data        0 1 2 3 4 5 2 6
   }
   
   // end
   animation 1
   {
       repeat      FALSE
       fps         8
       data        7 8 9 10
   }
}

...

Here are some things you should notice right off the bat:

  • We use different lines that start with //, because they help us to keep track of what our sprite is doing. Remember, these are entirely up to the individual user and they aren't required - but they are helpful.
  • sprite "Collectible", located at the top, remains the same. This is so we don't have to modify any levels to replace all collectibles with our modified version. It also means that we must remove the old Collectible sprite definition from the sprites folder, so the engine won't try to define what is a Collectible sprite twice. Since we're modifying the original .spr file itself, this shouldn't be a concern.
  • The source_file is different. This is because we have created a new image and it has a different file name than the original.
  • The source_rect is different, since the frames of the new sprite are at a different places inside the new image than the originals were.
  • The frame_size is the same. We have used a standard size rectangle to create our collectibles, so that they can seamlessly replace the built-in ones.
  • The hot_spot is the same. This is because we didn't see any need to change this from what it already was.
  • The animation <NUMBER> lines are the same. As in the original sprite, animation 0 specifies the spinning animation and animation 1, the disappearing one.
    • The repeat entries are set to the same values, since the modified sprite acts in a similar way compared to the original one.
    • The fps values are the same. This could be modified if we wanted to speed up or slow down the animation.
    • The data values are different. This is because the frames of our modified sprite must be presented in a different order to be a complete animation.

Now that we understand how the engine reads these files, it is easier to know what input we need to give it in order for our sprites to be displayed correctly.

Modifying sprites The Right Way™

Overriding sprites

While it's tempting to modify the sprites simply by editing the original .spr files that are shipped with Open Surge (due to the simplicity of the process), this introduce an issue: you'll lose your changes as soon as you upgrade the engine. Not only that: you'll also lose the original sprite.

Open Surge version 0.5.2 introduced a special folder, sprites/overrides/. Sprites defined in this folder override sprites defined elsewhere.

If you want to modify a sprite that is shipped with Open Surge, do not modify its .spr file directly. If you do so, you'll lose your changes as soon as you upgrade the engine. Instead, copy the file you want to modify into sprites/overrides/ and modify YOUR COPY instead. Files stored in this folder won't be overwritten when upgrading the engine.

When modifying a sprite, do not edit the original image files that are shipped with Open Surge. Instead, make a copy and edit YOUR COPY. This helps you keep your changes if you upgrade the engine.

Modifying the battery sprite The Right Way™

When modifying the battery sprite above, we edited file sprites/items/collectibles.spr directly. We will no longer do this. Instead, we will copy the original file that is shipped with Open Surge into sprites/overrides/collectibles.spr. Next, we will edit sprites/overrides/collectibles.spr. Notice the following:

  • File sprites/items/collectibles.spr is the original sprite definition that is shipped with Open Surge, totally unchanged
  • File sprites/overrides/collectibles.spr is your modification
  • File images/collectibles.png is the original spritesheet that is shipped with Open Surge, totally unchanged
  • File images/my_collectibles.png is your modification

We now have two .spr files defining the same sprite, "Collectible". Since sprites defined in sprites/overrides/ take precedence over sprites defined elsewhere, the engine will display your modification. When you upgrade the engine, your modification will be kept.

Note: feel free to create subfolders at will. We can store our modified collectibles.spr in sprites/overrides/items/, and it will work just as well.

Try it yourself!

As an exercise, write a sprite definition for the spritesheet below:

Save it to images/my_rings.png