2D games are commonly built by many images that are presented as is (for backgrounds or sprites), used in flip-book animation (for sprites), combined and rigged to create Spine animation (for sprites) or mapped out into tilemaps and used for levels or backgrounds.
For performance reasons, images are often combined into one or a few larger images, but the small original image can still be referenced as a sub-image on the larger one. Combining smaller images into larger is especially important on mobile devices where memory and processing power is more scarce than on desktop machines or dedicated game consoles.
In Defold, there are two types of asset that represent such a larger image:
Defold needs all assets that should be in your project hierarchy. Therefore you should start by importing the image files you want to build your graphics from. To import image assets, simply drag the files from the file system on your computer and drop them in an appropriate place in the Defold editor Project Explorer.
Currently, Defold supports the PNG and JPEG image formats.
You need to populate an Atlas before you can use it. As soon as you have added images and/or animations to the Atlas, it can be used as a graphics source for object components like Sprites and ParticleFX components.
A dialog opens from which you can find and select the images you want to add to the Atlas. Note that you can filter the image files and select multiple files at once.
You can define flip-book animations of selected sub-images in an atlas:
You can reorder the images in the Outline by dragging them, if needed. You can also easily create duplicates by copying and pasting (From the Edit menu, the right click context menu or keyboard shortcuts) images in the outline. Select an animation and press Space on your keyboard to preview the animation.
To create a Tile Source you need an image containing all the tiles. All tiles must have the exact same dimensions and be placed in a grid. Defold supports spacing between the tiles and padding around each tile. Defold can also automatically extrude borders which is sometimes neccessary to avoid visual artifacts.
Once you have the source image created, you can create a Tile Source:
If you use linear filtering (see below) and a Tile Source where each tile lies immediately next to each other (i.e. has no borders), there is a risk that you will experience a visual artifact called edge bleeding: if a neighboring tile has colored pixels on its edge, their color might bleed over at the edges. The easiest way to fix this problem is to set the Extrude Border property (which can be found on Atlases and Tile Sources). The value specifies how many times the edge pixels should be automatically replicated in the final texture used in when the game is run.
A good measure is to specify a number that corresponds to how much you scale the textures when viewed in game. If you display the game world at half scale (you can see 2 times as much) then set Extrude Borders to 2. When the texture is used scaled down to half the size, a mipmap is used for rendering. That mipmap is half the width and height of the original image.
Collision shapes that enable physics interaction with Tile Maps can be automatically generated. Defold uses the alpha channel from the image specified in the Collision property to generate a convex shape for each tile. Often it is sensible to use the same image for collision as the one containing the actual graphics, but you are free to specify a separate image if you want collision shapes that differ from the visuals. When you specify a collision image, the preview is updated with an outline on each tile indicating the generated collision shapes. See the Physics documentation for more details.
To define an animation in a Tile Source each frame must correspond to one tile (be on a grid of a certain width and height). Each frame tile must lie next to each other in a sequence left to right. The sequence can wrap from one row to the next. All newly created Tile Sources have a default animation named “anim”. Selecting it displays the animation Properties that allow you to set a descriptive name, start and end frame, playback method, playback speed, and whether the animation should be visually flipped horizontally or vertically.
You can easily add more animations to the Tile Source by selecting Add Animation in the context menu that can be accessed by right clicking the root Tile Source in the Outline view.
When you add visual components (Sprites, ParticleFX, etc) to a game object, you are able to set the position and rotation of the component. These values are used as offsets against the position and rotation of the game object. What’s more, the values are set in the component when you assemble the game object.
Defold game objects can be moved, rotated, and have any of their properties animated. Components belonging to a manipulated game object undergo the same manipulations as the game object, but will keep their relative position and rotation as set in the game object. Components can be turned on and off, but it’s not possible to animate, move, or rotate them dynamically (with an exception described below). Therefore, if you have graphics that you intend to alter you should put the graphics in separate game objects. A group of game objects or a game object hierarchy is conveniently assembled in a Collection. Then you can freely manipulate the objects through script:
-- Animate the wand game object to specified position and rotation. go.animate("wand", "position", go.PLAYBACK_ONCE_FORWARD, vmath.vector3(530, 79, -0.1), go.EASING_INOUTSINE, 0.5) go.animate("wand", "euler", go.PLAYBACK_ONCE_FORWARD, vmath.vector3(0, 0, -70), go.EASING_INOUTSINE, 0.5)
It is actually possible to dynamically alter the scale of Sprite components in a non-uniform way. This is a special feature that may feel odd when you try to construct a mental model for how game objects and components are related to each other and how to work with them.
Sprites have a property
scale which is of type
vmath.vector3. You can animate the components separately:
go.animate("my_object#sprite", "scale.x", go.PLAYBACK_ONCE_FORWARD, 1.5, go.EASING_INOUTSINE, 2)
Sprite components are used to add graphics and flip-book animations to game objects. They are typically used to create characters and props. Creating a Sprite component is very straightforward:
The default animation is played when the game object is created in the running game. Note that if you use an Atlas as the image resource you will see still images as well as animations in the Default Animation drop down menu. If you want to create a Sprite with a still image out of a Tile Source, you can create a 1 frame animation and set its Playback property to “None”.
Sprites do not yet support Collision Shapes generated in Tile Sources. Instead, you add Collision Objects with Collision Shapes like you would for any game object. See the Physics documentation for details.
The Blend Mode property defines how the sprite should be blended with the graphics behind it. These are the available blend modes and how they are calculated:
The default sprite shading files are located under /builtins/material/sprite.* in your project. The default shading performs a regular texture lookup, but also has a tint (a fragment shader constant) which is multiplied with the texture color.
To obtain effects like flashing a sprite white when it is hit, you can implement custom shading. To set a custom shading for your sprites, follow these steps:
A Tile Map is a component that allows you to assemble, or paint, tiles from a Tile Source onto a large grid area. Tile Maps are commonly used to build game level environments. You can also use the Collision Shapes from the Tile Source in your maps for collision detection and physics simulation.
You can also pick tiles directly from the Tile Map to use as a brush. Hold Shift and click a tile to pick it up as the current brush. While holding Shift you can also click and drag to select a block of tiles to use as a larger brush.
The Eraser tool is used to erase painted tiles. To select the Eraser, you can either:
You can attach physics to the Tile Map to do collision detection or physics simulations involving tiles. To attach physics to a Tile Map, see the Physics documentation for details.
You can change the content of a Tile Map dynamically while your game is running. To do so, call the
-- Replace the two door-tiles with "open door" tiles. -- The door is two tiles, one on top of the other. local x = 3 local y = 4 -- Lower part of door tilemap.set_tile("/level#tilemap", "layer1", x, y, 58) -- Upper part of door tilemap.set_tile("/level#tilemap", "layer1", x, y+1, 46)
To add a Tile map to your game:
The game object now contains the Tile Map and you can place or spawn the game object wherever you want it.
Defold supports two different ways to do texture sampling. The method governs the visual result in cases when a texel (a pixel in a texture) is not perfectly aligned with a screen pixel. This happens when you move a Sprite containing the texture seamlessly (say 0.2 pixels in any direction), if your camera is moving seamlessly or if your camera zooms in or out:
The setting for which filtering to use is stored in the Project Settings file. There are two settings:
Both settings accept the values
nearest. For example:
[graphics] default_texture_min_filter = nearest default_texture_mag_filter = nearest
If you don’t specify anything, both are set to
linear by default.
(Some of the graphic assets used are made by Kenney: http://kenney.nl/assets)