Getting Started
Most of the functions in Floaty closely resemble functions in Pico-8. The main difference is that instead of global functions, Floaty uses a scope() method that provides all engine functions. This works better in a web context where multiple things can exist on the same page.
The quickest way to get started is to use the following snippet as a starting point:
import Engine from 'https://floaty.dev/engine-v2.js';
const engine = new Engine();
engine.scope(({ start, cls, spr }) => {
const sprites = {
player: [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 7, 7, 7, 7, 0, 0,
0, 7, 7, 7, 7, 7, 7, 0,
7, 7, 0, 7, 7, 0, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
0, 7, 7, 7, 7, 7, 7, 0,
0, 0, 7, 7, 7, 7, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
],
};
const sounds = {};
function draw() {
cls(1);
spr('player', 60, 60);
}
start({
target: document.querySelector('.game'),
sprites,
sounds,
draw,
});
});
The scope() Method
In Pico-8, functions like cls(), spr(), and btn() are always available. In Floaty, you access these same functions through the scope() method:
engine.scope(({ start, cls, spr, btn, text }) => {
// All engine functions are available in this closure
// No global pollution, no this.engine references needed
start({
target: document.querySelector('.game'),
draw() {
cls();
text('hello world', 40, 60, 7);
}
});
});
You list the functions you want to use in the parentheses, and they become available inside your code. This approach works well for JavaScript running in a web browser where many different scripts might be running on the same page.
Multiple Games
Unlike Pico-8 where you run one game at a time, you can run multiple Floaty games on the same web page simultaneously:
// First game
const engine1 = new Engine();
engine1.scope(({ start, cls }) => {
start({
target: document.querySelector('.game1'),
draw() { cls(8); }
});
});
// Second game - no conflicts!
const engine2 = new Engine();
engine2.scope(({ start, cls }) => {
start({
target: document.querySelector('.game2'),
draw() { cls(12); }
});
});
Audio System
Like Pico-8, you can create sounds using arrays of frequencies. Unlike Pico-8, you can also load audio files directly (wav/ogg/mp3). The sfx() function supports three formats:
engine.scope(({ sfx }) => {
// Synthesized sound (array format)
const sounds = {
jump: [523, 587, 659],
};
// Audio file (wav/ogg/mp3)
sfx('/sounds/explosion.wav');
// Data URI
sfx('data:audio/wav;base64,UklGRiQAAABXQVZFZm10...');
});
You can play background music with the music() function:
engine.scope(({ music }) => {
// Play background music at 50% volume
music('/music/theme.mp3', { volume: 0.5 });
// Stop the music
music(false);
});
Loading Remote Assets
Use queue() to mark sprites or sounds for deferred loading, then call await load() inside an async init() to fetch them all before gameplay starts:
engine.scope(({ start, queue, load, cls, text }) => {
const sprites = {
player: queue('https://example.com/player-sprite.json'),
};
const sounds = {
jump: queue('https://example.com/jump-sound.json'),
};
start({
target: document.querySelector('.game'),
sprites,
sounds,
async init() {
await load();
},
draw() { /* ... */ },
});
});
Defaults
Like Pico-8, Floaty has some sensible defaults to get you started quickly:
Screen size
The screen is 128 pixels wide and 128 pixels high. If the container is larger, the canvas will scale to fit while maintaining a square aspect ratio. Your game will always look pixelated, even if each pixel is actually a square block of pixels.
The rest of the screen around the game canvas will be the same as color 0. If you want to override this, you can provide a different background color to the start() function:
engine.scope(({ start }) => {
start({
target: document.querySelector('.game'),
background: '#FF77A8', // any CSS color
draw() { /* ... */ }
});
});
It can be tricky to get the container to stretch, especially if you're not overly familiar with CSS or HTML. Try something like this:
<div style="width: 100vw; height: 100vh">
<div class="game" style="width: 100%; height: 100%"></div>
</div>
Sprites
Sprites are 8x8 pixels or a multiple thereof. Larger sprites are drawn using optional parameters on the spr function. Use this pattern to define sprites:
const sprites = {
player: [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 7, 7, 7, 7, 0, 0,
0, 7, 7, 7, 7, 7, 7, 0,
7, 7, 0, 7, 7, 0, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
0, 7, 7, 7, 7, 7, 7, 0,
0, 0, 7, 7, 7, 7, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
],
};
In sprite arrays, -1 means no color is drawn on that pixel (transparent). All other numbers (0-15) correspond to palette colors.
Colors
Like Pico-8, Floaty uses a 16-color palette:
Click a color to copy its hex code.
Copied!