littlejsengine 1.9.7 → 1.9.9
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/LICENSE +22 -0
- package/README.md +13 -8
- package/dist/littlejs.d.ts +75 -69
- package/dist/littlejs.esm.js +313 -354
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +307 -350
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +244 -319
- package/examples/box2d/game.js +137 -0
- package/examples/box2d/index.html +12 -0
- package/examples/box2d/scenes.js +412 -0
- package/examples/box2d/tiles.png +0 -0
- package/examples/breakout/game.js +3 -3
- package/examples/breakout/index.html +4 -3
- package/examples/breakoutTutorial/index.html +2 -2
- package/examples/electron/build.js +1 -1
- package/examples/electron/index.html +2 -2
- package/examples/js13k/build.js +19 -1
- package/examples/js13k/index.html +13 -13
- package/examples/module/index.html +1 -1
- package/examples/particles/index.html +1 -1
- package/examples/platformer/gameEffects.js +2 -2
- package/examples/platformer/gameLevel.js +0 -1
- package/examples/platformer/index.html +8 -8
- package/examples/puzzle/index.html +2 -2
- package/examples/starter/build.js +1 -1
- package/examples/starter/index.html +13 -13
- package/examples/stress/index.html +1 -1
- package/examples/typescript/index.html +1 -1
- package/package.json +1 -1
- package/plugins/Box2D_v2.3.1_min.wasm.js +630 -0
- package/plugins/Box2D_v2.3.1_min.wasm.wasm +0 -0
- package/plugins/box2d.js +879 -0
- package/plugins/newgrounds.js +169 -0
- package/plugins/postProcess.js +102 -0
- package/src/engine.js +48 -29
- package/src/engineAudio.js +20 -12
- package/src/engineBuild.js +1 -1
- package/src/engineDebug.js +68 -33
- package/src/engineDraw.js +1 -1
- package/src/engineExport.js +6 -4
- package/src/engineInput.js +7 -4
- package/src/engineMedals.js +40 -171
- package/src/engineObject.js +33 -2
- package/src/engineRelease.js +5 -2
- package/src/engineSettings.js +14 -2
- package/src/engineUtilities.js +75 -2
- package/src/engineWebGL.js +1 -94
package/src/engineDraw.js
CHANGED
|
@@ -320,7 +320,7 @@ function drawCanvas2D(pos, size, angle, mirror, drawFunction, screenSpace, conte
|
|
|
320
320
|
context.save();
|
|
321
321
|
context.translate(pos.x+.5, pos.y+.5);
|
|
322
322
|
context.rotate(angle);
|
|
323
|
-
context.scale(mirror ? -size.x : size.x, size.y);
|
|
323
|
+
context.scale(mirror ? -size.x : size.x, -size.y);
|
|
324
324
|
drawFunction(context);
|
|
325
325
|
context.restore();
|
|
326
326
|
}
|
package/src/engineExport.js
CHANGED
|
@@ -20,6 +20,7 @@ export {
|
|
|
20
20
|
engineObjectsUpdate,
|
|
21
21
|
engineObjectsDestroy,
|
|
22
22
|
engineObjectsCallback,
|
|
23
|
+
engineAddPlugin,
|
|
23
24
|
|
|
24
25
|
// Globals
|
|
25
26
|
debug,
|
|
@@ -29,13 +30,16 @@ export {
|
|
|
29
30
|
// Debug
|
|
30
31
|
ASSERT,
|
|
31
32
|
debugRect,
|
|
33
|
+
debugPoly,
|
|
32
34
|
debugCircle,
|
|
33
35
|
debugPoint,
|
|
34
36
|
debugLine,
|
|
35
|
-
|
|
37
|
+
debugOverlap,
|
|
36
38
|
debugText,
|
|
37
39
|
debugClear,
|
|
38
40
|
debugSaveCanvas,
|
|
41
|
+
debugSaveText,
|
|
42
|
+
debugSaveDataURL,
|
|
39
43
|
|
|
40
44
|
// Settings
|
|
41
45
|
cameraPos,
|
|
@@ -98,6 +102,7 @@ export {
|
|
|
98
102
|
setObjectMaxSpeed,
|
|
99
103
|
setGravity,
|
|
100
104
|
setParticleEmitRateScale,
|
|
105
|
+
setTouchInputEnable,
|
|
101
106
|
setGamepadsEnable,
|
|
102
107
|
setGamepadDirectionEmulateStick,
|
|
103
108
|
setInputWASDEmulateDirection,
|
|
@@ -187,7 +192,6 @@ export {
|
|
|
187
192
|
glCompileShader,
|
|
188
193
|
glCreateProgram,
|
|
189
194
|
glCreateTexture,
|
|
190
|
-
glInitPostProcess,
|
|
191
195
|
|
|
192
196
|
// Input
|
|
193
197
|
keyIsDown,
|
|
@@ -246,7 +250,5 @@ export {
|
|
|
246
250
|
medals,
|
|
247
251
|
medalsPreventUnlock,
|
|
248
252
|
medalsInit,
|
|
249
|
-
newgroundsInit,
|
|
250
253
|
Medal,
|
|
251
|
-
Newgrounds,
|
|
252
254
|
};
|
package/src/engineInput.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* - Tracks keyboard down, pressed, and released
|
|
4
4
|
* - Tracks mouse buttons, position, and wheel
|
|
5
5
|
* - Tracks multiple analog gamepads
|
|
6
|
+
* - Touch input is handled as mouse input
|
|
6
7
|
* - Virtual gamepad for touch devices
|
|
7
8
|
* @namespace Input
|
|
8
9
|
*/
|
|
@@ -136,7 +137,8 @@ function inputUpdate()
|
|
|
136
137
|
if (headlessMode) return;
|
|
137
138
|
|
|
138
139
|
// clear input when lost focus (prevent stuck keys)
|
|
139
|
-
isTouchDevice
|
|
140
|
+
if(!(touchInputEnable && isTouchDevice) && !document.hasFocus())
|
|
141
|
+
clearInput();
|
|
140
142
|
|
|
141
143
|
// update mouse world space position
|
|
142
144
|
mousePos = screenToWorld(mousePosScreen);
|
|
@@ -208,7 +210,7 @@ function inputInit()
|
|
|
208
210
|
oncontextmenu = (e)=> false; // prevent right click menu
|
|
209
211
|
|
|
210
212
|
// init touch input
|
|
211
|
-
if (isTouchDevice)
|
|
213
|
+
if (isTouchDevice && touchInputEnable && !headlessMode)
|
|
212
214
|
touchInputInit();
|
|
213
215
|
}
|
|
214
216
|
|
|
@@ -336,12 +338,12 @@ function vibrateStop() { vibrate(0); }
|
|
|
336
338
|
|
|
337
339
|
/** True if a touch device has been detected
|
|
338
340
|
* @memberof Input */
|
|
339
|
-
const isTouchDevice =
|
|
341
|
+
const isTouchDevice = window.ontouchstart !== undefined;
|
|
340
342
|
|
|
341
343
|
// touch gamepad internal variables
|
|
342
344
|
let touchGamepadTimer = new Timer, touchGamepadButtons, touchGamepadStick;
|
|
343
345
|
|
|
344
|
-
//
|
|
346
|
+
// enable touch input mouse passthrough
|
|
345
347
|
function touchInputInit()
|
|
346
348
|
{
|
|
347
349
|
// add non passive touch event listeners
|
|
@@ -450,6 +452,7 @@ function touchInputInit()
|
|
|
450
452
|
// render the touch gamepad, called automatically by the engine
|
|
451
453
|
function touchGamepadRender()
|
|
452
454
|
{
|
|
455
|
+
if (!touchInputEnable || !isTouchDevice || headlessMode) return;
|
|
453
456
|
if (!touchGamepadEnable || !touchGamepadTimer.isSet())
|
|
454
457
|
return;
|
|
455
458
|
|
package/src/engineMedals.js
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
11
|
/** List of all medals
|
|
12
|
-
* @type {
|
|
12
|
+
* @type {Object}
|
|
13
13
|
* @memberof Medals */
|
|
14
|
-
const medals =
|
|
14
|
+
const medals = {};
|
|
15
15
|
|
|
16
16
|
// Engine internal variables not exposed to documentation
|
|
17
17
|
let medalsDisplayQueue = [], medalsSaveName, medalsDisplayTimeLast;
|
|
@@ -27,9 +27,46 @@ function medalsInit(saveName)
|
|
|
27
27
|
{
|
|
28
28
|
// check if medals are unlocked
|
|
29
29
|
medalsSaveName = saveName;
|
|
30
|
-
|
|
30
|
+
if (!debugMedals)
|
|
31
|
+
medalsForEach(medal=> medal.unlocked = (localStorage[medal.storageKey()] | 0));
|
|
32
|
+
|
|
33
|
+
// engine automatically renders medals
|
|
34
|
+
engineAddPlugin(undefined, medalsRender);
|
|
35
|
+
function medalsRender()
|
|
36
|
+
{
|
|
37
|
+
if (!medalsDisplayQueue.length)
|
|
38
|
+
return;
|
|
39
|
+
|
|
40
|
+
// update first medal in queue
|
|
41
|
+
const medal = medalsDisplayQueue[0];
|
|
42
|
+
const time = timeReal - medalsDisplayTimeLast;
|
|
43
|
+
if (!medalsDisplayTimeLast)
|
|
44
|
+
medalsDisplayTimeLast = timeReal;
|
|
45
|
+
else if (time > medalDisplayTime)
|
|
46
|
+
{
|
|
47
|
+
medalsDisplayTimeLast = 0;
|
|
48
|
+
medalsDisplayQueue.shift();
|
|
49
|
+
}
|
|
50
|
+
else
|
|
51
|
+
{
|
|
52
|
+
// slide on/off medals
|
|
53
|
+
const slideOffTime = medalDisplayTime - medalDisplaySlideTime;
|
|
54
|
+
const hidePercent =
|
|
55
|
+
time < medalDisplaySlideTime ? 1 - time / medalDisplaySlideTime :
|
|
56
|
+
time > slideOffTime ? (time - slideOffTime) / medalDisplaySlideTime : 0;
|
|
57
|
+
medal.render(hidePercent);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
31
60
|
}
|
|
32
61
|
|
|
62
|
+
/** Calls a function for each medal
|
|
63
|
+
* @param {Function} callback
|
|
64
|
+
* @memberof Medals */
|
|
65
|
+
function medalsForEach(callback)
|
|
66
|
+
{ Object.values(medals).forEach(medal=>callback(medal)); }
|
|
67
|
+
|
|
68
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
69
|
+
|
|
33
70
|
/**
|
|
34
71
|
* Medal - Tracks an unlockable medal
|
|
35
72
|
* @example
|
|
@@ -74,7 +111,6 @@ class Medal
|
|
|
74
111
|
ASSERT(medalsSaveName, 'save name must be set');
|
|
75
112
|
localStorage[this.storageKey()] = this.unlocked = 1;
|
|
76
113
|
medalsDisplayQueue.push(this);
|
|
77
|
-
newgrounds && newgrounds.unlockMedal(this.id);
|
|
78
114
|
}
|
|
79
115
|
|
|
80
116
|
/** Render a medal
|
|
@@ -122,171 +158,4 @@ class Medal
|
|
|
122
158
|
|
|
123
159
|
// Get local storage key used by the medal
|
|
124
160
|
storageKey() { return medalsSaveName + '_' + this.id; }
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// engine automatically renders medals
|
|
128
|
-
function medalsRender()
|
|
129
|
-
{
|
|
130
|
-
if (!medalsDisplayQueue.length)
|
|
131
|
-
return;
|
|
132
|
-
|
|
133
|
-
// update first medal in queue
|
|
134
|
-
const medal = medalsDisplayQueue[0];
|
|
135
|
-
const time = timeReal - medalsDisplayTimeLast;
|
|
136
|
-
if (!medalsDisplayTimeLast)
|
|
137
|
-
medalsDisplayTimeLast = timeReal;
|
|
138
|
-
else if (time > medalDisplayTime)
|
|
139
|
-
{
|
|
140
|
-
medalsDisplayTimeLast = 0;
|
|
141
|
-
medalsDisplayQueue.shift();
|
|
142
|
-
}
|
|
143
|
-
else
|
|
144
|
-
{
|
|
145
|
-
// slide on/off medals
|
|
146
|
-
const slideOffTime = medalDisplayTime - medalDisplaySlideTime;
|
|
147
|
-
const hidePercent =
|
|
148
|
-
time < medalDisplaySlideTime ? 1 - time / medalDisplaySlideTime :
|
|
149
|
-
time > slideOffTime ? (time - slideOffTime) / medalDisplaySlideTime : 0;
|
|
150
|
-
medal.render(hidePercent);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
155
|
-
|
|
156
|
-
// global Newgrounds object
|
|
157
|
-
let newgrounds;
|
|
158
|
-
|
|
159
|
-
/** This can used to enable Newgrounds functionality
|
|
160
|
-
* @param {Number} app_id - The newgrounds App ID
|
|
161
|
-
* @param {String} [cipher] - The encryption Key (AES-128/Base64)
|
|
162
|
-
* @param {Object} [cryptoJS] - An instance of CryptoJS, if there is a cipher
|
|
163
|
-
* @memberof Medals */
|
|
164
|
-
function newgroundsInit(app_id, cipher, cryptoJS)
|
|
165
|
-
{ newgrounds = new Newgrounds(app_id, cipher, cryptoJS); }
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Newgrounds API wrapper object
|
|
169
|
-
* @example
|
|
170
|
-
* // create a newgrounds object, replace the app id with your own
|
|
171
|
-
* const app_id = '53123:1ZuSTQ9l';
|
|
172
|
-
* newgrounds = new Newgrounds(app_id);
|
|
173
|
-
*/
|
|
174
|
-
class Newgrounds
|
|
175
|
-
{
|
|
176
|
-
/** Create a newgrounds object
|
|
177
|
-
* @param {Number} app_id - The newgrounds App ID
|
|
178
|
-
* @param {String} [cipher] - The encryption Key (AES-128/Base64)
|
|
179
|
-
* @param {Object} [cryptoJS] - An instance of CryptoJS, if there is a cipher */
|
|
180
|
-
constructor(app_id, cipher, cryptoJS)
|
|
181
|
-
{
|
|
182
|
-
ASSERT(!newgrounds && app_id>0, 'there can only be one newgrounds object');
|
|
183
|
-
ASSERT(!cipher || cryptoJS, 'must provide cryptojs if there is a cipher');
|
|
184
|
-
|
|
185
|
-
this.app_id = app_id;
|
|
186
|
-
this.cipher = cipher;
|
|
187
|
-
this.cryptoJS = cryptoJS;
|
|
188
|
-
this.host = location ? location.hostname : '';
|
|
189
|
-
|
|
190
|
-
// get session id from url search params
|
|
191
|
-
const url = new URL(location.href);
|
|
192
|
-
this.session_id = url.searchParams.get('ngio_session_id');
|
|
193
|
-
|
|
194
|
-
if (!this.session_id)
|
|
195
|
-
return; // only use newgrounds when logged in
|
|
196
|
-
|
|
197
|
-
// get medals
|
|
198
|
-
const medalsResult = this.call('Medal.getList');
|
|
199
|
-
this.medals = medalsResult ? medalsResult.result.data['medals'] : [];
|
|
200
|
-
debugMedals && console.log(this.medals);
|
|
201
|
-
for (const newgroundsMedal of this.medals)
|
|
202
|
-
{
|
|
203
|
-
const medal = medals[newgroundsMedal['id']];
|
|
204
|
-
if (medal)
|
|
205
|
-
{
|
|
206
|
-
// copy newgrounds medal data
|
|
207
|
-
medal.image = new Image;
|
|
208
|
-
medal.image.src = newgroundsMedal['icon'];
|
|
209
|
-
medal.name = newgroundsMedal['name'];
|
|
210
|
-
medal.description = newgroundsMedal['description'];
|
|
211
|
-
medal.unlocked = newgroundsMedal['unlocked'];
|
|
212
|
-
medal.difficulty = newgroundsMedal['difficulty'];
|
|
213
|
-
medal.value = newgroundsMedal['value'];
|
|
214
|
-
|
|
215
|
-
if (medal.value)
|
|
216
|
-
medal.description = medal.description + ' (' + medal.value + ')';
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// get scoreboards
|
|
221
|
-
const scoreboardResult = this.call('ScoreBoard.getBoards');
|
|
222
|
-
this.scoreboards = scoreboardResult ? scoreboardResult.result.data.scoreboards : [];
|
|
223
|
-
debugMedals && console.log(this.scoreboards);
|
|
224
|
-
|
|
225
|
-
const keepAliveMS = 5 * 60 * 1e3;
|
|
226
|
-
setInterval(()=>this.call('Gateway.ping', 0, true), keepAliveMS);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/** Send message to unlock a medal by id
|
|
230
|
-
* @param {Number} id - The medal id */
|
|
231
|
-
unlockMedal(id) { return this.call('Medal.unlock', {'id':id}, true); }
|
|
232
|
-
|
|
233
|
-
/** Send message to post score
|
|
234
|
-
* @param {Number} id - The scoreboard id
|
|
235
|
-
* @param {Number} value - The score value */
|
|
236
|
-
postScore(id, value) { return this.call('ScoreBoard.postScore', {'id':id, 'value':value}, true); }
|
|
237
|
-
|
|
238
|
-
/** Get scores from a scoreboard
|
|
239
|
-
* @param {Number} id - The scoreboard id
|
|
240
|
-
* @param {String} [user] - A user's id or name
|
|
241
|
-
* @param {Number} [social] - If true, only social scores will be loaded
|
|
242
|
-
* @param {Number} [skip] - Number of scores to skip before start
|
|
243
|
-
* @param {Number} [limit] - Number of scores to include in the list
|
|
244
|
-
* @return {Object} - The response JSON object
|
|
245
|
-
*/
|
|
246
|
-
getScores(id, user, social=0, skip=0, limit=10)
|
|
247
|
-
{ return this.call('ScoreBoard.getScores', {'id':id, 'user':user, 'social':social, 'skip':skip, 'limit':limit}); }
|
|
248
|
-
|
|
249
|
-
/** Send message to log a view */
|
|
250
|
-
logView() { return this.call('App.logView', {'host':this.host}, true); }
|
|
251
|
-
|
|
252
|
-
/** Send a message to call a component of the Newgrounds API
|
|
253
|
-
* @param {String} component - Name of the component
|
|
254
|
-
* @param {Object} [parameters] - Parameters to use for call
|
|
255
|
-
* @param {Boolean} [async] - If true, don't wait for response before continuing
|
|
256
|
-
* @return {Object} - The response JSON object
|
|
257
|
-
*/
|
|
258
|
-
call(component, parameters, async=false)
|
|
259
|
-
{
|
|
260
|
-
const call = {'component':component, 'parameters':parameters};
|
|
261
|
-
if (this.cipher)
|
|
262
|
-
{
|
|
263
|
-
// encrypt using AES-128 Base64 with cryptoJS
|
|
264
|
-
const cryptoJS = this.cryptoJS;
|
|
265
|
-
const aesKey = cryptoJS['enc']['Base64']['parse'](this.cipher);
|
|
266
|
-
const iv = cryptoJS['lib']['WordArray']['random'](16);
|
|
267
|
-
const encrypted = cryptoJS['AES']['encrypt'](JSON.stringify(call), aesKey, {'iv':iv});
|
|
268
|
-
call['secure'] = cryptoJS['enc']['Base64']['stringify'](iv.concat(encrypted['ciphertext']));
|
|
269
|
-
call['parameters'] = 0;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// build the input object
|
|
273
|
-
const input =
|
|
274
|
-
{
|
|
275
|
-
'app_id': this.app_id,
|
|
276
|
-
'session_id': this.session_id,
|
|
277
|
-
'call': call
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
// build post data
|
|
281
|
-
const formData = new FormData();
|
|
282
|
-
formData.append('input', JSON.stringify(input));
|
|
283
|
-
|
|
284
|
-
// send post data
|
|
285
|
-
const xmlHttp = new XMLHttpRequest();
|
|
286
|
-
const url = 'https://newgrounds.io/gateway_v3.php';
|
|
287
|
-
xmlHttp.open('POST', url, !debugMedals && async);
|
|
288
|
-
xmlHttp.send(formData);
|
|
289
|
-
debugMedals && console.log(xmlHttp.responseText);
|
|
290
|
-
return xmlHttp.responseText && JSON.parse(xmlHttp.responseText);
|
|
291
|
-
}
|
|
292
161
|
}
|
package/src/engineObject.js
CHANGED
|
@@ -205,7 +205,7 @@ class EngineObject
|
|
|
205
205
|
if (o.mass) // push away if not fixed
|
|
206
206
|
o.velocity = o.velocity.subtract(velocity);
|
|
207
207
|
|
|
208
|
-
debugOverlay && debugPhysics &&
|
|
208
|
+
debugOverlay && debugPhysics && debugOverlap(this.pos, this.size, o.pos, o.size, '#f00');
|
|
209
209
|
continue;
|
|
210
210
|
}
|
|
211
211
|
|
|
@@ -267,7 +267,7 @@ class EngineObject
|
|
|
267
267
|
else // bounce if other object is fixed
|
|
268
268
|
this.velocity.x *= -elasticity;
|
|
269
269
|
}
|
|
270
|
-
debugOverlay && debugPhysics &&
|
|
270
|
+
debugOverlay && debugPhysics && debugOverlap(this.pos, this.size, o.pos, o.size, '#f0f');
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
273
|
if (this.collideTiles)
|
|
@@ -328,6 +328,22 @@ class EngineObject
|
|
|
328
328
|
for (const child of this.children)
|
|
329
329
|
child.destroy(child.parent = 0);
|
|
330
330
|
}
|
|
331
|
+
|
|
332
|
+
/** Convert from local space to world space
|
|
333
|
+
* @param {Vector2} pos - local space point */
|
|
334
|
+
localToWorld(pos) { return this.pos.add(pos.rotate(-this.angle)); }
|
|
335
|
+
|
|
336
|
+
/** Convert from world space to local space
|
|
337
|
+
* @param {Vector2} pos - world space point */
|
|
338
|
+
worldToLocal(pos) { return pos.subtract(this.pos).rotate(this.angle); }
|
|
339
|
+
|
|
340
|
+
/** Convert from local space to world space for a vector (rotation only)
|
|
341
|
+
* @param {Vector2} vec - local space vector */
|
|
342
|
+
localToWorldVector(vec) { return vec.rotate(this.angle); }
|
|
343
|
+
|
|
344
|
+
/** Convert from world space to local space for a vector (rotation only)
|
|
345
|
+
* @param {Vector2} vec - world space vector */
|
|
346
|
+
worldToLocalVector(vec) { return vec.rotate(-this.angle); }
|
|
331
347
|
|
|
332
348
|
/** Called to check if a tile collision should be resolved
|
|
333
349
|
* @param {Number} tileData - the value of the tile at the position
|
|
@@ -414,4 +430,19 @@ class EngineObject
|
|
|
414
430
|
return text;
|
|
415
431
|
}
|
|
416
432
|
}
|
|
433
|
+
|
|
434
|
+
/** Render debug info for this object */
|
|
435
|
+
renderDebugInfo()
|
|
436
|
+
{
|
|
437
|
+
if (debug)
|
|
438
|
+
{
|
|
439
|
+
// show object info for debugging
|
|
440
|
+
const size = vec2(max(this.size.x, .2), max(this.size.y, .2));
|
|
441
|
+
const color1 = rgb(this.collideTiles?1:0, this.collideSolidObjects?1:0, this.isSolid?1:0, this.parent?.2:.5);
|
|
442
|
+
const color2 = this.parent ? rgb(1,1,1,.5) : rgb(0,0,0,.8);
|
|
443
|
+
drawRect(this.pos, size, color1, this.angle, false);
|
|
444
|
+
drawRect(this.pos, size.scale(.8), color2, this.angle, false);
|
|
445
|
+
this.parent && drawLine(this.pos, this.parent.pos, .1, rgb(0,0,1,.5), false);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
417
448
|
}
|
package/src/engineRelease.js
CHANGED
|
@@ -22,10 +22,13 @@ function debugInit (){}
|
|
|
22
22
|
function debugUpdate (){}
|
|
23
23
|
function debugRender (){}
|
|
24
24
|
function debugRect (){}
|
|
25
|
+
function debugPoly (){}
|
|
25
26
|
function debugCircle (){}
|
|
26
27
|
function debugPoint (){}
|
|
27
28
|
function debugLine (){}
|
|
28
|
-
function
|
|
29
|
+
function debugOverlap (){}
|
|
29
30
|
function debugText (){}
|
|
30
31
|
function debugClear (){}
|
|
31
|
-
function debugSaveCanvas (){}
|
|
32
|
+
function debugSaveCanvas (){}
|
|
33
|
+
function debugSaveText (){}
|
|
34
|
+
function debugSaveDataURL(){}
|
package/src/engineSettings.js
CHANGED
|
@@ -26,9 +26,9 @@ let cameraScale = 32;
|
|
|
26
26
|
|
|
27
27
|
/** The max size of the canvas, centered if window is larger
|
|
28
28
|
* @type {Vector2}
|
|
29
|
-
* @default Vector2(1920,
|
|
29
|
+
* @default Vector2(1920,1080)
|
|
30
30
|
* @memberof Settings */
|
|
31
|
-
let canvasMaxSize = vec2(1920,
|
|
31
|
+
let canvasMaxSize = vec2(1920, 1080);
|
|
32
32
|
|
|
33
33
|
/** Fixed size of the canvas, if enabled canvas size never changes
|
|
34
34
|
* - you may also need to set mainCanvasSize if using screen space coords in startup
|
|
@@ -169,6 +169,13 @@ let gamepadDirectionEmulateStick = true;
|
|
|
169
169
|
* @memberof Settings */
|
|
170
170
|
let inputWASDEmulateDirection = true;
|
|
171
171
|
|
|
172
|
+
/** True if touch input is enabled for mobile devices
|
|
173
|
+
* - Touch events will be routed to mouse events
|
|
174
|
+
* @type {Boolean}
|
|
175
|
+
* @default
|
|
176
|
+
* @memberof Settings */
|
|
177
|
+
let touchInputEnable = true;
|
|
178
|
+
|
|
172
179
|
/** True if touch gamepad should appear on mobile devices
|
|
173
180
|
* - Supports left analog stick, 4 face buttons and start button (button 9)
|
|
174
181
|
* - Must be set by end of gameInit to be activated
|
|
@@ -384,6 +391,11 @@ function setGamepadDirectionEmulateStick(enable) { gamepadDirectionEmulateStick
|
|
|
384
391
|
* @memberof Settings */
|
|
385
392
|
function setInputWASDEmulateDirection(enable) { inputWASDEmulateDirection = enable; }
|
|
386
393
|
|
|
394
|
+
/** Set if touch input is allowed
|
|
395
|
+
* @param {Boolean} enable
|
|
396
|
+
* @memberof Settings */
|
|
397
|
+
function setTouchInputEnable(enable) { touchInputEnable = enable; }
|
|
398
|
+
|
|
387
399
|
/** Set if touch gamepad should appear on mobile devices
|
|
388
400
|
* @param {Boolean} enable
|
|
389
401
|
* @memberof Settings */
|
package/src/engineUtilities.js
CHANGED
|
@@ -301,7 +301,7 @@ class RandomGenerator
|
|
|
301
301
|
*/
|
|
302
302
|
function vec2(x=0, y)
|
|
303
303
|
{
|
|
304
|
-
return typeof x
|
|
304
|
+
return typeof x == 'number' ?
|
|
305
305
|
new Vector2(x, y == undefined? x : y) :
|
|
306
306
|
new Vector2(x.x, x.y);
|
|
307
307
|
}
|
|
@@ -330,13 +330,19 @@ class Vector2
|
|
|
330
330
|
* @param {Number} [y] - Y axis location */
|
|
331
331
|
constructor(x=0, y=0)
|
|
332
332
|
{
|
|
333
|
-
ASSERT(typeof x
|
|
333
|
+
ASSERT(typeof x == 'number' && typeof y == 'number');
|
|
334
334
|
/** @property {Number} - X axis location */
|
|
335
335
|
this.x = x;
|
|
336
336
|
/** @property {Number} - Y axis location */
|
|
337
337
|
this.y = y;
|
|
338
338
|
}
|
|
339
339
|
|
|
340
|
+
/** Sets values of this vector and returns self
|
|
341
|
+
* @param {Number} [x] - X axis location
|
|
342
|
+
* @param {Number} [y] - Y axis location
|
|
343
|
+
* @return {Vector2} */
|
|
344
|
+
set(x=0, y=0) { this.x=x; this.y=y; return this; }
|
|
345
|
+
|
|
340
346
|
/** Returns a new vector that is a copy of this
|
|
341
347
|
* @return {Vector2} */
|
|
342
348
|
copy() { return new Vector2(this.x, this.y); }
|
|
@@ -588,6 +594,15 @@ class Color
|
|
|
588
594
|
this.a = a;
|
|
589
595
|
}
|
|
590
596
|
|
|
597
|
+
/** Sets values of this color and returns self
|
|
598
|
+
* @param {Number} [r] - red
|
|
599
|
+
* @param {Number} [g] - green
|
|
600
|
+
* @param {Number} [b] - blue
|
|
601
|
+
* @param {Number} [a] - alpha
|
|
602
|
+
* @return {Color} */
|
|
603
|
+
set(r=1, g=1, b=1, a=1)
|
|
604
|
+
{ this.r=r; this.g=g; this.b=b; this.a=a; return this; }
|
|
605
|
+
|
|
591
606
|
/** Returns a new color that is a copy of this
|
|
592
607
|
* @return {Color} */
|
|
593
608
|
copy() { return new Color(this.r, this.g, this.b, this.a); }
|
|
@@ -749,6 +764,64 @@ class Color
|
|
|
749
764
|
}
|
|
750
765
|
}
|
|
751
766
|
|
|
767
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
768
|
+
// default colors
|
|
769
|
+
|
|
770
|
+
/** Color - White
|
|
771
|
+
* @type {Color}
|
|
772
|
+
* @memberof Utilities */
|
|
773
|
+
const WHITE = rgb();
|
|
774
|
+
|
|
775
|
+
/** Color - Black
|
|
776
|
+
* @type {Color}
|
|
777
|
+
* @memberof Utilities */
|
|
778
|
+
const BLACK = rgb(0,0,0);
|
|
779
|
+
|
|
780
|
+
/** Color - Gray
|
|
781
|
+
* @type {Color}
|
|
782
|
+
* @memberof Utilities */
|
|
783
|
+
const GRAY = rgb(.5,.5,.5);
|
|
784
|
+
|
|
785
|
+
/** Color - Red
|
|
786
|
+
* @type {Color}
|
|
787
|
+
* @memberof Utilities */
|
|
788
|
+
const RED = rgb(1,0,0);
|
|
789
|
+
|
|
790
|
+
/** Color - Orange
|
|
791
|
+
* @type {Color}
|
|
792
|
+
* @memberof Utilities */
|
|
793
|
+
const ORANGE = rgb(1,.5,0);
|
|
794
|
+
|
|
795
|
+
/** Color - Yellow
|
|
796
|
+
* @type {Color}
|
|
797
|
+
* @memberof Utilities */
|
|
798
|
+
const YELLOW = rgb(1,1,0);
|
|
799
|
+
|
|
800
|
+
/** Color - Green
|
|
801
|
+
* @type {Color}
|
|
802
|
+
* @memberof Utilities */
|
|
803
|
+
const GREEN = rgb(0,1,0);
|
|
804
|
+
|
|
805
|
+
/** Color - Cyan
|
|
806
|
+
* @type {Color}
|
|
807
|
+
* @memberof Utilities */
|
|
808
|
+
const CYAN = rgb(0,1,1);
|
|
809
|
+
|
|
810
|
+
/** Color - Blue
|
|
811
|
+
* @type {Color}
|
|
812
|
+
* @memberof Utilities */
|
|
813
|
+
const BLUE = rgb(0,0,1);
|
|
814
|
+
|
|
815
|
+
/** Color - Purple
|
|
816
|
+
* @type {Color}
|
|
817
|
+
* @memberof Utilities */
|
|
818
|
+
const PURPLE = rgb(.5,0,1);
|
|
819
|
+
|
|
820
|
+
/** Color - Magenta
|
|
821
|
+
* @type {Color}
|
|
822
|
+
* @memberof Utilities */
|
|
823
|
+
const MAGENTA = rgb(1,0,1);
|
|
824
|
+
|
|
752
825
|
///////////////////////////////////////////////////////////////////////////////
|
|
753
826
|
|
|
754
827
|
/**
|
package/src/engineWebGL.js
CHANGED
|
@@ -87,7 +87,7 @@ function glPreRender()
|
|
|
87
87
|
|
|
88
88
|
// clear and set to same size as main canvas
|
|
89
89
|
glContext.viewport(0, 0, glCanvas.width=mainCanvas.width, glCanvas.height=mainCanvas.height);
|
|
90
|
-
|
|
90
|
+
glContext.clear(gl_COLOR_BUFFER_BIT);
|
|
91
91
|
|
|
92
92
|
// set up the shader
|
|
93
93
|
glContext.useProgram(glShader);
|
|
@@ -270,99 +270,6 @@ function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba, rgbaAdd
|
|
|
270
270
|
glInstanceCount++;
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
274
|
-
// post processing - can be enabled to pass other canvases through a final shader
|
|
275
|
-
|
|
276
|
-
let glPostShader, glPostTexture, glPostIncludeOverlay;
|
|
277
|
-
|
|
278
|
-
/** Set up a post processing shader
|
|
279
|
-
* @param {String} shaderCode
|
|
280
|
-
* @param {Boolean} includeOverlay
|
|
281
|
-
* @memberof WebGL */
|
|
282
|
-
function glInitPostProcess(shaderCode, includeOverlay=false)
|
|
283
|
-
{
|
|
284
|
-
ASSERT(!glPostShader, 'can only have 1 post effects shader');
|
|
285
|
-
if (headlessMode) return;
|
|
286
|
-
if (!shaderCode) // default shader pass through
|
|
287
|
-
shaderCode = 'void mainImage(out vec4 c,vec2 p){c=texture(iChannel0,p/iResolution.xy);}';
|
|
288
|
-
|
|
289
|
-
// create the shader
|
|
290
|
-
glPostShader = glCreateProgram(
|
|
291
|
-
'#version 300 es\n' + // specify GLSL ES version
|
|
292
|
-
'precision highp float;'+ // use highp for better accuracy
|
|
293
|
-
'in vec2 p;'+ // position
|
|
294
|
-
'void main(){'+ // shader entry point
|
|
295
|
-
'gl_Position=vec4(p+p-1.,1,1);'+ // set position
|
|
296
|
-
'}' // end of shader
|
|
297
|
-
,
|
|
298
|
-
'#version 300 es\n' + // specify GLSL ES version
|
|
299
|
-
'precision highp float;'+ // use highp for better accuracy
|
|
300
|
-
'uniform sampler2D iChannel0;'+ // input texture
|
|
301
|
-
'uniform vec3 iResolution;'+ // size of output texture
|
|
302
|
-
'uniform float iTime;'+ // time
|
|
303
|
-
'out vec4 c;'+ // out color
|
|
304
|
-
'\n' + shaderCode + '\n'+ // insert custom shader code
|
|
305
|
-
'void main(){'+ // shader entry point
|
|
306
|
-
'mainImage(c,gl_FragCoord.xy);'+ // call post process function
|
|
307
|
-
'c.a=1.;'+ // always use full alpha
|
|
308
|
-
'}' // end of shader
|
|
309
|
-
);
|
|
310
|
-
|
|
311
|
-
// create buffer and texture
|
|
312
|
-
glPostTexture = glCreateTexture(undefined);
|
|
313
|
-
glPostIncludeOverlay = includeOverlay;
|
|
314
|
-
|
|
315
|
-
// hide the original 2d canvas
|
|
316
|
-
mainCanvas.style.visibility = 'hidden';
|
|
317
|
-
if (glPostIncludeOverlay)
|
|
318
|
-
overlayCanvas.style.visibility = 'hidden';
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// Render the post processing shader, called automatically by the engine
|
|
322
|
-
function glRenderPostProcess()
|
|
323
|
-
{
|
|
324
|
-
if (!glPostShader || headlessMode) return;
|
|
325
|
-
|
|
326
|
-
// prepare to render post process shader
|
|
327
|
-
if (glEnable)
|
|
328
|
-
{
|
|
329
|
-
glFlush(); // clear out the buffer
|
|
330
|
-
mainContext.drawImage(glCanvas, 0, 0); // copy to the main canvas
|
|
331
|
-
}
|
|
332
|
-
else
|
|
333
|
-
{
|
|
334
|
-
// set the viewport
|
|
335
|
-
glContext.viewport(0, 0, glCanvas.width = mainCanvas.width, glCanvas.height = mainCanvas.height);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// copy overlay canvas so it will be included in post processing
|
|
339
|
-
glPostIncludeOverlay && mainContext.drawImage(overlayCanvas, 0, 0);
|
|
340
|
-
|
|
341
|
-
// setup shader program to draw one triangle
|
|
342
|
-
glContext.useProgram(glPostShader);
|
|
343
|
-
glContext.bindBuffer(gl_ARRAY_BUFFER, glGeometryBuffer);
|
|
344
|
-
glContext.pixelStorei(gl_UNPACK_FLIP_Y_WEBGL, 1);
|
|
345
|
-
glContext.disable(gl_BLEND);
|
|
346
|
-
|
|
347
|
-
// set textures, pass in the 2d canvas and gl canvas in separate texture channels
|
|
348
|
-
glContext.activeTexture(gl_TEXTURE0);
|
|
349
|
-
glContext.bindTexture(gl_TEXTURE_2D, glPostTexture);
|
|
350
|
-
glContext.texImage2D(gl_TEXTURE_2D, 0, gl_RGBA, gl_RGBA, gl_UNSIGNED_BYTE, mainCanvas);
|
|
351
|
-
|
|
352
|
-
// set vertex position attribute
|
|
353
|
-
const vertexByteStride = 8;
|
|
354
|
-
const pLocation = glContext.getAttribLocation(glPostShader, 'p');
|
|
355
|
-
glContext.enableVertexAttribArray(pLocation);
|
|
356
|
-
glContext.vertexAttribPointer(pLocation, 2, gl_FLOAT, false, vertexByteStride, 0);
|
|
357
|
-
|
|
358
|
-
// set uniforms and draw
|
|
359
|
-
const uniformLocation = (name)=>glContext.getUniformLocation(glPostShader, name);
|
|
360
|
-
glContext.uniform1i(uniformLocation('iChannel0'), 0);
|
|
361
|
-
glContext.uniform1f(uniformLocation('iTime'), time);
|
|
362
|
-
glContext.uniform3f(uniformLocation('iResolution'), mainCanvas.width, mainCanvas.height, 1);
|
|
363
|
-
glContext.drawArrays(gl_TRIANGLE_STRIP, 0, 4);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
273
|
///////////////////////////////////////////////////////////////////////////////
|
|
367
274
|
// store gl constants as integers so their name doesn't use space in minifed
|
|
368
275
|
const
|