littlejsengine 1.12.4 → 1.13.1
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/dist/box2d.wasm.js +630 -0
- package/dist/box2d.wasm.wasm +0 -0
- package/dist/littlejs.d.ts +437 -219
- package/dist/littlejs.esm.js +5950 -5307
- package/dist/littlejs.esm.min.js +4 -1
- package/dist/littlejs.js +5921 -5295
- package/dist/littlejs.min.js +4 -1
- package/dist/littlejs.release.js +5485 -4886
- package/examples/box2d/game.js +37 -42
- package/examples/box2d/gameObjects.js +41 -37
- package/examples/box2d/index.html +2 -2
- package/examples/box2d/scenes.js +24 -20
- package/examples/box2d/tiles.png +0 -0
- package/examples/breakout/game.js +1 -1
- package/examples/breakout/gameObjects.js +2 -2
- package/examples/breakout/index.html +1 -1
- package/examples/breakoutTutorial/README.md +2 -2
- package/examples/breakoutTutorial/game.js +1 -1
- package/examples/breakoutTutorial/index.html +1 -1
- package/examples/empty/index.html +1 -1
- package/examples/htmlMenu/index.html +1 -1
- package/examples/index.html +410 -159
- package/examples/module/game.js +1 -1
- package/examples/module/index.html +1 -1
- package/examples/platformer/game.js +6 -15
- package/examples/platformer/gameCharacter.js +6 -6
- package/examples/platformer/gameEffects.js +74 -57
- package/examples/platformer/gameLevel.js +61 -70
- package/examples/platformer/gameObjects.js +4 -4
- package/examples/platformer/index.html +1 -1
- package/examples/puzzle/index.html +1 -1
- package/examples/shorts/base.html +24 -3
- package/examples/shorts/box2d.js +46 -0
- package/examples/shorts/box2dCar.js +45 -0
- package/examples/shorts/flappyGame.js +52 -0
- package/examples/shorts/helloWorld.js +6 -3
- package/examples/shorts/hillGlideGame.js +56 -0
- package/examples/shorts/landerGame.js +32 -0
- package/examples/shorts/maze.js +47 -0
- package/examples/shorts/medals.js +42 -0
- package/examples/shorts/nineSlice.js +21 -0
- package/examples/shorts/piano.js +52 -0
- package/examples/shorts/platformer.js +24 -20
- package/examples/shorts/{pong.js → pongGame.js} +1 -1
- package/examples/shorts/postProcess.js +45 -0
- package/examples/shorts/raycasting.js +71 -0
- package/examples/shorts/slidingPuzzle.js +42 -0
- package/examples/shorts/spaceGame.js +56 -0
- package/examples/shorts/starfield.js +17 -0
- package/examples/shorts/tileLayer.js +3 -5
- package/examples/shorts/tiles.png +0 -0
- package/examples/shorts/tiltedView.js +8 -7
- package/examples/shorts/topDown.js +18 -26
- package/examples/shorts/uiSystem.js +36 -0
- package/examples/starter/build.bat +6 -1
- package/examples/starter/game.js +4 -2
- package/examples/starter/index.html +23 -13
- package/examples/stress/index.html +2 -3
- package/examples/style.css +136 -0
- package/examples/typescript/build.js +1 -2
- package/examples/typescript/game.js +2 -2
- package/examples/typescript/game.ts +1 -1
- package/examples/typescript/index.html +1 -1
- package/examples/uiSystem/game.js +9 -25
- package/examples/uiSystem/index.html +1 -1
- package/package.json +1 -1
- package/plugins/box2d.js +29 -35
- package/plugins/drawUtilities.js +126 -0
- package/plugins/newgrounds.js +1 -1
- package/plugins/pluginExport.js +8 -2
- package/plugins/postProcess.js +2 -2
- package/plugins/uiSystem.js +162 -68
- package/plugins/zzfxm.js +1 -1
- package/reference.md +10 -10
- package/src/engine.js +59 -39
- package/src/engineAudio.js +38 -20
- package/src/engineBuild.bat +6 -1
- package/src/engineBuild.js +32 -7
- package/src/engineDebug.js +53 -26
- package/src/engineDraw.js +108 -57
- package/src/engineExport.js +22 -9
- package/src/engineInput.js +112 -40
- package/src/engineObject.js +68 -67
- package/src/engineParticles.js +26 -9
- package/src/engineSettings.js +15 -16
- package/src/engineTileLayer.js +312 -153
- package/src/engineUtilities.js +198 -130
- package/src/engineWebGL.js +58 -35
package/examples/module/game.js
CHANGED
|
@@ -77,7 +77,7 @@ function gameInit()
|
|
|
77
77
|
.99, 1, 1, Math.PI, // damping, angleDamping, gravityScale, cone
|
|
78
78
|
.05, .5, true, true // fadeRate, randomness, collide, additive
|
|
79
79
|
);
|
|
80
|
-
particleEmitter.
|
|
80
|
+
particleEmitter.restitution = .3; // bounce when it collides
|
|
81
81
|
particleEmitter.trailScale = 2; // stretch in direction of motion
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -16,14 +16,14 @@ import * as GamePlayer from './gamePlayer.js';
|
|
|
16
16
|
import * as GameLevel from './gameLevel.js';
|
|
17
17
|
const {vec2} = LJS;
|
|
18
18
|
|
|
19
|
-
// enable touch gamepad on touch devices
|
|
20
|
-
LJS.setTouchGamepadEnable(true);
|
|
21
|
-
|
|
22
19
|
// globals
|
|
23
|
-
export let spriteAtlas, player, score, deaths
|
|
20
|
+
export let gameLevelData, spriteAtlas, player, score, deaths;
|
|
24
21
|
export function addToScore(delta=1) { score += delta; }
|
|
25
22
|
export function addToDeaths() { ++deaths; }
|
|
26
23
|
|
|
24
|
+
// enable touch gamepad on touch devices
|
|
25
|
+
LJS.setTouchGamepadEnable(true);
|
|
26
|
+
|
|
27
27
|
///////////////////////////////////////////////////////////////////////////////
|
|
28
28
|
function loadLevel()
|
|
29
29
|
{
|
|
@@ -41,17 +41,8 @@ function loadLevel()
|
|
|
41
41
|
///////////////////////////////////////////////////////////////////////////////
|
|
42
42
|
async function gameInit()
|
|
43
43
|
{
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// load level data from external JSON file
|
|
47
|
-
const response = await fetch('gameLevelData.json');
|
|
48
|
-
gameLevelData = await response.json();
|
|
49
|
-
console.log('Level data loaded successfully');
|
|
50
|
-
}
|
|
51
|
-
catch (error)
|
|
52
|
-
{
|
|
53
|
-
console.error('Failed to load level data!');
|
|
54
|
-
}
|
|
44
|
+
// load the game level data
|
|
45
|
+
gameLevelData = await LJS.fetchJSON('gameLevelData.json');
|
|
55
46
|
|
|
56
47
|
// engine settings
|
|
57
48
|
LJS.setGravity(vec2(0,-.01));
|
|
@@ -108,7 +108,7 @@ export class Character extends GameObjects.GameObject
|
|
|
108
108
|
for (let y=2;y--;)
|
|
109
109
|
{
|
|
110
110
|
const testPos = this.pos.add(vec2(0, y + .1*moveInput.y - this.size.y/2));
|
|
111
|
-
const collisionData = LJS.
|
|
111
|
+
const collisionData = LJS.tileCollisionGetData(testPos);
|
|
112
112
|
touchingLadder ||= collisionData == GameLevel.tileType_ladder;
|
|
113
113
|
}
|
|
114
114
|
if (!touchingLadder)
|
|
@@ -133,7 +133,7 @@ export class Character extends GameObjects.GameObject
|
|
|
133
133
|
moveInput.x *= .2;
|
|
134
134
|
|
|
135
135
|
// exit ladder if ground is below
|
|
136
|
-
this.climbingLadder = moveInput.y >= 0 || LJS.
|
|
136
|
+
this.climbingLadder = moveInput.y >= 0 || LJS.tileCollisionGetData(this.pos.subtract(vec2(0,1))) <= 0;
|
|
137
137
|
}
|
|
138
138
|
else
|
|
139
139
|
{
|
|
@@ -234,7 +234,7 @@ export class Character extends GameObjects.GameObject
|
|
|
234
234
|
if (!this.isDead())
|
|
235
235
|
{
|
|
236
236
|
// bounce pos with walk cycle
|
|
237
|
-
bodyPos = bodyPos.add(vec2(0,.
|
|
237
|
+
bodyPos = bodyPos.add(vec2(0,.05*Math.sin(this.walkCyclePercent*LJS.PI)));
|
|
238
238
|
|
|
239
239
|
// make bottom flush
|
|
240
240
|
bodyPos = bodyPos.add(vec2(0,(this.drawSize.y-this.size.y)/2));
|
|
@@ -281,9 +281,9 @@ export class Character extends GameObjects.GameObject
|
|
|
281
281
|
if (pos.y + 1 > this.lastPos.y - this.size.y/2)
|
|
282
282
|
return false;
|
|
283
283
|
|
|
284
|
-
if (LJS.
|
|
285
|
-
&& !LJS.
|
|
286
|
-
&& !LJS.
|
|
284
|
+
if (LJS.tileCollisionGetData(pos.add(vec2(0,1))) // above
|
|
285
|
+
&& !LJS.tileCollisionGetData(pos.add(vec2(1,0))) // left
|
|
286
|
+
&& !LJS.tileCollisionGetData(pos.add(vec2(1,0)))) // right
|
|
287
287
|
return false; // don't collide if something above it and nothing to left or right
|
|
288
288
|
|
|
289
289
|
// allow standing on top of ladders
|
|
@@ -40,7 +40,7 @@ export const persistentParticleDestroyCallback = (particle)=>
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export function makeBlood(pos, amount) { makeDebris(pos, hsl(0,1,.5), amount, .1, 0); }
|
|
43
|
-
export function makeDebris(pos, color = hsl(), amount = 50, size=.2,
|
|
43
|
+
export function makeDebris(pos, color = hsl(), amount = 50, size=.2, restitution = .3)
|
|
44
44
|
{
|
|
45
45
|
const color2 = color.lerp(hsl(), .5);
|
|
46
46
|
const emitter = new LJS.ParticleEmitter(
|
|
@@ -52,7 +52,7 @@ export function makeDebris(pos, color = hsl(), amount = 50, size=.2, elasticity
|
|
|
52
52
|
1, .95, .4, 3.14, 0, // damp, angleDamp, gravity, particleCone, fade
|
|
53
53
|
.5, 1 // randomness, collide, additive, colorLinear, renderOrder
|
|
54
54
|
);
|
|
55
|
-
emitter.
|
|
55
|
+
emitter.restitution = restitution;
|
|
56
56
|
emitter.particleDestroyCallback = persistentParticleDestroyCallback;
|
|
57
57
|
return emitter;
|
|
58
58
|
}
|
|
@@ -82,6 +82,9 @@ export function explosion(pos, radius=3)
|
|
|
82
82
|
GameLevel.decorateTile(pos.add(vec2(x,y)).floor());
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
// update webgl texture
|
|
86
|
+
GameLevel.updateWebGL(GameLevel.foregroundTileLayer);
|
|
87
|
+
|
|
85
88
|
// kill/push objects
|
|
86
89
|
LJS.engineObjectsCallback(pos, radius*3, (o)=>
|
|
87
90
|
{
|
|
@@ -126,7 +129,7 @@ export function explosion(pos, radius=3)
|
|
|
126
129
|
|
|
127
130
|
///////////////////////////////////////////////////////////////////////////////
|
|
128
131
|
|
|
129
|
-
export function destroyTile(pos, makeSound = 1,
|
|
132
|
+
export function destroyTile(pos, makeSound = 1, cleanup = 1)
|
|
130
133
|
{
|
|
131
134
|
// pos must be an int
|
|
132
135
|
pos = pos.floor();
|
|
@@ -146,16 +149,17 @@ export function destroyTile(pos, makeSound = 1, cleanNeighbors = 1)
|
|
|
146
149
|
makeDebris(centerPos, layerData.color.mutate());
|
|
147
150
|
makeSound && sound_destroyObject.play(centerPos);
|
|
148
151
|
|
|
149
|
-
|
|
150
|
-
layer.setData(pos, new LJS.TileLayerData,
|
|
152
|
+
// set and clear tile
|
|
153
|
+
layer.setData(pos, new LJS.TileLayerData, true);
|
|
151
154
|
layer.setCollisionData(pos, GameLevel.tileType_empty);
|
|
152
155
|
|
|
153
|
-
// cleanup neighbors
|
|
154
|
-
if (
|
|
156
|
+
// cleanup neighbors and rebuild webgl
|
|
157
|
+
if (cleanup)
|
|
155
158
|
{
|
|
156
159
|
for (let i=-1;i<=1;++i)
|
|
157
160
|
for (let j=-1;j<=1;++j)
|
|
158
161
|
GameLevel.decorateTile(pos.add(vec2(i,j)));
|
|
162
|
+
GameLevel.updateWebGL(layer);
|
|
159
163
|
}
|
|
160
164
|
|
|
161
165
|
return true;
|
|
@@ -180,16 +184,16 @@ export class Sky extends LJS.EngineObject
|
|
|
180
184
|
{
|
|
181
185
|
// fill background with a gradient
|
|
182
186
|
const canvas = LJS.mainCanvas;
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
context.globalCompositeOperation = 'lighter';
|
|
187
|
+
const gradientDelta = 5;
|
|
188
|
+
for(let y=0; y<canvas.height; y+=gradientDelta)
|
|
189
|
+
{
|
|
190
|
+
// draw horizontal lines to create a gradient
|
|
191
|
+
const color = this.skyColor.lerp(this.horizonColor, y/canvas.height);
|
|
192
|
+
LJS.drawRect(vec2(0,y), vec2(canvas.width*2, gradientDelta*2), color, 0, undefined, true)
|
|
193
|
+
}
|
|
191
194
|
|
|
192
195
|
// draw stars
|
|
196
|
+
LJS.setBlendMode(true);
|
|
193
197
|
const random = new LJS.RandomGenerator(this.seed);
|
|
194
198
|
for (let i=1e3; i--;)
|
|
195
199
|
{
|
|
@@ -201,61 +205,74 @@ export class Sky extends LJS.EngineObject
|
|
|
201
205
|
const screenPos = vec2(
|
|
202
206
|
(random.float(w)+LJS.time*speed)%w-extraSpace,
|
|
203
207
|
(random.float(h)+LJS.time*speed*random.float())%h-extraSpace);
|
|
204
|
-
|
|
205
|
-
context.fillRect(screenPos.x, screenPos.y, size, size);
|
|
208
|
+
LJS.drawRect(screenPos, vec2(size), color, 0, undefined, true)
|
|
206
209
|
}
|
|
207
|
-
|
|
210
|
+
LJS.setBlendMode(false);
|
|
208
211
|
}
|
|
209
212
|
}
|
|
210
213
|
|
|
211
214
|
///////////////////////////////////////////////////////////////////////////////
|
|
212
215
|
// parallax background mountain ranges
|
|
213
216
|
|
|
214
|
-
export class ParallaxLayer extends LJS.
|
|
217
|
+
export class ParallaxLayer extends LJS.CanvasLayer
|
|
215
218
|
{
|
|
216
|
-
constructor(
|
|
219
|
+
constructor(depth)
|
|
217
220
|
{
|
|
218
|
-
|
|
221
|
+
const renderOrder = depth - 3e3;
|
|
222
|
+
const canvasSize = vec2(512, 256);
|
|
223
|
+
super(vec2(), vec2(), 0, renderOrder, canvasSize);
|
|
224
|
+
this.canvasSize = canvasSize;
|
|
225
|
+
this.depth = depth;
|
|
226
|
+
|
|
227
|
+
// create a gradient for the mountains
|
|
228
|
+
const topColor = GameLevel.levelColor.mutate(.2).lerp(GameLevel.sky.skyColor, .8 - depth*.15);
|
|
229
|
+
const bottomColor = GameLevel.levelColor.subtract(LJS.CLEAR_WHITE).mutate(.2);
|
|
230
|
+
for(let i = canvasSize.y; i--;)
|
|
231
|
+
{
|
|
232
|
+
// draw a 1 pixel gradient line on the left side of the canvas
|
|
233
|
+
const p = i/canvasSize.y;
|
|
234
|
+
this.context.fillStyle = topColor.lerp(bottomColor, p);
|
|
235
|
+
this.context.fillRect(0, i, 1, 1);
|
|
236
|
+
}
|
|
219
237
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
238
|
+
// draw random mountains
|
|
239
|
+
const pointiness = .2; // how pointy the mountains are
|
|
240
|
+
const levelness = .005; // how much the mountains level out
|
|
241
|
+
const slopeRange = 1; // max slope of the mountains
|
|
242
|
+
const startGroundLevel = canvasSize.y/2;
|
|
243
|
+
let y = startGroundLevel, groundSlope = LJS.rand(-slopeRange, slopeRange);
|
|
244
|
+
for(let x=canvasSize.x; x--;)
|
|
245
|
+
{
|
|
246
|
+
// pull slope towards start ground level
|
|
247
|
+
y += groundSlope -= (y-startGroundLevel)*levelness;
|
|
248
|
+
|
|
249
|
+
// random change slope
|
|
250
|
+
if (LJS.rand() < pointiness)
|
|
251
|
+
groundSlope = LJS.rand(-slopeRange, slopeRange);
|
|
252
|
+
|
|
253
|
+
// draw 1 pixel wide vertical slice of mountain
|
|
254
|
+
this.context.drawImage(this.canvas, 0, 0, 1, canvasSize.y, x, y, 1, canvasSize.y - y);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// remove gradient sliver from left side
|
|
258
|
+
this.context.clearRect(0,0,1,canvasSize.y);
|
|
259
|
+
|
|
260
|
+
// make webgl texture
|
|
261
|
+
this.useWebGL(LJS.glEnable);
|
|
243
262
|
}
|
|
244
263
|
|
|
245
264
|
render()
|
|
246
265
|
{
|
|
247
|
-
|
|
248
|
-
const
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
const scale =
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
// draw the parallax layer onto the main canvas
|
|
259
|
-
LJS.mainContext.drawImage(this.canvas, pos.x, pos.y, scale.x, scale.y);
|
|
266
|
+
const depth = this.depth
|
|
267
|
+
const distance = 4 + depth;
|
|
268
|
+
const parallax = vec2(150, 30).scale(depth**2+1);
|
|
269
|
+
const levelCenter = GameLevel.levelSize.scale(.5);
|
|
270
|
+
const cameraDeltaFromCenter = LJS.cameraPos.subtract(levelCenter).divide(levelCenter.scale(-1).divide(parallax));
|
|
271
|
+
const scale = distance/LJS.cameraScale;
|
|
272
|
+
const positonOffset = vec2(0, 2-depth);
|
|
273
|
+
const cameraOffset = cameraDeltaFromCenter.scale(1/LJS.cameraScale);
|
|
274
|
+
this.pos = LJS.cameraPos.add(positonOffset).add(cameraOffset);
|
|
275
|
+
this.size = this.canvasSize.scale(scale);
|
|
276
|
+
super.render();
|
|
260
277
|
}
|
|
261
278
|
}
|
|
@@ -14,6 +14,7 @@ import * as GameEffects from './gameEffects.js';
|
|
|
14
14
|
import * as Game from './game.js';
|
|
15
15
|
const {vec2, hsl, tile} = LJS;
|
|
16
16
|
|
|
17
|
+
export const useWebGLTileLayers = true;
|
|
17
18
|
export const tileType_ladder = -1;
|
|
18
19
|
export const tileType_empty = 0;
|
|
19
20
|
export const tileType_solid = 1;
|
|
@@ -31,9 +32,9 @@ export function buildLevel()
|
|
|
31
32
|
levelColor = LJS.randColor(hsl(0,0,.2), hsl(0,0,.8));
|
|
32
33
|
levelBackgroundColor = levelColor.mutate().scale(.4,1);
|
|
33
34
|
levelOutlineColor = levelColor.mutate().add(hsl(0,0,.4)).clamp();
|
|
34
|
-
|
|
35
|
+
loadLevelData();
|
|
35
36
|
|
|
36
|
-
// create sky object with gradient and stars
|
|
37
|
+
// create sky object with gradient background and stars
|
|
37
38
|
sky = new GameEffects.Sky;
|
|
38
39
|
|
|
39
40
|
// create parallax layers
|
|
@@ -41,114 +42,99 @@ export function buildLevel()
|
|
|
41
42
|
new GameEffects.ParallaxLayer(i);
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
function
|
|
45
|
+
function loadLevelData()
|
|
45
46
|
{
|
|
46
|
-
// load level data
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
tileMapData.width = 100;
|
|
53
|
-
tileMapData.height = 20;
|
|
54
|
-
tileMapData.layers = [{data:[]}];
|
|
55
|
-
for(let i=100*20;i--;)
|
|
56
|
-
tileMapData.layers[0].data[i] = i>100 ? 2 : 0;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
levelSize = vec2(tileMapData.width, tileMapData.height);
|
|
47
|
+
// load the level data
|
|
48
|
+
const tileMapData = Game.gameLevelData;
|
|
49
|
+
tileLayers = LJS.tileCollisionLoad(tileMapData, tile(0,16,1));
|
|
50
|
+
levelSize = tileLayers[0].size;
|
|
51
|
+
playerStartPos = vec2(0, levelSize.y); // default player start
|
|
52
|
+
foregroundTileLayer = tileLayers[0];
|
|
60
53
|
|
|
61
54
|
// create table for tiles in the level tilemap
|
|
62
55
|
const tileLookup =
|
|
63
56
|
{
|
|
64
|
-
circle:
|
|
65
|
-
ground:
|
|
66
|
-
ladder:
|
|
67
|
-
metal:
|
|
68
|
-
player:
|
|
69
|
-
crate:
|
|
70
|
-
enemy:
|
|
71
|
-
coin:
|
|
57
|
+
circle: 0,
|
|
58
|
+
ground: 1,
|
|
59
|
+
ladder: 3,
|
|
60
|
+
metal: 4,
|
|
61
|
+
player: 16,
|
|
62
|
+
crate: 17,
|
|
63
|
+
enemy: 18,
|
|
64
|
+
coin: 19,
|
|
72
65
|
}
|
|
73
66
|
|
|
74
|
-
|
|
75
|
-
tileLayers = [];
|
|
76
|
-
playerStartPos = vec2(1, levelSize.y);
|
|
77
|
-
const layerCount = tileMapData.layers.length;
|
|
78
|
-
for (let layer=layerCount; layer--;)
|
|
67
|
+
for (let i=tileLayers.length; i--;)
|
|
79
68
|
{
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
if (
|
|
83
|
-
tileLayer = new LJS.TileLayer(vec2(), levelSize, tile(0,16,1));
|
|
84
|
-
else
|
|
85
|
-
{
|
|
86
|
-
// only foreground layer has collision
|
|
87
|
-
tileLayer = new LJS.TileCollisionLayer(vec2(), levelSize, tile(0,16,1));
|
|
69
|
+
const tileLayer = tileLayers[i];
|
|
70
|
+
const isForeground = i == tileLayers.length - 1;
|
|
71
|
+
if (isForeground)
|
|
88
72
|
foregroundTileLayer = tileLayer;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
tileLayers[layer] = tileLayer;
|
|
73
|
+
else
|
|
74
|
+
tileLayer.isSolid = false;
|
|
92
75
|
|
|
93
76
|
for (let x=levelSize.x; x--;)
|
|
94
77
|
for (let y=levelSize.y; y--;)
|
|
95
78
|
{
|
|
96
79
|
const pos = vec2(x,levelSize.y-1-y);
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
if (tile >= tileLookup.player)
|
|
80
|
+
const tileData = tileLayer.getData(pos).tile;
|
|
81
|
+
if (tileData >= tileLookup.player)
|
|
100
82
|
{
|
|
101
83
|
// create object instead of tile
|
|
102
84
|
const objectPos = pos.add(vec2(.5));
|
|
103
|
-
if (
|
|
85
|
+
if (tileData == tileLookup.player)
|
|
104
86
|
playerStartPos = objectPos;
|
|
105
|
-
if (
|
|
87
|
+
if (tileData == tileLookup.crate)
|
|
106
88
|
new GameObjects.Crate(objectPos);
|
|
107
|
-
if (
|
|
89
|
+
if (tileData == tileLookup.enemy)
|
|
108
90
|
new GameObjects.Enemy(objectPos);
|
|
109
|
-
if (
|
|
91
|
+
if (tileData == tileLookup.coin)
|
|
110
92
|
new GameObjects.Coin(objectPos);
|
|
93
|
+
|
|
94
|
+
// replace with empty tile and empty collision
|
|
95
|
+
tileLayer.setData(pos, new LJS.TileLayerData);
|
|
96
|
+
tileLayer.setCollisionData(pos, 0);
|
|
111
97
|
continue;
|
|
112
98
|
}
|
|
113
|
-
|
|
114
|
-
// get tile type
|
|
115
|
-
let tileType = tileType_empty;
|
|
116
|
-
if (
|
|
117
|
-
tileType = tileType_breakable;
|
|
118
|
-
if (tile == tileLookup.ladder)
|
|
99
|
+
|
|
100
|
+
// get tile type
|
|
101
|
+
let tileType = tileData? tileType_breakable : tileType_empty;
|
|
102
|
+
if (tileData == tileLookup.ladder)
|
|
119
103
|
tileType = tileType_ladder;
|
|
120
|
-
if (
|
|
104
|
+
if (tileData == tileLookup.metal)
|
|
121
105
|
tileType = tileType_solid;
|
|
122
106
|
if (tileType)
|
|
123
107
|
{
|
|
124
108
|
// set collision for solid tiles
|
|
125
|
-
if (tileLayer
|
|
109
|
+
if (tileLayer.isSolid)
|
|
126
110
|
tileLayer.setCollisionData(pos, tileType);
|
|
127
|
-
|
|
128
|
-
// randomize tile appearance
|
|
129
|
-
let direction, mirror, color;
|
|
130
111
|
if (tileType == tileType_breakable)
|
|
131
112
|
{
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
113
|
+
// randomize tile appearance
|
|
114
|
+
let direction = LJS.randInt(4);
|
|
115
|
+
let mirror = LJS.randInt(2);
|
|
116
|
+
let color = i ? levelColor : levelBackgroundColor;
|
|
135
117
|
color = color.mutate(.03);
|
|
136
|
-
}
|
|
137
118
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
119
|
+
// set tile layer data
|
|
120
|
+
const data = new LJS.TileLayerData(tileData, direction, mirror, color);
|
|
121
|
+
tileLayer.setData(pos, data);
|
|
122
|
+
}
|
|
141
123
|
}
|
|
142
124
|
}
|
|
143
125
|
tileLayer.redraw();
|
|
144
126
|
}
|
|
145
|
-
|
|
127
|
+
|
|
146
128
|
// apply decoration to all level tiles
|
|
147
129
|
const pos = vec2();
|
|
130
|
+
const layerCount = tileMapData.layers.length;
|
|
148
131
|
for (let layer=layerCount; layer--;)
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
132
|
+
{
|
|
133
|
+
for (pos.x=levelSize.x; pos.x--;)
|
|
134
|
+
for (pos.y=levelSize.y; pos.y--;)
|
|
135
|
+
decorateTile(pos, layer);
|
|
136
|
+
updateWebGL(tileLayers[layer]);
|
|
137
|
+
}
|
|
152
138
|
}
|
|
153
139
|
|
|
154
140
|
export function decorateTile(pos, layer=1)
|
|
@@ -213,4 +199,9 @@ export function getCameraTarget()
|
|
|
213
199
|
// camera is above player
|
|
214
200
|
const offset = 100/LJS.cameraScale*LJS.percent(LJS.mainCanvasSize.y, 300, 600);
|
|
215
201
|
return Game.player.pos.add(vec2(0, offset));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function updateWebGL(layer)
|
|
205
|
+
{
|
|
206
|
+
layer.useWebGL(useWebGLTileLayers);
|
|
216
207
|
}
|
|
@@ -188,7 +188,7 @@ export class Grenade extends GameObject
|
|
|
188
188
|
super(pos, vec2(.2), Game.spriteAtlas.grenade);
|
|
189
189
|
|
|
190
190
|
this.beepTimer = new Timer(1);
|
|
191
|
-
this.
|
|
191
|
+
this.restitution = .3;
|
|
192
192
|
this.friction = .9;
|
|
193
193
|
this.angleDamping = .96;
|
|
194
194
|
this.renderOrder = 1e8;
|
|
@@ -253,7 +253,7 @@ export class Weapon extends LJS.EngineObject
|
|
|
253
253
|
1, .95, 1, 0, 0, // damp, angleDamp, gravity, particleCone, fade
|
|
254
254
|
.1, 1 // randomness, collide, additive, colorLinear, renderOrder
|
|
255
255
|
), vec2(.1,0), -.8);
|
|
256
|
-
this.shellEmitter.
|
|
256
|
+
this.shellEmitter.restitution = .5;
|
|
257
257
|
this.shellEmitter.particleDestroyCallback = GameEffects.persistentParticleDestroyCallback;
|
|
258
258
|
}
|
|
259
259
|
|
|
@@ -263,7 +263,7 @@ export class Weapon extends LJS.EngineObject
|
|
|
263
263
|
|
|
264
264
|
// update recoil
|
|
265
265
|
if (this.recoilTimer.active())
|
|
266
|
-
this.localAngle = LJS.lerp(this.recoilTimer.getPercent()
|
|
266
|
+
this.localAngle = LJS.lerp(this.localAngle, 0, this.recoilTimer.getPercent());
|
|
267
267
|
|
|
268
268
|
this.mirror = this.parent.mirror;
|
|
269
269
|
this.fireTimeBuffer += LJS.timeDelta;
|
|
@@ -375,7 +375,7 @@ export class Bullet extends LJS.EngineObject
|
|
|
375
375
|
.5, 1, 1 // randomness, collide, additive, colorLinear, renderOrder
|
|
376
376
|
);
|
|
377
377
|
emitter.trailScale = 1;
|
|
378
|
-
emitter.
|
|
378
|
+
emitter.restitution = .3;
|
|
379
379
|
emitter.angle = this.velocity.angle() + LJS.PI;
|
|
380
380
|
}
|
|
381
381
|
}
|
|
@@ -1,7 +1,28 @@
|
|
|
1
1
|
<!DOCTYPE html><meta charset=utf-8><body>
|
|
2
|
-
<script src=../../dist/littlejs.js?
|
|
3
|
-
<script>
|
|
2
|
+
<script src=../../dist/littlejs.js?11212></script>
|
|
3
|
+
<script src=../../dist/box2d.wasm.js></script>
|
|
4
4
|
|
|
5
|
+
<!-- LittleJS Engine Source
|
|
6
|
+
<script src=../../src/engineDebug.js></script>
|
|
7
|
+
<script src=../../src/engineUtilities.js></script>
|
|
8
|
+
<script src=../../src/engineSettings.js></script>
|
|
9
|
+
<script src=../../src/engineObject.js></script>
|
|
10
|
+
<script src=../../src/engineDraw.js></script>
|
|
11
|
+
<script src=../../src/engineInput.js></script>
|
|
12
|
+
<script src=../../src/engineAudio.js></script>
|
|
13
|
+
<script src=../../src/engineTileLayer.js></script>
|
|
14
|
+
<script src=../../src/engineParticles.js></script>
|
|
15
|
+
<script src=../../src/engineMedals.js></script>
|
|
16
|
+
<script src=../../src/engineWebGL.js></script>
|
|
17
|
+
<script src=../../src/engine.js></script>
|
|
18
|
+
<script src=../../plugins/box2d.js></script>
|
|
19
|
+
<script src=../../plugins/box2d.wasm.js></script>
|
|
20
|
+
<script src=../../plugins/drawUtilities.js></script>
|
|
21
|
+
<script src=../../plugins/postProcess.js></script>
|
|
22
|
+
<script src=../../plugins/uiSystem.js></script>
|
|
23
|
+
<script src=../../plugins/zzfxm.js></script>
|
|
24
|
+
-->
|
|
25
|
+
<script>
|
|
5
26
|
'use strict';
|
|
6
27
|
|
|
7
28
|
// use fixed size canvas for examples
|
|
@@ -23,4 +44,4 @@ function gameUpdatePost() {}
|
|
|
23
44
|
function gameRender() {}
|
|
24
45
|
function gameRenderPost() {}
|
|
25
46
|
|
|
26
|
-
</script>
|
|
47
|
+
</script>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
async function gameInit()
|
|
2
|
+
{
|
|
3
|
+
// setup box2d
|
|
4
|
+
await box2dInit();
|
|
5
|
+
mouseJoint = 0;
|
|
6
|
+
gravity.y = -50;
|
|
7
|
+
|
|
8
|
+
// create ground object
|
|
9
|
+
groundObject = new Box2dObject(vec2(-8), vec2(), 0, 0, GRAY, box2d.bodyTypeStatic);
|
|
10
|
+
groundObject.addBox(vec2(100,2));
|
|
11
|
+
|
|
12
|
+
// add some random objects
|
|
13
|
+
for(let i=50; i--;)
|
|
14
|
+
{
|
|
15
|
+
const o = new Box2dObject(randInCircle(5), vec2(), 0, 0, randColor());
|
|
16
|
+
randInt(2) ? o.addCircle(rand(1,2)) : o.addRandomPoly(rand(1,2));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function gameUpdate()
|
|
21
|
+
{
|
|
22
|
+
// mouse controls
|
|
23
|
+
if (mouseJoint)
|
|
24
|
+
{
|
|
25
|
+
// update mouse joint
|
|
26
|
+
mouseJoint.setTarget(mousePos);
|
|
27
|
+
if (mouseWasReleased(0))
|
|
28
|
+
{
|
|
29
|
+
// release object
|
|
30
|
+
mouseJoint = mouseJoint.destroy();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else if (mouseWasPressed(0))
|
|
34
|
+
{
|
|
35
|
+
// grab object
|
|
36
|
+
const object = box2d.pointCast(mousePos);
|
|
37
|
+
if (object)
|
|
38
|
+
mouseJoint = new Box2dTargetJoint(object, groundObject, mousePos);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function gameRenderPost()
|
|
43
|
+
{
|
|
44
|
+
// draw mouse joint
|
|
45
|
+
mouseJoint && drawLine(mousePos, mouseJoint.getAnchorB(), .2, RED);
|
|
46
|
+
}
|