W4
roc-wasm4
Build wasm4 games using Roc
Palette : [ None, Color1, Color2, Color3, Color4 ]
The Palette
consists of four colors. There is also None
which is used to
represent a transparent or no change color. Each pixel on the screen will be
drawn using one of these colors.
You may find it helpful to create an alias for your game.
red = Color2 green = Color3 W4.setTextColors { fg: red, bg: green }
Gamepad
Represents the current state of a Player
gamepad.
Gamepad : { button1 : Bool, button2 : Bool, left : Bool, right : Bool, up : Bool, down : Bool, }
Mouse
Represents the current state of the mouse.
Mouse : { x : I16, y : I16, left : Bool, right : Bool, middle : Bool, }
Netplay
Represents the current state of Netplay.
Netplay connects gamepad inputs over the Internet using WebRTC.
Netplay : [ Enabled Player, Disabled, ]
Player : [ Player1, Player2, Player3, Player4 ]
Represents Player
.
WASM-4 supports realtime multiplayer of up to 4 players, either locally or online.
Shader
Represents fragment shader for raw operations with the framebuffer.
Shader : U8, U8, Palette -> Palette
screenWidth
screenHeight
setPalette : { color1 : U32, color2 : U32, color3 : U32, color4 : U32 } -> Task {} *
Set the color Palette
for your game.
W4.setPalette { color1: 0xffffff, color2: 0xff0000, color3: 0x000ff00, color4: 0x0000ff, }
Warning: this will overwrite the existing Palette
, changing all colors on the screen.
getPalette : Task { color1 : U32, color2 : U32, color3 : U32, color4 : U32 } *
Get the color Palette
for your game.
{color1, color2, color3, color4} <- W4.getPalette |> Task.await
setDrawColors : DrawColors -> Task {} *
Set the draw colors for the next draw command.
blue = Color1 white = Color4 W4.setDrawColors { primary : blue, secondary : white, tertiary : None, quaternary : None, }
Warning: this will overwrite any existing draw colors that are set.
getDrawColors : Task DrawColors *
Get the currently set draw colors.
{primary, secondary} <- W4.getDrawColors |> Task.await
setPrimaryColor : W4.Palette -> Task {} *
Helper for primary drawing color.
blue = Color1 W4.setPrimaryColor blue
Warning: this will overwrite any existing draw colors, and sets the
secondary, tertiary and quaternary values to None
.
setTextColors : { fg : Palette, bg : Palette } -> Task {} *
Helper for setting the draw colors for text.
blue = Color1 white = Color4 W4.setTextColors { fg : blue, bg : white }
Warning: this will overwrite any existing draw colors, and sets the
tertiary and quaternary values to None
.
setShapeColors : { border : W4.Palette, fill : W4.Palette } -> Task {} *
Helper for colors when drawing a shape.
blue = Color1 white = Color4 W4.setShapeColors { border : blue, fill : white }
Warning: this will overwrite any existing draw colors, and sets the
tertiary and quaternary values to None
.
text : Str, { x : I32, y : I32 } -> Task {} *
Draw text to the screen.
W4.text "Hello, World" {x: 0, y: 0}
Text color is the Primary draw color.
Background color is the Secondary draw color.
rect : { x : I32, y : I32, width : U32, height : U32 } -> Task {} *
Draw a rectangle to the screen.
W4.rect {x: 0, y: 10, width: 40, height: 60}
Fill color is the Primary draw color.
Border color is the Secondary draw color.
oval : { x : I32, y : I32, width : U32, height : U32 } -> Task {} *
Draw an oval to the screen.
W4.oval {x, y, width: 20, height: 30}
Fill color is the Primary draw color.
Border color is the Secondary draw color.
line : { x : I32, y : I32 }, { x : I32, y : I32 } -> Task {} *
Draw a line between two points to the screen.
W4.line {x: 0, y: 0}, {x: 10, y: 10}
Line color is the Primary draw color.
hline : { x : I32, y : I32, len : U32 } -> Task {} *
Draw a horizontal line starting at (x, y) with len to the screen.
W4.hline {x: 10, y: 20, len: 30}
Line color is the Primary draw color.
vline : { x : I32, y : I32, len : U32 } -> Task {} *
Draw a vertical line starting at (x, y) with len to the screen.
W4.vline {x: 10, y: 20, len: 30}
Line color is the Primary draw color.
getGamepad : Player -> Task Gamepad *
Get the controls for a Gamepad
.
{button1,button2,left,right,up,down} <- W4.getGamepad Player1 |> Task.await
getMouse : Task Mouse *
Get the current Mouse
position.
{x,y,left,right,middle} <- W4.getMouse |> Task.await
getNetplay : Task Netplay *
Get the Netplay
status.
netplay <- W4.getNetplay |> Task.await when netplay is Enabled Player1 -> # .. Enabled Player2 -> # .. Enabled Player3 -> # .. Enabled Player4 -> # .. Disabled -> # ..
Note: All WASM-4 games that support local multiplayer automatically support netplay. There are no additional steps developers need to take to make their games netplay-ready. Netplay can be used to implement advanced features such as non-shared screen multiplayer
seedRand : U64 -> Task {} *
Seeds the global pseudo-random number generator.
{} <- W4.seedRand framesSinceStart |> Task.await
Wasm4 exposes no way to seed a random number generator. As such, anything random will be exactly the same on every run by default. To work around this, it is suggested to count the number of frames the user is on the title screen before starting the game and use that to seed the prng.
rand : Task I32 *
Generate a pseudo-random number.
# pseudo-random number between Num.minI32 and Num.maxI32 (inclusive of both) i <- W4.rand |> Task.await
Warning: Wasm4 exposes no way to seed a random number generator. As such, anything random will be exactly the same on every run by default. To work around this, it is suggested to count the number of frames the user is on the title screen before starting the game and use that to seed the prng.
randBetween : { start : I32, before : I32 } -> Task I32 *
Generate a pseudo-random number in the range.
The range has an inclusive start and exclusive end.
# random number in the range 0-99 i <- W4.randBetween {start: 0, before: 100} |> Task.await
Warning: Wasm4 exposes no way to seed a random number generator. As such, anything random will be exactly the same on every run by default. To work around this, it is suggested to count the number of frames the user is on the title screen before starting the game and use that to seed the prng.
trace : Str -> Task {} *
Prints a message to the debug console.
W4.trace "Hello, World"
debug : Str, val -> Task {} * where val implements Inspect.Inspect
Prints a message with a debug formatting of the value to the console.
W4.debug "my int" 7
saveToDisk : List U8 -> Task {} [SaveFailed]
Saves data to persistent storage. Any previously saved data on the disk is replaced.
Returns Err SaveFailed
on failure.
result <- W4.saveToDisk [0x10] |> Task.attempt when result is Ok {} -> # success Err SaveFailed -> # handle failure
Games can persist up to 1024 bytes of data.
loadFromDisk : Task (List U8) *
Gets all saved data from persistent storage.
data <- W4.loadFromDisk |> Task.await
Games can persist up to 1024 bytes of data.
preserveFrameBuffer : Task {} *
Set a flag to keep the framebuffer between frames.
This can be helpful if you only want to update part of the screen.
clearFrameBufferEachUpdate : Task {} *
Set a flag to clear the framebuffer between frames.
hideGamepadOverlay : Task {} *
Set a flag to hide the game overlay.
showGamepadOverlay : Task {} *
Set a flag to show the game overlay.
getPixel : { x : U8, y : U8 } -> Task Palette *
Get the color for an individual pixel in the framebuffer.
setPixel : { x : U8, y : U8 }, Palette -> Task {} *
Set the color for an individual pixel in the framebuffer.
runShader : Shader -> Task {} *
tone : { startFreq ? U16, endFreq ? U16, channel ? [ Pulse1 [ Eighth, Quarter, Half, ThreeQuarters ], Pulse2 [ Eighth, Quarter, Half, ThreeQuarters ], Triangle, Noise ], pan ? [ Center, Left, Right ], sustainTime ? U8, releaseTime ? U8, decayTime ? U8, attackTime ? U8, volume ? U8, peakVolume ? U8 } -> Task {} *
Plays a tone sound.
Please refer to the wasm4 audio docs.
The sound.roc example app along with the wasm4 sound tools can be quite helpful to play with.