2026-07-24 10:33:45 +02:00
|
|
|
|
internal import CPlaydate
|
|
|
|
|
|
|
2026-09-18 13:15:08 +00:00
|
|
|
|
/// `playdate->graphics->tilemap`.
|
2026-07-25 10:43:32 +02:00
|
|
|
|
private var tilemapAPI: UnsafePointer<playdate_tilemap> { Playdate.tilemapAPI.unsafelyUnwrapped }
|
2026-07-24 10:33:45 +02:00
|
|
|
|
|
2026-07-24 11:10:25 +02:00
|
|
|
|
extension Graphics {
|
2026-07-24 10:33:45 +02:00
|
|
|
|
/// A grid of tiles drawn from a bitmap table. Wraps `LCDTileMap`.
|
|
|
|
|
|
public final class TileMap {
|
|
|
|
|
|
let pointer: OpaquePointer
|
2026-09-18 13:15:08 +00:00
|
|
|
|
/// The C tilemap holds only a raw pointer to its table.
|
2026-07-24 10:33:45 +02:00
|
|
|
|
private var retainedImageTable: BitmapTable?
|
|
|
|
|
|
|
|
|
|
|
|
public init() {
|
2026-07-25 07:23:19 +02:00
|
|
|
|
pointer = tilemapAPI.pointee.newTilemap.unsafelyUnwrapped().unsafelyUnwrapped
|
2026-07-24 10:33:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
deinit {
|
2026-07-25 07:23:19 +02:00
|
|
|
|
tilemapAPI.pointee.freeTilemap.unsafelyUnwrapped(pointer)
|
2026-07-24 10:33:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-18 13:15:08 +00:00
|
|
|
|
/// Retained while set.
|
2026-07-24 10:33:45 +02:00
|
|
|
|
public var imageTable: BitmapTable? {
|
|
|
|
|
|
get { retainedImageTable }
|
|
|
|
|
|
set {
|
|
|
|
|
|
retainedImageTable = newValue
|
2026-07-25 07:23:19 +02:00
|
|
|
|
tilemapAPI.pointee.setImageTable.unsafelyUnwrapped(pointer, newValue?.pointer)
|
2026-07-24 10:33:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public func setSize(tilesWide: Int, tilesHigh: Int) {
|
2026-07-25 07:23:19 +02:00
|
|
|
|
tilemapAPI.pointee.setSize.unsafelyUnwrapped(pointer, Int32(tilesWide), Int32(tilesHigh))
|
2026-07-24 10:33:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public var size: (tilesWide: Int, tilesHigh: Int) {
|
|
|
|
|
|
var wide: Int32 = 0, high: Int32 = 0
|
2026-07-25 07:23:19 +02:00
|
|
|
|
tilemapAPI.pointee.getSize.unsafelyUnwrapped(pointer, &wide, &high)
|
2026-07-24 10:33:45 +02:00
|
|
|
|
return (Int(wide), Int(high))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-18 13:15:08 +00:00
|
|
|
|
/// Tile image size times tile counts.
|
2026-07-24 10:33:45 +02:00
|
|
|
|
public var pixelSize: (width: Int, height: Int) {
|
|
|
|
|
|
var width: UInt32 = 0, height: UInt32 = 0
|
2026-07-25 07:23:19 +02:00
|
|
|
|
tilemapAPI.pointee.getPixelSize.unsafelyUnwrapped(pointer, &width, &height)
|
2026-07-24 10:33:45 +02:00
|
|
|
|
return (Int(width), Int(height))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-18 13:15:08 +00:00
|
|
|
|
/// Sets all tiles row by row, resizing to `rowWidth` × `indexes.count / rowWidth`.
|
|
|
|
|
|
/// `indexes.count` must be a multiple of `rowWidth`.
|
|
|
|
|
|
public func setTiles(_ indexes: Span<UInt16>, rowWidth: Int) {
|
|
|
|
|
|
indexes.withUnsafeBufferPointer { buffer in
|
|
|
|
|
|
// Non-const in C, but only read (and copied).
|
|
|
|
|
|
tilemapAPI.pointee.setTiles.unsafelyUnwrapped(
|
|
|
|
|
|
pointer, UnsafeMutablePointer(mutating: buffer.baseAddress),
|
|
|
|
|
|
Int32(buffer.count), Int32(rowWidth))
|
2026-07-24 10:33:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-18 13:15:08 +00:00
|
|
|
|
/// Sets all tiles row by row, resizing to `rowWidth` × `indexes.count / rowWidth`.
|
|
|
|
|
|
/// `indexes.count` must be a multiple of `rowWidth`.
|
|
|
|
|
|
public func setTiles(_ indexes: [UInt16], rowWidth: Int) {
|
|
|
|
|
|
indexes.withUnsafeBufferPointer { setTiles($0.span, rowWidth: rowWidth) }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// `x` is the column, `y` the row, `index` an image table index.
|
2026-07-24 10:33:45 +02:00
|
|
|
|
public func setTile(x: Int, y: Int, index: UInt16) {
|
2026-07-25 07:23:19 +02:00
|
|
|
|
tilemapAPI.pointee.setTileAtPosition.unsafelyUnwrapped(pointer, Int32(x), Int32(y), index)
|
2026-07-24 10:33:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-18 13:15:08 +00:00
|
|
|
|
/// The image table index at column `x`, row `y`; `nil` if out of bounds.
|
2026-07-24 10:33:45 +02:00
|
|
|
|
public func tile(x: Int, y: Int) -> Int? {
|
2026-07-25 07:23:19 +02:00
|
|
|
|
let index = tilemapAPI.pointee.getTileAtPosition.unsafelyUnwrapped(pointer, Int32(x), Int32(y))
|
2026-07-24 10:33:45 +02:00
|
|
|
|
return index < 0 ? nil : Int(index)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-18 13:15:08 +00:00
|
|
|
|
/// (x, y) is the upper-left corner, in pixels.
|
2026-07-24 10:33:45 +02:00
|
|
|
|
public func draw(x: Float, y: Float) {
|
2026-07-25 07:23:19 +02:00
|
|
|
|
tilemapAPI.pointee.drawAtPoint.unsafelyUnwrapped(pointer, x, y)
|
2026-07-24 10:33:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|