littlejsengine 1.18.4 → 1.18.8
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/COPYRIGHT.txt +38 -0
- package/FAQ.md +633 -0
- package/README.md +19 -1
- package/dist/littlejs.d.ts +354 -55
- package/dist/littlejs.esm.js +1531 -489
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +1499 -476
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +1493 -470
- package/package.json +8 -1
- package/plugins/box2d.js +32 -7
- package/{src/engineMedals.js → plugins/medalSystem.js} +248 -196
- package/plugins/pathFinder.js +758 -0
- package/plugins/pluginExport.js +19 -0
- package/plugins/{tween.js → tweenSystem.js} +7 -7
- package/plugins/uiSystem.js +186 -25
- package/src/engine.js +2 -141
- package/src/engineAudio.js +3 -3
- package/src/engineBuild.mjs +4 -2
- package/src/engineDebug.js +7 -7
- package/src/engineDraw.js +26 -8
- package/src/engineExport.js +13 -13
- package/src/engineInput.js +8 -8
- package/src/engineLogo.js +146 -0
- package/src/engineMath.js +15 -6
- package/src/engineObject.js +11 -5
- package/src/engineParticles.js +6 -3
- package/src/engineRelease.js +1 -1
- package/src/engineSettings.js +0 -47
- package/src/engineUtilities.js +13 -8
- package/src/engineWebGL.js +34 -7
- package/src/jsconfig.json +3 -1
- package/.github/workflows/test.yml +0 -17
- package/AI.md +0 -173
- package/CLAUDE.md +0 -1
- package/examples/box2d/game.js +0 -192
- package/examples/box2d/gameObjects.js +0 -564
- package/examples/box2d/index.html +0 -9
- package/examples/box2d/scenes.js +0 -194
- package/examples/box2d/tiles.png +0 -0
- package/examples/breakout/game.js +0 -175
- package/examples/breakout/gameObjects.js +0 -147
- package/examples/breakout/index.html +0 -8
- package/examples/breakout/tiles.png +0 -0
- package/examples/breakoutTutorial/README.md +0 -521
- package/examples/breakoutTutorial/game.js +0 -191
- package/examples/breakoutTutorial/images/1.png +0 -0
- package/examples/breakoutTutorial/images/10.png +0 -0
- package/examples/breakoutTutorial/images/11.png +0 -0
- package/examples/breakoutTutorial/images/2.png +0 -0
- package/examples/breakoutTutorial/images/3.png +0 -0
- package/examples/breakoutTutorial/images/4.png +0 -0
- package/examples/breakoutTutorial/images/5.png +0 -0
- package/examples/breakoutTutorial/images/6.png +0 -0
- package/examples/breakoutTutorial/images/7.png +0 -0
- package/examples/breakoutTutorial/images/8.png +0 -0
- package/examples/breakoutTutorial/images/9.png +0 -0
- package/examples/breakoutTutorial/index.html +0 -8
- package/examples/electron/build.mjs +0 -127
- package/examples/electron/electron.js +0 -35
- package/examples/electron/game.js +0 -54
- package/examples/electron/index.html +0 -13
- package/examples/electron/package.json +0 -5
- package/examples/electron/tiles.png +0 -0
- package/examples/empty/game.js +0 -51
- package/examples/empty/index.html +0 -5
- package/examples/empty/tiles.png +0 -0
- package/examples/favicon.png +0 -0
- package/examples/games.jpg +0 -0
- package/examples/htmlMenu/game.js +0 -82
- package/examples/htmlMenu/index.html +0 -45
- package/examples/htmlMenu/tiles.png +0 -0
- package/examples/index.html +0 -62
- package/examples/logo.png +0 -0
- package/examples/logo2.png +0 -0
- package/examples/module/build.mjs +0 -124
- package/examples/module/game.js +0 -132
- package/examples/module/index.html +0 -10
- package/examples/module/tiles.png +0 -0
- package/examples/particles/index.html +0 -426
- package/examples/particles/tiles.png +0 -0
- package/examples/platformer/data/gameLevelData.tmx +0 -143
- package/examples/platformer/data/gameLevelData.tsx +0 -4
- package/examples/platformer/game.js +0 -147
- package/examples/platformer/gameCharacter.js +0 -309
- package/examples/platformer/gameEffects.js +0 -278
- package/examples/platformer/gameLevel.js +0 -205
- package/examples/platformer/gameLevelData.json +0 -171
- package/examples/platformer/gameObjects.js +0 -378
- package/examples/platformer/gamePlayer.js +0 -35
- package/examples/platformer/index.html +0 -9
- package/examples/platformer/tiles.png +0 -0
- package/examples/platformer/tilesLevel.png +0 -0
- package/examples/puzzle/game.js +0 -331
- package/examples/puzzle/index.html +0 -8
- package/examples/puzzle/tiles.png +0 -0
- package/examples/screenshot.jpg +0 -0
- package/examples/shorts/animation.js +0 -18
- package/examples/shorts/base.html +0 -54
- package/examples/shorts/blending.js +0 -14
- package/examples/shorts/box2d.js +0 -51
- package/examples/shorts/box2dCar.js +0 -59
- package/examples/shorts/box2dPool.js +0 -107
- package/examples/shorts/box2dTileLayer.js +0 -48
- package/examples/shorts/cameraDrag.js +0 -22
- package/examples/shorts/clock.js +0 -21
- package/examples/shorts/colors.js +0 -25
- package/examples/shorts/debugDraw.js +0 -37
- package/examples/shorts/empty.js +0 -30
- package/examples/shorts/flappyGame.js +0 -55
- package/examples/shorts/fontImage.js +0 -17
- package/examples/shorts/fps.js +0 -90
- package/examples/shorts/helloWorld.js +0 -11
- package/examples/shorts/hillGlideGame.js +0 -63
- package/examples/shorts/input.js +0 -64
- package/examples/shorts/landerGame.js +0 -57
- package/examples/shorts/maze.js +0 -48
- package/examples/shorts/medals.js +0 -51
- package/examples/shorts/music.js +0 -78
- package/examples/shorts/musicPlayer.js +0 -137
- package/examples/shorts/nineSlice.js +0 -40
- package/examples/shorts/parallax.js +0 -72
- package/examples/shorts/particles.js +0 -28
- package/examples/shorts/piano.js +0 -44
- package/examples/shorts/platformer.js +0 -45
- package/examples/shorts/pongGame.js +0 -41
- package/examples/shorts/postProcess.js +0 -62
- package/examples/shorts/sequencer.js +0 -124
- package/examples/shorts/shader.js +0 -29
- package/examples/shorts/shapes.js +0 -21
- package/examples/shorts/slidingPuzzle.js +0 -52
- package/examples/shorts/song.mp3 +0 -0
- package/examples/shorts/sound.js +0 -36
- package/examples/shorts/spaceGame.js +0 -58
- package/examples/shorts/spriteAtlas.js +0 -31
- package/examples/shorts/starfield.js +0 -15
- package/examples/shorts/texture.js +0 -16
- package/examples/shorts/textureWrapped.js +0 -12
- package/examples/shorts/tileLayer.js +0 -48
- package/examples/shorts/tileRaycast.js +0 -39
- package/examples/shorts/tiles.png +0 -0
- package/examples/shorts/tiltedView.js +0 -63
- package/examples/shorts/timers.js +0 -53
- package/examples/shorts/topDown.js +0 -38
- package/examples/shorts/tween.js +0 -24
- package/examples/shorts/uiSystem.js +0 -61
- package/examples/shorts/video.webm +0 -0
- package/examples/shorts/videoPlayer.js +0 -34
- package/examples/shorts.js +0 -743
- package/examples/starter/build.bat +0 -7
- package/examples/starter/build.mjs +0 -126
- package/examples/starter/game.js +0 -137
- package/examples/starter/index.html +0 -35
- package/examples/starter/tiles.png +0 -0
- package/examples/stress/index.html +0 -173
- package/examples/style.css +0 -150
- package/examples/tweenSystem/game.js +0 -171
- package/examples/tweenSystem/index.html +0 -10
- package/examples/tweenSystem/tiles.png +0 -0
- package/examples/typescript/build.mjs +0 -60
- package/examples/typescript/game.js +0 -100
- package/examples/typescript/game.ts +0 -132
- package/examples/typescript/index.html +0 -10
- package/examples/typescript/tiles.png +0 -0
- package/examples/typescript/tsconfig.json +0 -17
- package/examples/uiSystem/game.js +0 -139
- package/examples/uiSystem/index.html +0 -10
- package/examples/uiSystem/tiles.png +0 -0
- package/jsconfig.json +0 -12
- package/plugins/desktop.ini +0 -2
- package/reference.md +0 -448
- package/test/math.test.mjs +0 -774
- package/test/setup.mjs +0 -22
- package/test/smoke.test.mjs +0 -274
- package/test/tween.test.mjs +0 -576
- package/test/util.test.mjs +0 -80
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
LittleJS Platformer Example - Character
|
|
3
|
-
- Platform style character
|
|
4
|
-
- Handles animation and sound effects
|
|
5
|
-
- Uses special platforming physics system
|
|
6
|
-
- Characters can jump, shoot, roll, and throw grenades
|
|
7
|
-
- Characters can climb ladders and break blocks
|
|
8
|
-
- Characters also have a damage and can die
|
|
9
|
-
- Has a weapon which can be fired
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
'use strict';
|
|
13
|
-
|
|
14
|
-
// import LittleJS module
|
|
15
|
-
import * as LJS from '../../dist/littlejs.esm.js';
|
|
16
|
-
import * as GameObjects from './gameObjects.js';
|
|
17
|
-
import * as GameEffects from './gameEffects.js';
|
|
18
|
-
import * as GameLevel from './gameLevel.js';
|
|
19
|
-
import * as Game from './game.js';
|
|
20
|
-
const {vec2, hsl, Timer} = LJS;
|
|
21
|
-
|
|
22
|
-
export class Character extends GameObjects.GameObject
|
|
23
|
-
{
|
|
24
|
-
constructor(pos)
|
|
25
|
-
{
|
|
26
|
-
super(pos, vec2(.6,.95));
|
|
27
|
-
|
|
28
|
-
this.lastPos = pos;
|
|
29
|
-
this.groundTimer = new Timer;
|
|
30
|
-
this.jumpTimer = new Timer;
|
|
31
|
-
this.pressedJumpTimer = new Timer;
|
|
32
|
-
this.dodgeTimer = new Timer;
|
|
33
|
-
this.dodgeRechargeTimer = new Timer;
|
|
34
|
-
this.deadTimer = new Timer;
|
|
35
|
-
this.grenadeThrowTimer = new Timer;
|
|
36
|
-
this.drawSize = vec2(1);
|
|
37
|
-
this.moveInput = vec2();
|
|
38
|
-
this.color = hsl(LJS.rand(),1,.7);
|
|
39
|
-
this.renderOrder = 10;
|
|
40
|
-
this.walkCyclePercent = 0;
|
|
41
|
-
this.health = 1;
|
|
42
|
-
this.climbingLadder = false;
|
|
43
|
-
this.setCollision(true,false);
|
|
44
|
-
|
|
45
|
-
// attach weapon
|
|
46
|
-
this.weapon = new GameObjects.Weapon(pos);
|
|
47
|
-
this.weapon.renderOrder = this.renderOrder + 1;
|
|
48
|
-
this.addChild(this.weapon, vec2(this.size.x,0));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
update()
|
|
52
|
-
{
|
|
53
|
-
this.gravityScale = 1; // reset to default gravity
|
|
54
|
-
|
|
55
|
-
if (this.isDead())
|
|
56
|
-
return super.update();
|
|
57
|
-
|
|
58
|
-
// get move input
|
|
59
|
-
const moveInput = this.moveInput.copy();
|
|
60
|
-
|
|
61
|
-
// jump
|
|
62
|
-
if (!this.holdingJump)
|
|
63
|
-
this.pressedJumpTimer.unset();
|
|
64
|
-
else if (!this.wasHoldingJump || this.climbingWall)
|
|
65
|
-
this.pressedJumpTimer.set(.3);
|
|
66
|
-
this.wasHoldingJump = this.holdingJump;
|
|
67
|
-
|
|
68
|
-
// wall climb
|
|
69
|
-
this.climbingWall = 0;
|
|
70
|
-
if (moveInput.x && !this.velocity.x && this.velocity.y < 0)
|
|
71
|
-
{
|
|
72
|
-
this.velocity.y *=.8;
|
|
73
|
-
this.climbingWall = 1;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (this.dodgeTimer.active())
|
|
77
|
-
{
|
|
78
|
-
// update roll
|
|
79
|
-
this.angle = this.getMirrorSign()*2*LJS.PI*this.dodgeTimer.getPercent();
|
|
80
|
-
if (this.groundObject)
|
|
81
|
-
this.velocity.x += this.getMirrorSign()*.1;
|
|
82
|
-
}
|
|
83
|
-
else
|
|
84
|
-
{
|
|
85
|
-
// not rolling
|
|
86
|
-
this.angle = 0;
|
|
87
|
-
if (this.pressedDodge && !this.dodgeRechargeTimer.active())
|
|
88
|
-
{
|
|
89
|
-
// start dodge
|
|
90
|
-
this.dodgeTimer.set(.4);
|
|
91
|
-
this.dodgeRechargeTimer.set(2);
|
|
92
|
-
this.jumpTimer.unset();
|
|
93
|
-
GameEffects.sound_dodge.play(this.pos);
|
|
94
|
-
|
|
95
|
-
if (!this.groundObject && this.getAliveTime() > .2)
|
|
96
|
-
this.velocity.y += .2;
|
|
97
|
-
}
|
|
98
|
-
if (this.pressingThrow && !this.wasPressingThrow && !this.grenadeThrowTimer.active())
|
|
99
|
-
{
|
|
100
|
-
// throw grenade
|
|
101
|
-
const grenade = new GameObjects.Grenade(this.pos);
|
|
102
|
-
const speed = vec2(this.getMirrorSign(),LJS.rand(.8,.7)).normalize(.2+LJS.rand(.02));
|
|
103
|
-
grenade.velocity = this.velocity.add(speed);
|
|
104
|
-
grenade.angleVelocity = this.getMirrorSign() * LJS.rand(.8,.5);
|
|
105
|
-
GameEffects.sound_jump.play(this.pos);
|
|
106
|
-
this.grenadeThrowTimer.set(1);
|
|
107
|
-
}
|
|
108
|
-
this.wasPressingThrow = this.pressingThrow;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// allow grabbing ladder at head or feet
|
|
112
|
-
let touchingLadder = 0;
|
|
113
|
-
for (let y=2;y--;)
|
|
114
|
-
{
|
|
115
|
-
const testPos = this.pos.add(vec2(0, y + .1*moveInput.y - this.size.y/2));
|
|
116
|
-
const collisionData = LJS.tileCollisionGetData(testPos);
|
|
117
|
-
touchingLadder ||= collisionData == GameLevel.tileType_ladder;
|
|
118
|
-
}
|
|
119
|
-
if (!touchingLadder)
|
|
120
|
-
this.climbingLadder = false;
|
|
121
|
-
else if (moveInput.y)
|
|
122
|
-
this.climbingLadder = true;
|
|
123
|
-
|
|
124
|
-
if (this.weapon) // update weapon trigger
|
|
125
|
-
this.weapon.triggerIsDown = this.holdingShoot && !this.dodgeTimer.active();
|
|
126
|
-
|
|
127
|
-
if (this.climbingLadder)
|
|
128
|
-
{
|
|
129
|
-
// update ladder
|
|
130
|
-
this.gravityScale = this.climbingWall = this.groundObject = 0;
|
|
131
|
-
this.jumpTimer.unset();
|
|
132
|
-
this.groundTimer.unset();
|
|
133
|
-
this.velocity = this.velocity.multiply(vec2(.85)).add(vec2(0,.02*moveInput.y));
|
|
134
|
-
|
|
135
|
-
// pull towards ladder
|
|
136
|
-
const delta = (this.pos.x|0)+.5 - this.pos.x;
|
|
137
|
-
this.velocity.x += .02*delta*LJS.abs(moveInput.x ? 0:moveInput.y);
|
|
138
|
-
moveInput.x *= .2;
|
|
139
|
-
|
|
140
|
-
// exit ladder if ground is below
|
|
141
|
-
this.climbingLadder = moveInput.y >= 0 || LJS.tileCollisionGetData(this.pos.subtract(vec2(0,1))) <= 0;
|
|
142
|
-
}
|
|
143
|
-
else
|
|
144
|
-
{
|
|
145
|
-
// update jumping and ground check
|
|
146
|
-
if (this.groundObject || this.climbingWall)
|
|
147
|
-
{
|
|
148
|
-
if (!this.groundTimer.isSet())
|
|
149
|
-
GameEffects.sound_walk.play(this.pos); // land sound
|
|
150
|
-
this.groundTimer.set(.1);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (this.groundTimer.active() && !this.dodgeTimer.active())
|
|
154
|
-
{
|
|
155
|
-
// is on ground
|
|
156
|
-
if (this.pressedJumpTimer.active() && !this.jumpTimer.active())
|
|
157
|
-
{
|
|
158
|
-
// start jump
|
|
159
|
-
if (this.climbingWall)
|
|
160
|
-
this.velocity.y = .25;
|
|
161
|
-
else
|
|
162
|
-
{
|
|
163
|
-
this.velocity.y = .15;
|
|
164
|
-
this.jumpTimer.set(.2);
|
|
165
|
-
}
|
|
166
|
-
GameEffects.sound_jump.play(this.pos);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (this.jumpTimer.active() && !this.climbingWall)
|
|
171
|
-
{
|
|
172
|
-
// update variable height jump
|
|
173
|
-
this.groundTimer.unset();
|
|
174
|
-
if (this.holdingJump && this.velocity.y > 0 && this.jumpTimer.active())
|
|
175
|
-
this.velocity.y += .017;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (!this.groundObject)
|
|
179
|
-
{
|
|
180
|
-
// air control
|
|
181
|
-
if (LJS.sign(moveInput.x) == LJS.sign(this.velocity.x))
|
|
182
|
-
moveInput.x *= .1; // moving with velocity
|
|
183
|
-
else
|
|
184
|
-
moveInput.x *= .2; // moving against velocity (stopping)
|
|
185
|
-
|
|
186
|
-
// slight extra gravity when moving down
|
|
187
|
-
if (this.velocity.y < 0)
|
|
188
|
-
this.velocity.y += LJS.gravity.y*.2;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// apply movement acceleration and clamp
|
|
193
|
-
const maxCharacterSpeed = .2;
|
|
194
|
-
this.velocity.x = LJS.clamp(this.velocity.x + moveInput.x * .04, -maxCharacterSpeed, maxCharacterSpeed);
|
|
195
|
-
|
|
196
|
-
// track last pos for ladder collision code
|
|
197
|
-
this.lastPos = this.pos.copy();
|
|
198
|
-
|
|
199
|
-
// call parent
|
|
200
|
-
super.update();
|
|
201
|
-
|
|
202
|
-
// update walk cycle
|
|
203
|
-
const speed = this.getSpeed();
|
|
204
|
-
if (this.climbingLadder || this.groundTimer.active() && !this.dodgeTimer.active())
|
|
205
|
-
{
|
|
206
|
-
this.walkCyclePercent += speed * .5;
|
|
207
|
-
this.walkCyclePercent = speed > .01 ? LJS.mod(this.walkCyclePercent) : 0;
|
|
208
|
-
}
|
|
209
|
-
else
|
|
210
|
-
this.walkCyclePercent = 0;
|
|
211
|
-
|
|
212
|
-
// update walk sound
|
|
213
|
-
this.walkSoundTime += speed;
|
|
214
|
-
if (speed > .001 && ((this.climbingLadder || this.groundTimer.active()) && !this.dodgeTimer.active()))
|
|
215
|
-
{
|
|
216
|
-
if (this.walkSoundTime > 1)
|
|
217
|
-
{
|
|
218
|
-
this.walkSoundTime = this.walkSoundTime%1;
|
|
219
|
-
GameEffects.sound_walk.play(this.pos);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
else
|
|
223
|
-
this.walkSoundTime = 0;
|
|
224
|
-
|
|
225
|
-
// update mirror
|
|
226
|
-
if (moveInput.x && !this.dodgeTimer.active())
|
|
227
|
-
this.mirror = moveInput.x < 0;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
render()
|
|
231
|
-
{
|
|
232
|
-
// update animation
|
|
233
|
-
const animationFrame = this.isDead() ? 0 :
|
|
234
|
-
this.climbingLadder || this.groundTimer.active() ?
|
|
235
|
-
2*this.walkCyclePercent|0 : 1;
|
|
236
|
-
this.tileInfo = Game.spriteAtlas.player.frame(animationFrame);
|
|
237
|
-
|
|
238
|
-
let bodyPos = this.pos;
|
|
239
|
-
if (!this.isDead())
|
|
240
|
-
{
|
|
241
|
-
// bounce pos with walk cycle
|
|
242
|
-
bodyPos = bodyPos.add(vec2(0,.05*LJS.sin(this.walkCyclePercent*LJS.PI)));
|
|
243
|
-
|
|
244
|
-
// make bottom flush
|
|
245
|
-
bodyPos = bodyPos.add(vec2(0,(this.drawSize.y-this.size.y)/2));
|
|
246
|
-
}
|
|
247
|
-
LJS.drawTile(bodyPos, this.drawSize, this.tileInfo, this.color, this.angle, this.mirror);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
damage(damage, damagingObject)
|
|
251
|
-
{
|
|
252
|
-
if (this.isDead() || this.getAliveTime() < 1 || this.dodgeTimer.active())
|
|
253
|
-
return 0;
|
|
254
|
-
|
|
255
|
-
GameEffects.makeBlood(damagingObject ? damagingObject.pos : this.pos);
|
|
256
|
-
return super.damage(damage, damagingObject);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
kill(damagingObject)
|
|
260
|
-
{
|
|
261
|
-
if (this.isDead())
|
|
262
|
-
return;
|
|
263
|
-
|
|
264
|
-
GameEffects.makeBlood(this.pos, 100);
|
|
265
|
-
GameEffects.sound_die.play(this.pos);
|
|
266
|
-
|
|
267
|
-
this.health = 0;
|
|
268
|
-
this.deadTimer.set();
|
|
269
|
-
this.size = this.size.scale(.5);
|
|
270
|
-
const fallDirection = damagingObject ? LJS.sign(damagingObject.velocity.x) : LJS.randSign();
|
|
271
|
-
this.angleVelocity = fallDirection*LJS.rand(.22,.14);
|
|
272
|
-
this.angleDamping = .9;
|
|
273
|
-
this.renderOrder = -1; // move to back layer
|
|
274
|
-
if (this.weapon)
|
|
275
|
-
this.weapon.destroy();
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
collideWithTile(data, pos)
|
|
279
|
-
{
|
|
280
|
-
if (!data)
|
|
281
|
-
return false;
|
|
282
|
-
|
|
283
|
-
if (data == GameLevel.tileType_ladder)
|
|
284
|
-
{
|
|
285
|
-
// handle ladder collisions
|
|
286
|
-
if (pos.y + 1 > this.lastPos.y - this.size.y/2)
|
|
287
|
-
return false;
|
|
288
|
-
|
|
289
|
-
if (LJS.tileCollisionGetData(pos.add(vec2(0,1))) // above
|
|
290
|
-
&& !LJS.tileCollisionGetData(pos.add(vec2(1,0))) // left
|
|
291
|
-
&& !LJS.tileCollisionGetData(pos.add(vec2(1,0)))) // right
|
|
292
|
-
return false; // don't collide if something above it and nothing to left or right
|
|
293
|
-
|
|
294
|
-
// allow standing on top of ladders
|
|
295
|
-
return !this.climbingLadder;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
const d = pos.y - this.pos.y;
|
|
299
|
-
if (!this.climbingLadder && this.velocity.y > .1 && d > 0 && d < this.size.y/2)
|
|
300
|
-
if (GameEffects.destroyTile(pos))
|
|
301
|
-
{
|
|
302
|
-
// break blocks above
|
|
303
|
-
this.velocity.y = 0;
|
|
304
|
-
return false;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
return true;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
LittleJS Platformer Example - Effects
|
|
3
|
-
- Plays different particle effects which can be persistent
|
|
4
|
-
- Destroys terrain and makes explosions
|
|
5
|
-
- Outlines tiles based on neighbor types
|
|
6
|
-
- Generates parallax background layers
|
|
7
|
-
- Draws moving starfield with plants and suns
|
|
8
|
-
- Tracks zzfx sound effects
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
'use strict';
|
|
12
|
-
|
|
13
|
-
// import LittleJS module
|
|
14
|
-
import * as LJS from '../../dist/littlejs.esm.js';
|
|
15
|
-
import * as GameLevel from './gameLevel.js';
|
|
16
|
-
const {vec2, hsl, rgb} = LJS;
|
|
17
|
-
|
|
18
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
19
|
-
// sound effects
|
|
20
|
-
|
|
21
|
-
export const sound_shoot = new LJS.Sound([,,90,,.01,.03,4,,,,,,,9,50,.2,,.2,.01]);
|
|
22
|
-
export const sound_destroyObject =new LJS.Sound([.5,,1e3,.02,,.2,1,3,.1,,,,,1,-30,.5,,.5]);
|
|
23
|
-
export const sound_die = new LJS.Sound([.5,.4,126,.05,,.2,1,2.09,,-4,,,1,1,1,.4,.03]);
|
|
24
|
-
export const sound_jump = new LJS.Sound([.4,.2,250,.04,,.04,,,1,,,,,3]);
|
|
25
|
-
export const sound_dodge = new LJS.Sound([.4,.2,150,.05,,.05,,,-1,,,,,4,,,,,.02]);
|
|
26
|
-
export const sound_walk = new LJS.Sound([.3,.1,50,.005,,.01,4,,,,,,,,10,,,.5]);
|
|
27
|
-
export const sound_explosion = new LJS.Sound([2,.2,72,.01,.01,.2,4,,,,,,,1,,.5,.1,.5,.02]);
|
|
28
|
-
export const sound_grenade = new LJS.Sound([.5,.01,300,,,.02,3,.22,,,-9,.2,,,,,,.5]);
|
|
29
|
-
export const sound_score = new LJS.Sound([,,783,,.03,.02,1,2,,,940,.03,,,,,.2,.6,,.06]);
|
|
30
|
-
|
|
31
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
32
|
-
// special effects
|
|
33
|
-
|
|
34
|
-
export const persistentParticleDestroyCallback = (particle)=>
|
|
35
|
-
{
|
|
36
|
-
// draw particle to tile layer on death
|
|
37
|
-
LJS.ASSERT(!particle.tileInfo, 'quick draw to tile layer uses canvas 2d so must be untextured');
|
|
38
|
-
if (particle.groundObject)
|
|
39
|
-
{
|
|
40
|
-
GameLevel.foregroundTileLayer.drawTile(particle.pos, particle.size, particle.tileInfo, particle.color, particle.angle, particle.mirror);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function makeBlood(pos, amount) { makeDebris(pos, hsl(0,1,.5), amount, .1, 0); }
|
|
45
|
-
export function makeDebris(pos, color = hsl(), amount = 50, size=.2, restitution = .3)
|
|
46
|
-
{
|
|
47
|
-
const color2 = color.lerp(hsl(), .5);
|
|
48
|
-
const emitter = new LJS.ParticleEmitter(
|
|
49
|
-
pos, 0, .5, .1, amount/.1, 3.14, // pos, angle, size, time, rate, cone
|
|
50
|
-
0, // tileInfo
|
|
51
|
-
color, color2, // colorStartA, colorStartB
|
|
52
|
-
color, color2, // colorEndA, colorEndB
|
|
53
|
-
3, size,size, .1, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
|
|
54
|
-
1, .95, .4, 3.14, 0, // damp, angleDamp, gravity, particleCone, fade
|
|
55
|
-
.5, 1 // randomness, collide
|
|
56
|
-
);
|
|
57
|
-
emitter.restitution = restitution;
|
|
58
|
-
emitter.particleDestroyCallback = persistentParticleDestroyCallback;
|
|
59
|
-
return emitter;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
63
|
-
|
|
64
|
-
export function explosion(pos, radius=3)
|
|
65
|
-
{
|
|
66
|
-
LJS.ASSERT(radius > 0);
|
|
67
|
-
|
|
68
|
-
sound_explosion.play(pos);
|
|
69
|
-
|
|
70
|
-
{
|
|
71
|
-
// destroy level
|
|
72
|
-
const layer = GameLevel.tileLayers[1];
|
|
73
|
-
layer.redrawStart();
|
|
74
|
-
for (let x = -radius; x < radius; ++x)
|
|
75
|
-
{
|
|
76
|
-
const h = (radius*radius - x*x)**.5;
|
|
77
|
-
for (let y = -h; y <= h; ++y)
|
|
78
|
-
destroyTile(pos.add(vec2(x,y)), 0, 0);
|
|
79
|
-
}
|
|
80
|
-
// cleanup neighbors
|
|
81
|
-
const cleanupRadius = radius + 2;
|
|
82
|
-
for (let x = -cleanupRadius; x < cleanupRadius; ++x)
|
|
83
|
-
{
|
|
84
|
-
const h = (cleanupRadius**2 - x**2)**.5;
|
|
85
|
-
for (let y = -h; y < h; ++y)
|
|
86
|
-
GameLevel.decorateTile(pos.add(vec2(x,y)).floor(), layer);
|
|
87
|
-
}
|
|
88
|
-
layer.redrawEnd();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// kill/push objects
|
|
92
|
-
LJS.engineObjectsCallback(pos, radius*3, (o)=>
|
|
93
|
-
{
|
|
94
|
-
const damage = radius*2;
|
|
95
|
-
const d = o.pos.distance(pos);
|
|
96
|
-
if (o.isGameObject)
|
|
97
|
-
{
|
|
98
|
-
// do damage
|
|
99
|
-
d < radius && o.damage(damage);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// push
|
|
103
|
-
const p = LJS.percent(d, 2*radius, radius);
|
|
104
|
-
const force = o.pos.subtract(pos).normalize(p*radius*.2);
|
|
105
|
-
o.applyForce(force);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// smoke
|
|
109
|
-
new LJS.ParticleEmitter(
|
|
110
|
-
pos, 0, // pos, angle
|
|
111
|
-
radius/2, .2, 50*radius, 3.14,// emitSize, emitTime, rate, cone
|
|
112
|
-
0, // tileInfo
|
|
113
|
-
hsl(0,0,0), hsl(0,0,0), // colorStartA, colorStartB
|
|
114
|
-
hsl(0,0,0,0), hsl(0,0,0,0), // colorEndA, colorEndB
|
|
115
|
-
1, .5, 2, .2, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
|
|
116
|
-
.9, 1, -.3, 3.14, .1, // damp, angleDamp, gravity, particleCone, fade
|
|
117
|
-
.5, 0, 0, 0, 1e8 // randomness, collide, additive, colorLinear, renderOrder
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
// fire
|
|
121
|
-
new LJS.ParticleEmitter(
|
|
122
|
-
pos, 0, // pos, angle
|
|
123
|
-
radius/2, .1, 100*radius, 3.14, // emitSize, emitTime, rate, cone
|
|
124
|
-
0, // tileInfo
|
|
125
|
-
rgb(1,.5,.1), rgb(1,.1,.1), // colorStartA, colorStartB
|
|
126
|
-
rgb(1,.5,.1,0), rgb(1,.1,.1,0), // colorEndA, colorEndB
|
|
127
|
-
.7, .8, .2, .2, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
|
|
128
|
-
.9, 1, -.2, 3.14, .05, // damp, angleDamp, gravity, particleCone, fade
|
|
129
|
-
.5, 0, 1, 0, 1e9 // randomness, collide, additive, colorLinear, renderOrder
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
134
|
-
|
|
135
|
-
export function destroyTile(pos, makeSound = 1, cleanup = 1)
|
|
136
|
-
{
|
|
137
|
-
// pos must be an int
|
|
138
|
-
pos = pos.floor();
|
|
139
|
-
|
|
140
|
-
// destroy tile
|
|
141
|
-
const layer = GameLevel.foregroundTileLayer;
|
|
142
|
-
const tileType = layer.getCollisionData(pos);
|
|
143
|
-
if (!tileType)
|
|
144
|
-
return true;
|
|
145
|
-
|
|
146
|
-
const centerPos = pos.add(vec2(.5));
|
|
147
|
-
const layerData = layer.getData(pos);
|
|
148
|
-
if (!layerData || tileType == GameLevel.tileType_solid)
|
|
149
|
-
return false;
|
|
150
|
-
|
|
151
|
-
// create effects
|
|
152
|
-
makeDebris(centerPos, layerData.color.mutate());
|
|
153
|
-
makeSound && sound_destroyObject.play(centerPos);
|
|
154
|
-
|
|
155
|
-
// set and clear tile
|
|
156
|
-
layer.clearData(pos, true);
|
|
157
|
-
layer.setCollisionData(pos, GameLevel.tileType_empty);
|
|
158
|
-
|
|
159
|
-
// cleanup neighbors and rebuild WebGL
|
|
160
|
-
if (cleanup)
|
|
161
|
-
{
|
|
162
|
-
const layer = GameLevel.tileLayers[1];
|
|
163
|
-
layer.redrawStart();
|
|
164
|
-
for (let i=-1;i<=1;++i)
|
|
165
|
-
for (let j=-1;j<=1;++j)
|
|
166
|
-
GameLevel.decorateTile(pos.add(vec2(i,j)), layer);
|
|
167
|
-
layer.redrawEnd();
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return true;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
174
|
-
// sky with background gradient, stars, and planets
|
|
175
|
-
|
|
176
|
-
export class Sky extends LJS.EngineObject
|
|
177
|
-
{
|
|
178
|
-
constructor()
|
|
179
|
-
{
|
|
180
|
-
super();
|
|
181
|
-
|
|
182
|
-
this.renderOrder = -1e4;
|
|
183
|
-
this.seed = LJS.randInt(1e9);
|
|
184
|
-
this.skyColor = LJS.randColor(hsl(0,0,.5), hsl(0,0,.9));
|
|
185
|
-
this.horizonColor = this.skyColor.subtract(hsl(0,0,.05,0)).mutate(.3);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
render()
|
|
189
|
-
{
|
|
190
|
-
// fill background with a gradient
|
|
191
|
-
const canvas = LJS.mainCanvas;
|
|
192
|
-
LJS.drawRectGradient(LJS.cameraPos, LJS.getCameraSize(), this.skyColor, this.horizonColor);
|
|
193
|
-
|
|
194
|
-
// draw stars
|
|
195
|
-
LJS.setBlendMode(true);
|
|
196
|
-
const random = new LJS.RandomGenerator(this.seed);
|
|
197
|
-
for (let i = 1e3; i--;)
|
|
198
|
-
{
|
|
199
|
-
const size = random.float(.5,2)**2;
|
|
200
|
-
const speed = random.float() < .9 ? random.float(5) : random.float(9,99);
|
|
201
|
-
const color = hsl(random.float(-.3,.2), random.float(), random.float());
|
|
202
|
-
const extraSpace = 50;
|
|
203
|
-
const w = canvas.width+2*extraSpace, h = canvas.height+2*extraSpace;
|
|
204
|
-
const screenPos = vec2(
|
|
205
|
-
(random.float(w)+LJS.time*speed)%w-extraSpace,
|
|
206
|
-
(random.float(h)+LJS.time*speed*random.float())%h-extraSpace);
|
|
207
|
-
LJS.drawRect(screenPos, vec2(size), color, 0, undefined, true)
|
|
208
|
-
}
|
|
209
|
-
LJS.setBlendMode(false);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
214
|
-
// parallax background mountain ranges
|
|
215
|
-
|
|
216
|
-
export class ParallaxLayer extends LJS.CanvasLayer
|
|
217
|
-
{
|
|
218
|
-
constructor(pos, topColor, bottomColor, depth)
|
|
219
|
-
{
|
|
220
|
-
const renderOrder = depth - 3e3;
|
|
221
|
-
const canvasSize = vec2(512, 256);
|
|
222
|
-
super(pos, vec2(), 0, renderOrder, canvasSize);
|
|
223
|
-
this.centerPos = pos;
|
|
224
|
-
this.depth = depth;
|
|
225
|
-
|
|
226
|
-
// create a gradient for the mountains
|
|
227
|
-
const w = canvasSize.x, h = canvasSize.y;
|
|
228
|
-
for (let i = h; i--;)
|
|
229
|
-
{
|
|
230
|
-
// draw a 1 pixel gradient line on the left side of the canvas
|
|
231
|
-
const p = i/h;
|
|
232
|
-
this.context.fillStyle = topColor.lerp(bottomColor, p);
|
|
233
|
-
this.context.fillRect(0, i, 1, 1);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// draw random mountains
|
|
237
|
-
const pointiness = .2; // how pointy the mountains are
|
|
238
|
-
const levelness = .005; // how much the mountains level out
|
|
239
|
-
const slopeRange = 1; // max slope of the mountains
|
|
240
|
-
const startGroundLevel = h/2;
|
|
241
|
-
let y = startGroundLevel, groundSlope = LJS.rand(-slopeRange, slopeRange);
|
|
242
|
-
for (let x=w; x--;)
|
|
243
|
-
{
|
|
244
|
-
// pull slope towards start ground level
|
|
245
|
-
y += groundSlope -= (y-startGroundLevel)*levelness;
|
|
246
|
-
|
|
247
|
-
// randomly change slope
|
|
248
|
-
if (LJS.rand() < pointiness)
|
|
249
|
-
groundSlope = LJS.rand(-slopeRange, slopeRange);
|
|
250
|
-
|
|
251
|
-
// draw 1 pixel wide vertical slice of mountain
|
|
252
|
-
this.context.drawImage(this.canvas, 0, 0, 1, h, x, y, 1, h - y);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// remove gradient sliver from left side
|
|
256
|
-
this.context.clearRect(0,0,1,h);
|
|
257
|
-
|
|
258
|
-
// make WebGL texture
|
|
259
|
-
this.updateWebGL();
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
render()
|
|
263
|
-
{
|
|
264
|
-
const canvasSize = vec2(this.canvas.width, this.canvas.height);
|
|
265
|
-
const depth = this.depth
|
|
266
|
-
const distance = 4 + depth;
|
|
267
|
-
const parallax = vec2(150, 30).scale(depth**2+1);
|
|
268
|
-
const levelCenter = this.centerPos;
|
|
269
|
-
const cameraDeltaFromCenter = LJS.cameraPos.subtract(levelCenter)
|
|
270
|
-
.divide(levelCenter.scale(-1).divide(parallax));
|
|
271
|
-
const scale = distance/LJS.cameraScale;
|
|
272
|
-
const positionOffset = vec2(0, 2-depth);
|
|
273
|
-
const cameraOffset = cameraDeltaFromCenter.scale(1/LJS.cameraScale);
|
|
274
|
-
this.pos = LJS.cameraPos.add(positionOffset).add(cameraOffset);
|
|
275
|
-
this.size = canvasSize.scale(scale);
|
|
276
|
-
super.render();
|
|
277
|
-
}
|
|
278
|
-
}
|