littlejsengine 1.9.2 → 1.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/littlejs.d.ts +23 -23
- package/dist/littlejs.esm.js +97 -87
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +97 -87
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +96 -86
- package/examples/logo.png +0 -0
- package/examples/platformer/data/{gameTileData.tmx → gameLevelData.tmx} +3 -3
- package/examples/platformer/game.js +31 -10
- package/examples/platformer/gameCharacter.js +8 -6
- package/examples/platformer/gameEffects.js +77 -68
- package/examples/platformer/gameLevel.js +33 -16
- package/examples/platformer/{gameTileData.js → gameLevelData.js} +3 -3
- package/examples/platformer/gameObjects.js +14 -14
- package/examples/platformer/index.html +1 -1
- package/examples/platformer/tiles.png +0 -0
- package/examples/screenshot.jpg +0 -0
- package/examples/stress/index.html +1 -1
- package/package.json +1 -1
- package/reference.md +409 -0
- package/src/engine.js +46 -41
- package/src/engineAudio.js +18 -9
- package/src/engineDebug.js +1 -1
- package/src/engineDraw.js +8 -7
- package/src/engineInput.js +1 -1
- package/src/engineMedals.js +1 -1
- package/src/engineObject.js +2 -2
- package/src/engineParticles.js +11 -10
- package/src/engineSettings.js +3 -3
- package/src/engineTileLayer.js +2 -2
- package/src/engineUtilities.js +3 -3
- package/src/engineWebGL.js +1 -7
- /package/examples/platformer/data/{gameTileData.tsx → gameLevelData.tsx} +0 -0
package/reference.md
ADDED
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
# LittleJS Engine Quick Reference Sheet
|
|
2
|
+
|
|
3
|
+
## This cheat sheet contains all LittleJS essentials.
|
|
4
|
+
- [LittleJS on GitHub](https://github.com/KilledByAPixel/LittleJS) - Official LittleJS website with more info
|
|
5
|
+
- [LittleJS Documentation](https://killedbyapixel.github.io/LittleJS/docs) - LittleJS documentation browser
|
|
6
|
+
- [Particle Deigner](https://killedbyapixel.github.io/LittleJS/examples/particles) - Editor for LittleJS Particle Systems
|
|
7
|
+
- [Sound Effect Designer](https://killedbyapixel.github.io/ZzFX) - Tool for creating ZzFX sound effects
|
|
8
|
+
- [Starter Project](https://killedbyapixel.github.io/LittleJS/examples/starter) - Simple LittleJS demo to start with
|
|
9
|
+
|
|
10
|
+
## LittleJS Setup
|
|
11
|
+
|
|
12
|
+
To start LittleJS, you need to create a few functions and pass them to engineInit.
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
// Start up LittleJS engine with your callback functions
|
|
16
|
+
engineInit(init, update, updatePost, render, renderPost, imageSources=['tiles.png'])
|
|
17
|
+
|
|
18
|
+
// Destroy and remove all objects
|
|
19
|
+
engineObjectsDestroy()
|
|
20
|
+
|
|
21
|
+
// Trigger a callback for each object within a given area
|
|
22
|
+
engineObjectsCallback(pos, size, callbackFunction, objects=engineObjects)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## LittleJS Utilities Classes and Functions
|
|
26
|
+
- General purpose math library
|
|
27
|
+
- Vector2 - Fast, simple, easy 2D vector class
|
|
28
|
+
- Color - Holds a rgba color with some math functions
|
|
29
|
+
- Timer - Tracks time automatically
|
|
30
|
+
- RandomGenerator - Seeded random number generator
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
|
|
34
|
+
// Object Constructors
|
|
35
|
+
vec2(x=0, y=x) // Create a 2D vector with Vector or floats
|
|
36
|
+
rgb(r=1, g=1, b=1, a=1) // Create a color object with RGBA values
|
|
37
|
+
hsl(h=0, s=0, l=1, a=1) // Create a color object with HSLA values
|
|
38
|
+
tile(pos=(0,0), size, textureIndex=0) // Create a tile info object
|
|
39
|
+
|
|
40
|
+
// Helper functions
|
|
41
|
+
abs(value) // Get absoulte value
|
|
42
|
+
min(valueA, valueB) // Get lowest of values
|
|
43
|
+
max(valueA, valueB) // Get highest of values
|
|
44
|
+
sign(value) // Get the sign of value
|
|
45
|
+
mod(dividend, divisor=1) // Get remainder of division
|
|
46
|
+
clamp(value, min=0, max=1) // Clamps between values
|
|
47
|
+
percent(value, valueA, valueB) // Get percentage between values
|
|
48
|
+
lerp(percent, valueA, valueB) // Linearly interpolates between values
|
|
49
|
+
distanceWrap(valueA, valueB, wrapSize=1) // Signed wrapped distance between values
|
|
50
|
+
lerpWrap(percent, valueA, valueB, wrapSize=1) // Linearly interpolates with wrapping
|
|
51
|
+
distanceAngle(angleA, angleB) // Signed wrapped distance between angles
|
|
52
|
+
lerpAngle(percent, angleA, angleB) // Linearly interpolates with wrapping
|
|
53
|
+
smoothStep(percent) // Applies smoothstep function
|
|
54
|
+
nearestPowerOfTwo(value) // Returns the nearest power of two
|
|
55
|
+
isOverlapping(pointA, sizeA, pointB, sizeB) // Checks if bounding boxes overlap
|
|
56
|
+
wave(frequency=1, amplitude=1, t=time) // Returns oscillating wave
|
|
57
|
+
formatTime(t) // Formats seconds for display
|
|
58
|
+
|
|
59
|
+
// Random functions
|
|
60
|
+
rand(valueA=1, valueB=0) // Random float between values
|
|
61
|
+
randInt(valueA, valueB=0) // Random integer between values
|
|
62
|
+
randSign() // Randomly bool either -1 or 1
|
|
63
|
+
randVector(length=1) // Random Vector2 with the passed in length
|
|
64
|
+
randInCircle(radius=1, minRadius=0) // Random Vector2 within a circle
|
|
65
|
+
randColor(colorA, colorB, linear) // Random color between values
|
|
66
|
+
|
|
67
|
+
// 2D vector math
|
|
68
|
+
Vector2(x=0, y=0) // Create a 2D vector
|
|
69
|
+
Vector2.copy() // Copy this vector
|
|
70
|
+
Vector2.add(v) // Add a vector
|
|
71
|
+
Vector2.subtract(v) // Subtract a vector
|
|
72
|
+
Vector2.multiply(v) // Multiply by a vector
|
|
73
|
+
Vector2.divide(v) // Divide by a vector
|
|
74
|
+
Vector2.scale(s) // Scale by a float
|
|
75
|
+
Vector2.length() // Get length
|
|
76
|
+
Vector2.lengthSquared() // Get length squared
|
|
77
|
+
Vector2.distance(v) // Get distance to vector
|
|
78
|
+
Vector2.distanceSquared(v) // Get distance to vector squared
|
|
79
|
+
Vector2.normalize(length=1) // Normalize this vector to length
|
|
80
|
+
Vector2.clampLength(length=1) // Clamp this vector to length
|
|
81
|
+
Vector2.dot(v) // Dot product with vector
|
|
82
|
+
Vector2.cross(v) // Cross product with vector
|
|
83
|
+
Vector2.invert() // Invert this vector
|
|
84
|
+
Vector2.floor() // Floor this vector
|
|
85
|
+
Vector2.area() // Get area covered by this vector as a rectangle
|
|
86
|
+
Vector2.lerp(v, percent) // Interpolate between vectors
|
|
87
|
+
Vector2.arrayCheck(arraySize) // Check if in bounds of array size
|
|
88
|
+
Vector2.angle() // Angle of this vector, up is 0
|
|
89
|
+
Vector2.setAngle(angle=0, length=1) // Set angle and length
|
|
90
|
+
Vector2.rotate(angle) // Rotate by angle
|
|
91
|
+
Vector2.setDirection(direction, length=1) // Set integer direction (0-3) and length
|
|
92
|
+
Vector2.direction() // Get integer direction (0-3)
|
|
93
|
+
Vector2.toString(digits=3) // Get string representation
|
|
94
|
+
|
|
95
|
+
// RGBA color object
|
|
96
|
+
Color(r=1, g=1, b=1, a=1) // Create an RGBA color
|
|
97
|
+
Color.copy() // Copy this color
|
|
98
|
+
Color.add(c) // Add a color
|
|
99
|
+
Color.subtract(c) // Subtract a color
|
|
100
|
+
Color.multiply(c) // Multiply by a color
|
|
101
|
+
Color.divide(c) // Divide by a color
|
|
102
|
+
Color.scale(scale, alphaScale=scale) // Scale by a float
|
|
103
|
+
Color.clamp() // Clamp this color
|
|
104
|
+
Color.lerp(c, percent) // Interpolate between colors
|
|
105
|
+
Color.setHSLA(h=0, s=0, l=1, a=1) // Set the color from HSLA values
|
|
106
|
+
Color.getHSLA() // Get the color in HSLA format
|
|
107
|
+
Color.mutate(amount=.05, alphaAmount=0) // Randomly diverge from this color
|
|
108
|
+
Color.setHex(hex) // Set this color from a hex code
|
|
109
|
+
Color.rgbaInt() // Get this color as 32 bit RGBA value
|
|
110
|
+
Color.toString(useAlpha=true) // Get hex color code as a string
|
|
111
|
+
|
|
112
|
+
// Seeded random number generator
|
|
113
|
+
RandomGenerator(seed) // Create a random number generator
|
|
114
|
+
RandomGenerator.float(valueA=1, valueB=0) // Random float between values
|
|
115
|
+
RandomGenerator.int(valueA, valueB=0) // Random integer between values
|
|
116
|
+
RandomGenerator.sign() // Randomly either -1 or 1
|
|
117
|
+
|
|
118
|
+
// Time tracking system
|
|
119
|
+
Timer(timeLeft) // Create a timer object
|
|
120
|
+
Timer.set(timeLeft=0) // Set the timer with seconds passed in
|
|
121
|
+
Timer.unset() // Unset the timer
|
|
122
|
+
Timer.isSet() // Returns true if set
|
|
123
|
+
Timer.active() // Returns true if set and has not elapsed
|
|
124
|
+
Timer.elapsed() // Returns true if set and elapsed
|
|
125
|
+
Timer.get() // Get how long since elapsed, 0 if not set
|
|
126
|
+
Timer.getPercent() // Get percent elapsed, 0 if not set
|
|
127
|
+
Timer.toString() // Get this timer expressed as a string
|
|
128
|
+
Timer.valueOf() // Get how long since elapsed, 0 if not set
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## LittleJS Drawing System
|
|
132
|
+
- Hybrid system with both Canvas2D and WebGL available
|
|
133
|
+
- Super fast tile sheet rendering with WebGL
|
|
134
|
+
- Can apply rotation, mirror, color and additive color
|
|
135
|
+
- Text and font rendering system with built in engine font
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
// Drawing functions
|
|
139
|
+
drawTile(pos, size=(1,1), tileInfo, color, angle=0, mirror, additiveColor)
|
|
140
|
+
drawRect(pos, size=(1,1), color=(1,1,1,1), angle=0)
|
|
141
|
+
drawPoly(points, color=(1,1,1,1))
|
|
142
|
+
drawLine(posA, posB, thickness=.1, color=(1,1,1,1))
|
|
143
|
+
drawCanvas2D(pos, size, angle, mirror, drawFunction)
|
|
144
|
+
drawText(text, pos, size=1, color=(1,1,1,1), lineWidth, lineColor)
|
|
145
|
+
drawTextScreen(text, pos, size=1, color=(1,1,1,1), lineWidth, lineColor)
|
|
146
|
+
setBlendMode(additive)
|
|
147
|
+
toggleFullscreen()
|
|
148
|
+
isFullscreen()
|
|
149
|
+
|
|
150
|
+
// Tile Info Object
|
|
151
|
+
TileInfo(pos=(0,0), size, textureIndex=0) // Create a tile info object
|
|
152
|
+
TileInfo.pos // Top left corner of tile in pixels
|
|
153
|
+
TileInfo.size // Size of tile in pixels
|
|
154
|
+
TileInfo.textureIndex // Texture index to use
|
|
155
|
+
TileInfo.offset(offset) // Offset this tile by a certain amount in pixels
|
|
156
|
+
TileInfo.getTextureInfo() // Returns texture info for this tile
|
|
157
|
+
|
|
158
|
+
// Texture Info Object
|
|
159
|
+
TextureInfo(image) // Created automatically for each image
|
|
160
|
+
TextureInfo.image // Image source
|
|
161
|
+
TextureInfo.size // Size of the image
|
|
162
|
+
TextureInfo.glTexture // WebGL texture
|
|
163
|
+
|
|
164
|
+
// Font Image Object draws text using characters in an image
|
|
165
|
+
FontImage(image, tileSize=(8,8), paddingSize=(0,1)) // Create an image font
|
|
166
|
+
FontImage.drawText(text, pos, scale, center) // Draw text in world space
|
|
167
|
+
FontImage.drawTextScreen(text, pos, scale, center) // Draw text in screen space
|
|
168
|
+
|
|
169
|
+
// Camera settings
|
|
170
|
+
cameraPos = (0,0) // Position of camera in world space
|
|
171
|
+
cameraScale = 32 // Scale of camera in world space
|
|
172
|
+
screenToWorld(screenPos) // Convert from screen to world space coordinates
|
|
173
|
+
worldToScreen(worldPos) // Convert from world to screen space coordinates
|
|
174
|
+
getCameraSize() // Get the camera's visible area in world space
|
|
175
|
+
|
|
176
|
+
// Display settings
|
|
177
|
+
canvasMaxSize = (1920, 1200) // The max size of the canvas
|
|
178
|
+
canvasFixedSize = (0, 0) // Fixed size of the canvas
|
|
179
|
+
fontDefault = 'arial' // Default font used for text rendering
|
|
180
|
+
canvasPixelated = true // Disable filtering for crisper pixel art?
|
|
181
|
+
showSplashScreen = false // Show the LittleJS splash screen on startup?
|
|
182
|
+
glEnable = true // Enable fast WebGL rendering?
|
|
183
|
+
glOverlay = true // Prevent compositing the WebGL canvas?
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## LittleJS Audio System
|
|
187
|
+
- Caches sounds and music for fast playback
|
|
188
|
+
- Can attenuate and apply stereo panning to sounds
|
|
189
|
+
- Ability to play mp3, ogg, and wave file
|
|
190
|
+
- [ZzFX Sound Effect Generator](https://killedbyapixel.github.io/ZzFX)
|
|
191
|
+
- [ZzFXM Music System](https://keithclark.github.io/ZzFXM)
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
// Sound Object
|
|
195
|
+
Sound(zzfxSound) // Create a zzfx sound
|
|
196
|
+
SoundWave(filename, randomness=0) // Load a wave, mp3, and ogg
|
|
197
|
+
Sound.play(pos, volume=1, pitch=1, randomness=1, loop) // Play a sound
|
|
198
|
+
Sound.playNote(semitoneOffset, pos, volume=1) // Play as note with a semitone offset
|
|
199
|
+
Sound.stop() // Stop the last instance that was played
|
|
200
|
+
Sound.getSource() // Get source of most recent instance
|
|
201
|
+
Sound.getDuration() // Get length of sound in seconds
|
|
202
|
+
Sound.isLoading() // Check if sound is loading
|
|
203
|
+
|
|
204
|
+
// ZzFXM - A tiny music system
|
|
205
|
+
Music(..zzfxMusic) // Create a zzfx music object
|
|
206
|
+
Music.playMusic(volume, loop=false) // Play the music
|
|
207
|
+
|
|
208
|
+
// Audio functions
|
|
209
|
+
playAudioFile(filename, volume=1, loop=false) // Play an audio file or url
|
|
210
|
+
speak(text, language='', volume=1, rate=1, pitch=1) // Speak text line
|
|
211
|
+
speakStop() // Stop all queued speech
|
|
212
|
+
|
|
213
|
+
// Audio settings
|
|
214
|
+
soundEnable = true // Should sound be enabled?
|
|
215
|
+
soundVolume = .5 // Volume scale to apply to all sound
|
|
216
|
+
soundDefaultRange = 40 // Default range where sound no longer plays
|
|
217
|
+
soundDefaultTaper = .7 // Default range percent to taper off sound (0-1)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## LittleJS Input System
|
|
221
|
+
- Tracks keyboard down, pressed, and released
|
|
222
|
+
- Tracks mouse buttons, position, and wheel
|
|
223
|
+
- Tracks multiple analog gamepads
|
|
224
|
+
- Routes touch input to mouse
|
|
225
|
+
- Virtual gamepad for touch devices
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
// Keyboard
|
|
229
|
+
keyIsDown(key) // Is key down?
|
|
230
|
+
keyWasPressed(key) // Was key pressed this frame?
|
|
231
|
+
keyWasReleased(key) // Was key released this frame?
|
|
232
|
+
|
|
233
|
+
// Mouse / Touch
|
|
234
|
+
mousePos // World space mouse position
|
|
235
|
+
mousePosScreen // Screen space mouse position
|
|
236
|
+
mouseWheel // Delta mouse wheel this frame
|
|
237
|
+
mouseIsDown(button) // Is mouse button down?
|
|
238
|
+
mouseWasPressed(button) // Was mouse button pressed this frame?
|
|
239
|
+
mouseWasReleased(button) // Was mouse button released this frame?
|
|
240
|
+
|
|
241
|
+
// Gamepad
|
|
242
|
+
isUsingGamepad // Is user currently using gamepad?
|
|
243
|
+
gamepadIsDown(button, gamepad=0) // Is gamepad button down?
|
|
244
|
+
gamepadWasPressed(button, gamepad=0) // Was gamepad button pressed this frame?
|
|
245
|
+
gamepadWasReleased(button, gamepad=0) // Was gamepad button released this frame?
|
|
246
|
+
gamepadStick(stickIndex, gamepad=0) // Get gamepad analog stick value
|
|
247
|
+
|
|
248
|
+
// Touch Gamepad
|
|
249
|
+
touchGamepadEnabled // Is on screen touch gamepad enabled?
|
|
250
|
+
touchGamepadAnalog // Is touch gamepad analog or 8 way dpad?
|
|
251
|
+
touchGamepadSize // Size of touch gamepad
|
|
252
|
+
touchGamepadAlpha // Alpha of touch gamepad
|
|
253
|
+
|
|
254
|
+
// Vibration
|
|
255
|
+
vibrate(pattern=100) // Pulse the vibration hardware if it exists
|
|
256
|
+
vibrateStop() // Stop all vibration
|
|
257
|
+
|
|
258
|
+
// Input settings
|
|
259
|
+
gamepadsEnable = true // Should gamepads be allowed?
|
|
260
|
+
gamepadDirectionEmulateStick = true // Should dpad be routed to the left analog stick?
|
|
261
|
+
inputWASDEmulateDirection = true // Should WASD keys be routed to the direction keys?
|
|
262
|
+
vibrateEnable = true // Allow vibration hardware if it exists?
|
|
263
|
+
touchGamepadEnable = false // Should touch gamepad appear on mobile devices?
|
|
264
|
+
touchGamepadAnalog = true // Should touch gamepad be analog or 8 way dpad?
|
|
265
|
+
touchGamepadSize = 99 // Size of virtual gamepad for touch devices
|
|
266
|
+
touchGamepadAlpha = .3 // Transparency of touch gamepad overlay
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## LittleJS Object System
|
|
270
|
+
- Top level object class used by the engine
|
|
271
|
+
- Automatically adds self to object list
|
|
272
|
+
- Will be updated and rendered each frame
|
|
273
|
+
- Renders as a sprite from a tile sheet by default
|
|
274
|
+
- Can have color and addtive color applied
|
|
275
|
+
- 2D Physics and collision system
|
|
276
|
+
- Sorted by renderOrder before drawing
|
|
277
|
+
- Objects can have children in local space
|
|
278
|
+
- Parents are updated before children
|
|
279
|
+
- Call destroy() to get rid of objects
|
|
280
|
+
|
|
281
|
+
```javascript
|
|
282
|
+
// Engine Object
|
|
283
|
+
EngineObject(pos=(0,0), size=(1,1), tileInfo, angle=0, color, renderOrder=0)
|
|
284
|
+
EngineObject.update() // Update object, called automatically
|
|
285
|
+
EngineObject.render() // Render object, called automatically
|
|
286
|
+
EngineObject.destroy() // Destroy this object and children
|
|
287
|
+
EngineObject.collideWithTile(tileData, pos) // Tile collision resolve check
|
|
288
|
+
EngineObject.collideWithTileRaycast(tileData, pos) // Check if raycast hit
|
|
289
|
+
EngineObject.collideWithObject(object) // Object collision resolve check
|
|
290
|
+
EngineObject.getAliveTime(object) // How long since object was created
|
|
291
|
+
EngineObject.applyAcceleration(acceleration) // Apply acceleration
|
|
292
|
+
EngineObject.applyForce(force) // Apply force
|
|
293
|
+
EngineObject.getMirrorSign() // Get mirror direction (1 or -1)
|
|
294
|
+
EngineObject.addChild(child, localPos, localAngle) // Attach a child
|
|
295
|
+
EngineObject.removeChild(child) // Remove a child
|
|
296
|
+
EngineObject.setCollision(solids, isSolid, tiles) // Set collision
|
|
297
|
+
|
|
298
|
+
// Engine Object Members
|
|
299
|
+
EngineObject.pos // World space position
|
|
300
|
+
EngineObject.size // World space width and height
|
|
301
|
+
EngineObject.drawSize // Size of object used for drawing if set
|
|
302
|
+
EngineObject.tileInfo // Tile info to render object
|
|
303
|
+
EngineObject.angle // Rotation angle for rendering
|
|
304
|
+
EngineObject.color // Color to apply when rendered
|
|
305
|
+
EngineObject.additiveColor // Additive color to apply when rendered
|
|
306
|
+
EngineObject.mirror // Should it flip along y axis when rendered
|
|
307
|
+
EngineObject.mass // Weight of object, static if 0
|
|
308
|
+
EngineObject.damping // How much to slow velocity each frame (0-1)
|
|
309
|
+
EngineObject.angleDamping // How much to slow rotation each frame (0-1)
|
|
310
|
+
EngineObject.elasticity // How bouncy is it when colliding (0-1)
|
|
311
|
+
EngineObject.friction // How much friction when sliding (0-1)
|
|
312
|
+
EngineObject.gravityScale // How much to scale gravity by
|
|
313
|
+
EngineObject.renderOrder // Objects are sorted by render order
|
|
314
|
+
EngineObject.velocity // Velocity of the object
|
|
315
|
+
EngineObject.angleVelocity // Angular velocity of the object
|
|
316
|
+
|
|
317
|
+
// Object settings
|
|
318
|
+
enablePhysicsSolver = true // Enable collisions between objects?
|
|
319
|
+
objectDefaultMass = 1 // Default object mass for collisions
|
|
320
|
+
objectDefaultDamping = 1 // How much to slow velocity by each frame (0-1)
|
|
321
|
+
objectDefaultAngleDamping = 1 // How much to slow angular velocity each frame (0-1)
|
|
322
|
+
objectDefaultElasticity = 0 // How much to bounce when a collision occurs (0-1)
|
|
323
|
+
objectDefaultFriction = .8 // How much to slow when touching (0-1)
|
|
324
|
+
objectMaxSpeed = 1 // Clamp max speed to avoid fast objects missing collisions
|
|
325
|
+
gravity = 0 // How much gravity to apply to objects
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## LittleJS Tile Layer System
|
|
329
|
+
- Caches arrays of tiles to off screen canvas for fast rendering
|
|
330
|
+
- Unlimited numbers of layers, allocates canvases as needed
|
|
331
|
+
- Interfaces with EngineObject for collision
|
|
332
|
+
- Collision layer is separate from visible layers
|
|
333
|
+
- It is recommended to have a visible layer that matches the collision
|
|
334
|
+
- Tile layers can be drawn to using their context with Canvas2d
|
|
335
|
+
- Drawn directly to the main canvas without using WebGL
|
|
336
|
+
|
|
337
|
+
```javascript
|
|
338
|
+
// Tile Collision System
|
|
339
|
+
tileCollisionSize // Size of the tile collision layer
|
|
340
|
+
initTileCollision(size) // Clear and initialize tile collision
|
|
341
|
+
setTileCollisionData(pos, data=0) // Set tile collision data at pos
|
|
342
|
+
getTileCollisionData(pos) // Get tile collision data at pos
|
|
343
|
+
tileCollisionTest(pos, size=(0,0), object) // Check if collision should occur
|
|
344
|
+
tileCollisionRaycast(posStart, posEnd, object) // Return the center of tile if hit
|
|
345
|
+
|
|
346
|
+
// Tile Layer Object
|
|
347
|
+
TileLayer(position, size, tileInfo, scale) // Create a tile layer object
|
|
348
|
+
TileLayer.setData(layerPos, data, redraw) // Set data at position
|
|
349
|
+
TileLayer.getData(layerPos) // Get data at position
|
|
350
|
+
TileLayer.redraw() // Draw to an offscreen canvas
|
|
351
|
+
TileLayer.drawTileData(layerPos, clear=true) // Draw the tile
|
|
352
|
+
TileLayer.drawRect(pos, size, color, angle) // Draw a rectangle to 2D canvas
|
|
353
|
+
TileLayer.drawTile(pos, size=(1,1), tileInfo, color, angle, mirror) // Draw tile
|
|
354
|
+
TileLayer.drawCanvas2D(pos, size, angle, mirror, drawFunction) // Draw to 2D canvas
|
|
355
|
+
|
|
356
|
+
// Tile Layer Data Object
|
|
357
|
+
TileLayerData(tile, direction=0, mirror=false, color=(1,1,1,1)) // Create tile data object
|
|
358
|
+
TileLayerData.clear() // Clear this tile data
|
|
359
|
+
|
|
360
|
+
// Tile sheet settings
|
|
361
|
+
tileSizeDefault = (16,16) // Default size of tiles in pixels
|
|
362
|
+
tileFixBleedScale = .3 // How much smaller to draw tiles to prevent bleeding
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## LittleJS Particle System
|
|
366
|
+
- Simple kinematic particle system with many parameters
|
|
367
|
+
- [Particle Effect Designer](https://killedbyapixel.github.io/LittleJS/examples/particles) - Editor for creating LittleJS Particle Systems
|
|
368
|
+
|
|
369
|
+
```javascript
|
|
370
|
+
// Particle Emitter Object
|
|
371
|
+
ParticleEmitter(position, angle, ...settings) // Create a particle system
|
|
372
|
+
ParticleEmitter.emitParticle() // Spawn one particle
|
|
373
|
+
|
|
374
|
+
// Particle Settings
|
|
375
|
+
particleEmitRateScale = 1 // Scales particles emit rate
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## LittleJS Debugging System
|
|
379
|
+
- Press Escape key to toggle debug overlay
|
|
380
|
+
- Number keys toggle debug functions
|
|
381
|
+
- +/- keys apply time scale to update
|
|
382
|
+
- Debug primitive rendering system
|
|
383
|
+
- Debug functions are only active in debug builds
|
|
384
|
+
|
|
385
|
+
```javascript
|
|
386
|
+
ASSERT(assert, output) // Asserts if the expression is false
|
|
387
|
+
debugRect(pos, size, color='#fff', time=0, angle=0, fill) // Draw debug rectangle
|
|
388
|
+
debugCircle(pos, radius, color='#fff', time=0, fill) // Draw debug circle
|
|
389
|
+
debugPoint(pos, color, time, angle) // Draw debug point
|
|
390
|
+
debugLine(posA, posB, color, thickness=.1, time) // Draw debug line
|
|
391
|
+
debugText(text, pos, size=1, color='#fff', time=0, angle=0) // Draw debug text
|
|
392
|
+
debugAABB(pA, sA, pB, sB, color) // Draw a debug axis aligned box
|
|
393
|
+
debugClear() // Clear all debug primitives
|
|
394
|
+
debugSaveCanvas(canvas, filename) // Save canvas to a file
|
|
395
|
+
debugSaveText(text, filename) // Save text to a file
|
|
396
|
+
debugSaveDataURL(dataURL, filename) // Save url to a file
|
|
397
|
+
|
|
398
|
+
// Debug settings
|
|
399
|
+
debug // Is debug enabled?
|
|
400
|
+
debugPointSize = .5 // Size to render debug points by default
|
|
401
|
+
debugKey = 'Escape' // Key code used to toggle debug mode
|
|
402
|
+
debugOverlay // True if the debug overlay is active
|
|
403
|
+
enableAsserts // True if asserts are enabled
|
|
404
|
+
showWatermark // True if watermark with FPS should be show
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
[LittleJS Engine](https://github.com/KilledByAPixel/LittleJS) Copyright 2021 Frank Force
|
|
408
|
+
|
|
409
|
+

|
package/src/engine.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* LittleJS - The Tiny JavaScript Game Engine
|
|
2
|
+
* LittleJS - The Tiny Fast JavaScript Game Engine
|
|
3
3
|
* MIT License - Copyright 2021 Frank Force
|
|
4
4
|
*
|
|
5
5
|
* Engine Features
|
|
@@ -30,9 +30,9 @@ const engineName = 'LittleJS';
|
|
|
30
30
|
* @type {String}
|
|
31
31
|
* @default
|
|
32
32
|
* @memberof Engine */
|
|
33
|
-
const engineVersion = '1.9.
|
|
33
|
+
const engineVersion = '1.9.3';
|
|
34
34
|
|
|
35
|
-
/** Frames per second to update
|
|
35
|
+
/** Frames per second to update
|
|
36
36
|
* @type {Number}
|
|
37
37
|
* @default
|
|
38
38
|
* @memberof Engine */
|
|
@@ -49,7 +49,7 @@ const timeDelta = 1/frameRate;
|
|
|
49
49
|
* @memberof Engine */
|
|
50
50
|
let engineObjects = [];
|
|
51
51
|
|
|
52
|
-
/** Array
|
|
52
|
+
/** Array with only objects set to collide with other objects this frame (for optimization)
|
|
53
53
|
* @type {Array}
|
|
54
54
|
* @memberof Engine */
|
|
55
55
|
let engineObjectsCollide = [];
|
|
@@ -59,7 +59,7 @@ let engineObjectsCollide = [];
|
|
|
59
59
|
* @memberof Engine */
|
|
60
60
|
let frame = 0;
|
|
61
61
|
|
|
62
|
-
/** Current engine time since start in seconds
|
|
62
|
+
/** Current engine time since start in seconds
|
|
63
63
|
* @type {Number}
|
|
64
64
|
* @memberof Engine */
|
|
65
65
|
let time = 0;
|
|
@@ -85,12 +85,12 @@ let frameTimeLastMS = 0, frameTimeBufferMS = 0, averageFPS = 0;
|
|
|
85
85
|
|
|
86
86
|
///////////////////////////////////////////////////////////////////////////////
|
|
87
87
|
|
|
88
|
-
/**
|
|
89
|
-
* @param {Function} gameInit
|
|
90
|
-
* @param {Function} gameUpdate
|
|
91
|
-
* @param {Function} gameUpdatePost
|
|
92
|
-
* @param {Function} gameRender
|
|
93
|
-
* @param {Function} gameRenderPost
|
|
88
|
+
/** Startup LittleJS engine with your callback functions
|
|
89
|
+
* @param {Function} gameInit - Called once after the engine starts up, setup the game
|
|
90
|
+
* @param {Function} gameUpdate - Called every frame at 60 frames per second, handle input and update the game state
|
|
91
|
+
* @param {Function} gameUpdatePost - Called after physics and objects are updated, setup camera and prepare for render
|
|
92
|
+
* @param {Function} gameRender - Called before objects are rendered, draw any background effects that appear behind objects
|
|
93
|
+
* @param {Function} gameRenderPost - Called after objects are rendered, draw effects or hud that appear above all objects
|
|
94
94
|
* @param {Array} [imageSources=['tiles.png']] - Image to load
|
|
95
95
|
* @memberof Engine */
|
|
96
96
|
function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources=['tiles.png'])
|
|
@@ -113,32 +113,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
113
113
|
frameTimeBufferMS += paused ? 0 : frameTimeDeltaMS;
|
|
114
114
|
if (!debugSpeedUp)
|
|
115
115
|
frameTimeBufferMS = min(frameTimeBufferMS, 50); // clamp incase of slow framerate
|
|
116
|
-
|
|
117
|
-
if (canvasFixedSize.x)
|
|
118
|
-
{
|
|
119
|
-
// clear canvas and set fixed size
|
|
120
|
-
mainCanvas.width = canvasFixedSize.x;
|
|
121
|
-
mainCanvas.height = canvasFixedSize.y;
|
|
122
|
-
|
|
123
|
-
// fit to window by adding space on top or bottom if necessary
|
|
124
|
-
const aspect = innerWidth / innerHeight;
|
|
125
|
-
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
126
|
-
(glCanvas||mainCanvas).style.width = mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
127
|
-
(glCanvas||mainCanvas).style.height = mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
128
|
-
}
|
|
129
|
-
else
|
|
130
|
-
{
|
|
131
|
-
// clear canvas and set size to same as window
|
|
132
|
-
mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
133
|
-
mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// clear overlay canvas and set size
|
|
137
|
-
overlayCanvas.width = mainCanvas.width;
|
|
138
|
-
overlayCanvas.height = mainCanvas.height;
|
|
139
|
-
|
|
140
|
-
// save canvas size
|
|
141
|
-
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
116
|
+
updateCanvas();
|
|
142
117
|
|
|
143
118
|
if (paused)
|
|
144
119
|
{
|
|
@@ -212,6 +187,35 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
212
187
|
requestAnimationFrame(engineUpdate);
|
|
213
188
|
}
|
|
214
189
|
|
|
190
|
+
function updateCanvas()
|
|
191
|
+
{
|
|
192
|
+
if (canvasFixedSize.x)
|
|
193
|
+
{
|
|
194
|
+
// clear canvas and set fixed size
|
|
195
|
+
mainCanvas.width = canvasFixedSize.x;
|
|
196
|
+
mainCanvas.height = canvasFixedSize.y;
|
|
197
|
+
|
|
198
|
+
// fit to window by adding space on top or bottom if necessary
|
|
199
|
+
const aspect = innerWidth / innerHeight;
|
|
200
|
+
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
201
|
+
(glCanvas||mainCanvas).style.width = mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
202
|
+
(glCanvas||mainCanvas).style.height = mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
203
|
+
}
|
|
204
|
+
else
|
|
205
|
+
{
|
|
206
|
+
// clear canvas and set size to same as window
|
|
207
|
+
mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
208
|
+
mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// clear overlay canvas and set size
|
|
212
|
+
overlayCanvas.width = mainCanvas.width;
|
|
213
|
+
overlayCanvas.height = mainCanvas.height;
|
|
214
|
+
|
|
215
|
+
// save canvas size
|
|
216
|
+
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
217
|
+
}
|
|
218
|
+
|
|
215
219
|
// setup html
|
|
216
220
|
const styleBody =
|
|
217
221
|
'margin:0;overflow:hidden;' + // fill the window
|
|
@@ -236,6 +240,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
236
240
|
const styleCanvas = 'position:absolute;' + // position
|
|
237
241
|
'top:50%;left:50%;transform:translate(-50%,-50%)'; // center
|
|
238
242
|
(glCanvas||mainCanvas).style.cssText = mainCanvas.style.cssText = overlayCanvas.style.cssText = styleCanvas;
|
|
243
|
+
updateCanvas();
|
|
239
244
|
|
|
240
245
|
// create promises for loading images
|
|
241
246
|
const promises = imageSources.map((src, textureIndex)=>
|
|
@@ -432,9 +437,9 @@ function drawEngineSplashScreen(t)
|
|
|
432
437
|
|
|
433
438
|
// big stack
|
|
434
439
|
rect(50,20,10,-10,color(0,1));
|
|
435
|
-
rect(50,20,6,-10,color(0,2));
|
|
436
|
-
rect(50,20,3,-10,color(0,3));
|
|
437
|
-
rect(50,
|
|
440
|
+
rect(50,20,6.5,-10,color(0,2));
|
|
441
|
+
rect(50,20,3.5,-10,color(0,3));
|
|
442
|
+
rect(50,20,10,-10);
|
|
438
443
|
circle(55,2,11.4,.5,PI-.5,color(3,3));
|
|
439
444
|
circle(55,2,11.4,.5,PI/2,color(3,2),1);
|
|
440
445
|
circle(55,2,11.4,.5,PI-.5);
|
|
@@ -453,7 +458,7 @@ function drawEngineSplashScreen(t)
|
|
|
453
458
|
|
|
454
459
|
// engine outline
|
|
455
460
|
circle(36,30,10,PI/2,PI*3/2);
|
|
456
|
-
circle(
|
|
461
|
+
circle(48,30,10,PI/2,PI*3/2);
|
|
457
462
|
circle(60,30,10);
|
|
458
463
|
line(36,20,60,20);
|
|
459
464
|
|
package/src/engineAudio.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Sound Object - Stores a
|
|
15
|
+
* Sound Object - Stores a sound for later use and can be played positionally
|
|
16
16
|
*
|
|
17
17
|
* <a href=https://killedbyapixel.github.io/ZzFX/>Create sounds using the ZzFX Sound Designer.</a>
|
|
18
18
|
* @example
|
|
@@ -27,7 +27,7 @@ class Sound
|
|
|
27
27
|
/** Create a sound object and cache the zzfx samples for later use
|
|
28
28
|
* @param {Array} zzfxSound - Array of zzfx parameters, ex. [.5,.5]
|
|
29
29
|
* @param {Number} [range=soundDefaultRange] - World space max range of sound, will not play if camera is farther away
|
|
30
|
-
* @param {Number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
|
|
30
|
+
* @param {Number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
|
|
31
31
|
*/
|
|
32
32
|
constructor(zzfxSound, range=soundDefaultRange, taper=soundDefaultTaper)
|
|
33
33
|
{
|
|
@@ -207,24 +207,24 @@ class Music extends Sound
|
|
|
207
207
|
|
|
208
208
|
/** Play the music
|
|
209
209
|
* @param {Number} [volume=1] - How much to scale volume by
|
|
210
|
-
* @param {Boolean} [loop
|
|
210
|
+
* @param {Boolean} [loop] - True if the music should loop
|
|
211
211
|
* @return {AudioBufferSourceNode} - The audio source node
|
|
212
212
|
*/
|
|
213
|
-
playMusic(volume, loop
|
|
213
|
+
playMusic(volume, loop=false)
|
|
214
214
|
{ return super.play(undefined, volume, 1, 1, loop); }
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
/** Play an mp3, ogg, or wav audio from a local file or url
|
|
218
|
-
* @param {String}
|
|
218
|
+
* @param {String} filename - Location of sound file to play
|
|
219
219
|
* @param {Number} [volume] - How much to scale volume by
|
|
220
220
|
* @param {Boolean} [loop] - True if the music should loop
|
|
221
221
|
* @return {HTMLAudioElement} - The audio element for this sound
|
|
222
222
|
* @memberof Audio */
|
|
223
|
-
function playAudioFile(
|
|
223
|
+
function playAudioFile(filename, volume=1, loop=false)
|
|
224
224
|
{
|
|
225
225
|
if (!soundEnable) return;
|
|
226
226
|
|
|
227
|
-
const audio = new Audio(
|
|
227
|
+
const audio = new Audio(filename);
|
|
228
228
|
audio.volume = soundVolume * volume;
|
|
229
229
|
audio.loop = loop;
|
|
230
230
|
audio.play();
|
|
@@ -276,6 +276,11 @@ function getNoteFrequency(semitoneOffset, rootFrequency=220)
|
|
|
276
276
|
* @memberof Audio */
|
|
277
277
|
let audioContext = new AudioContext;
|
|
278
278
|
|
|
279
|
+
/** Keep track if audio was suspended when last sound was played
|
|
280
|
+
* @type {Boolean}
|
|
281
|
+
* @memberof Audio */
|
|
282
|
+
let audioSuspended = false;
|
|
283
|
+
|
|
279
284
|
/** Play cached audio samples with given settings
|
|
280
285
|
* @param {Array} sampleChannels - Array of arrays of samples to play (for stereo playback)
|
|
281
286
|
* @param {Number} [volume] - How much to scale volume by
|
|
@@ -290,11 +295,15 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=false, sample
|
|
|
290
295
|
if (!soundEnable) return;
|
|
291
296
|
|
|
292
297
|
// prevent sounds from building up if they can't be played
|
|
293
|
-
|
|
298
|
+
const audioWasSuspended = audioSuspended;
|
|
299
|
+
if (audioSuspended = audioContext.state != 'running')
|
|
294
300
|
{
|
|
295
301
|
// fix stalled audio
|
|
296
302
|
audioContext.resume();
|
|
297
|
-
|
|
303
|
+
|
|
304
|
+
// prevent suspended sounds from building up
|
|
305
|
+
if (audioWasSuspended)
|
|
306
|
+
return;
|
|
298
307
|
}
|
|
299
308
|
|
|
300
309
|
// create buffer and source
|
package/src/engineDebug.js
CHANGED
|
@@ -52,7 +52,7 @@ let debugPrimitives = [], debugPhysics = false, debugRaycast = false, debugParti
|
|
|
52
52
|
///////////////////////////////////////////////////////////////////////////////
|
|
53
53
|
// Debug helper functions
|
|
54
54
|
|
|
55
|
-
/** Asserts if the
|
|
55
|
+
/** Asserts if the expression is false, does not do anything in release builds
|
|
56
56
|
* @param {Boolean} assert
|
|
57
57
|
* @param {Object} [output]
|
|
58
58
|
* @memberof Debug */
|