littlejsengine 1.1.2 → 1.1.3
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 +55 -0
- package/build.bat +2 -1
- package/engine/engine.all.js +1320 -930
- package/engine/engine.all.min.js +1 -1
- package/engine/engine.all.release.js +965 -601
- package/engine/engine.js +71 -60
- package/engine/engineAudio.js +80 -22
- package/engine/engineBuild.bat +2 -2
- package/engine/engineDebug.js +65 -36
- package/engine/engineDraw.js +71 -56
- package/engine/engineInput.js +178 -28
- package/engine/engineMedals.js +66 -58
- package/engine/engineObject.js +86 -71
- package/engine/engineParticles.js +101 -63
- package/engine/engineRelease.js +4 -1
- package/engine/engineSettings.js +62 -53
- package/engine/engineTileLayer.js +99 -83
- package/engine/engineUtilities.js +95 -59
- package/engine/engineWebGL.js +53 -48
- package/examples/breakout/game.js +1 -1
- package/examples/breakout/gameObjects.js +2 -2
- package/examples/breakout/index.html +7 -5
- package/examples/platformer/game.js +7 -4
- package/examples/platformer/gameEffects.js +8 -11
- package/examples/platformer/gameLevel.js +15 -8
- package/examples/platformer/gameObjects.js +2 -2
- package/examples/platformer/gamePlayer.js +6 -6
- package/examples/platformer/index.html +10 -8
- package/examples/puzzle/game.js +3 -3
- package/examples/puzzle/index.html +6 -4
- package/examples/stress/index.html +7 -5
- package/game.js +10 -10
- package/index.html +17 -15
- package/package.json +4 -7
- package/tiles.png +0 -0
- package/LittleJS.zip +0 -0
- package/docs/Audio.html +0 -2264
- package/docs/Color.html +0 -2506
- package/docs/Debug.html +0 -2929
- package/docs/Draw.html +0 -3854
- package/docs/EngineObject.html +0 -2506
- package/docs/Input.html +0 -2478
- package/docs/Medal.html +0 -992
- package/docs/Medals.html +0 -624
- package/docs/Music.html +0 -569
- package/docs/Newgrounds.html +0 -1384
- package/docs/Particle.html +0 -567
- package/docs/ParticleEmitter.html +0 -1537
- package/docs/Random.html +0 -1770
- package/docs/Settings.html +0 -2885
- package/docs/Sound.html +0 -998
- package/docs/TileLayer.html +0 -3211
- package/docs/TileLayerData.html +0 -569
- package/docs/Timer.html +0 -1168
- package/docs/Utilities.html +0 -3266
- package/docs/Vector2.html +0 -3956
- package/docs/WebGL.html +0 -1842
- package/docs/engine.js.html +0 -428
- package/docs/engineAudio.js.html +0 -567
- package/docs/engineDebug.js.html +0 -721
- package/docs/engineDraw.js.html +0 -409
- package/docs/engineInput.js.html +0 -397
- package/docs/engineMedals.js.html +0 -445
- package/docs/engineObject.js.html +0 -492
- package/docs/engineParticles.js.html +0 -399
- package/docs/engineSettings.js.html +0 -358
- package/docs/engineTileLayer.js.html +0 -482
- package/docs/engineUtilities.js.html +0 -600
- package/docs/engineWebGL.js.html +0 -507
- package/docs/fonts/MavenPro-Regular.ttf +0 -0
- package/docs/fonts/Montserrat-Regular.ttf +0 -0
- package/docs/fonts/Muli-Black.ttf +0 -0
- package/docs/fonts/OFL-hind.txt +0 -93
- package/docs/fonts/OFL-montserrat.txt +0 -93
- package/docs/global.html +0 -1635
- package/docs/index.html +0 -243
- package/docs/scripts/fix-code-block.js +0 -53
- package/docs/scripts/fix-navbar.js +0 -25
- package/docs/scripts/linenumber.js +0 -25
- package/docs/scripts/misc.js +0 -217
- package/docs/scripts/resize.js +0 -85
- package/docs/scripts/search.js +0 -83
- package/docs/scripts/third-party/Apache-License-2.0.txt +0 -202
- package/docs/scripts/third-party/fuse.js +0 -9
- package/docs/scripts/third-party/lang-css.js +0 -2
- package/docs/scripts/third-party/prettify.js +0 -28
- package/docs/static/favicon.png +0 -0
- package/docs/styles/clean-jsdoc-theme-base.css +0 -393
- package/docs/styles/clean-jsdoc-theme-dark.css +0 -324
- package/docs/styles/clean-jsdoc-theme-light.css +0 -319
- package/docs/styles/reset.css +0 -346
- package/docs/styles/third-party/ionicons.min.css +0 -11
- package/docs/styles/third-party/prettify-jsdoc.css +0 -111
- package/docs/styles/third-party/prettify-tomorrow.css +0 -5
package/engine/engineWebGL.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
2
|
+
* LittleJS WebGL Interface
|
|
3
|
+
* <br> - All webgl used by the engine is wrapped up here
|
|
4
|
+
* <br> - For normal stuff you won't need to see or call anything in this file
|
|
5
|
+
* <br> - For advanced stuff there are helper functions to create shaders, textures, etc
|
|
6
|
+
* <br> - Can be disabled with glEnable to revert to 2D canvas rendering
|
|
7
|
+
* <br> - Batches sprite rendering on GPU for incredibly fast performance
|
|
8
|
+
* <br> - Sprite transform math is done in the shader where possible
|
|
9
|
+
* @namespace WebGL
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
@@ -27,7 +27,7 @@ let glContext;
|
|
|
27
27
|
let glTileTexture;
|
|
28
28
|
|
|
29
29
|
// WebGL internal variables not exposed to documentation
|
|
30
|
-
let glActiveTexture, glShader, glPositionData, glColorData, glBatchCount,
|
|
30
|
+
let glActiveTexture, glShader, glPositionData, glColorData, glBatchCount, glBatchAdditive, glAdditive;
|
|
31
31
|
|
|
32
32
|
///////////////////////////////////////////////////////////////////////////////
|
|
33
33
|
|
|
@@ -38,19 +38,16 @@ function glInit()
|
|
|
38
38
|
|
|
39
39
|
// create the canvas and tile texture
|
|
40
40
|
glCanvas = document.createElement('canvas');
|
|
41
|
-
glContext = glCanvas.getContext('webgl'
|
|
41
|
+
glContext = glCanvas.getContext('webgl');
|
|
42
|
+
glCanvas.style = styleCanvas;
|
|
42
43
|
glTileTexture = glCreateTexture(tileImage);
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// firefox is much faster without copying the gl buffer so we just overlay it with some tradeoffs
|
|
47
|
-
document.body.appendChild(glCanvas);
|
|
48
|
-
glCanvas.style = mainCanvas.style.cssText;
|
|
49
|
-
}
|
|
45
|
+
// some browsers are much faster without copying the gl buffer so we just overlay it instead
|
|
46
|
+
glOverlay && document.body.appendChild(glCanvas);
|
|
50
47
|
|
|
51
48
|
// setup vertex and fragment shaders
|
|
52
49
|
glShader = glCreateProgram(
|
|
53
|
-
'precision
|
|
50
|
+
'precision highp float;'+ // use highp for better accuracy, lowp for better perf
|
|
54
51
|
'uniform mat4 m;'+ // transform matrix
|
|
55
52
|
'attribute float a;'+ // angle
|
|
56
53
|
'attribute vec2 p,s,t;'+ // position, size, uv
|
|
@@ -62,7 +59,7 @@ function glInit()
|
|
|
62
59
|
'v=t;d=c;e=b;'+ // pass stuff to fragment shader
|
|
63
60
|
'}' // end of shader
|
|
64
61
|
,
|
|
65
|
-
'precision
|
|
62
|
+
'precision highp float;'+ // use highp for better accuracy, lowp for better perf
|
|
66
63
|
'varying vec2 v;'+ // uv
|
|
67
64
|
'varying vec4 d,e;'+ // color, additiveColor
|
|
68
65
|
'uniform sampler2D j;'+ // texture
|
|
@@ -78,6 +75,7 @@ function glInit()
|
|
|
78
75
|
glColorData = new Uint32Array(glVertexData);
|
|
79
76
|
|
|
80
77
|
// setup the vertex data array
|
|
78
|
+
let offset = glBatchCount = 0;
|
|
81
79
|
const initVertexAttribArray = (name, type, typeSize, size, normalize=0)=>
|
|
82
80
|
{
|
|
83
81
|
const location = glContext.getAttribLocation(glShader, name);
|
|
@@ -85,7 +83,6 @@ function glInit()
|
|
|
85
83
|
glContext.vertexAttribPointer(location, size, type, normalize, gl_VERTEX_BYTE_STRIDE, offset);
|
|
86
84
|
offset += size*typeSize;
|
|
87
85
|
}
|
|
88
|
-
let offset = glDirty = glBatchCount = 0;
|
|
89
86
|
initVertexAttribArray('a', gl_FLOAT, 4, 1); // angle
|
|
90
87
|
initVertexAttribArray('p', gl_FLOAT, 4, 2); // position
|
|
91
88
|
initVertexAttribArray('s', gl_FLOAT, 4, 2); // size
|
|
@@ -101,14 +98,8 @@ function glSetBlendMode(additive)
|
|
|
101
98
|
{
|
|
102
99
|
if (!glEnable) return;
|
|
103
100
|
|
|
104
|
-
if (additive != glAdditive)
|
|
105
|
-
glFlush();
|
|
106
|
-
|
|
107
101
|
// setup blending
|
|
108
102
|
glAdditive = additive;
|
|
109
|
-
const destBlend = additive ? gl_ONE : gl_ONE_MINUS_SRC_ALPHA;
|
|
110
|
-
glContext.blendFuncSeparate(gl_SRC_ALPHA, destBlend, gl_ONE, destBlend);
|
|
111
|
-
glContext.enable(gl_BLEND);
|
|
112
103
|
}
|
|
113
104
|
|
|
114
105
|
/** Set the WebGl texture, not normally necessary unless multiple tile sheets are used
|
|
@@ -118,7 +109,8 @@ function glSetBlendMode(additive)
|
|
|
118
109
|
function glSetTexture(texture=glTileTexture)
|
|
119
110
|
{
|
|
120
111
|
if (!glEnable) return;
|
|
121
|
-
|
|
112
|
+
|
|
113
|
+
// must flush cache with the old texture to set a new one
|
|
122
114
|
if (texture != glActiveTexture)
|
|
123
115
|
glFlush();
|
|
124
116
|
|
|
@@ -183,36 +175,35 @@ function glCreateBuffer(bufferType, size, usage)
|
|
|
183
175
|
return buffer;
|
|
184
176
|
}
|
|
185
177
|
|
|
186
|
-
/** Create WebGL texture from an image
|
|
178
|
+
/** Create WebGL texture from an image and set the texture settings
|
|
187
179
|
* @param {Image} image
|
|
188
180
|
* @return {WebGLTexture}
|
|
189
181
|
* @memberof WebGL */
|
|
190
182
|
function glCreateTexture(image)
|
|
191
183
|
{
|
|
192
|
-
if (!glEnable) return;
|
|
184
|
+
if (!glEnable || !image || !image.width) return;
|
|
193
185
|
|
|
194
186
|
// build the texture
|
|
195
187
|
const texture = glContext.createTexture();
|
|
196
188
|
glContext.bindTexture(gl_TEXTURE_2D, texture);
|
|
197
189
|
glContext.texImage2D(gl_TEXTURE_2D, 0, gl_RGBA, gl_RGBA, gl_UNSIGNED_BYTE, image);
|
|
198
|
-
|
|
190
|
+
|
|
199
191
|
// use point filtering for pixelated rendering
|
|
200
|
-
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_MIN_FILTER,
|
|
201
|
-
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_MAG_FILTER,
|
|
192
|
+
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_MIN_FILTER, cavasPixelated ? gl_NEAREST : gl_LINEAR);
|
|
193
|
+
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_MAG_FILTER, cavasPixelated ? gl_NEAREST : gl_LINEAR);
|
|
202
194
|
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_WRAP_S, gl_CLAMP_TO_EDGE);
|
|
203
195
|
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_WRAP_T, gl_CLAMP_TO_EDGE);
|
|
204
196
|
return texture;
|
|
205
197
|
}
|
|
206
198
|
|
|
207
199
|
// called automatically by engine before render
|
|
208
|
-
function glPreRender(width, height)
|
|
200
|
+
function glPreRender(width, height, cameraX, cameraY, cameraScale)
|
|
209
201
|
{
|
|
210
202
|
if (!glEnable) return;
|
|
211
203
|
|
|
212
204
|
// clear and set to same size as main canvas
|
|
213
|
-
glCanvas.width = width;
|
|
214
|
-
|
|
215
|
-
glContext.viewport(0, 0, width, height);
|
|
205
|
+
glContext.viewport(0, 0, glCanvas.width = width, glCanvas.height = height);
|
|
206
|
+
glContext.clear(gl_COLOR_BUFFER_BIT);
|
|
216
207
|
|
|
217
208
|
// set up the shader
|
|
218
209
|
glContext.bindTexture(gl_TEXTURE_2D, glActiveTexture = glTileTexture);
|
|
@@ -227,7 +218,7 @@ function glPreRender(width, height)
|
|
|
227
218
|
sx, 0, 0, 0,
|
|
228
219
|
0, sy, 0, 0,
|
|
229
220
|
1, 1, -1, 1,
|
|
230
|
-
-1-sx*
|
|
221
|
+
-1-sx*cameraX, -1-sy*cameraY, 0, 0
|
|
231
222
|
])
|
|
232
223
|
);
|
|
233
224
|
}
|
|
@@ -238,11 +229,16 @@ function glFlush()
|
|
|
238
229
|
{
|
|
239
230
|
if (!glEnable || !glBatchCount) return;
|
|
240
231
|
|
|
232
|
+
const destBlend = glBatchAdditive ? gl_ONE : gl_ONE_MINUS_SRC_ALPHA;
|
|
233
|
+
glContext.blendFuncSeparate(gl_SRC_ALPHA, destBlend, gl_ONE, destBlend);
|
|
234
|
+
glContext.enable(gl_BLEND);
|
|
235
|
+
|
|
241
236
|
// draw all the sprites in the batch and reset the buffer
|
|
242
237
|
glContext.bufferSubData(gl_ARRAY_BUFFER, 0,
|
|
243
238
|
glPositionData.subarray(0, glBatchCount * gl_VERTICES_PER_QUAD * gl_INDICIES_PER_VERT));
|
|
244
239
|
glContext.drawArrays(gl_TRIANGLES, 0, glBatchCount * gl_VERTICES_PER_QUAD);
|
|
245
240
|
glBatchCount = 0;
|
|
241
|
+
glBatchAdditive = glAdditive;
|
|
246
242
|
}
|
|
247
243
|
|
|
248
244
|
/** Draw any sprites still in the buffer, copy to main canvas and clear
|
|
@@ -251,29 +247,38 @@ function glFlush()
|
|
|
251
247
|
* @memberof WebGL */
|
|
252
248
|
function glCopyToContext(context, forceDraw)
|
|
253
249
|
{
|
|
254
|
-
if (!glEnable || !
|
|
250
|
+
if (!glEnable || !glBatchCount) return;
|
|
255
251
|
|
|
256
252
|
glFlush();
|
|
253
|
+
|
|
254
|
+
// do not draw in overlay mode because the canvas is visible
|
|
257
255
|
if (!glOverlay || forceDraw)
|
|
258
|
-
|
|
259
|
-
// do not draw/clear in overlay mode because the canvas is visible
|
|
260
|
-
context.drawImage(glCanvas, 0, glAdditive = glDirty = 0);
|
|
261
|
-
glContext.clear(gl_COLOR_BUFFER_BIT);
|
|
262
|
-
}
|
|
256
|
+
context.drawImage(glCanvas, 0, 0);
|
|
263
257
|
}
|
|
264
258
|
|
|
265
|
-
|
|
266
|
-
|
|
259
|
+
/** Add a sprite to the gl draw list, used by all gl draw functions
|
|
260
|
+
* @param x
|
|
261
|
+
* @param y
|
|
262
|
+
* @param sizeX
|
|
263
|
+
* @param sizeY
|
|
264
|
+
* @param angle
|
|
265
|
+
* @param uv0X
|
|
266
|
+
* @param uv0Y
|
|
267
|
+
* @param uv1X
|
|
268
|
+
* @param uv1Y
|
|
269
|
+
* @param [rgba=0xffffffff]
|
|
270
|
+
* @param [rgbaAdditive=0]
|
|
271
|
+
* @memberof WebGL */
|
|
272
|
+
function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba=0xffffffff, rgbaAdditive=0)
|
|
267
273
|
{
|
|
268
274
|
if (!glEnable) return;
|
|
269
|
-
|
|
270
|
-
// flush if there is no room for more verts
|
|
271
|
-
if (glBatchCount == gl_MAX_BATCH)
|
|
275
|
+
|
|
276
|
+
// flush if there is no room for more verts or if different blend mode
|
|
277
|
+
if (glBatchCount == gl_MAX_BATCH || glBatchAdditive != glAdditive)
|
|
272
278
|
glFlush();
|
|
273
279
|
|
|
274
280
|
// setup 2 triangles to form a quad
|
|
275
281
|
let offset = glBatchCount++ * gl_VERTICES_PER_QUAD * gl_INDICIES_PER_VERT;
|
|
276
|
-
glDirty = 1;
|
|
277
282
|
|
|
278
283
|
// vertex 0
|
|
279
284
|
glPositionData[offset++] = angle;
|
|
@@ -14,7 +14,7 @@ const sound_bounce = new Sound([,,1e3,,.03,.02,1,2,,,940,.03,,,,,.2,.6,,.06]
|
|
|
14
14
|
///////////////////////////////////////////////////////////////////////////////
|
|
15
15
|
function gameInit()
|
|
16
16
|
{
|
|
17
|
-
|
|
17
|
+
canvasFixedSize = vec2(1280, 720); // 720p
|
|
18
18
|
levelSize = vec2(72, 40);
|
|
19
19
|
cameraPos = levelSize.scale(.5);
|
|
20
20
|
paddle = new Paddle(vec2(levelSize.x/2-12,2));
|
|
@@ -18,7 +18,7 @@ class Paddle extends EngineObject
|
|
|
18
18
|
|
|
19
19
|
update()
|
|
20
20
|
{
|
|
21
|
-
if (
|
|
21
|
+
if (isUsingGamepad)
|
|
22
22
|
{
|
|
23
23
|
// control with gamepad
|
|
24
24
|
this.pos.x += gamepadStick(0).x;
|
|
@@ -28,7 +28,7 @@ class Paddle extends EngineObject
|
|
|
28
28
|
// move to mouse
|
|
29
29
|
this.pos.x = mousePos.x;
|
|
30
30
|
}
|
|
31
|
-
this.pos.x = clamp(this.pos.x,
|
|
31
|
+
this.pos.x = clamp(this.pos.x, this.size.x/2, levelSize.x - this.size.x/2);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
<html><head><
|
|
2
|
-
<meta name=viewport content=width=device-width,initial-scale=1,maximum-scale=1>
|
|
1
|
+
<html><head><meta charset=utf-8>
|
|
2
|
+
<meta name=viewport content=width=device-width,height=device-height,initial-scale=1,maximum-scale=1>
|
|
3
|
+
<meta name=apple-mobile-web-app-capable content=yes>
|
|
4
|
+
<meta name=mobile-web-app-capable content=yes>
|
|
3
5
|
<link rel=icon type=image/png href=../../favicon.png>
|
|
4
6
|
</head><body>
|
|
5
7
|
|
|
6
|
-
<script src=../../engine/engine.all.
|
|
7
|
-
<script src=game.js?
|
|
8
|
-
<script src=gameObjects.js?
|
|
8
|
+
<script src=../../engine/engine.all.js?93></script>
|
|
9
|
+
<script src=game.js?93></script>
|
|
10
|
+
<script src=gameObjects.js?93></script>
|
|
@@ -10,6 +10,9 @@ let score, deaths;
|
|
|
10
10
|
///////////////////////////////////////////////////////////////////////////////
|
|
11
11
|
function gameInit()
|
|
12
12
|
{
|
|
13
|
+
// enable touch gamepad on touch devices
|
|
14
|
+
touchGamepadEnable = 1;
|
|
15
|
+
|
|
13
16
|
// setup game
|
|
14
17
|
score = deaths = 0;
|
|
15
18
|
gravity = -.01;
|
|
@@ -30,7 +33,7 @@ function gameUpdate()
|
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
// mouse wheel = zoom
|
|
33
|
-
cameraScale = clamp(cameraScale*(1-mouseWheel/10),
|
|
36
|
+
cameraScale = clamp(cameraScale*(1-mouseWheel/10), 1, 1e3);
|
|
34
37
|
|
|
35
38
|
// T = drop test crate
|
|
36
39
|
if (keyWasPressed(84))
|
|
@@ -70,7 +73,7 @@ function gameRender()
|
|
|
70
73
|
function gameRenderPost()
|
|
71
74
|
{
|
|
72
75
|
// draw to overlay canvas for hud rendering
|
|
73
|
-
const
|
|
76
|
+
const drawText = (text, x, y, size=70) =>
|
|
74
77
|
{
|
|
75
78
|
overlayContext.textAlign = 'center';
|
|
76
79
|
overlayContext.textBaseline = 'top';
|
|
@@ -80,8 +83,8 @@ function gameRenderPost()
|
|
|
80
83
|
overlayContext.strokeText(text, x, y);
|
|
81
84
|
overlayContext.fillText(text, x, y);
|
|
82
85
|
}
|
|
83
|
-
|
|
84
|
-
|
|
86
|
+
drawText('Score: ' + score, overlayCanvas.width*1/3, 20);
|
|
87
|
+
drawText('Deaths: ' + deaths, overlayCanvas.width*2/3, 20);
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -89,7 +89,7 @@ function explosion(pos, radius=3)
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
// push
|
|
92
|
-
const p = percent(d, radius,
|
|
92
|
+
const p = percent(d, 2*radius, radius);
|
|
93
93
|
const force = o.pos.subtract(pos).normalize(p*radius*.2);
|
|
94
94
|
o.applyForce(force);
|
|
95
95
|
if (o.isDead && o.isDead())
|
|
@@ -157,6 +157,9 @@ function destroyTile(pos, makeSound = 1, cleanNeighbors = 1)
|
|
|
157
157
|
|
|
158
158
|
function decorateBackgroundTile(pos)
|
|
159
159
|
{
|
|
160
|
+
if (!tileBackgroundLayer)
|
|
161
|
+
return;
|
|
162
|
+
|
|
160
163
|
const tileData = getTileBackgroundData(pos);
|
|
161
164
|
if (tileData <= 0)
|
|
162
165
|
return;
|
|
@@ -254,17 +257,11 @@ function drawStars()
|
|
|
254
257
|
(randSeeded(w)+time*speed)%w-extraSpace,
|
|
255
258
|
(randSeeded(h)+time*speed*randSeeded())%h-extraSpace);
|
|
256
259
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
mainContext.fillStyle = color.rgba();
|
|
261
|
-
if (size < 9)
|
|
262
|
-
mainContext.fillRect(screenPos.x, screenPos.y, size, size);
|
|
263
|
-
else
|
|
264
|
-
mainContext.beginPath(mainContext.fill(mainContext.arc(screenPos.x, screenPos.y, size, 0, 9)));
|
|
265
|
-
}
|
|
260
|
+
mainContext.fillStyle = color.rgba();
|
|
261
|
+
if (size < 9)
|
|
262
|
+
mainContext.fillRect(screenPos.x, screenPos.y, size, size);
|
|
266
263
|
else
|
|
267
|
-
|
|
264
|
+
mainContext.beginPath(mainContext.fill(mainContext.arc(screenPos.x, screenPos.y, size, 0, 9)));
|
|
268
265
|
}
|
|
269
266
|
}
|
|
270
267
|
|
|
@@ -28,7 +28,7 @@ function buildTerrain(size)
|
|
|
28
28
|
{
|
|
29
29
|
tileBackground = [];
|
|
30
30
|
initTileCollision(size);
|
|
31
|
-
let startGroundLevel =
|
|
31
|
+
let startGroundLevel = 40;
|
|
32
32
|
let groundLevel = startGroundLevel;
|
|
33
33
|
let groundSlope = rand(-1,1);
|
|
34
34
|
let backgroundDelta = 0, backgroundDeltaSlope = 0;
|
|
@@ -46,7 +46,7 @@ function buildTerrain(size)
|
|
|
46
46
|
{
|
|
47
47
|
// big jump
|
|
48
48
|
const jumpDelta = rand(19,-19);
|
|
49
|
-
startGroundLevel = clamp(startGroundLevel + jumpDelta,
|
|
49
|
+
startGroundLevel = clamp(startGroundLevel + jumpDelta, 20, 80);
|
|
50
50
|
groundLevel += jumpDelta;
|
|
51
51
|
groundSlope = rand(-1,1);
|
|
52
52
|
}
|
|
@@ -58,9 +58,9 @@ function buildTerrain(size)
|
|
|
58
58
|
backgroundDelta = 0;
|
|
59
59
|
if (rand() < .1)
|
|
60
60
|
backgroundDeltaSlope = rand(-1,1);
|
|
61
|
-
backgroundDelta = clamp(backgroundDelta,
|
|
61
|
+
backgroundDelta = clamp(backgroundDelta, -1, 3)
|
|
62
62
|
|
|
63
|
-
groundLevel = clamp(groundLevel,
|
|
63
|
+
groundLevel = clamp(groundLevel, 20, levelSize.y-20);
|
|
64
64
|
for (let y=0; y < size.y; y++)
|
|
65
65
|
{
|
|
66
66
|
const pos = vec2(x,y);
|
|
@@ -90,7 +90,7 @@ function buildTerrain(size)
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
// add ladders
|
|
93
|
-
for (let ladderCount=
|
|
93
|
+
for (let ladderCount = 40; ladderCount--;)
|
|
94
94
|
{
|
|
95
95
|
// pick random pos
|
|
96
96
|
const pos = vec2(randInt(levelSize.x), randInt(levelSize.y))
|
|
@@ -122,7 +122,7 @@ function buildTerrain(size)
|
|
|
122
122
|
new Crate(vec2((randInt(levelSize.x))+.5, randInt(levelSize.y)));
|
|
123
123
|
|
|
124
124
|
// spawn enemies
|
|
125
|
-
for (let enemyCount=
|
|
125
|
+
for (let enemyCount=10; enemyCount--;)
|
|
126
126
|
new Enemy(vec2(rand(levelSize.x), rand(levelSize.y)));
|
|
127
127
|
}
|
|
128
128
|
|
|
@@ -181,11 +181,18 @@ function makeTileLayers()
|
|
|
181
181
|
}
|
|
182
182
|
tileLayer.redraw();
|
|
183
183
|
tileBackgroundLayer.redraw();
|
|
184
|
+
|
|
185
|
+
if (!glEnable)
|
|
186
|
+
{
|
|
187
|
+
// get rid of background if webgl is not enabled
|
|
188
|
+
tileBackgroundLayer.destroy();
|
|
189
|
+
tileBackgroundLayer = 0;
|
|
190
|
+
}
|
|
184
191
|
}
|
|
185
192
|
|
|
186
193
|
function buildLevel()
|
|
187
194
|
{
|
|
188
|
-
levelSize = vec2(
|
|
195
|
+
levelSize = vec2(256);
|
|
189
196
|
levelColor = randColor(new Color(.2,.2,.2), new Color(.8,.8,.8));
|
|
190
197
|
levelGroundColor = levelColor.mutate().add(new Color(.4,.4,.4)).clamp();
|
|
191
198
|
|
|
@@ -205,7 +212,7 @@ function buildLevel()
|
|
|
205
212
|
|
|
206
213
|
// warm up level
|
|
207
214
|
warmup = 1;
|
|
208
|
-
for (let i=5*
|
|
215
|
+
for (let i=5*frameRate; i--;)
|
|
209
216
|
engineObjectsUpdate();
|
|
210
217
|
warmup = 0;
|
|
211
218
|
|
|
@@ -25,7 +25,7 @@ class GameObject extends EngineObject
|
|
|
25
25
|
// flash white when damaged
|
|
26
26
|
if (!this.isDead() && this.damageTimer.isSet())
|
|
27
27
|
{
|
|
28
|
-
const a = .5*percent(this.damageTimer.get(),
|
|
28
|
+
const a = .5*percent(this.damageTimer.get(), .15, 0);
|
|
29
29
|
this.additiveColor = new Color(a,a,a,0);
|
|
30
30
|
}
|
|
31
31
|
else
|
|
@@ -66,7 +66,7 @@ class Crate extends GameObject
|
|
|
66
66
|
{
|
|
67
67
|
constructor(pos, typeOverride)
|
|
68
68
|
{
|
|
69
|
-
super(pos,
|
|
69
|
+
super(pos, objectDefaultSize, 2, vec2(16), (randInt(4))*PI/2);
|
|
70
70
|
|
|
71
71
|
this.color = (new Color).setHSLA(rand(),1,.8);
|
|
72
72
|
this.health = 5;
|
|
@@ -24,7 +24,7 @@ class Character extends GameObject
|
|
|
24
24
|
this.deadTimer = new Timer;
|
|
25
25
|
this.grendeThrowTimer = new Timer;
|
|
26
26
|
this.drawSize = vec2(1);
|
|
27
|
-
this.color = (new Color).setHSLA(rand(),1,.
|
|
27
|
+
this.color = (new Color).setHSLA(rand(),1,.7);
|
|
28
28
|
this.renderOrder = 10;
|
|
29
29
|
this.walkCyclePercent = 0;
|
|
30
30
|
this.health = 1;
|
|
@@ -169,7 +169,7 @@ class Character extends GameObject
|
|
|
169
169
|
|
|
170
170
|
// apply movement acceleration and clamp
|
|
171
171
|
const maxCharacterSpeed = .2;
|
|
172
|
-
this.velocity.x = clamp(this.velocity.x + moveInput.x * .042, maxCharacterSpeed,
|
|
172
|
+
this.velocity.x = clamp(this.velocity.x + moveInput.x * .042, -maxCharacterSpeed, maxCharacterSpeed);
|
|
173
173
|
|
|
174
174
|
// track last pos for ladder collision code
|
|
175
175
|
this.lastPos = this.pos.copy();
|
|
@@ -182,7 +182,7 @@ class Character extends GameObject
|
|
|
182
182
|
if (this.climbingLadder || this.groundTimer.active() && !this.dodgeTimer.active())
|
|
183
183
|
{
|
|
184
184
|
this.walkCyclePercent += speed * .5;
|
|
185
|
-
this.walkCyclePercent = speed > .01 ? mod(this.walkCyclePercent
|
|
185
|
+
this.walkCyclePercent = speed > .01 ? mod(this.walkCyclePercent) : 0;
|
|
186
186
|
}
|
|
187
187
|
else
|
|
188
188
|
this.walkCyclePercent = 0;
|
|
@@ -292,11 +292,11 @@ class Player extends Character
|
|
|
292
292
|
// player controls
|
|
293
293
|
this.holdingJump = keyIsDown(38) || gamepadIsDown(0);
|
|
294
294
|
this.holdingShoot = mouseIsDown(0) || keyIsDown(90) || gamepadIsDown(2);
|
|
295
|
-
this.
|
|
296
|
-
this.
|
|
295
|
+
this.pressingThrow = mouseIsDown(1) || keyIsDown(67) || gamepadIsDown(1);
|
|
296
|
+
this.pressedDodge = mouseIsDown(2) || keyIsDown(88) || gamepadIsDown(3);
|
|
297
297
|
|
|
298
298
|
// movement control
|
|
299
|
-
this.moveInput =
|
|
299
|
+
this.moveInput = isUsingGamepad ? gamepadStick(0) :
|
|
300
300
|
vec2(keyIsDown(39) - keyIsDown(37), keyIsDown(38) - keyIsDown(40));
|
|
301
301
|
|
|
302
302
|
super.update();
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
<html><head><
|
|
2
|
-
<meta name=viewport content=width=device-width,initial-scale=1,maximum-scale=1>
|
|
1
|
+
<html><head><meta charset=utf-8>
|
|
2
|
+
<meta name=viewport content=width=device-width,height=device-height,initial-scale=1,maximum-scale=1>
|
|
3
|
+
<meta name=apple-mobile-web-app-capable content=yes>
|
|
4
|
+
<meta name=mobile-web-app-capable content=yes>
|
|
3
5
|
<link rel=icon type=image/png href=../../favicon.png>
|
|
4
6
|
</head><body>
|
|
5
7
|
|
|
6
|
-
<script src=../../engine/engine.all.
|
|
7
|
-
<script src=gameObjects.js?
|
|
8
|
-
<script src=gamePlayer.js?
|
|
9
|
-
<script src=gameEffects.js?
|
|
10
|
-
<script src=gameLevel.js?
|
|
11
|
-
<script src=game.js?
|
|
8
|
+
<script src=../../engine/engine.all.js?93></script>
|
|
9
|
+
<script src=gameObjects.js?93></script>
|
|
10
|
+
<script src=gamePlayer.js?93></script>
|
|
11
|
+
<script src=gameEffects.js?93></script>
|
|
12
|
+
<script src=gameLevel.js?93></script>
|
|
13
|
+
<script src=game.js?93></script>
|
package/examples/puzzle/game.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
cavasPixelated = 0; // do not use pixelated rendering
|
|
10
10
|
|
|
11
11
|
const fallTime = .2;
|
|
12
12
|
const cameraOffset = vec2(0,-.5);
|
|
@@ -42,7 +42,7 @@ const setTile = (pos, data) => level[pos.x + pos.y * levelSize.x] = data;
|
|
|
42
42
|
function gameInit()
|
|
43
43
|
{
|
|
44
44
|
// setup canvas
|
|
45
|
-
|
|
45
|
+
canvasFixedSize = vec2(1920, 1080); // 1080p
|
|
46
46
|
mainCanvas.style.background = backgroundColor.rgba();
|
|
47
47
|
|
|
48
48
|
// load high score
|
|
@@ -100,7 +100,7 @@ function gameUpdate()
|
|
|
100
100
|
|
|
101
101
|
if (keepFalling)
|
|
102
102
|
{
|
|
103
|
-
const p = percent(comboCount,
|
|
103
|
+
const p = percent(comboCount, 9, 0);
|
|
104
104
|
fallTimer.set(fallTime*p);
|
|
105
105
|
sound_fall.play();
|
|
106
106
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
<html><head><
|
|
2
|
-
<meta name=viewport content=width=device-width,initial-scale=1,maximum-scale=1>
|
|
1
|
+
<html><head><meta charset=utf-8>
|
|
2
|
+
<meta name=viewport content=width=device-width,height=device-height,initial-scale=1,maximum-scale=1>
|
|
3
|
+
<meta name=apple-mobile-web-app-capable content=yes>
|
|
4
|
+
<meta name=mobile-web-app-capable content=yes>
|
|
3
5
|
<link rel=icon type=image/png href=../../favicon.png>
|
|
4
6
|
</head><body>
|
|
5
7
|
|
|
6
|
-
<script src=../../engine/engine.all.
|
|
7
|
-
<script src=game.js?
|
|
8
|
+
<script src=../../engine/engine.all.js?93></script>
|
|
9
|
+
<script src=game.js?93></script>
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
<html><head><
|
|
2
|
-
<meta name=viewport content=width=device-width,initial-scale=1,maximum-scale=1>
|
|
1
|
+
<html><head><meta charset=utf-8>
|
|
2
|
+
<meta name=viewport content=width=device-width,height=device-height,initial-scale=1,maximum-scale=1>
|
|
3
|
+
<meta name=apple-mobile-web-app-capable content=yes>
|
|
4
|
+
<meta name=mobile-web-app-capable content=yes>
|
|
3
5
|
<link rel=icon type=image/png href=../../favicon.png>
|
|
4
6
|
</head><body>
|
|
5
7
|
|
|
6
|
-
<script src=../../engine/engine.all.min.js?
|
|
8
|
+
<script src=../../engine/engine.all.min.js?93></script>
|
|
7
9
|
<script>
|
|
8
10
|
|
|
9
11
|
/*
|
|
@@ -81,7 +83,7 @@ function gameUpdate()
|
|
|
81
83
|
});
|
|
82
84
|
|
|
83
85
|
// mouse wheel = zoom
|
|
84
|
-
cameraScale = clamp(cameraScale*(1-mouseWheel/10),
|
|
86
|
+
cameraScale = clamp(cameraScale*(1-mouseWheel/10), 1, 1e3);
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -94,7 +96,7 @@ function gameRender()
|
|
|
94
96
|
{
|
|
95
97
|
// track fps and update stats
|
|
96
98
|
const frameTimeMS = Date.now();
|
|
97
|
-
showFPS = lerp(.05, 1e3/(frameTimeMS - timeMS||1)
|
|
99
|
+
showFPS = lerp(.05, showFPS, 1e3/(frameTimeMS - timeMS||1));
|
|
98
100
|
timeMS = frameTimeMS;
|
|
99
101
|
|
|
100
102
|
const spriteCount = sprites.length
|
package/game.js
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
'use strict';
|
|
6
6
|
|
|
7
|
+
// popup errors if there are any (help diagnose issues on mobile devices)
|
|
8
|
+
if (debug)
|
|
9
|
+
onerror = (...parameters)=> alert(parameters);
|
|
10
|
+
|
|
7
11
|
// game variables
|
|
8
12
|
let particleEmiter, clickCount = 0;
|
|
9
13
|
|
|
@@ -11,7 +15,7 @@ let particleEmiter, clickCount = 0;
|
|
|
11
15
|
const sound_click = new Sound([.5,.5]);
|
|
12
16
|
|
|
13
17
|
// medals
|
|
14
|
-
const medal_example = new Medal(0, 'Example Medal', '
|
|
18
|
+
const medal_example = new Medal(0, 'Example Medal', 'Medal description goes here.');
|
|
15
19
|
const medal_tenClicks = new Medal(1, 'Ten Clicks!', 'You have clicked 10 times.', '🖱️');
|
|
16
20
|
medalsInit('Hello World');
|
|
17
21
|
|
|
@@ -60,7 +64,7 @@ function gameInit()
|
|
|
60
64
|
new Color(1,1,1,0), new Color(0,0,0,0), // colorEndA, colorEndB
|
|
61
65
|
2, .2, .2, .1, .05, // particleTime, sizeStart, sizeEnd, particleSpeed, particleAngleSpeed
|
|
62
66
|
.99, 1, 1, PI, .05, // damping, angleDamping, gravityScale, particleCone, fadeRate,
|
|
63
|
-
.5, 1 // randomness, collide, additive, randomColorLinear, renderOrder
|
|
67
|
+
.5, 1, 1 // randomness, collide, additive, randomColorLinear, renderOrder
|
|
64
68
|
);
|
|
65
69
|
particleEmiter.elasticity = .3;
|
|
66
70
|
particleEmiter.trailScale = 2;
|
|
@@ -100,19 +104,15 @@ function gameUpdatePost()
|
|
|
100
104
|
///////////////////////////////////////////////////////////////////////////////
|
|
101
105
|
function gameRender()
|
|
102
106
|
{
|
|
103
|
-
// draw a grey square without using webgl
|
|
104
|
-
|
|
105
|
-
{
|
|
106
|
-
context.fillStyle='#333'
|
|
107
|
-
context.fillRect(-.5,-.5,1,1);
|
|
108
|
-
});
|
|
107
|
+
// draw a grey square in the background without using webgl
|
|
108
|
+
drawRect(cameraPos, tileCollisionSize.add(vec2(5)), new Color(.2,.2,.2), 0, 0);
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
///////////////////////////////////////////////////////////////////////////////
|
|
112
112
|
function gameRenderPost()
|
|
113
113
|
{
|
|
114
114
|
// draw to overlay canvas for hud rendering
|
|
115
|
-
const
|
|
115
|
+
const drawText = (text, x, y, size=70) =>
|
|
116
116
|
{
|
|
117
117
|
overlayContext.textAlign = 'center';
|
|
118
118
|
overlayContext.textBaseline = 'top';
|
|
@@ -122,7 +122,7 @@ function gameRenderPost()
|
|
|
122
122
|
overlayContext.strokeText(text, x, y);
|
|
123
123
|
overlayContext.fillText(text, x, y);
|
|
124
124
|
}
|
|
125
|
-
|
|
125
|
+
drawText('Hello World', overlayCanvas.width/2, 40);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
///////////////////////////////////////////////////////////////////////////////
|