Haskell

  • Template: cart_haskell - press "Use this template" and you have a working game.
  • Docker image: ghcr.io/notnullgames/null0-cart-haskell:latest
  • Your code: cart/Main.hs, compiled with wasm32-wasi-ghc (reactor mode)
  • Bindings: carts/haskell/Null0.hs (baked into the docker image for you)
  • WASI is available, so ordinary file and stdio calls work.

building

You do not install wasm32-wasi-ghc (reactor mode) - the docker image has it, and the current null0 bindings, baked in. That is the whole point: there is nothing in your project to keep in sync with the engine.

docker run --rm --user $(id -u):$(id -g) \
  -v ./cart:/src -v ./webroot:/out \
  ghcr.io/notnullgames/null0-cart-haskell:latest mygame

The template wraps that in npm start, which also serves the result and rebuilds when you save.

Haskell notes

  • Everything is in IO. Each null0 call is imported through a generated C trampoline.
  • Carts get no environment variables, so anything reading $PWD sees nothing.

a cart, in Haskell

This is carts/haskell/simple/Main.hs in the engine repo - the same file CI builds into the cart below, so it always compiles.

{-# LANGUAGE ForeignFunctionInterface #-}
module Main where

import Null0

-- required by GHC's module conventions, but never called: -no-hs-main
-- means the linker drops the usual RTS-wrapped main, and null0 only calls
-- the foreign-exported functions below
main :: IO ()
main = return ()

foreign export ccall "load" load :: IO ()

load :: IO ()
load = do
  clear blue
  drawCircle 100 100 50 red

-- callbacks (optional - implement, and foreign export, as needed)

-- foreign export ccall "update" update :: IO ()
-- update :: IO ()
-- update = return ()

-- foreign export ccall "unload" unload :: IO ()
-- unload :: IO ()
-- unload = return ()

-- foreign export ccall "buttonUp" buttonUp :: Int32 -> Word32 -> IO ()
-- buttonUp :: Int32 -> Word32 -> IO ()
-- buttonUp button player = return ()

-- foreign export ccall "buttonDown" buttonDown :: Int32 -> Word32 -> IO ()
-- buttonDown :: Int32 -> Word32 -> IO ()
-- buttonDown button player = return ()

-- foreign export ccall "keyUp" keyUp :: Int32 -> IO ()
-- keyUp :: Int32 -> IO ()
-- keyUp key = return ()

-- foreign export ccall "keyDown" keyDown :: Int32 -> IO ()
-- keyDown :: Int32 -> IO ()
-- keyDown key = return ()

-- foreign export ccall "mouseDown" mouseDown :: Int32 -> IO ()
-- mouseDown :: Int32 -> IO ()
-- mouseDown button = return ()

-- foreign export ccall "mouseUp" mouseUp :: Int32 -> IO ()
-- mouseUp :: Int32 -> IO ()
-- mouseUp button = return ()

-- foreign export ccall "mouseMoved" mouseMoved :: CFloat -> CFloat -> IO ()
-- mouseMoved :: CFloat -> CFloat -> IO ()
-- mouseMoved x y = return ()
carts/haskell/simple/Main.hs

callbacks

A cart implements the callbacks it cares about. In Haskell they look like this:

foreign export ccall update :: IO ()

See anatomy of a cart for the full list and what each one is passed.

more Haskell carts

the API, in Haskell

Every null0 function, spelled the way Haskell spells it. These are read out of the generated bindings themselves, so they match what your editor completes.

colors (7)

Tint a color with another color.

colorTint :: Color -> Color -> IO Color

Fade a color.

colorFade :: Color -> CFloat -> IO Color

Change the brightness of a color.

colorBrightness :: Color -> CFloat -> IO Color

Invert a color.

colorInvert :: Color -> IO Color

Blend 2 colors together.

colorAlphaBlend :: Color -> Color -> IO Color

Change contrast of a color.

colorContrast :: Color -> CFloat -> IO Color

Interpolate colors.

colorBilinearInterpolate :: Color -> Color -> Color -> Color -> CFloat -> CFloat -> IO Color
graphics (75)

Create a new blank image.

newImage :: Int32 -> Int32 -> Color -> IO Word32

Copy an image to a new image.

imageCopy :: Word32 -> IO Word32

Create an image from a region of another image.

imageSubimage :: Word32 -> Int32 -> Int32 -> Int32 -> Int32 -> IO Word32

Clear the screen.

clear :: Color -> IO ()

Draw a single pixel on the screen.

drawPoint :: Int32 -> Int32 -> Color -> IO ()

Draw a line on the screen.

drawLine :: Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a filled rectangle on the screen.

drawRectangle :: Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a filled triangle on the screen.

drawTriangle :: Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a filled ellipse on the screen.

drawEllipse :: Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a filled circle on the screen.

drawCircle :: Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a filled polygon on the screen.

drawPolygon :: [Vector] -> Color -> IO ()

Draw a filled arc on the screen.

drawArc :: Int32 -> Int32 -> CFloat -> CFloat -> CFloat -> Int32 -> Color -> IO ()

Draw a filled round-rectangle on the screen.

drawRectangleRounded :: Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw an image on the screen.

drawImage :: Word32 -> Int32 -> Int32 -> IO ()

Draw a tinted image on the screen.

drawImageTint :: Word32 -> Int32 -> Int32 -> Color -> IO ()

Draw an image, rotated, on the screen.

drawImageRotated :: Word32 -> Int32 -> Int32 -> CFloat -> CFloat -> CFloat -> Int32 -> IO ()

Draw an image, flipped, on the screen.

drawImageFlipped :: Word32 -> Int32 -> Int32 -> Bool -> Bool -> Bool -> IO ()

Draw an image, scaled, on the screen.

drawImageScaled :: Word32 -> Int32 -> Int32 -> CFloat -> CFloat -> CFloat -> CFloat -> Int32 -> IO ()

Draw some text on the screen.

drawText :: Word32 -> String -> Int32 -> Int32 -> Color -> IO ()

Save an image to persistant storage.

saveImage :: Word32 -> String -> IO ()

Load an image from a file in cart.

loadImage :: String -> IO Word32

Resize an image, return copy.

imageResize :: Word32 -> Int32 -> Int32 -> Int32 -> IO Word32

Scale an image, return copy.

imageScale :: Word32 -> CFloat -> CFloat -> Int32 -> IO Word32

Replace a color in an image, in-place.

imageColorReplace :: Word32 -> Color -> Color -> IO ()

Tint a color in an image, in-place.

imageColorTint :: Word32 -> Color -> IO ()

Fade a color in an image, in-place.

imageColorFade :: Word32 -> CFloat -> IO ()

Copy a font to a new font.

fontCopy :: Word32 -> IO Word32

Scale a font, return a new font.

fontScale :: Word32 -> CFloat -> CFloat -> Int32 -> IO Word32

Load a BMF font from a file in cart.

loadFontBmf :: String -> String -> IO Word32

Load a BMF font from an image.

loadFontBmfFromImage :: Word32 -> String -> IO Word32

Measure the size of some text.

measureText :: Word32 -> String -> Int32 -> IO Dimensions

Meaure an image (use 0 for screen).

measureImage :: Word32 -> IO Dimensions

Load a TTY font from a file in cart.

loadFontTty :: String -> Int32 -> Int32 -> String -> IO Word32

Load a TTY font from an image.

loadFontTtyFromImage :: Word32 -> Int32 -> Int32 -> String -> IO Word32

Load a TTF font from a file in cart.

loadFontTtf :: String -> Int32 -> IO Word32

Invert the colors in an image, in-place.

imageColorInvert :: Word32 -> IO ()

Calculate a rectangle representing the available alpha border in an image.

imageAlphaBorder :: Word32 -> CFloat -> IO Rectangle

Crop an image, in-place.

imageCrop :: Word32 -> Int32 -> Int32 -> Int32 -> Int32 -> IO ()

Crop an image based on the alpha border, in-place.

imageAlphaCrop :: Word32 -> CFloat -> IO ()

Adjust the brightness of an image, in-place.

imageColorBrightness :: Word32 -> CFloat -> IO ()

Flip an image, in-place.

imageFlip :: Word32 -> Bool -> Bool -> IO ()

Change the contrast of an image, in-place.

imageColorContrast :: Word32 -> CFloat -> IO ()

Use an image as an alpha-mask on another image.

imageAlphaMask :: Word32 -> Word32 -> Int32 -> Int32 -> IO ()

Create a new image, rotating another image.

imageRotate :: Word32 -> CFloat -> Int32 -> IO Word32

Create a new image of a gradient.

imageGradient :: Int32 -> Int32 -> Color -> Color -> Color -> Color -> IO Word32

Unload an image.

unloadImage :: Word32 -> IO ()

Unload a font.

unloadFont :: Word32 -> IO ()

Clear an image.

clearImage :: Word32 -> Color -> IO ()

Draw a single pixel on an image.

drawPointOnImage :: Word32 -> Int32 -> Int32 -> Color -> IO ()

Draw a line on an image.

drawLineOnImage :: Word32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a filled rectangle on an image.

drawRectangleOnImage :: Word32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a filled triangle on an image.

drawTriangleOnImage :: Word32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a filled ellipse on an image.

drawEllipseOnImage :: Word32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a circle on an image.

drawCircleOnImage :: Word32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a filled polygon on an image.

drawPolygonOnImage :: Word32 -> [Vector] -> Color -> IO ()

Draw a filled round-rectangle on an image.

drawRectangleRoundedOnImage :: Word32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw an image on an image.

drawImageOnImage :: Word32 -> Word32 -> Int32 -> Int32 -> IO ()

Draw a tinted image on an image.

drawImageTintOnImage :: Word32 -> Word32 -> Int32 -> Int32 -> Color -> IO ()

Draw an image, rotated, on an image.

drawImageRotatedOnImage :: Word32 -> Word32 -> Int32 -> Int32 -> CFloat -> CFloat -> CFloat -> Int32 -> IO ()

Draw an image, flipped, on an image.

drawImageFlippedOnImage :: Word32 -> Word32 -> Int32 -> Int32 -> Bool -> Bool -> Bool -> IO ()

Draw an image, scaled, on an image.

drawImageScaledOnImage :: Word32 -> Word32 -> Int32 -> Int32 -> CFloat -> CFloat -> CFloat -> CFloat -> Int32 -> IO ()

Draw some text on an image.

drawTextOnImage :: Word32 -> Word32 -> String -> Int32 -> Int32 -> Color -> IO ()

Draw a outlined (with thickness) rectangle on the screen.

drawRectangleOutline :: Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a outlined (with thickness) triangle on the screen.

drawTriangleOutline :: Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a outlined (with thickness) ellipse on the screen.

drawEllipseOutline :: Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a outlined (with thickness) circle on the screen.

drawCircleOutline :: Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a outlined (with thickness) polygon on the screen.

drawPolygonOutline :: [Vector] -> Int32 -> Color -> IO ()

Draw a outlined (with thickness) arc on the screen.

drawArcOutline :: Int32 -> Int32 -> CFloat -> CFloat -> CFloat -> Int32 -> Int32 -> Color -> IO ()

Draw a outlined (with thickness) round-rectangle on the screen.

drawRectangleRoundedOutline :: Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a outlined (with thickness) rectangle on an image.

drawRectangleOutlineOnImage :: Word32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a outlined (with thickness) triangle on an image.

drawTriangleOutlineOnImage :: Word32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a outlined (with thickness) ellipse on an image.

drawEllipseOutlineOnImage :: Word32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a outlined (with thickness) circle on an image.

drawCircleOutlineOnImage :: Word32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a outlined (with thickness) polygon on an image.

drawPolygonOutlineOnImage :: Word32 -> [Vector] -> Int32 -> Color -> IO ()

Draw a outlined (with thickness) round-rectangle on an image.

drawRectangleRoundedOutlineOnImage :: Word32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()
gui (10)

Begin a GUI window. Returns false if the window is collapsed or closed - skip its contents, but still call gui_end_window.

guiBeginWindow :: String -> Rectangle -> IO Bool

End the current GUI window.

guiEndWindow :: IO ()

A button. Returns true when it is clicked.

guiButton :: String -> IO Bool

A static text label.

guiLabel :: String -> IO ()

A block of wrapping text.

guiText :: String -> IO ()

A checkbox. Returns the (possibly changed) state.

guiCheckbox :: String -> Bool -> IO Bool

A slider. Returns the (possibly changed) value.

guiSlider :: CFloat -> CFloat -> CFloat -> IO CFloat

Set the current layout row - the column widths (negative for flexible), and the row height.

guiLayoutRow :: [Int32] -> Int32 -> IO ()

Finish building the GUI for this frame. Called automatically at the end of update if you do not call it.

guiEnd :: IO ()

Draw the GUI to an image (0 is the screen).

guiDraw :: Word32 -> IO ()
input (12)

Has the key been pressed? (tracks unpress/read correctly.)

keyPressed :: Int32 -> IO Bool

Is the key currently down?

keyDown :: Int32 -> IO Bool

Has the key been released? (tracks press/read correctly.)

keyReleased :: Int32 -> IO Bool

Is the key currently up?

keyUp :: Int32 -> IO Bool

Has the button been pressed? (tracks unpress/read correctly.)

gamepadButtonPressed :: Int32 -> Int32 -> IO Bool

Is the button currently down?

gamepadButtonDown :: Int32 -> Int32 -> IO Bool

Has the button been released? (tracks press/read correctly.)

gamepadButtonReleased :: Int32 -> Int32 -> IO Bool

Get current position of mouse.

mousePosition :: IO Vector

Has the button been pressed? (tracks unpress/read correctly.)

mouseButtonPressed :: Int32 -> IO Bool

Is the button currently down?

mouseButtonDown :: Int32 -> IO Bool

Has the button been released? (tracks press/read correctly.)

mouseButtonReleased :: Int32 -> IO Bool

Is the button currently up?

mouseButtonUp :: Int32 -> IO Bool
sound (7)

Load a sound from a file in cart.

loadSound :: String -> IO Word32

Play a sound.

playSound :: Word32 -> Bool -> IO ()

Stop a sound.

stopSound :: Word32 -> IO ()

Unload a sound.

unloadSound :: Word32 -> IO ()

Speak some text and return a sound. Set things to 0 for defaults.

ttsSound :: String -> Bool -> Int32 -> Int32 -> Int32 -> Int32 -> Bool -> IO Word32

Create Sfx sound.

sfxSound :: SfxParams -> IO Word32

Create Sfx parameters.

sfxGenerate :: Int32 -> IO SfxParams
tile (38)

Load a tilemap (a Tiled map, exported as JSON) from a file in cart.

loadTilemap :: String -> IO Word32

Unload a tilemap.

unloadTilemap :: Word32 -> IO ()

Update a tilemap's animation timers (deltaTime is in seconds).

tileUpdate :: Word32 -> CFloat -> IO ()

Get the size of a tilemap, in tiles.

tileMapSize :: Word32 -> IO Dimensions

Get the size of a single tile of a tilemap, in pixels.

tileTileSize :: Word32 -> IO Dimensions

Get a custom property of a tilemap, by name (PROP_NONE when there is no such property.)

tileMapProp :: Word32 -> String -> IO TilemapProp

Get the number of custom properties on a tilemap.

tileMapPropCount :: Word32 -> IO Int32

Get a custom property of a tilemap, by index (PROP_NONE when out of range.)

tileMapPropAt :: Word32 -> Int32 -> IO TilemapProp

Draw a tilemap on the screen.

tileDraw :: Word32 -> Int32 -> Int32 -> IO ()

Draw a tilemap on the screen, tinted by a color.

tileDrawTint :: Word32 -> Int32 -> Int32 -> Color -> IO ()

Draw a tilemap on an image.

tileDrawOnImage :: Word32 -> Word32 -> Int32 -> Int32 -> IO ()

Render a whole tilemap to a new image.

tilemapImage :: Word32 -> IO Word32

Get the number of layers in a tilemap. Layers are numbered depth-first, so the children of a group layer have their own indexes too.

tileLayerCount :: Word32 -> IO Int32

Get the index of a layer of a tilemap, by name (-1 when there is no such layer.)

tileLayerIndex :: Word32 -> String -> IO Int32

Get the name of a layer of a tilemap.

tileLayerName :: Word32 -> Int32 -> IO String

Get the kind of a layer of a tilemap.

tileLayerType :: Word32 -> Int32 -> IO Int32

Get the size of a layer of a tilemap, in tiles.

tileLayerSize :: Word32 -> Int32 -> IO Dimensions

Get whether a layer of a tilemap is visible. Drawing a layer that Tiled marked hidden draws nothing.

tileLayerVisible :: Word32 -> Int32 -> IO Bool

Get a custom property of a layer of a tilemap, by name (PROP_NONE when there is no such property.)

tileLayerProp :: Word32 -> Int32 -> String -> IO TilemapProp

Get the number of custom properties on a layer of a tilemap.

tileLayerPropCount :: Word32 -> Int32 -> IO Int32

Get a custom property of a layer of a tilemap, by index (PROP_NONE when out of range.)

tileLayerPropAt :: Word32 -> Int32 -> Int32 -> IO TilemapProp

Draw a single layer of a tilemap on the screen.

tileDrawLayer :: Word32 -> Int32 -> Int32 -> Int32 -> IO ()

Draw a single layer of a tilemap on the screen, tinted by a color.

tileDrawLayerTint :: Word32 -> Int32 -> Int32 -> Int32 -> Color -> IO ()

Draw a single layer of a tilemap on an image.

tileDrawLayerOnImage :: Word32 -> Word32 -> Int32 -> Int32 -> Int32 -> IO ()

Render a single layer of a tilemap to a new image.

tileLayerImage :: Word32 -> Int32 -> IO Word32

Get the gid of the tile at a column/row in a tilemap layer.

tileGetTile :: Word32 -> Int32 -> Int32 -> Int32 -> IO Int32

Set the gid of the tile at a column/row in a tilemap layer. Swapping a gid is how a cart keeps changing state in the map itself.

tileSetTile :: Word32 -> Int32 -> Int32 -> Int32 -> Int32 -> IO ()

Draw a single tile from a tilemap on the screen.

tileDrawTile :: Word32 -> Int32 -> Int32 -> Int32 -> IO ()

Get a copy of the image of a single tile in a tilemap.

tileImage :: Word32 -> Int32 -> IO Word32

Get a custom property of a tile of a tilemap, by name (PROP_NONE when there is no such property.) These come from the tileset, so every tile with this gid shares them.

tileGidProp :: Word32 -> Int32 -> String -> IO TilemapProp

Get the number of custom properties on a tile of a tilemap.

tileGidPropCount :: Word32 -> Int32 -> IO Int32

Get a custom property of a tile of a tilemap, by index (PROP_NONE when out of range.)

tileGidPropAt :: Word32 -> Int32 -> Int32 -> IO TilemapProp

Get the number of objects on an object-layer of a tilemap.

tileObjectCount :: Word32 -> Int32 -> IO Int32

Get an object from an object-layer of a tilemap.

tileObject :: Word32 -> Int32 -> Int32 -> IO TilemapObject

Get the index of an object on an object-layer of a tilemap, by name (-1 when there is no such object.)

tileObjectIndex :: Word32 -> Int32 -> String -> IO Int32

Get a custom property of an object of a tilemap, by name (PROP_NONE when there is no such property.)

tileObjectProp :: Word32 -> Int32 -> Int32 -> String -> IO TilemapProp

Get the number of custom properties on an object of a tilemap.

tileObjectPropCount :: Word32 -> Int32 -> Int32 -> IO Int32

Get a custom property of an object of a tilemap, by index (PROP_NONE when out of range.)

tileObjectPropAt :: Word32 -> Int32 -> Int32 -> Int32 -> IO TilemapProp
utilities (5)

Get system-time (ms) since unix epoch.

currentTime :: IO Word64

Get the change in time (seconds) since the last update run.

deltaTime :: IO CFloat

Get a random integer between 2 numbers.

randomInt :: Int32 -> Int32 -> IO Int32

Get the random-seed.

randomSeedGet :: IO Word64

Set the random-seed.

randomSeedSet :: Word64 -> IO ()