Sprites are any moving object in a videogame that are not a background: a character, enemy, bullet, player, ball, special effect... They can be animated and placed freely anywhere.
Sprites are referenced by an index, starting at 0 up to number of sprites minus 1. The total number of sprites is pre-allocated when the engine is initialized with TLN_Init and cannot be changed later at runtime.
A sprite needs at least a spriteset, a collection of related images packed together inside a single bitmap. It's common to pack together all the animation frames of a single character inside the same spriteset, so to change the displayed graphic it's only needed to change the image index.
Spritesets are loaded with TLN_LoadSpriteset (read more about spritesets). Once loaded, call TLN_SetSpriteSet to attach it to the sprite, passing the sprite index and the reference to the spriteset:
Now the sprite is displayed at position 0,0 by default (top-left corner) with the first graphic inside the spriteset. Each graphic inside a spriteset has a unique index, starting from 0, and an unique name. To change the graphic show, call TLN_SetSpritePicture passing the sprite index and the graphic index inside the spriteset, starting with 0. For example to set sprite 0 with the 4th graphic inside the spriteset:
Sometimes it's convenient to use the graphic name instead of the index, because the latter can be difficult to know. To get the index of a given name, call TLN_FindSpritesetSprite. This will return the graphic index (staring from 0), or -1 if not found:
This searches de index of graphic with name "ship4" inside spriteset, and if found, assigns it to sprite 0.
By default the pivot position of the sprite is located at its top-left corner. This pivot point is the "anchor" that determines the exact location when positioning, and the scaling origin. Depending on gameplay it's more natural to have the pivot on another position. For example in games with pseudo-3D graphics, like 3/4 perspective or 3D roads, it's more natural to have the pivot at the bottom, at the "floor" level.
This can be accomplished with the TLN_SetSpritePivot function, that takes normalized coordinates in the range 0.0 (top/left) and 1.0 (bottom/right).
For example to set sprite 3 pivot to 50% horizontal and full bottom:
To move the sprite to a different location, call the TLN_SetSpritePosition, passing the sprite index, and the x,y coordinates. These values are absolute screen coordinates. For example to move sprite 3 to 160,120:
There are some special modifiers that control sprite flipping, priority and masking. Sprite flipping allows to draw a sprite upside down and/or horizontally mirrored. For example a platformer game just needs to have sprites drawn facing to the right, when character need to walk to the left, just set the horizontal flipping flag.
Priority will draw the sprite in front of priority layers, instead of behind them. To set attributes, call TLN_EnableSpriteFlag passing the sprite index and a combination of TLN_TileFlags. For example to draw sprite 0 upside down:
Flipping modes: a) 0, b) FLAG_FLIPX, c) FLAG_FLIPY, d) FLAG_FLIPX + FLAG_FLIPY:
Masking will mark the sprite as affected by mask region if flagged with FLAG_MASKED. Read "sprite masking" section below to know more about masking.
By default, a sprite is assigned the associated palette of its spriteset, but this can be changed calling TLN_SetSpritePalette passing the sprite index and a TLN_Palette reference:
Blending is supported in sprites, with different modes and effects. To get extended information about the modes and their effects, please refer to Blending section.
To enable blending, call TLN_SetSpriteBlendMode passing the sprite index and the blending mode. For example, to set 50%/50% blending in sprite 0:
The last parameter, factor, is kept for compatibility but isn't used.
To disable blending, call the same function with blending mode set to BLEND_NONE :
Sprites can be drawn upscaled or downscaled with an arbitrary factor. To enable scaling, call TLN_SetSpriteScaling passing the sprite index and two floating point values with the horizontal and vertical factor, respectively. Values greater than 1.0 upscale, and smaller than 1.0 downscale. For example to set an horizontal downscaling of 0.5 and vertical upscaling of 1.5 for layer 0:
Different sprite scaling examples:
To disable scaling, call TLN_ResetSpriteScaling passing the sprite index. For example to disable scaling in sprite 0:
A basic action on any game is checking if two given sprites collide. For example, if our hero is hit by any enemy bullet. A quick way to determine a collision is to check if their bounding boxes overlap (a bounding box is the rectangular area that fully encloses a sprite). This method is fast and easy to implement, but sometimes the bounding boxes of two sprites can overlap, but in regions where there aren't solid pixels, just transparent ones. In this case, you see that the bullet isn't going to hit your hero, but it gets actually hit without touching it. A common solution is to use bounding boxes that are smaller than the sprite, but this can have the opposite effect: missing collisions that actually happen.
To solve this, Tilengine implements pixel-based collision detection. With this feature enabled, you know that a sprite gets involved in a collision only if there are actual non-transparent pixels in both sprites overlapping. But this method also has a limitation: it can tell you that a given sprite is per-pixel colliding with another sprite, but you don't know with which sprite.
The final solution consists in combining both methods as they compliment each other: first determine coarse collision with bounding boxes, and then check per-pixel collision detection in those sprites.
Per-pixel collision detection requires more CPU cycles that regular sprites, so it's an optional feature that is disabled by default. You can enable it for each sprite calling TLN_EnableSpriteCollision passing the sprite index and a boolean value with true to enable or false to disable the feature. For example, to enable collision detection for sprite 0 and disable it for sprite 3:
To query the collision status for a given sprite, call TLN_GetSpriteCollision passing the sprite index to check. It returns a boolean value indicating the collision status:
By default, each sprite activated is added to the end of a list of sprites that are drawn from first to last, following painter's algorithm. That means dat sprites added later will overlap the ones added first. For example if sprites 0, 1, 2, 3 are added in sequence:
Sprite 0 will be drawn first, sprite 3 will be drawn last, overlapping the others.
This order can be changed with TLN_SetFirstSprite and TLN_SetNextSprite functions.
To set the first sprite in the list, call TLN_SetFirstSprite passing the index of first sprite. In the above example, to set 2 at the beginning:
The list becomes:
To change any other sprite, call TLN_SetNextSprite, passing the current sprite, and which one goes next. Taking the previous list, to move sprite 0 from its position to be drawn after sprite 3:
The list becomes:
Now sprite 0 overlaps sprite 3
Sprite masking allows defining a rectangular region that spans the whole frame width, where selected sprites won't be drawn when they cross this region.
To define the masking area, call TLN_SetSpritesMaskRegion, passing the bottom and top scanlines that define the exclusion area. For example to create a masking area that goes from y = 120 to y = 160, call:
To disable masking region, pass 0, 0:
Only sprites flagged with TLN_MASKED flag will disappear inside the mask region. Use TLN_EnableSpriteFlag to enable or disable FLAG_MASKED flag.
Although it is possible to animate a sprite manually using the TLN_SetSpritePicture function at timed intervals, tilengine has built-in animation support. To animate a sprite it is necessary to have a TLN_Sequence object describing the animation. See the chapter Sequences to see how to create a TLN_Sequence object from a TLN_Spriteset object.
For example, assuming a spriteset called spriteset
, containing frames numbered sequentially from walk1
to walk8
, you can create the sequence with these frames, with a cadence of 6 fps at 60 Hz:
Once created, set the animation to the sprite with TLN_SetSpriteAnimation, indicating the index of the sprite, the TLN_Sequence object, and the number of times the animation should loop, indicating 0 for it to repeat indefinitely. For example, to animate sprite 0 with the walk_sequence
previously created and to be repeated continuously:
NOTE: the sprite must have been previously assigned with the same spriteset used to create the sequence.
To finish playing an ongoing animation, call TLN_DisableSpriteAnimation passing the index of the sprite to stop animation:
To disable a sprite so it is not rendered, just call TLN_DisableSprite passing the sprite index:
This is a quick reference of related functions in this chapter:
Function | Quick description |
---|---|
TLN_SetSpriteSet | Assigns the spriteset and its palette to a given sprite |
TLN_EnableSpriteFlag | Sets flags for a given sprite |
TLN_SetSpritePosition | Sets the sprite position inside the viewport |
TLN_SetSpritePivot | Sets the pivot of the sprite |
TLN_SetSpritePicture | Sets the actual graphic to the sprite |
TLN_SetSpritePalette | Assigns a palette to a sprite |
TLN_SetSpriteBlendMode | Sets the blending mode (transparency effect) |
TLN_SetSpriteScaling | Sets the scaling factor of the sprite |
TLN_ResetSpriteScaling | Disables scaling for a given sprite |
TLN_GetSpritePicture | Returns the index of the assigned picture from the spriteset |
TLN_GetAvailableSprite | Returns the first available (unused) sprite |
TLN_EnableSpriteCollision | Enable sprite collision checking at pixel level |
TLN_GetSpriteCollision | Gets the collision status of a given sprite |
TLN_SetSpritesMaskRegion | Defines masking region to hide FLAG_MASKED sprites |
TLN_SetSpriteAnimation | Starts a sprite animation |
TLN_DisableSpriteAnimation | Disables animation of sprite |
TLN_GetSpritePalette | Returns the current palette of a sprite |
TLN_DisableSprite | Disables the sprite so it is not drawn |
Last update on Tue Aug 29 2023 for Tilengine 2.15.1