graphics¶
This module allows working with “graphic” assets, which are spritesheets converted to the GBA’s pixel format with an accompanying palette and metadata, stored in ROM.
Tutorial¶
To add a new graphic asset to your game:
Export a spritesheet as a vertical strip.
For example, this is a spritesheet for a 32x32 graphic with 8 frames:
Save it to
graphics/dog.png
.Add a line to your project’s
graphics.nims
file:# ... graphic "dog.png", s32x32 # A handle called gfxDog will be created
Import
natu/graphics
in your game and start using the asset:import natu/[video, graphics] # Init # ---- var dog = initObj( pos = vec2i(100, 50), tileId = allocObjTiles(gfxDog), # Allocate tiles for a single frame of animation. palId = acquireObjPal(gfxDog), # Obtain palette. size = gfxDog.size, # Set to correct size. ) # During vblank # ------------- # Copy a frame of animation into VRAM. copyFrame(addr objTileMem[dog.tileId], gfxDog, frame = 0) # Copy the object into OAM. objMem[0] = dog # Clean up # -------- freeObjTiles(obj.tileId) releaseObjPal(gfxDog)
Configuration¶
The graphics.nims
config file is used to add new graphics to your project. This is a nimscript file executed in a local scope in your project’s config.nims
before compiling the game.
The following operations are available:
- proc graphic(name: string, size: ObjSize, bpp = 4, strictPal = false)¶
Specify an image to be added to the graphics list, converted and embedded in the ROM.
If the image is an indexed PNG then the palette will be preserved exactly, except duplicate colours will be removed (use
strictPal=true
to avoid this behaviour). Otherwise, if the image is a true-color PNG then the palette will be derived from the image in the order the colours appear.- Name:
Path to a .png file, relative to the current working directory.
- Size:
Specifies the dimensions that sprites using this graphic should have.
Note
The provided spritesheet must be a vertical strip. i.e. its width equal to the given width, and its height a multiple of the given height.
- Bpp:
The desired bits-per-pixel that the graphic should be converted to.
Possible values are:
2
– The image can have up to 4 colours (including transparent). This may be handy if you’re tight on ROM space, but note that the GBA hardware doesn’t actually support 2bpp graphics. You could useBitUnPack
to load the data into VRAM.4
(default) – The image can have up to 16 colours (including transparent).8
– The image can have up to 256 colors (including transparent).
- StrictPal:
For use with indexed PNGs. Any duplicate colours in the palette will not be reduced into a single index. If the graphic is part of a
sharePal
block, then any colours which already exist in the shared palette at this point must appear in the same order in this image.
This can be used to define a group of graphics which all share the same palette data.
Example:
cd "graphics" sharePal: # These two graphics use the same palette: graphic "dog.png", s32x32 graphic "hamster.png", s16x16 # But this one has its own palette. graphic "cat.png", s32x32
Types¶
- type Graphic = enum¶
Enum type representing spritesheets in ROM.
This type is generated based on the contents of your project’s graphics.nims file. Each image gets a corresponding enum value based on its filename, for example,
dog.png
becomesgfxDog
.For each item, the following read-only properties are available:
- template width(g: Graphic): int¶
The width of the graphic in pixels.
- template height(g: Graphic): int¶
The height of the graphic in pixels.
- template size(g: Graphic): ObjSize¶
The size value for the graphic, as required by hardware sprites.
For example a 16x32 sprite will have a size value of
s16x32
.
- template bpp(g: Graphic): int¶
The number of bits-per-pixel used by the sprite’s gfx data.
This will be either 2, 4 or 8.
- template frameTiles(g: Graphic): int¶
How many 4bpp tiles does a single frame of animation occupy in VRAM? Note, 8bpp graphics take up twice as many tiles.
- template allTiles(g: Graphic): int¶
How many 4bpp tiles does the entire spritesheet occupy in VRAM? Note, 8bpp graphics take up twice as many tiles.
- template numFrames(g: Graphic): int¶
How many frames exist in the sprite sheet?
Tip
Since most Graphic
metadata is known at compile-time and accessed via templates, it’s slightly more efficient to work with constant graphics rather than variables.
For example, this:
const g = gfxDog
acquireObjPal(g)
is preferable to:
var g = gfxDog
acquireObjPal(g)
The latter is of course necessary if you want to change graphics at runtime, or make a general-purpose type which can display any graphic.
Loading Data Directly¶
- template copyPal(dest: var Palette, g: Graphic)¶
Copy palette data from a graphic into some destination, 4bpp version.
- template copyPal(dest: ptr Color | ptr Palette, g: Graphic)¶
Copy palette data from a graphic into some destination (unsafe version, works with 8bpp)
- template copyFrame(dest: ptr Tile4, g: Graphic, frame: int)¶
Copy a single frame of animation to a location in Object VRAM
- template copyAllFrames(dest: ptr Tile4 | ptr Tile8, g: Graphic)¶
Copy all frames of animation to a location in Object VRAM
Utilities¶
- template onscreen(g: Graphic, pos: Vec2i): bool¶
Check if a graphic would be onscreen when drawn at a given location
- func onscreen(r: Rect): bool¶
Check if a rectangle is on-screen
Palette Management¶
- template acquireObjPal(g: Graphic): int¶
Increase the reference count for a graphic’s palette data.
If the count was zero, a slot in Obj PAL RAM will be allocated using
allocObjPal
, and the palette data will be copied into the corresponding slot inobjPalBuf
.Returns which slot in Obj PAL RAM was used, but you don’t have to use the returned value, as you can always check it later with
getPalId
.
- template releaseObjPal(g: Graphic)¶
Decrease the reference count for a graphic’s palette data.
If the count reaches zero, the palette will be freed.
- template getPalId(g: Graphic): int¶
Get the current slot in Obj PAL RAM used by a graphic.
- template loadPal(g: Graphic)¶
Load palette data from a graphic into the correct slot in the Obj PAL RAM buffer.
Obj PAL RAM Allocator¶
These procedures let you allocate & free palettes for sprites.
Note
If you are trying to load a palette from a Graphic
you should use acquireObjPal
and releaseObjPal
instead of these.
- proc allocObjPal(): int¶
Allocate a 4bpp palette in Obj PAL RAM.
- proc freeObjPal(i: int)¶
Deallocate a 4bpp palette in Obj PAL RAM.
Palette Buffers¶
These are targeted by gfx and bg operations such as acquireObjPal
and bg.loadPal
, or you can write directly to them.
Be sure to call flushPals
during VBlank to update the real palettes. Or you can use clrFadeFast
from the video
module to blend in a certain colour while copying.
- template bgPalBuf(): array[numBgPals, Palette]¶
Access the BG PAL RAM buffer as a table of 16-color palettes.
This is useful when working when 4bpp backgrounds.
- template objPalBuf(): array[numObjPals, Palette]¶
Access the OBJ PAL RAM buffer as a table of 16-color palettes.
This is useful when working when 4bpp sprites.
- template bgColorBuf(): array[numBgColors, Color]¶
Access the BG PAL RAM buffer as a single array of colors.
This is useful when working with 8bpp backgrounds, or display mode 4.
- template objColorBuf(): array[numObjColors, Color]¶
Access the OBJ PAL RAM buffer as a single array of colors.
This is useful when working with 8bpp sprites.
- proc flushPals()¶
Copy the palette buffers into PAL RAM.
This should be called every frame during VBlank.
Tile Management¶
- template allocObjTiles(g: Graphic): int¶
Allocate tiles for 1 frame of animation with the ideal snap amount
- proc allocObjTiles(tiles: range[1..1024], snap: range[0..9] = 0): int¶
Allocate some tiles in Obj VRAM
Parameters:
- tiles
- How many 4bpp tiles to allocate.If you want 8bpp tiles, you have to ask for twice as many.
- snap
Quantise the allocation to the nearest
2^snap
tiles.
- proc freeObjTiles(tileId: int)¶
Free tiles from Obj VRAM