Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/leoncvlt/itto

🕹ī¸ An itty bitty javascript game engine
https://github.com/leoncvlt/itto

canvas game-engine javascript minimalist

Last synced: 22 days ago
JSON representation

🕹ī¸ An itty bitty javascript game engine

Awesome Lists containing this project

README

        

# `itto`

An itty bitty javascript game engine

## âŦ‡ī¸ Install & Usage

### Global Object

``

`const { game } = itto`

### ES Module

``

`import { game } from "itto"`

### Bundler

`npm i itto`

`import { game } from "itto"`

## 🚀 Quick start

Call `game.play` to initialize the game loop. The function takes on object with 4 named parameters:

* `settings` - an `object` containing the game settings. See [game settings](#%EF%B8%8F-game-settings)
* `init` - a `function` which runs once, on game start
* `tick` - a `function` which runs on every game tick (by default, game runs at 60 ticks per second)
* `draw` - a `function` which runs on every animation frame (always tries to target 60 frames per second)

```js
import { game, clear, circle } from "itto";

let x, y;
let dx = Math.sign(Math.random() - 0.5) * 2;
let dy = Math.sign(Math.random() - 0.5) * 2;
const r = 8;

game.play({
settings: {
size: [360, 96],
},
init: () => {
x = game.width / 2;
y = game.height / 2;
},
tick: () => {
x = x + dx * game.delta;
y = y + dy * game.delta;

if (x > game.width - r / 2 || x < 0) {
dx = -dx;
}
if (y > game.height - r / 2 || y < 0) {
dy = -dy;
}
},
draw: () => {
clear(13);
circle(x, y, r, 14);
},
});
```

## 💾 Examples

* [benchmark](https://leoncvlt.github.io/itto/benchmark)
* [breakout](https://leoncvlt.github.io/itto/breakout)
* [hello](https://leoncvlt.github.io/itto/hello)
* [snake](https://leoncvlt.github.io/itto/snake)

## ⚙ī¸ Game settings

The following properties can be passed to the `settings` parameter of the `game.play` function:

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| [canvas] | HTMLElement | document.querySelector("canvas") | The canvas element. Defaults to the first canvas in the page. |
| [size] | Array.<number> | [240, 236] | `[x, y]` tuple defining the width and height of the game |
| resize | string | "integer" | The resizing behaviour - `itto` will attempt to resize the canvas to fill up its parent, while keeping the aspect ratio. "integer" will scale the canvas in integer increments (2x, 3x, etc). "linear" will always scale it to the max size. "none" or `null` will disable the automatic scaling, leaving you to sort out the canvas sizing manually |
| [offset] | number \| Array.<number> | 0 | The amount of pixels to keep around the game area when resizing it. Pass a number for the same amount across all dimensions, or a `[x, y]` tuple to have different offset for the sides and the top/bottom |
| [supersampling] | number | 0 | Scale the game's graphics up by this amount, before rendering them on the canvas. Can make text / shapes sharper (especially on Chrome) at the expense of worse performance |
| [assets] | object | {} | An ojbect containing ID/Urls pairs for the external resources you want to preload and use in the game. See [Loading Assets](#-loading-assets) |
| [palette] | Array.<number> | [sweetie16] | An array containing colors whose index can be passed to drawing functions (such as `clear` or `rect`. Defaults to the [Sweetie 16](https://lospec.com/palette-list/sweetie-16) palette) |

## 🧩 Game properties

Inside `init`, `tick` or `draw` methods you can query different parameters from the `game` object to get specific properties of the game currently running:

* [`game`](#game)
* [`.canvas`](#game.canvas) : HTMLElement
* [`.context`](#game.context) : CanvasContext
* [`.width`](#game.width) : number
* [`.height`](#game.height) : number
* [`.delta`](#game.delta) : number
* [`.elapsed`](#game.elapsed) : number
* [`.ready`](#game.ready) : boolean
* [`.palette`](#game.palette) : Array.<number>
* [`.assets`](#game.assets) : object

#### `game.canvas` : HTMLElement
The canvas element the game is being drawn in

#### `game.context` : CanvasContext
Drawing context of the canvas element the game is being drawn in

#### `game.width` : number
Width of the game area, in pixels

#### `game.height` : number
Height of the game area, in pixels

#### `game.delta` : number
Delta time since last frame

#### `game.elapsed` : number
Time elapsed since the game start, in ticks (1 second = 60 ticks)

#### `game.ready` : boolean
Whether the game assets have finished loading or not

#### `game.palette` : Array.<number>
An array of colors as defined in the game settings

#### `game.assets` : object
The external game assets, as defined in the game settings

## đŸ“Ļ Loading assets

In the game settings, you can use the `assets` object to map specific IDs to external resources you'd want to use during the game (for example, images to draw with the `image` function, or sounds to play with the `sound` function). The assets will be preloaded and processed accordingly. The `game.ready` variable will be set to `true` as soon as all assets are loaded, allowing you to create loading screens.

```js
import { game, image, text } from "itto";

game.play({
settings: {
assets: {
logo: "/assets/logo.png"
}
},
draw: () => {
if (itto.ready) {
clear(0);
text("Loading...", 8, 8)
}
clear(1);
image(logo, 16, 16);
},
});
```

Assets are processed based on their extension:

| Extension | Processed as |
| :-- | :-- |
| `.jpg` `.jpeg` `.png` | [`HTMLImageElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image)
| `.wav` `.mp3` `.ogg` | [`AudioBuffer`](https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer)
| everything else | Raw URL of the asset

While assets are normally used by passing their IDs to specific functions, they can also be accessed at any time inside `game` by accessing `game.assets[id]`, provided they are loaded (if not, it will return a promise).

## ✨ Functions

The library offers a barebone set of functions to build your game with. All methods are named imports from the `"itto"` namespace or the global `itto` object.

### 🎨 Drawing


`clear(color)`


Fills the screen with a solid color



`line(x0, y0, x1, y1, color)`


Draws a line



`rect(x, y, w, h, color, border)`


Draws a rectangle



`circle(x, y, r, color, border)`


Draws a circle



`image(id, x, y, sx, sy, w, h, options)`


Draws an image



`text(text, x, y, color, options)`


Draws text on screen



### `clear(color)`
Fills the screen with a solid color

| Param | Type | Description |
| --- | --- | --- |
| color | number \| string | the color to fill the screen with. Omit to use a transparent color |

### `line(x0, y0, x1, y1, color)`
Draws a line

| Param | Type | Default | Description |
| --- | --- | --- | --- |
| x0 | number | | x coordinate of the line start point |
| y0 | number | | y coordinate of the line start point |
| x1 | number | | x coordinate of the line end point |
| y1 | number | | y coordinate of the line end point |
| color | number \| string | 0 | the line color |

### `rect(x, y, w, h, color, border)`
Draws a rectangle

| Param | Type | Default | Description |
| --- | --- | --- | --- |
| x | number | | the x coordinate of the rectangle top-left corner |
| y | number | | the y coordinate of the rectangle top-left corner |
| w | number | | the width of the rectangle |
| h | number | | the height of the rectangle |
| color | number \| string | 0 | the color of the rectangle |
| border | boolean | false | whether to draw the border only or a filled shape |

### `circle(x, y, r, color, border)`
Draws a circle

| Param | Type | Default | Description |
| --- | --- | --- | --- |
| x | number | | the x coordinate of the circle center |
| y | number | | the y coordinate of the circle center |
| r | number | | the circle radius |
| color | number \| string | 0 | the circle color |
| border | boolean | false | whether to draw the border only or a filled shape |

### `image(id, x, y, sx, sy, w, h, options)`
Draws an image

| Param | Type | Description |
| --- | --- | --- |
| id | string | id of the asset of the image to draw |
| x | number | x coordinate to draw the image at |
| y | number | y coordinate to draw the image at |
| sx | number | top-left x coordinate of the portion of the source image to draw |
| sy | number | top-left y coordinate of the portion of the source image to draw |
| w | object | width of the portion of the source image to draw. If undefined, defaults to the natural width of the image. |
| h | number | height of the portion of the source image to draw. If undefined, defaults to the natural height of the image. |
| options | object | additional options |
| options.origin | Array.<number> | `[x, y]` tuple of the coordinates of the origin. Defaults to the top left corner `[0, 0]` |
| options.anchor | Array.<number> | `[x, y]` tuple of the coordinates to apply scale / rotation from |
| options.scale | Array.<number> | `[x, y]` tuple of the scale factor values |
| options.angle | number | angle to rotate the image by |

### `text(text, x, y, color, options)`
Draws text on screen

| Param | Type | Default | Description |
| --- | --- | --- | --- |
| text | string | | the text to draw |
| x | number | | x coordinate to draw the text at |
| y | number | | y coordinate to draw the text at |
| color | number \| string | 0 | text color |
| options | object | | additional options |
| options.size | number | | text size, in px |
| options.align | string | | horizontal text alignment (`left` / `center` / `right`, defaults to `left`) |
| options.font | string | | id of the font asset to use |

### 🕹ī¸ Input

When querying an input with the `input` function, the inputs IDs map is as follows (IDs are case-insensitive):

| ID | Input |
| :-- | :----- |
| `up` | Up Arrow
| `down` | Down Arrow
| `left` | Left Arrow
| `right` | Right Arrow
| `a` | Z
| `b` | X
| `c` | A
| `d` | S
| `mouse` | Left Mouse Button
| `mouseright` | Right Mouse Button
| `mousemid` | Middle Mouse Button
| `touch` | One-finger touch
| `touchtwo` | Two-fingers touch
| `touchthree` | Three-fingers touch



`input(id, period)` ⇒ boolean


Checks if an input (keyboard / gamepad / mouse / touchscreen) is or has been pressed.




`pointer()` ⇒ Array.<number>


Checks the current pointer position



### `input(id, period)` ⇒ boolean
Checks if an input (keyboard / gamepad / mouse / touchscreen) is or has been pressed.

**Returns**: boolean - whether the queried input is pressed or not

| Param | Type | Default | Description |
| --- | --- | --- | --- |
| id | number | | the id of the input |
| period | number | 1 | if the input is held down,the time in game ticks before the function returns `true` again. If omitted defaults to an interval of `1`, checking every tick. Pass `false` or `0` to check for a single press only. |

**Example**
```js
input("up") // returns true as long as the arrow up key is pressed
input("a", 60) // if Z is pressed, returns true every 60 ticks (1 seconds), otherwise false
input("mouse", 0) // returns true if the left mouse button has just been pressed, otherwise false
input() // returns true if any input is being pressed
```

### `pointer()` ⇒ Array.<number>
Checks the current pointer position

**Returns**: Array.<number> - `[x, y]` tuple containing the current x and y pointer coordinates

### 🔊 Sound

### `sound`
Plays a sound

| Param | Type | Description |
| --- | --- | --- |
| id | string | id of the asset of the sound file to play |
| options | object | additional options |
| options.channel | number | the channel to play the sound in. Playing a sound in a specific channel stops other sounds playing in that same channel. Call this method with a `null` src and a channel to stop the sound playing in that channel. |
| options.volume | number | volume to play the sound at |
| options.loop | boolean | whether to loop the sound or not |