punter.js 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.MD +11 -11
- package/games/pong.html +19 -6
- package/package.json +3 -2
- package/punter.js +17 -17
- package/tests/fixtures/index.html +2 -2
- package/tests/interface-spec.js +1 -1
package/README.MD
CHANGED
|
@@ -14,7 +14,7 @@ A simple, dependency-free 2D game engine for the browser. No build step, no fram
|
|
|
14
14
|
- [Install](#install)
|
|
15
15
|
- [Run the Example](#run-the-example)
|
|
16
16
|
- [How it Works](#how-it-works)
|
|
17
|
-
- [
|
|
17
|
+
- [Setup](#setup)
|
|
18
18
|
- [Scenes](#scenes)
|
|
19
19
|
- [Events](#events)
|
|
20
20
|
- [Sprites](#sprites)
|
|
@@ -61,15 +61,15 @@ Then open **http://localhost:3000/games/pong.html** in your browser.
|
|
|
61
61
|
|
|
62
62
|
Every punter.js game follows the same three-step pattern:
|
|
63
63
|
|
|
64
|
-
1. **
|
|
64
|
+
1. **setup** - specify which canvas to use and which images/sounds to preload
|
|
65
65
|
2. **scene** - define a named scene (level, menu, etc.) with update/draw logic
|
|
66
66
|
3. **ready** - switch to a scene once everything has loaded
|
|
67
67
|
|
|
68
68
|
```js
|
|
69
69
|
// 1. Load assets
|
|
70
|
-
punter.
|
|
70
|
+
punter.setup({
|
|
71
71
|
canvas: '#game',
|
|
72
|
-
|
|
72
|
+
images: { player: 'images/player.png' },
|
|
73
73
|
sounds: { jump: 'sounds/jump.mp3' }
|
|
74
74
|
});
|
|
75
75
|
|
|
@@ -96,15 +96,15 @@ punter.on('ready', function () {
|
|
|
96
96
|
});
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
##
|
|
99
|
+
## Setup
|
|
100
100
|
|
|
101
101
|
Call this once at the start. The `ready` event fires once all assets have loaded.
|
|
102
102
|
|
|
103
103
|
```js
|
|
104
|
-
punter.
|
|
104
|
+
punter.setup({
|
|
105
105
|
canvas: '#game', // CSS selector or HTMLCanvasElement
|
|
106
106
|
debug: false, // true = show FPS and bounding boxes
|
|
107
|
-
|
|
107
|
+
images: {
|
|
108
108
|
player: 'images/player.png',
|
|
109
109
|
coin: 'images/coin.png'
|
|
110
110
|
},
|
|
@@ -117,7 +117,7 @@ punter.init({
|
|
|
117
117
|
Option | Required | Description
|
|
118
118
|
----------|----------|------------------------------------------------
|
|
119
119
|
`canvas` | Yes | CSS selector (`'#game'`) or `HTMLCanvasElement`
|
|
120
|
-
`
|
|
120
|
+
`images` | No | Key/path pairs of images to preload
|
|
121
121
|
`sounds` | No | Key/path pairs of audio files to preload
|
|
122
122
|
`debug` | No | Enables the debug overlay. Default: `false`
|
|
123
123
|
|
|
@@ -179,7 +179,7 @@ var player = punter.createSprite({
|
|
|
179
179
|
Option | Default | Description
|
|
180
180
|
-----------------|------------|----------------------------------------------------------------------------------------------------
|
|
181
181
|
`id` | - | **Required.** Unique name for this sprite.
|
|
182
|
-
`key` | - | **Required.** Image key from `config.
|
|
182
|
+
`key` | - | **Required.** Image key from `config.images`. Pass an array (`['frame1','frame2']`) for animation.
|
|
183
183
|
`x` | - | **Required.** Horizontal position in pixels or `'50%'`.
|
|
184
184
|
`y` | - | **Required.** Vertical position in pixels or `'50%'`.
|
|
185
185
|
`w` | auto | Width in pixels or percent. Inferred from the image if omitted.
|
|
@@ -294,7 +294,7 @@ punter.on('update', function () {
|
|
|
294
294
|
## Sound
|
|
295
295
|
|
|
296
296
|
```js
|
|
297
|
-
punter.
|
|
297
|
+
punter.setup({
|
|
298
298
|
sounds: { jump: 'sounds/jump.mp3', music: 'sounds/theme.mp3' }
|
|
299
299
|
});
|
|
300
300
|
|
|
@@ -419,7 +419,7 @@ html:not([data-punter-loading]) #loader { display: none; }
|
|
|
419
419
|
## Debug Mode
|
|
420
420
|
|
|
421
421
|
```js
|
|
422
|
-
punter.
|
|
422
|
+
punter.setup({ canvas: '#game', debug: true }); // enable at startup
|
|
423
423
|
punter.debug = true; // or toggle at runtime
|
|
424
424
|
```
|
|
425
425
|
|
package/games/pong.html
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
|
+
<title>Pong</title>
|
|
4
5
|
<meta charset="utf-8">
|
|
5
6
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
-
<title>Pong</title>
|
|
7
7
|
<style>
|
|
8
|
-
* {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
* {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
html, body {
|
|
15
|
+
width: 100%;
|
|
16
|
+
height: 100%;
|
|
17
|
+
background: #1e2230;
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
canvas {
|
|
22
|
+
display: block;
|
|
23
|
+
}
|
|
11
24
|
</style>
|
|
12
25
|
<script src="../punter.js"></script>
|
|
13
26
|
</head>
|
|
@@ -80,9 +93,9 @@
|
|
|
80
93
|
// SETUP
|
|
81
94
|
// Load the two sprite images before the game starts.
|
|
82
95
|
// =========================================================
|
|
83
|
-
punter.
|
|
96
|
+
punter.setup({
|
|
84
97
|
canvas: '#game',
|
|
85
|
-
|
|
98
|
+
images: {
|
|
86
99
|
paddle: '../images/pong/sprites/paddle.png',
|
|
87
100
|
ball: '../images/pong/sprites/ball.png'
|
|
88
101
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "punter.js",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "A
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "A simple, dependency-free 2D game engine for the browser. No build step, no frameworks - just one script tag.",
|
|
5
5
|
"main": "punter.js",
|
|
6
6
|
"directories": {
|
|
7
7
|
"test": "tests"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "npx serve .",
|
|
11
|
+
"start:pong": "npx serve . -l 4000 & npx open-cli http://localhost:4000/games/pong.html",
|
|
11
12
|
"test": ". \"$NVM_DIR/nvm.sh\" && nvm use && NODE_ENV=test TZ=UTC node_modules/.bin/jasmine --config=tests/jasmine/config.json"
|
|
12
13
|
},
|
|
13
14
|
"repository": {
|
package/punter.js
CHANGED
|
@@ -106,11 +106,11 @@
|
|
|
106
106
|
})();
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
|
-
* Initialises the engine with canvas,
|
|
109
|
+
* Initialises the engine with canvas, images, sounds, and buttons
|
|
110
110
|
* @param {Object} config - configuration object
|
|
111
111
|
* @returns {void}
|
|
112
112
|
*/
|
|
113
|
-
function
|
|
113
|
+
function setup(config) {
|
|
114
114
|
|
|
115
115
|
config = config || {};
|
|
116
116
|
|
|
@@ -151,11 +151,11 @@
|
|
|
151
151
|
_boundsCanvas = document.createElement('canvas');
|
|
152
152
|
_boundsCtx = _boundsCanvas.getContext('2d', { willReadFrequently: true });
|
|
153
153
|
|
|
154
|
-
|
|
154
|
+
loadImages(config.images || {}).then(function() {
|
|
155
155
|
|
|
156
156
|
// precompute bounds for all sprite frames
|
|
157
|
-
if (config.
|
|
158
|
-
for (var key in config.
|
|
157
|
+
if (config.images) {
|
|
158
|
+
for (var key in config.images) {
|
|
159
159
|
var img = images[key];
|
|
160
160
|
if (img && img.complete && img.naturalWidth) {
|
|
161
161
|
// this warms up the boundingCache
|
|
@@ -182,13 +182,13 @@
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
/**
|
|
185
|
-
* Loads and decodes all
|
|
186
|
-
* @param {Object}
|
|
185
|
+
* Loads and decodes all images
|
|
186
|
+
* @param {Object} images - Key-value map of image keys to image URLs
|
|
187
187
|
* @returns {Promise} - Resolves when all images are loaded and decoded
|
|
188
188
|
*/
|
|
189
|
-
function
|
|
189
|
+
function loadImages(imageMap) {
|
|
190
190
|
|
|
191
|
-
var keys = Object.keys(
|
|
191
|
+
var keys = Object.keys(imageMap);
|
|
192
192
|
var total = keys.length;
|
|
193
193
|
|
|
194
194
|
if (!total) return Promise.resolve();
|
|
@@ -234,7 +234,7 @@
|
|
|
234
234
|
|
|
235
235
|
for (var i = 0; i < total; i++) {
|
|
236
236
|
var key = keys[i];
|
|
237
|
-
var url =
|
|
237
|
+
var url = imageMap[key];
|
|
238
238
|
var img = new Image();
|
|
239
239
|
img.key = key; // for debugging
|
|
240
240
|
img.onload = handleLoad.bind(img, key);
|
|
@@ -1003,7 +1003,7 @@
|
|
|
1003
1003
|
*/
|
|
1004
1004
|
function startLoop() {
|
|
1005
1005
|
|
|
1006
|
-
if (!_initilised) throw new Error('punter.
|
|
1006
|
+
if (!_initilised) throw new Error('punter.setup must be called first');
|
|
1007
1007
|
|
|
1008
1008
|
_canvasCtx = _canvas.getContext('2d', { alpha: true, desynchronized: true });
|
|
1009
1009
|
_canvasCtx.imageSmoothingEnabled = false;
|
|
@@ -1067,7 +1067,7 @@
|
|
|
1067
1067
|
|
|
1068
1068
|
function pauseLoop() {
|
|
1069
1069
|
|
|
1070
|
-
if (!_initilised) throw new Error('punter.
|
|
1070
|
+
if (!_initilised) throw new Error('punter.setup must be called first');
|
|
1071
1071
|
|
|
1072
1072
|
if (_loopId !== null) {
|
|
1073
1073
|
cancelAnimationFrame(_loopId);
|
|
@@ -1090,7 +1090,7 @@
|
|
|
1090
1090
|
*/
|
|
1091
1091
|
function playSound(name, options) {
|
|
1092
1092
|
|
|
1093
|
-
if (!_initilised) throw new Error('punter.
|
|
1093
|
+
if (!_initilised) throw new Error('punter.setup must be called first');
|
|
1094
1094
|
|
|
1095
1095
|
var buffer = sounds[name];
|
|
1096
1096
|
if (!buffer) return;
|
|
@@ -1131,7 +1131,7 @@
|
|
|
1131
1131
|
|
|
1132
1132
|
function stopSound(name) {
|
|
1133
1133
|
|
|
1134
|
-
if (!_initilised) throw new Error('punter.
|
|
1134
|
+
if (!_initilised) throw new Error('punter.setup must be called first');
|
|
1135
1135
|
|
|
1136
1136
|
var arr = playingSounds[name];
|
|
1137
1137
|
if (!arr || !arr.length) return;
|
|
@@ -1296,7 +1296,7 @@
|
|
|
1296
1296
|
var api = {
|
|
1297
1297
|
|
|
1298
1298
|
// initialization
|
|
1299
|
-
|
|
1299
|
+
setup: setup,
|
|
1300
1300
|
|
|
1301
1301
|
// scene lifecycle
|
|
1302
1302
|
scene: function (name, handler) {
|
|
@@ -1304,7 +1304,7 @@
|
|
|
1304
1304
|
},
|
|
1305
1305
|
go: function (name) {
|
|
1306
1306
|
|
|
1307
|
-
if (!_initilised) throw new Error('punter.
|
|
1307
|
+
if (!_initilised) throw new Error('punter.setup must be called first');
|
|
1308
1308
|
if (!_scenes[name]) throw new Error('punter.go: unknown scene "' + name + '"');
|
|
1309
1309
|
|
|
1310
1310
|
// remove existing game loop handlers
|
|
@@ -1355,7 +1355,7 @@
|
|
|
1355
1355
|
|
|
1356
1356
|
// sprite factory
|
|
1357
1357
|
createSprite: function(opts) {
|
|
1358
|
-
if (!_initilised) throw new Error('createSprite: punter.
|
|
1358
|
+
if (!_initilised) throw new Error('createSprite: punter.setup must be called first');
|
|
1359
1359
|
return new Sprite(opts);
|
|
1360
1360
|
},
|
|
1361
1361
|
getSprite: function(id) {
|
package/tests/interface-spec.js
CHANGED
|
@@ -19,7 +19,7 @@ describe('Interface', function () {
|
|
|
19
19
|
it('exposes the expected methods', async function () {
|
|
20
20
|
var result = await page.evaluate(function () {
|
|
21
21
|
return {
|
|
22
|
-
|
|
22
|
+
setup: typeof punter.setup,
|
|
23
23
|
scene: typeof punter.scene,
|
|
24
24
|
go: typeof punter.go,
|
|
25
25
|
on: typeof punter.on,
|