Bricksets

From Open Surge Wiki
Revision as of 00:45, 6 August 2020 by Alexandre (Talk | contribs) (Design guidelines)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Definitions

Bricks being displayed in the level editor

In Open Surge, levels are built using elements called bricks. A brick is a reusable scenery element. Bricks may be: blocks, floors, walls, ceilings, movable platforms, trees, plants, decorative objects, and so on. Bricks are like tiles, but more flexible:

  • Bricks can be of varying sizes (whereas tiles have a fixed size)
  • Bricks may be placed anywhere in space, even on top of each other
  • Bricks may be endowed with special behavior & movement

Bricks are imported into Open Surge via a brickset. If you want to create new scenery for new levels, you must first create a brickset. A brickset is composed of two elements:

1) The brickset image

A brickset image
No brickset would ever exist without the image in which the bricks are contained. This image features the artwork and may be organized in many ways. It's recommended to align the bricks to a 16x16 grid. This makes things convenient when designing levels and when creating the brickset script.

Note: to ensure maximum compatibility with most video cards, brickset images must not exceed 4096x4096 pixels. That's more than enough for most cases, but if you ever run out of space, split the artwork into two or more images.

Previously, the limit was 2048x2048 pixels. It has been increased in Open Surge 0.5.2.

2) The brickset script

The brickset script specifies how the bricks get put into the game for your use. It connects the artwork with the game. A brickset script is a .brk file in the themes/ folder. The engine reads this script for references on bricks, gets their parameters, and the physics take care of the rest once you're done placing the bricks in your levels.

The brickset script contains references to the brickset image(s), how big the bricks are, what part of the image to use as their "face", the animation sequence (if any), the collision mask (if any), and their behavior: whether they react as a plain stepping stone, collapse beneath you once touched, act as a "cloud" (we will discuss this soon), move around in mid-air to make jumping challenges, and so on.

Design guidelines

A brickset created using these guidelines
Collision mask of a brickset

While you have great flexibility to design your brickset, experience shows that certain approaches work better than others. We present guidelines that increase the likelihood of creating a brickset that easy to use and easy to write.

Divide the brickset into 3 parts (this division is conceptual):

1) Blocks (you may use bricks numbered from 0 to 127)

These are 128x128 bricks that represent: walls, platforms, ceilings, parts of a loop, and so on. They are the building blocks of your level and will help you build its structure. Make sure that they are tileable (repeatable).

2) Things (you may use bricks numbered from 128 upwards)

These are generally passable/decorative bricks like: flowers, trees, rocks, pipes, and so on. All such bricks must be built within a 16x16 grid (width and height must be divisible by 16, like 64x64, 32x64, etc.)

3) Special (you may use bricks numbered from 255 downwards)

These are special bricks such as: movable platforms, breakable walls, and so on. All such bricks must fit a 16x16 grid (width and height must be divisible by 16).

The brickset image may be a .png image of size 1024x1024, 1024x2048, 2048x2048 or even 4096x4096 pixels (depending on your needs). To make things easier, work with two grids simultaneously:

  • A basic grid of 16x16
  • A block-level grid of 128x128

Tip!

Imaging software (such as GIMP) have the ability to work with grids. Enable the 16x16 grid in your software. Activate the option snap to grid, so that your grid becomes "magnetic". Create a separate grid of 128x128 pixels by making a custom image and display it on top of your brickset - in a separate layer - while you're working on your art.

In addition to the artwork, you may specify a collision mask: an image that specifies the solidity of each pixel of the bricks. A collision mask gives you a finer amount of control regarding how the collisions should be handled. Sometimes collisions require manual inspection, so it's better to create a mask.

How to create a collision mask

Art and collision mask are split into different files. Once the artwork is ready, the mask can be created easily by copying the image and deciding which parts are solid and which aren't. A mask has two basic colors: magenta means non-solid. You may use black as solid. Artwork and mask must be aligned (share the same position in the image).
Collision masks must be smooth and should have no "holes" in it (see the example on the side). Pay attention if your artwork is irregular: in this case you need to adjust the mask. Examples:
1. if you have a grass brick with lots of "spikes" on top of it, smooth it out: you don't really want "spiky" artifacts affecting the collisions.
2. if your artwork includes metallic grids or other features with holes in them, fill in the gaps: these artistic features must not affect the collisions.

If you follow these guidelines, writing the brickset script (.brk file) will be a piece of cake and shouldn't take more than a few minutes. You may either write the brickset script yourself or use automated tools.

Creating & finding artwork

Creating new scenery implies creating new artwork. You may create the artwork yourself, work with an artist, or find it online. There are many pixel art tutorials on the Internet, and OpenGameArt.org provides freely licensed art that you can use and remix.

Tip!

When creating your artwork, you may find inspiration in the artwork that is shipped with Open Surge (explore the images/ folder). You can use that as a base to help you get started with your own artwork.

Writing the brickset

A brickset script is a file that has one or more brick definitions.

brick

In the brickset script, every brick definition starts with brick and is followed by its number. Following a logical sequence is highly advisable. After the brick number comes a block containing a set of parameters that describe what the brick is.

A brick is defined like this:

brick 16
{
    type                SOLID
    behavior            DEFAULT
    mask                "images/brickset_mask.png"     // optional
    zindex              0.5                            // optional

    sprite
    {
        source_file     "images/brickset.png"
        source_rect     16 224 64 64
        frame_size      64 64

        animation
        {
            repeat      TRUE
            fps         8
            data        0
        }
    }
}

We'll now cover the brick parameters.

sprite

The sprite block describes the graphical properties of the brick - how it's going to be displayed on the screen. For more information, read the Sprites page.

type

The type will tell the physics core how to handle collisions with this brick.

SOLID

SOLID means: a solid brick

Solid brick

You can't go through it

Note: in versions of the engine prior to 0.5.0, the solid brick type was called OBSTACLE.

PASSABLE

PASSABLE means: you can pass through it (it's a non-solid brick, meaning that it doesn't affect collisions)

The bushes are passable bricks

CLOUD

CLOUD means: you can go to the top of it from below, but not the opposite. Also known as "one-way platforms".

The rock is a cloud brick

See? You can step on top of it

mask

Collision mask example

A collision mask is a mechanism that specifies which parts of the bricks are solid and which parts aren't. This gives you a finer amount of control regarding how the collisions should be handled. Example: if you have a "grass" brick with lots of "spikes" on the top, most likely you don't want the "spiky" artifacts to affect the collisions. Collision masks must always be smooth and should not have any "holes".

Usually, a collision mask is represented by a .png image with two colors only: magenta (if the pixel is non-solid) and black (if the pixel is solid). The collision mask image must be aligned with the brick image, so that the brick and its mask get to be on the same position (although they are on different images, they share the same position). If the brick is animated, the collision mask of the brick must be at the location of the first frame of the animation.

This is an optional parameter. If not specified, the engine will assign a collision mask automatically: pixels will be solid if they are not transparent (magenta). Depending on your artwork, this may not be desirable, so creating your own mask is a good idea.

// path to the mask image
mask "images/brickset_mask.png"

zindex

Usually a value between 0.0 and 1.0, zindex specifies the order in which bricks are rendered to the screen. Bricks with a large zindex will be displayed in front of others. Bricks with a small zindex will be rendered behind others. Finally, a brick will be drawn behind the player if, and only if, its zindex is lower or equal to 0.5.

This is an optional parameter. If not specified, it defaults to 0.5.

// the brick will be rendered in front of others that have a lower zindex
zindex 1.0
// bricks with a higher zindex will be rendered in front of this one
zindex 0.1

behavior

The behavior specifies the kind of movement or behavior the brick will adopt.

DEFAULT

DEFAULT means: a brick that stands still, with no special behavior. This is the behavior that is likely to be used in most cases. Example:

// a regular brick
type SOLID
behavior DEFAULT

The syntax above shows just the type and the behavior of a brick; a more complete brick definition would be as follows:

// This is just an example
brick 154
{
    type                SOLID
    behavior            DEFAULT
    zindex              0.5
    mask                "images/waterworks_mask.png"

    sprite
    {
        source_file     "images/waterworks.png"
        source_rect     512 768 32 32
        frame_size      32 32

        animation
        {
            repeat      TRUE
            fps         8
            data        0
        }
    }
}

FALL

FALL means: the brick will collapse and be destroyed upon being stepped on. Example:

// syntax: behavior FALL horizontal-pieces vertical-pieces [orientation]
// whenever the player steps on the brick, it will collapse into (horizontal-pieces x vertical-pieces) parts
type SOLID
behavior FALL 8 2

An optional orientation parameter may be specified:

  • If orientation is non-negative (e.g., orientation = 1), the brick collapses from the right to the left (default)
  • If orientation is negative (e.g., orientation = -1), the brick collapses from the left to the right
The brick collapses

BREAKABLE

BREAKABLE means: the player can destroy the brick by rolling on it. Example:

// syntax: behavior BREAKABLE horizontal-pieces vertical-pieces
// the brick will be broken in 25 pieces (5x5) of equal size
type SOLID
behavior BREAKABLE 5 5
Breakable bricks

Broken in 25 parts

SMASHABLE

SMASHABLE means: a brick that can be smashed when the player jumps on top of it. Similar to BREAKABLE.

Note: the SMASHABLE behavior was added in Open Surge 0.5.0.

// syntax: behavior SMASHABLE horizontal-pieces vertical-pieces
// a smashable brick that will be broken in 2 pieces, horizontally
type SOLID
behavior SMASHABLE 2 1
Smashable brick

FLOAT

FLOAT means: a brick that goes slightly down when the player steps on top of it. An optional modifier parameter may be specified:

  • If no modifier is specified: the floating brick does nothing special
  • If modifier = 1: the floating brick falls down after the player steps on top of it

Note: the FLOAT behavior was added in Open Surge 0.5.0.

// syntax: behavior FLOAT [modifier]
type SOLID
behavior FLOAT
Floating platform

CIRCULAR

CIRCULAR specifies a movable platform that moves along an ellipse.

//
// syntax: behavior CIRCULAR x-dist y-dist x-speed y-speed [initial-phase]
//
// x-dist and y-dist specify how wide/tall is the movement of the brick, in pixels
// x-speed and y-speed specify the cycles per second rate
// (try setting both to 0.25; the larger the value, the faster the brick)
// initial-phase is an optional value in degrees typically set to 0 (default) or 180 (opposite phase)
//

// Example 1: the brick will move horizontally. The trajectory has an amplitude
// of 128 pixels (to left and to right, meaning that it is 256 pixels wide), and
// the brick completes 25% of a cycle in a second (meaning it takes 4 seconds
// to complete a cycle).
type CLOUD
behavior CIRCULAR 128 0 0.25 0 0

// Example 2: the brick will move along a circle of radius 128 pixels,
// at a rate of 0.25 cycles per second
type CLOUD
behavior CIRCULAR 128 128 0.25 0.25 0

// Example 3: a brick like example 2, but in the opposite phase
type CLOUD
behavior CIRCULAR 128 128 0.25 0.25 180
Movable platform

Another example

PENDULAR

PENDULAR specifies a brick that swings like a pendulum.

Note: the PENDULAR behavior was added in Open Surge 0.5.0.

//
// syntax: behavior PENDULAR radius cycles-per-second [initial-phase [angular-offset [amplitude-offset]]]
//
// radius is the distance between the brick (e.g., the weight of the pendulum) and the pivot, in pixels
// cycles-per-second is typically set to 0.25 (meaning it takes 4 seconds to complete one cycle)
// initial-phase is a value in degrees typically set to 0 (default) or 180 (opposite phase)
// angular-offset controls the direction of the swing and is typically set to 0 (default) or 180 degrees
// amplitude-offset controls the amplitude of the swing and may be set to 0 (default), -30, -45, -60, -90...
//

// the following is a standard pendular brick with a radius of 128 pixels
// moving at a rate of 0.25 cycles per second (one cycle takes 4 seconds)
type CLOUD
behavior PENDULAR 128 0.25

// a similar pendular brick, but in the opposite phase
type CLOUD
behavior PENDULAR 128 0.25 180
Pendular brick

Can you see it?

MARKER

A MARKER is a brick that is only rendered in the editor. Used to complement collisions.

Note: the MARKER behavior was added in Open Surge 0.5.0.

// a marker won't be rendered during gameplay
type SOLID
behavior MARKER

angle

The "angle" parameter is deprecated and should no longer be used. It's ignored by current versions of the engine. If, however, you're using a legacy version of Open Surge (0.2.0), then this information still applies. In this case, though, you're strongly encouraged to upgrade.

Previous versions of Open Surge used a parameter called angle. The angle told the system whether the brick was a floor, a wall, a ceiling, or a slope. 0º was usually flat ground, 90º a right wall, 180º a ceiling and 270º a left wall. Anything in between these values were slopes.

Now, how exactly did you calculate the angle? Suppose you have a slope like the one below. To calculate the angle, you used some basic math:

Brickangle2.png

As you can see, the angle was measured from the positive x-axis. A plain floor would have 0 degrees. Simple walls/blocks (on which the player can't run through them, vertically) also would have an angle of 0 degrees. For slopes such as the one displayed on the picture above, function atan2(y,x) would give the angle.

Using automated tools

When it comes to generating the brickset scripts, you can either write them manually or use automated tools to do the job. Although written some years ago, tools such as the Brickset Editor Tool or JBlocks can still be used today. In any case, the recommendation to use a 16x16 grid in your brickset image still applies.

JBlocks
Brickset Editor Tool