littlejsengine 1.1.26 → 1.2.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/README.md +7 -9
- package/build.bat +1 -1
- package/engine/engine.all.js +369 -377
- package/engine/engine.all.min.js +1 -1
- package/engine/engine.all.release.js +338 -147
- package/engine/engine.js +7 -7
- package/engine/engineAudio.js +2 -2
- package/engine/engineBuild.bat +9 -1
- package/engine/engineDebug.js +32 -231
- package/engine/engineDraw.js +130 -20
- package/engine/engineFont.png +0 -0
- package/engine/engineInput.js +32 -9
- package/engine/engineMedals.js +7 -4
- package/engine/engineObject.js +30 -11
- package/engine/engineParticles.js +5 -3
- package/engine/engineSettings.js +5 -0
- package/engine/engineTileLayer.js +17 -14
- package/engine/engineUtilities.js +50 -18
- package/engine/engineWebGL.js +53 -59
- package/engine/index.d.ts +1644 -0
- package/examples/breakout/game.js +9 -7
- package/examples/breakout/gameObjects.js +3 -3
- package/examples/breakout/index.html +3 -3
- package/examples/particles/index.html +366 -0
- package/examples/particles/tiles.png +0 -0
- package/examples/platformer/game.js +5 -5
- package/examples/platformer/gameEffects.js +10 -10
- package/examples/platformer/gameLevel.js +3 -3
- package/examples/platformer/gameObjects.js +3 -3
- package/examples/platformer/gamePlayer.js +11 -6
- package/examples/platformer/index.html +6 -6
- package/examples/platformer/tiles.png +0 -0
- package/examples/puzzle/game.js +3 -3
- package/examples/puzzle/index.html +2 -2
- package/examples/screenshot.jpg +0 -0
- package/examples/stress/index.html +4 -4
- package/game.js +4 -7
- package/index.html +13 -13
- package/package.json +8 -1
- package/engine/engineBuildSetup.bat +0 -6
|
@@ -47,21 +47,23 @@ function gameUpdatePost()
|
|
|
47
47
|
///////////////////////////////////////////////////////////////////////////////
|
|
48
48
|
function gameRender()
|
|
49
49
|
{
|
|
50
|
-
// draw a
|
|
51
|
-
drawRect(cameraPos, levelSize, new Color(.
|
|
50
|
+
// draw a the background
|
|
51
|
+
drawRect(cameraPos, levelSize.scale(2), new Color(.4,.4,.4));
|
|
52
|
+
drawRect(cameraPos, levelSize, new Color(.1,.1,.1));
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
///////////////////////////////////////////////////////////////////////////////
|
|
55
56
|
function gameRenderPost()
|
|
56
57
|
{
|
|
57
|
-
//
|
|
58
|
-
|
|
58
|
+
// use built in image font for text
|
|
59
|
+
const font = new FontImage;
|
|
60
|
+
font.drawText('Score: ' + score, cameraPos.add(vec2(0,22)), .2, 1);
|
|
59
61
|
if (!blockCount)
|
|
60
|
-
drawText('You Win!', cameraPos.add(vec2(0,-5)),
|
|
62
|
+
font.drawText('You Win!', cameraPos.add(vec2(0,-5)), .25, 1);
|
|
61
63
|
else if (!ball)
|
|
62
|
-
drawText('Click to Play', cameraPos.add(vec2(0,-5)),
|
|
64
|
+
font.drawText('Click to Play', cameraPos.add(vec2(0,-5)), .25, 1);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
///////////////////////////////////////////////////////////////////////////////
|
|
66
68
|
// Startup LittleJS Engine
|
|
67
|
-
engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, 'tiles.png');
|
|
69
|
+
engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, 'tiles.png?1');
|
|
@@ -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
|
|
|
@@ -56,11 +56,11 @@ class Block extends EngineObject
|
|
|
56
56
|
const color1 = this.color;
|
|
57
57
|
const color2 = color1.lerp(new Color, .5);
|
|
58
58
|
new ParticleEmitter(
|
|
59
|
-
this.pos, this.size, .1, 200, PI,
|
|
59
|
+
this.pos, 0, this.size, .1, 200, PI, // pos, angle, emitSize, emitTime, emitRate, emiteCone
|
|
60
60
|
0, vec2(16), // tileIndex, tileSize
|
|
61
61
|
color1, color2, // colorStartA, colorStartB
|
|
62
62
|
color1.scale(1,0), color2.scale(1,0), // colorEndA, colorEndB
|
|
63
|
-
.2, 1, 1, .1, .05,
|
|
63
|
+
.2, 1, 1, .1, .05, // particleTime, sizeStart, sizeEnd, particleSpeed, particleAngleSpeed
|
|
64
64
|
.99, .95, .4, PI, .1, // damping, angleDamping, gravityScale, particleCone, fadeRate,
|
|
65
65
|
1, 0, 1 // randomness, collide, additive, randomColorLinear, renderOrder
|
|
66
66
|
);
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
<link rel=icon type=image/png href=../../favicon.png>
|
|
6
6
|
</head><body>
|
|
7
7
|
|
|
8
|
-
<script src=../../engine/engine.all.js?
|
|
9
|
-
<script src=game.js?
|
|
10
|
-
<script src=gameObjects.js?
|
|
8
|
+
<script src=../../engine/engine.all.js?104></script>
|
|
9
|
+
<script src=game.js?104></script>
|
|
10
|
+
<script src=gameObjects.js?104></script>
|
|
@@ -0,0 +1,366 @@
|
|
|
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>
|
|
5
|
+
<link rel=icon type=image/png href=favicon.png>
|
|
6
|
+
<style>
|
|
7
|
+
input
|
|
8
|
+
{
|
|
9
|
+
width:99px;
|
|
10
|
+
}
|
|
11
|
+
button
|
|
12
|
+
{
|
|
13
|
+
margin:1px;
|
|
14
|
+
}
|
|
15
|
+
</style>
|
|
16
|
+
</head><body>
|
|
17
|
+
|
|
18
|
+
<script src=../../engine/engineDebug.js?104></script>
|
|
19
|
+
<script src=../../engine/engineUtilities.js?104></script>
|
|
20
|
+
<script src=../../engine/engineSettings.js?104></script>
|
|
21
|
+
<script src=../../engine/engineObject.js?104></script>
|
|
22
|
+
<script src=../../engine/engineDraw.js?104></script>
|
|
23
|
+
<script src=../../engine/engineInput.js?104></script>
|
|
24
|
+
<script src=../../engine/engineAudio.js?104></script>
|
|
25
|
+
<script src=../../engine/engineTileLayer.js?104></script>
|
|
26
|
+
<script src=../../engine/engineParticles.js?104></script>
|
|
27
|
+
<script src=../../engine/engineMedals.js?104></script>
|
|
28
|
+
<script src=../../engine/engineWebGL.js?104></script>
|
|
29
|
+
<script src=../../engine/engine.js?104></script>
|
|
30
|
+
<script>
|
|
31
|
+
|
|
32
|
+
'use strict';
|
|
33
|
+
|
|
34
|
+
let particleEditor = 0, particleSystem, particleSystemDiv, particleSystemCode;
|
|
35
|
+
let inputCondense;
|
|
36
|
+
let restartTimer = new Timer();
|
|
37
|
+
const storagePrefix = 'particles_';
|
|
38
|
+
|
|
39
|
+
const particleSettings = [];
|
|
40
|
+
function addSetting(name, type, min, max, step, description)
|
|
41
|
+
{
|
|
42
|
+
particleSettings.push({name, type:type||'number', min, max, step, description});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
addSetting('emitSize', '', 0, 1e9, .1);
|
|
46
|
+
addSetting('emitTime', '', 0, 1e9, .1);
|
|
47
|
+
addSetting('emitRate', '', 0, 1e9, 1);
|
|
48
|
+
addSetting('emitConeAngle', '', 0, 1e9, .01);
|
|
49
|
+
addSetting('tileIndex', '', -1, 1e9, 1);
|
|
50
|
+
addSetting('tileSizeX', '', 0, 1e9, 1);
|
|
51
|
+
addSetting('tileSizeY', '', 0, 1e9, 1);
|
|
52
|
+
addSetting('colorStartA', 'color');
|
|
53
|
+
addSetting('colorStartB', 'color');
|
|
54
|
+
addSetting('colorEndA', 'color');
|
|
55
|
+
addSetting('colorEndB', 'color');
|
|
56
|
+
addSetting('colorAlphaStartA', 'alpha', 0, 1, .01);
|
|
57
|
+
addSetting('colorAlphaStartB', 'alpha', 0, 1, .01);
|
|
58
|
+
addSetting('colorAlphaEndA', 'alpha', 0, 1, .01);
|
|
59
|
+
addSetting('colorAlphaEndB', 'alpha', 0, 1, .01);
|
|
60
|
+
addSetting('particleTime', '', 0, 1e9, .1);
|
|
61
|
+
addSetting('sizeStart', '', 0, 1e9, .01);
|
|
62
|
+
addSetting('sizeEnd', '', 0, 1e9, .01);
|
|
63
|
+
addSetting('speed', '', 0, 1e9, .01);
|
|
64
|
+
addSetting('angleSpeed', '', 0, 1e9, .01);
|
|
65
|
+
addSetting('damping', '', 0, 1, .01);
|
|
66
|
+
addSetting('angleDamping', '', 0, 1, .01);
|
|
67
|
+
addSetting('gravityScale', '', -1e9, 1e9, .1);
|
|
68
|
+
addSetting('particleConeAngle','', 0, 1e9, .1);
|
|
69
|
+
addSetting('fadeRate', '', 0, 1, .01);
|
|
70
|
+
addSetting('randomness', '', 0, 1, .01);
|
|
71
|
+
addSetting('collideTiles', 'checkbox');
|
|
72
|
+
addSetting('additive', 'checkbox');
|
|
73
|
+
addSetting('randomColorLinear','checkbox');
|
|
74
|
+
|
|
75
|
+
function makeEmitter()
|
|
76
|
+
{
|
|
77
|
+
particleSystem = new ParticleEmitter(cameraPos);
|
|
78
|
+
particleSystem.emitConeAngle =
|
|
79
|
+
particleSystem.particleConeAngle = 3.14;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
83
|
+
function gameInit()
|
|
84
|
+
{
|
|
85
|
+
makeEmitter();
|
|
86
|
+
gravity = -.01;
|
|
87
|
+
cameraScale = 50;
|
|
88
|
+
|
|
89
|
+
const div = particleSystemDiv = document.createElement('div');
|
|
90
|
+
div.innerHTML = '<big><b>LittleJS Particle Tool';
|
|
91
|
+
div.style = 'position:absolute;top:10;left:10;color:#fff';
|
|
92
|
+
document.body.appendChild(div);
|
|
93
|
+
|
|
94
|
+
for (const setting of particleSettings)
|
|
95
|
+
{
|
|
96
|
+
const input = setting.input = document.createElement('input');
|
|
97
|
+
const name = setting.name;
|
|
98
|
+
input.oninput = (e)=> updateParticles();
|
|
99
|
+
input.type = setting.type == 'alpha' ? 'number' : setting.type;
|
|
100
|
+
if (setting.min !== undefined)
|
|
101
|
+
input.min = setting.min;
|
|
102
|
+
if (setting.max !== undefined)
|
|
103
|
+
input.max = setting.max;
|
|
104
|
+
if (setting.step !== undefined)
|
|
105
|
+
input.step = setting.step;
|
|
106
|
+
if (name == 'emitConeAngle' || name == 'particleConeAngle')
|
|
107
|
+
particleSystem[name] = 3.14; // simplify pi
|
|
108
|
+
|
|
109
|
+
div.appendChild(document.createElement('br'));
|
|
110
|
+
div.appendChild(input);
|
|
111
|
+
div.appendChild(document.createTextNode(' ' + name));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
div.appendChild(document.createElement('br'));
|
|
115
|
+
div.appendChild(document.createElement('br'));
|
|
116
|
+
|
|
117
|
+
{
|
|
118
|
+
const button = document.createElement('button')
|
|
119
|
+
div.appendChild(button);
|
|
120
|
+
button.innerHTML = 'Copy To Clipboard';
|
|
121
|
+
button.onclick = (e)=> navigator.clipboard.writeText(particleSystemCode.value);
|
|
122
|
+
}
|
|
123
|
+
{
|
|
124
|
+
const button = document.createElement('button');
|
|
125
|
+
div.appendChild(button);
|
|
126
|
+
button.innerHTML = 'Reset';
|
|
127
|
+
button.onclick = (e)=>
|
|
128
|
+
{
|
|
129
|
+
if (!confirm('Reset to default?'))
|
|
130
|
+
return;
|
|
131
|
+
particleSystem.destroy();
|
|
132
|
+
makeEmitter();
|
|
133
|
+
updateInputs(0);
|
|
134
|
+
cameraScale = 50;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
{
|
|
138
|
+
inputCondense = document.createElement('input');
|
|
139
|
+
div.appendChild(inputCondense);
|
|
140
|
+
inputCondense.checked = 'true';
|
|
141
|
+
inputCondense.type = 'checkbox';
|
|
142
|
+
inputCondense.style.width = 'initial';
|
|
143
|
+
inputCondense.oninput = (e)=> updateParticles();
|
|
144
|
+
div.appendChild(document.createTextNode(' Condense'));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
//div.appendChild(document.createTextNode('JavaScript Code... '));
|
|
148
|
+
div.appendChild(document.createElement('br'));
|
|
149
|
+
div.appendChild(particleSystemCode = document.createElement('textarea'));
|
|
150
|
+
particleSystemCode.style.width = 500;
|
|
151
|
+
particleSystemCode.style.height = 100;
|
|
152
|
+
particleSystemCode.disabled = true;
|
|
153
|
+
|
|
154
|
+
updateInputs(0);
|
|
155
|
+
|
|
156
|
+
// load from storage
|
|
157
|
+
for (const setting of particleSettings)
|
|
158
|
+
{
|
|
159
|
+
const type = setting.type;
|
|
160
|
+
const storageName = storagePrefix + setting.name;
|
|
161
|
+
const savedValue = localStorage[storageName];
|
|
162
|
+
if (savedValue == undefined)
|
|
163
|
+
continue;
|
|
164
|
+
|
|
165
|
+
if (type == 'checkbox')
|
|
166
|
+
setting.input.checked = savedValue == 'true';
|
|
167
|
+
else
|
|
168
|
+
setting.input.value = savedValue;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
updateParticles();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function updateParticles()
|
|
175
|
+
{
|
|
176
|
+
for (const setting of particleSettings)
|
|
177
|
+
{
|
|
178
|
+
const input = setting.input;
|
|
179
|
+
const name = setting.name;
|
|
180
|
+
const type = setting.type;
|
|
181
|
+
const inputFloat = parseFloat(input.value) || 0;
|
|
182
|
+
if (type == 'color')
|
|
183
|
+
{
|
|
184
|
+
const color = new Color().setHex(input.value);
|
|
185
|
+
particleSystem[name].r = color.r;
|
|
186
|
+
particleSystem[name].g = color.g;
|
|
187
|
+
particleSystem[name].b = color.b;
|
|
188
|
+
}
|
|
189
|
+
else if (type == 'alpha')
|
|
190
|
+
{
|
|
191
|
+
if (name == 'colorAlphaStartA')
|
|
192
|
+
particleSystem.colorStartA.a = clamp(inputFloat);
|
|
193
|
+
else if (name == 'colorAlphaStartB')
|
|
194
|
+
particleSystem.colorStartB.a = clamp(inputFloat);
|
|
195
|
+
else if (name == 'colorAlphaEndA')
|
|
196
|
+
particleSystem.colorEndA.a = clamp(inputFloat);
|
|
197
|
+
else if (name == 'colorAlphaEndB')
|
|
198
|
+
particleSystem.colorEndB.a = clamp(inputFloat);
|
|
199
|
+
}
|
|
200
|
+
else if (name == 'tileSizeX')
|
|
201
|
+
{
|
|
202
|
+
particleSystem.tileSize = vec2(parseInt(input.value), particleSystem.tileSize.y);
|
|
203
|
+
}
|
|
204
|
+
else if (name == 'tileSizeY')
|
|
205
|
+
{
|
|
206
|
+
particleSystem.tileSize = vec2(particleSystem.tileSize.x, parseInt(input.value));
|
|
207
|
+
}
|
|
208
|
+
else if (type == 'checkbox')
|
|
209
|
+
particleSystem[name] = input.checked ? 1 : 0;
|
|
210
|
+
else if (name == 'emitRate')
|
|
211
|
+
particleSystem[name] = min(inputFloat,1e3);
|
|
212
|
+
else
|
|
213
|
+
particleSystem[name] = clamp(inputFloat, setting.min, setting.max);
|
|
214
|
+
}
|
|
215
|
+
updateInputs();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function updateInputs(save=1)
|
|
219
|
+
{
|
|
220
|
+
for (const setting of particleSettings)
|
|
221
|
+
{
|
|
222
|
+
const input = setting.input;
|
|
223
|
+
const name = setting.name;
|
|
224
|
+
const type = setting.type;
|
|
225
|
+
|
|
226
|
+
if (type == 'color')
|
|
227
|
+
{
|
|
228
|
+
const color = particleSystem[name];
|
|
229
|
+
input.value = color.hex();
|
|
230
|
+
}
|
|
231
|
+
else if (type == 'alpha')
|
|
232
|
+
{
|
|
233
|
+
if (name == 'colorAlphaStartA')
|
|
234
|
+
input.value = particleSystem.colorStartA.a;
|
|
235
|
+
else if (name == 'colorAlphaStartB')
|
|
236
|
+
input.value = particleSystem.colorStartB.a;
|
|
237
|
+
else if (name == 'colorAlphaEndA')
|
|
238
|
+
input.value = particleSystem.colorEndA.a;
|
|
239
|
+
else if (name == 'colorAlphaEndB')
|
|
240
|
+
input.value = particleSystem.colorEndB.a;
|
|
241
|
+
}
|
|
242
|
+
else if (name == 'tileSizeX')
|
|
243
|
+
input.value = particleSystem.tileSize.x;
|
|
244
|
+
else if (name == 'tileSizeY')
|
|
245
|
+
input.value = particleSystem.tileSize.y;
|
|
246
|
+
else if (type == 'checkbox')
|
|
247
|
+
input.checked = particleSystem[name];
|
|
248
|
+
else
|
|
249
|
+
input.value = particleSystem[name] || '0';
|
|
250
|
+
|
|
251
|
+
if (save)
|
|
252
|
+
{
|
|
253
|
+
const storageName = storagePrefix + setting.name;
|
|
254
|
+
localStorage[storageName] = type == 'checkbox' ?
|
|
255
|
+
input.checked : input.value;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
particleSystemCode.value = getCode();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function getCode()
|
|
262
|
+
{
|
|
263
|
+
const condense = inputCondense.checked;
|
|
264
|
+
let code = '';
|
|
265
|
+
|
|
266
|
+
// https://www.codingem.com/javascript-how-to-limit-decimal-places/
|
|
267
|
+
Number.prototype.round = function(n) {
|
|
268
|
+
const d = Math.pow(10, n);
|
|
269
|
+
return Math.round((this + Number.EPSILON) * d) / d;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
code = 'new ParticleEmitter(';
|
|
273
|
+
if (condense)
|
|
274
|
+
code += 'vec2(), 0, ';
|
|
275
|
+
else
|
|
276
|
+
code += '\n vec2(), 0,\t//position, angle\n';
|
|
277
|
+
|
|
278
|
+
let count = 0;
|
|
279
|
+
for (const setting of particleSettings)
|
|
280
|
+
{
|
|
281
|
+
const name = setting.name;
|
|
282
|
+
const type = setting.type;
|
|
283
|
+
let value;
|
|
284
|
+
if (name == 'tileSizeX' || type == 'alpha')
|
|
285
|
+
continue;
|
|
286
|
+
|
|
287
|
+
if (name == 'tileSizeY')
|
|
288
|
+
value = `vec2(${particleSystem.tileSize.x}, ${particleSystem.tileSize.y})`;
|
|
289
|
+
else if (type == 'color')
|
|
290
|
+
{
|
|
291
|
+
const c = particleSystem[name];
|
|
292
|
+
const p = 3;
|
|
293
|
+
value = `new Color(${c.r.round(p)}, ${c.g.round(p)}, ${c.b.round(p)}, ${c.a.round(p)})`;
|
|
294
|
+
}
|
|
295
|
+
else if (type == 'checkbox')
|
|
296
|
+
value = particleSystem[name] ? 1 : 0;
|
|
297
|
+
else
|
|
298
|
+
value = particleSystem[name].round(3);
|
|
299
|
+
if (!condense)
|
|
300
|
+
code += ' ';
|
|
301
|
+
code += value;
|
|
302
|
+
|
|
303
|
+
const isEnd = name == 'randomColorLinear';
|
|
304
|
+
if (!condense)
|
|
305
|
+
{
|
|
306
|
+
code += ',\t// ' + name;
|
|
307
|
+
if (!isEnd)
|
|
308
|
+
code += '\n';
|
|
309
|
+
}
|
|
310
|
+
else if (!isEnd)
|
|
311
|
+
code += ', ';
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
if (condense)
|
|
316
|
+
code += ');';
|
|
317
|
+
else
|
|
318
|
+
code += '\n); // particle emitter';
|
|
319
|
+
|
|
320
|
+
return code;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
324
|
+
function gameUpdate()
|
|
325
|
+
{
|
|
326
|
+
if (!restartTimer.isSet() && particleSystem.destroyed)
|
|
327
|
+
restartTimer.set(1);
|
|
328
|
+
else if (restartTimer.elapsed())
|
|
329
|
+
{
|
|
330
|
+
restartTimer.unset()
|
|
331
|
+
makeEmitter();
|
|
332
|
+
updateParticles();
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (document.activeElement == document.body)
|
|
336
|
+
{
|
|
337
|
+
particleSystem.pos = mouseIsDown(0) ? mousePos : vec2();
|
|
338
|
+
if (mouseWheel)
|
|
339
|
+
{
|
|
340
|
+
cameraScale -= sign(mouseWheel)*cameraScale/5;
|
|
341
|
+
cameraScale = clamp(cameraScale, 10, 300);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
347
|
+
function gameUpdatePost()
|
|
348
|
+
{
|
|
349
|
+
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
353
|
+
function gameRender()
|
|
354
|
+
{
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
358
|
+
function gameRenderPost()
|
|
359
|
+
{
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
363
|
+
// Startup LittleJS Engine
|
|
364
|
+
engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, 'tiles.png');
|
|
365
|
+
|
|
366
|
+
</script>
|
|
Binary file
|
|
@@ -33,7 +33,7 @@ function gameUpdate()
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// mouse wheel = zoom
|
|
36
|
-
cameraScale = clamp(cameraScale*(1-mouseWheel/10),
|
|
36
|
+
cameraScale = clamp(cameraScale*(1-mouseWheel/10), 1, 1e3);
|
|
37
37
|
|
|
38
38
|
// T = drop test crate
|
|
39
39
|
if (keyWasPressed(84))
|
|
@@ -73,18 +73,18 @@ function gameRender()
|
|
|
73
73
|
function gameRenderPost()
|
|
74
74
|
{
|
|
75
75
|
// draw to overlay canvas for hud rendering
|
|
76
|
-
const drawText = (text, x, y, size=
|
|
76
|
+
const drawText = (text, x, y, size=50) =>
|
|
77
77
|
{
|
|
78
78
|
overlayContext.textAlign = 'center';
|
|
79
79
|
overlayContext.textBaseline = 'top';
|
|
80
80
|
overlayContext.font = size + 'px arial';
|
|
81
81
|
overlayContext.fillStyle = '#fff';
|
|
82
|
-
overlayContext.lineWidth =
|
|
82
|
+
overlayContext.lineWidth = 2;
|
|
83
83
|
overlayContext.strokeText(text, x, y);
|
|
84
84
|
overlayContext.fillText(text, x, y);
|
|
85
85
|
}
|
|
86
|
-
drawText('Score: ' + score, overlayCanvas.width*1/
|
|
87
|
-
drawText('Deaths: ' + deaths, overlayCanvas.width*
|
|
86
|
+
drawText('Score: ' + score, overlayCanvas.width*1/4, 20);
|
|
87
|
+
drawText('Deaths: ' + deaths, overlayCanvas.width*3/4, 20);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -39,7 +39,7 @@ function makeDebris(pos, color = new Color, amount = 100, size=.2, elasticity =
|
|
|
39
39
|
{
|
|
40
40
|
const color2 = color.lerp(new Color, .5);
|
|
41
41
|
const emitter = new ParticleEmitter(
|
|
42
|
-
pos, 1, .1, 100, PI, // pos, emitSize, emitTime, emitRate, emiteCone
|
|
42
|
+
pos, 0, 1, .1, 100, PI, // pos, angle, emitSize, emitTime, emitRate, emiteCone
|
|
43
43
|
undefined, undefined, // tileIndex, tileSize
|
|
44
44
|
color, color2, // colorStartA, colorStartB
|
|
45
45
|
color, color2, // colorEndA, colorEndB
|
|
@@ -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())
|
|
@@ -100,7 +100,7 @@ function explosion(pos, radius=3)
|
|
|
100
100
|
|
|
101
101
|
// smoke
|
|
102
102
|
new ParticleEmitter(
|
|
103
|
-
pos, radius/2, .2, 50*radius, PI, // pos, emitSize, emitTime, emitRate, emiteCone
|
|
103
|
+
pos, 0, radius/2, .2, 50*radius, PI, // pos, angle, emitSize, emitTime, emitRate, emiteCone
|
|
104
104
|
0, undefined, // tileIndex, tileSize
|
|
105
105
|
new Color(0,0,0), new Color(0,0,0), // colorStartA, colorStartB
|
|
106
106
|
new Color(0,0,0,0), new Color(0,0,0,0), // colorEndA, colorEndB
|
|
@@ -111,7 +111,7 @@ function explosion(pos, radius=3)
|
|
|
111
111
|
|
|
112
112
|
// fire
|
|
113
113
|
new ParticleEmitter(
|
|
114
|
-
pos, radius/2, .1, 100*radius, PI, // pos, emitSize, emitTime, emitRate, emiteCone
|
|
114
|
+
pos, 0, radius/2, .1, 100*radius, PI, // pos, angle, emitSize, emitTime, emitRate, emiteCone
|
|
115
115
|
0, undefined, // tileIndex, tileSize
|
|
116
116
|
new Color(1,.5,.1), new Color(1,.1,.1), // colorStartA, colorStartB
|
|
117
117
|
new Color(1,.5,.1,0), new Color(1,.1,.1,0), // colorEndA, colorEndB
|
|
@@ -203,7 +203,7 @@ function decorateTile(pos)
|
|
|
203
203
|
|
|
204
204
|
// make pixel perfect outlines
|
|
205
205
|
const size = i&1 ? vec2(2, 16) : vec2(16, 2);
|
|
206
|
-
tileLayer.context.fillStyle = levelGroundColor.mutate(.1)
|
|
206
|
+
tileLayer.context.fillStyle = levelGroundColor.mutate(.1);
|
|
207
207
|
const drawPos = pos.scale(16)
|
|
208
208
|
.add(vec2(i==1?14:0,(i==0?14:0)))
|
|
209
209
|
.subtract((i&1? vec2(0,8-size.y/2) : vec2(8-size.x/2,0)));
|
|
@@ -228,8 +228,8 @@ function drawSky()
|
|
|
228
228
|
{
|
|
229
229
|
// fill background with a gradient
|
|
230
230
|
const gradient = mainContext.fillStyle = mainContext.createLinearGradient(0, 0, 0, mainCanvas.height);
|
|
231
|
-
gradient.addColorStop(0, skyColor
|
|
232
|
-
gradient.addColorStop(1, horizonColor
|
|
231
|
+
gradient.addColorStop(0, skyColor);
|
|
232
|
+
gradient.addColorStop(1, horizonColor);
|
|
233
233
|
mainContext.fillRect(0, 0, mainCanvas.width, mainCanvas.height);
|
|
234
234
|
}
|
|
235
235
|
|
|
@@ -257,7 +257,7 @@ function drawStars()
|
|
|
257
257
|
(randSeeded(w)+time*speed)%w-extraSpace,
|
|
258
258
|
(randSeeded(h)+time*speed*randSeeded())%h-extraSpace);
|
|
259
259
|
|
|
260
|
-
mainContext.fillStyle = color
|
|
260
|
+
mainContext.fillStyle = color;
|
|
261
261
|
if (size < 9)
|
|
262
262
|
mainContext.fillRect(screenPos.x, screenPos.y, size, size);
|
|
263
263
|
else
|
|
@@ -285,8 +285,8 @@ function initParallaxLayers()
|
|
|
285
285
|
const layerColor = levelColor.mutate(.2).lerp(skyColor,.95-i*.15);
|
|
286
286
|
const gradient = tileParallaxLayer.context.fillStyle =
|
|
287
287
|
tileParallaxLayer.context.createLinearGradient(0,0,0,tileParallaxLayer.canvas.height = parallaxSize.y);
|
|
288
|
-
gradient.addColorStop(0,layerColor
|
|
289
|
-
gradient.addColorStop(1,layerColor.subtract(new Color(1,1,1,0)).mutate(.1).clamp()
|
|
288
|
+
gradient.addColorStop(0,layerColor);
|
|
289
|
+
gradient.addColorStop(1,layerColor.subtract(new Color(1,1,1,0)).mutate(.1).clamp());
|
|
290
290
|
|
|
291
291
|
// draw mountains ranges
|
|
292
292
|
let groundLevel = startGroundLevel, groundSlope = rand(-1,1);
|
|
@@ -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, levelSize.y-20
|
|
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);
|
|
@@ -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
|
|
@@ -210,7 +210,7 @@ class Weapon extends EngineObject
|
|
|
210
210
|
|
|
211
211
|
// shell effect
|
|
212
212
|
this.addChild(this.shellEmitter = new ParticleEmitter(
|
|
213
|
-
vec2(), 0, 0, 0, .1, // pos, emitSize, emitTime, emitRate, emiteCone
|
|
213
|
+
vec2(), 0, 0, 0, 0, .1, // pos, angle, emitSize, emitTime, emitRate, emiteCone
|
|
214
214
|
undefined, undefined, // tileIndex, tileSize
|
|
215
215
|
new Color(1,.8,.5), new Color(.9,.7,.5), // colorStartA, colorStartB
|
|
216
216
|
new Color(1,.8,.5), new Color(.9,.7,.5), // colorEndA, colorEndB
|
|
@@ -321,7 +321,7 @@ class Bullet extends EngineObject
|
|
|
321
321
|
|
|
322
322
|
// spark effects
|
|
323
323
|
const emitter = new ParticleEmitter(
|
|
324
|
-
this.pos, 0, .1, 100, .5, // pos, emitSize, emitTime, emitRate, emiteCone
|
|
324
|
+
this.pos, 0, 0, .1, 100, .5, // pos, angle, emitSize, emitTime, emitRate, emiteCone
|
|
325
325
|
undefined, undefined, // tileIndex, tileSize
|
|
326
326
|
new Color(1,1,0), new Color(1,0,0), // colorStartA, colorStartB
|
|
327
327
|
new Color(1,1,0), new Color(1,0,0), // colorEndA, colorEndB
|
|
@@ -126,7 +126,12 @@ class Character extends GameObject
|
|
|
126
126
|
{
|
|
127
127
|
// update jumping and ground check
|
|
128
128
|
if (this.groundObject || this.climbingWall)
|
|
129
|
+
{
|
|
130
|
+
if (!this.groundTimer.isSet())
|
|
131
|
+
sound_walk.play(this.pos); // land sound
|
|
132
|
+
|
|
129
133
|
this.groundTimer.set(.1);
|
|
134
|
+
}
|
|
130
135
|
|
|
131
136
|
if (this.groundTimer.active() && !this.dodgeTimer.active())
|
|
132
137
|
{
|
|
@@ -169,7 +174,7 @@ class Character extends GameObject
|
|
|
169
174
|
|
|
170
175
|
// apply movement acceleration and clamp
|
|
171
176
|
const maxCharacterSpeed = .2;
|
|
172
|
-
this.velocity.x = clamp(this.velocity.x + moveInput.x * .042, maxCharacterSpeed,
|
|
177
|
+
this.velocity.x = clamp(this.velocity.x + moveInput.x * .042, -maxCharacterSpeed, maxCharacterSpeed);
|
|
173
178
|
|
|
174
179
|
// track last pos for ladder collision code
|
|
175
180
|
this.lastPos = this.pos.copy();
|
|
@@ -189,16 +194,16 @@ class Character extends GameObject
|
|
|
189
194
|
|
|
190
195
|
// update walk sound
|
|
191
196
|
this.walkSoundTime += speed;
|
|
192
|
-
if (speed > .
|
|
197
|
+
if (speed > .001 && ((this.climbingLadder || this.groundTimer.active()) && !this.dodgeTimer.active()))
|
|
193
198
|
{
|
|
194
199
|
if (this.walkSoundTime > 1)
|
|
195
200
|
{
|
|
196
|
-
this.walkSoundTime =
|
|
201
|
+
this.walkSoundTime = this.walkSoundTime%1;
|
|
197
202
|
sound_walk.play(this.pos);
|
|
198
203
|
}
|
|
199
204
|
}
|
|
200
205
|
else
|
|
201
|
-
this.walkSoundTime =
|
|
206
|
+
this.walkSoundTime = 0;
|
|
202
207
|
|
|
203
208
|
// update mirror
|
|
204
209
|
if (moveInput.x && !this.dodgeTimer.active())
|
|
@@ -292,8 +297,8 @@ class Player extends Character
|
|
|
292
297
|
// player controls
|
|
293
298
|
this.holdingJump = keyIsDown(38) || gamepadIsDown(0);
|
|
294
299
|
this.holdingShoot = mouseIsDown(0) || keyIsDown(90) || gamepadIsDown(2);
|
|
295
|
-
this.
|
|
296
|
-
this.
|
|
300
|
+
this.pressingThrow = mouseIsDown(1) || keyIsDown(67) || gamepadIsDown(1);
|
|
301
|
+
this.pressedDodge = mouseIsDown(2) || keyIsDown(88) || gamepadIsDown(3);
|
|
297
302
|
|
|
298
303
|
// movement control
|
|
299
304
|
this.moveInput = isUsingGamepad ? gamepadStick(0) :
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
<link rel=icon type=image/png href=../../favicon.png>
|
|
6
6
|
</head><body>
|
|
7
7
|
|
|
8
|
-
<script src=../../engine/engine.all.js?
|
|
9
|
-
<script src=gameObjects.js?
|
|
10
|
-
<script src=gamePlayer.js?
|
|
11
|
-
<script src=gameEffects.js?
|
|
12
|
-
<script src=gameLevel.js?
|
|
13
|
-
<script src=game.js?
|
|
8
|
+
<script src=../../engine/engine.all.js?104></script>
|
|
9
|
+
<script src=gameObjects.js?104></script>
|
|
10
|
+
<script src=gamePlayer.js?104></script>
|
|
11
|
+
<script src=gameEffects.js?104></script>
|
|
12
|
+
<script src=gameLevel.js?104></script>
|
|
13
|
+
<script src=game.js?103></script>
|
|
Binary file
|