Playdate Mode7 is a library designed to recreate the graphics mode known as "Mode 7".
Locate the pre-compiled binaries for your platform in the platforms/[platform] folder and copy the files (elf, dylib, dll) into the Source folder of the project.
Then import the Lua library:
import "mode7"
World is the root object of the library, it manages displays and sprites.
Creates a new world with the given configuration. By default, a world has a main display and a main camera.
Returns a new default configuration for the world.
Returns the world size.
Returned values are width and height of the 2D plane, depth is the third dimension.
Returns the main display managed by the world.
By default, the main display has a camera already set.
Sets a bitmap for the plane.
The bitmap is a grayscale image loaded with bitmap.loadPGM(path).
Returns the plane bitmap.
Sets the plane color to be used for the out-of-bounds space.
Create the color with mode7.color.grayscale.new(gray, alpha)
Returns the plane color to be used for the out-of-bounds space.
Converts a world point to a display point. The z component of the returned value is 1 if the point is in front of the camera or -1 if the point is behind the camera.
Converts a display point to a plane point. The z component of the returned value is 0 if the display point is on the plane, -1 if the display point is not on the plane.
Returns a multiplier that can be used to convert a length on a scanline, from the world coordinate system to the display coordinate system. This function is used to calculate the size of a sprite on display.
The z component of the multiplier is 1 if the point is in front of the camera or -1 if the point is behind the camera.
-- Calculate the width of a sprite on display widthOnDisplay = spriteWidth * multiplierX
Returns a bitmap point from a plane point. If the world scale is 1, the two points are equal.
The returned values are not rounded.
Returns a bitmap point from a plane point. If the world scale is 1, the two points are equal.
Adds the display to the world. It returns true if the display is added successfully, false if the maximum number of displays is reached or the display is already linked to a world.
Adds the sprite to the world.
Updates the world state before drawing. This function calculates the visible sprites and their rects on screen.
Draws the contents of the world for the given display.
Returns a mode7.array (not a Lua array) of all sprites added to the world.
Returns a mode7.array (not a Lua array) of all visible sprite instances for the display.
You should call it after world:update.
The configuration used to initialize the world.
{ width=1024, height=1024, depth=1024, gridCellSize=256 }
A Display draws the contents of a world on screen. You can add up to 4 displays to a world to get split screen or add a rear view camera in a racing game.
Creates a new display with the given rect.
Sets the rect of the display.
The x and width values must be multiple of 8.
Gets the rect of the display.
Sets the display orientation, default value is "landscape left".
You should set the display rect relative to the orientation. E.g. for a portrait display, the rect is x = 0, y = 0, width = 240, height = 400.
Functions such as world:worldToDisplayPoint return display coordinates relative to the orientation as well.
You can use display:convertPointFromOrientation to convert a point from the orientation coordinate system.
mode7.display.kOrientationLandscapeLeft mode7.display.kOrientationLandscapeRight mode7.display.kOrientationPortrait mode7.display.kOrientationPortraitUpsideDown
Gets the display orientation.
Sets the camera to the display.
Gets the camera of the display.
Sets the scale factor for the plane. It changes the plane resolution similarly to playdate.display.setScale(scale). You can change it to improve performance, default value is 2x2.
mode7.display.kScale1x1 mode7.display.kScale2x1 mode7.display.kScale2x2 mode7.display.kScale4x1 mode7.display.kScale4x2
Gets the scale factor for the plane.
Returns the background interface associated to the display.
Returns the y position of the horizon, relative to the current display.
It converts a point from the orientation coordinate system, to the standard coordinate system. For a portrait orientation, the portrait point (0, 0) is converted to the standard point (400, 0).
It converts a point from the standard coordinate system, to the orientation coordinate system. For a portrait orientation, the standard point (0, 0) is converted to the portrait point (0, 400).
Returns the world associated to the display.
Background is an interface that manages the world background.
Returns the background interface associated to the display.
Sets the background bitmap. You should use mode7.image.new(filename) to load it, you can't directly pass a Playdate image.
Gets the background bitmap.
Gets the background offset.
Returned values are rounded according to the rounding increment.
Sets the rounding increment for the background. This value is used for rounding the position to the nearest integer. Default value is 1.
A value of 2 is usually good to prevent screen flashing.
Gets the rounding increment for the background.
Sets the background center (0.0 - 1.0). Default value is (0.5, 0.5) so that the background is centered when the camera angle is 0.
Bitmap is a grayscale image.
Loads a PGM file at the given path, it returns NULL if the file can't be opened.
PGM is a grayscale image format, you can encode it with ImageMagick (recommended):
magick input.png -fx '(r+g+b)/3' -colorspace gray output.pgm
Bitmap data is stored in the pool.
Gets the bitmap size.
Gets the color value at the given position.
Sets a mask for the bitmap (transparent pixels are black). The mask size must be equal to the bitmap size.
You can create a mask with ImageMagick:
magick input.png -alpha extract mask.pgm
Mask is not supported for the plane bitmap.
Gets the bitmap mask.
Adds a layer to the bitmap.
Returns a mode7.array (not a Lua array) of all layers added to the bitmap.
A layer for drawing on top of a bitmap.
Please note that layers can't overlap each other. Also, a bitmap doesn't support hierarchical layers.
Creates a new layer with the given bitmap.
Sets a bitmap for the layer.
Consider setting a bitmap with the same size as the current bitmap to reduce memory allocations.
Gets the bitmap of the layer.
Sets the left-top position of the layer.
Gets the layer position.
Sets the layer visibility.
Gets the layer visibility.
Invalidates the layer forcing a redraw. This function is needed only for special cases, such as setting a new mask for the bitmap.
The Pool allows to store data in pre-allocated memory.
A Camera is a point of view with its own position and rotation.
Sets the camera position.
Gets the camera position.
Sets the camera yaw angle.
Gets the camera yaw angle.
Sets the camera pitch angle.
Gets the camera pitch angle.
Sets the camera FOV angle.
Gets the camera FOV angle.
Sets the camera clip distance (distance within sprites are visible) expressed as units of the grid. A value of 1 will mark the sorrounding cells by a movement of 1 unit in all directions.
Gets the camera clip distance units.
A Sprite is a 2D scalable image that represents a 3D entity in the world.
Creates a new sprite with the given size. Width and height are 2D values on the plane, depth is the third dimension.
Gets the sprite instance for the given display.
Sets the sprite center at the given position.
Gets the sprite position.
Sets the sprite size.
Gets the sprite size.
Sets the sprite yaw angle.
Gets the sprite yaw angle.
Sets the sprite pitch angle.
Gets the sprite pitch angle.
Sets the sprite frame index (all instances).
See also sprite.instance:setFrame
Sets the sprite visibility for all the instances.
See also sprite.instance:setVisible
Sets the image center for all the instances.
See also sprite.instance:setImageCenter
Sets the sprite rounding increment for all the instances.
See also sprite.instance:setRoundingIncrement
Sets the sprite alignment for all the instances.
See also sprite.instance:setAlignment
Sets the sprite image table for all the instances.
See also sprite.instance:setImageTable
Sets the billboard size behavior for all the instances.
Sets the billboard size for all the instances.
See also sprite.instance:setBillboardSize
Sets a custom draw function for all the instances.
See also sprite.instance:setDrawFunctionName
Gets the sprite data source interface.
Sets the maximum width for the data source (all instances).
Sets the minimum width for the data source (all instances).
Sets the length for the given data source key (all instances).
Sets the layout for the data source (all instances).
See also sprite.instance.datasource:setLayout
Returns the world associated to the sprite.
A Sprite Instance allows to configure a sprite for a specific display.
Gets the sprite instance for the given display.
Returns the sprite associated to the instance.
Sets the visibility for the instance.
Gets the visibility for the instance.
Sets the sprite frame index for the instance. If you want to animate your sprite, use this property to set the animation frame (starting from 0).
Animation length must be set in the data source by calling sprite.instance.datasource:setLengthForKey with the mode7.sprite.datasource.kFrame key.
Gets the sprite frame index for the instance.
Sets the image center (0.0 - 1.0) for the instance. Use this property to adjust the sprite position on screen, default value is (0.5, 0.5).
Gets the image center for the instance.
Sets the sprite rounding increment for the instance. This value is used for rounding the position on screen to the nearest integer. Default value is 1.
Gets the sprite rounding increment for the instance.
Sets the sprite alignment for the instance. It aligns the sprite position on screen to even or odd values.
mode7.sprite.kAlignmentNone mode7.sprite.kAlignmentEven mode7.sprite.kAlignmentOdd
Gets the sprite alignment for the instance.
Sets the image table for the instance. You should use mode7.imagetable.new to load it, you can't directly pass a Playdate image table.
You can set this property at any time (e.g. changing a character's image from idle to run). You can pass nil if you want to use a custom draw function sprite.instance:setDrawFunctionName
Gets the image table for the instance.
Sets a custom draw function for the instance, you should pass the function name as a string (passing a table path with dots is not recommended).
To draw the sprite, call the provided callback drawSprite with instance as the first parameter.
function drawFunction(instance, x, y, w, h, drawSprite) drawSprite(instance) end instance:setDrawFunctionName("drawFunction")
Sets the behavior for determining the billboard size.
When the behavior is set to automatic, the billboard width is determined by the longer side of the sprite.
When the behavior is set to custom, the billboard width is determined by the custom width.
Typically, only the billboard width is used to calculate the sprite rect on screen. The billboard height serves as a fallback value when the image is unavailable.
mode7.sprite.kBillboardSizeAutomatic mode7.sprite.kBillboardSizeCustom
Sets a custom size for the billboard. The size is expressed in the world coordinate system. In order to use this property, set the behavior to custom.
Gets the billboard size behavior.
Gets the billboard custom size.
It returns the visible image for the instance.
The property is up-to-date for visible instances only. Ensure the instance is visible and call it after world:update
It returns the display rect for the instance.
The property is up-to-date for visible instances only. Ensure the instance is visible and call it after world:update
It returns true if the instance is visible on the associated display.
The property is up-to-date for visible instances only. Ensure the instance is visible and call it after world:update
The Sprite Data Source is an interface that describes how to retrieve an image from the image table.
Returns the data source of the instance.
Sets the maximum width for the data source. This is the maximum width supported by the image table.
Pass 0 if you don't want to define a maximum width (sprite will always be drawn).
Gets the maximum width for the data source.
Sets the minimum width for the data source. This is the minimum width supported by the image table.
Gets the minimum width for the data source.
Sets the length for the given data source key. The default length for each key is 1 (length must be greater than 0).
Use this function to specify how many times a sprite is scaled and rotated in the image table.
E.g. For a rotation by 10 degrees, set a length of 36. For a scaling from 100px to 10px, set a length of 10.
mode7.sprite.datasource.kFrame mode7.sprite.datasource.kAngle mode7.sprite.datasource.kPitch mode7.sprite.datasource.kScale
Sets the layout for the data source. It defines the order of the image table, the default value "frame, angle, pitch, scale" implies the following structure:
begin frame-1 begin angle-1 begin pitch-1 save [scale-1, scale-2, scale-3, ...] end pitch-1 begin pitch-2 save [scale-1, scale-2, scale-3, ...] end pitch-2 ... end angle-1 ... end frame-1 ...
A sprite is: rotated clockwise starting from the frontal position (for a character sprite, angle-1 will show the character's face), rotated in the positive pitch direction (for a character sprite, the head will move towards you), scaled from maximum to minimum width.
Notes:
An image is never repeated twice in the table.
Keys with a length of 1 are considered optional. For example, you can have a sprite with a single frame, angle, pitch but multiple scales.
Layout is not valid if you use the same key twice.
Gets the length for the given data source key.
Gets the layout for the data source.
The library includes some primitives.
Loads the image at the given path. Equivalent to playdate.graphics.image.new(path). Returns nil if the image can't be opened.
Returns the underlying Playdate image.
Loads the image table at the given path. Equivalent to playdate.graphics.imagetable.new(path). Returns nil if the image table can't be opened.
Gets the number of items in the array.
Gets the item at the given index, array starts at index 1.
Here are some tips to improve the performance of your game:
Set an appropriate display scale (1x1 is the slowest, while 4x2 is the fastest).
Reduce the bitmap resolution to minimize cache misses.
Change the display scale or bitmap dynamically. When the camera is far from the plane, consider adjusting the display scale or swapping out the plane bitmap with a lower resolution version.
You can use Blender to automatically generate a sprite image table. A Blender project is included in the blender folder of the library.
On macOS you need to launch Blender from the command line:
cd /Applications/Blender.app/Contents/MacOS ./Blender
Install Blender 4.0+
Install ImageMagick
Open the project in Blender and switch to the Scripting tab
Run the script
The image table will be saved in blender/output
You can find a Python script to resize images (e.g. trees) in the tools/resize folder of the library. ImageMagick is required.
The resize.py script allows you to specify an image or a folder as input (-i), a maximum width (-max), a minimum width (-min), a step value (-step). Run "resize.py -h" for more info.
Copy the lua/stub.lua file into your VSCode workspace to support autocomplete and inline documentation.
This file contains placeholder code, you should not place it into the Source folder of the game.