How to create Sprite Sheets and Animations with Solar2D

Andreas Löw, Joachim Grill
GitHub
How to create Sprite Sheets and Animations with Solar2D

Solar2D was formerly known as CoronaSDK

What you are going to learn:

  • Creating image sheets with TexturePacker
  • Using image sheets in Solar2D
  • Creating animations
  • Handle multiple screen resolutions

The complete tutorial project is available on GitHub.

Create image sheets

With TexturePacker you can easily create sprite sheets for Solar2D. In Solar2D they are called Image Sheets.

Download TexturePacker, it is available for macOS, Windows and Linux. You can test it within a 7-day trial period before purchasing a license:

Start TexturePacker and drop the sprites that should be packed in a sprite sheet on TexturePacker's main window. You can also drop folders, TexturePacker will automatically scan them for image files and add them to the sheet.

TexturePacker: Add sprites for packing
TexturePacker: Sprites added for packing

Click on the Framework button located at the top of the right sidebar, then choose Solar2D (Corona SDK) as the data format. With this configuration, TexturePacker will generate a Lua file that contains coordinates and size information for each sprite on the sheet.

TexturePacker: Select Solar2D framework

Use the LUA file field (below the framework button) to specify the location and file name of the Lua data file. You can leave the Texture file name field empty; TexturePacker will automatically save the PNG containing the sprite sheet next to the data file.

Now, click the Publish sprite sheet button in the toolbar. This will save both the sprite sheet image and the .lua file containing the sprite coordinates.

Use image sheets with Solar2D

Getting started

To set up the demo project, start the Corona simulator and click on New project.

Solar2D: Create new project

Create a Blank project, as screen size we use the size of our background image. This virtual content size we're going to use in the code. Solar2D will automatically scale the content to fit the actual screen size of the device.

Display images from sheet

First we have to load the Lua file generated by TexturePacker. If it's located in a subdirectory, use "." as separator instead of "/":

local sheetInfo = require("spritesheets.cityscene")

From the sheetInfo object we can now get all the options that newImageSheet requires in its second parameter:

local myImageSheet = graphics.newImageSheet( "spritesheets/cityscene.png", sheetInfo:getSheet())

In Solar2D, images from image sheets can only be selected by their frame number. The Lua code generated by TexturePacker also contains a function to look up this frame number by name:

local background = display.newImage(myImageSheet, sheetInfo:getFrameIndex("background"))
background.x = display.contentCenterX
background.y = display.contentCenterY

local capguy = display.newImage(myImageSheet, sheetInfo:getFrameIndex("capguy/walk/0001"))
capguy.x = display.contentHeight * .2
capguy.y = display.contentHeight * .8

That's it, reload your code in the simulator to see capguy in front of the cityscene:

Capguy scene

Animated sprites

To create an animated sprite we need an array that contains the frame numbers of all animation frames. TexturePacker 7.1 (and newer) automatically detects sprites which differ only in a sequence number and exports them as animations. You can use the getAnimation() function to get the frame number array:

local framesNumbers = sheetInfo:getAnimation("capguy/walk");

Next, we define one or more sequences. Each sequence has a name that can be used later to activate it. Using this sequence data, we can create a new sprite:

local sequenceData = {
    {
        name="walk",          -- name of the animation (used with setSequence)
        sheet=myImageSheet,   -- the image sheet
        frames=framesNumbers,
        time=1000,            -- speed (milliseconds for the complete sequence)
    },
}
capguy = display.newSprite(myImageSheet, sequenceData)

Once the sprite is created, we can set its position, select the desired sequence, and start the animation:

capguy.x = display.contentHeight * .2
capguy.y = display.contentHeight * .8
capguy:setSequence("walk")
capguy:play()

Take a look on the example code on GitHub, it includes additional code that moves the sprite both from left to right and back again.

Dynamic Image Selection

If you are developing your app for devices with different screen resolutions, it makes sense to offer image sheets in different resolutions as well:

  • On a high-resolution display, you want to use a high resolution image sheet for sharp, crisp sprites.
  • For low-resolution devices, a smaller image sheet is sufficient, preventing unnecessary memory usage and CPU time for downscaling.

TexturePacker and Solar2D make this easy to achieve:

  • TexturePacker's Scaling Variants feature automates the generation of scaled image sheets.
  • Solar2D's Dynamic Image Selection feature automatically chooses the best matching image at runtime.

Generate scaling variants

To generate scaled variants of the sprite sheet, click on the cog icon in TexturePacker's right sidebar. It opens the Scaling variants dialog, where you can apply the Solar2D @4x/@2x preset.

Create scaling variants

This preset defines two scaled variants in addition to the unscaled image sheet:

Scale factorTexture fileData file
1.0sheet@4x.pngsheet@4x.lua
0.5sheet@2x.pngsheet@2x.lua
0.25sheet.pngsheet.lua

Insert the {v} placeholder in the LUA file name to indicate where TexturePacker should insert the variant name, as shown in the screenshot above. Then press Publish to generate and save the new set of output files on disk.

Configure image selection

Solar2D's dynamic image selection is configured in config.lua. The content size is now set to the smallest resolution:

application =
	content =
	{
		width = 320,
		height = 480,
		scale = "letterbox",
		fps = 60,

		imageSuffix =
		{
			    ["@2x"] = 2,
			    ["@4x"] = 4
		}
	}
}

The imageSuffix table configures the image selection. The number assigned to a suffix represents a scale factor. It specifies the scale threshold above which Solar2D will use images with that suffix.

In the provided example, the @2x image sheet is used when the display resolution is at least twice as large as the specified content size. If the display resolution is four times larger, the @4x variant is selected. This means that for resolutions between these thresholds, the smaller image sheet is upscaled - which results in blurry images. To use downscaling instead, adjust the scale thresholds like this:

		imageSuffix =
		{
			    ["@2x"] = 1.01,  -- avoid upscaling of 1x texture
			    ["@4x"] = 2.01   -- avoid upscaling of 2x texture
		}

The example code on GitHub prints the current content scale factor to the console. In the upper right corner of the background image, you can see which scaling variant is displayed. You can test with various screen resolutions using the devices in the Simulator's Window -> View As menu.

Screenshot of demo app