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/dist/littlejs.release.js
CHANGED
|
@@ -71,7 +71,7 @@ function min(valueA, valueB) { return Math.min(valueA, valueB); }
|
|
|
71
71
|
* @memberof Utilities */
|
|
72
72
|
function max(valueA, valueB) { return Math.max(valueA, valueB); }
|
|
73
73
|
|
|
74
|
-
/** Returns the sign of value passed in
|
|
74
|
+
/** Returns the sign of value passed in
|
|
75
75
|
* @param {Number} value
|
|
76
76
|
* @return {Number}
|
|
77
77
|
* @memberof Utilities */
|
|
@@ -118,7 +118,7 @@ function lerp(percent, valueA, valueB) { return valueA + clamp(percent) * (value
|
|
|
118
118
|
function distanceWrap(valueA, valueB, wrapSize=1)
|
|
119
119
|
{ const d = (valueA - valueB) % wrapSize; return d*2 % wrapSize - d; }
|
|
120
120
|
|
|
121
|
-
/** Linearly interpolates between values passed in with
|
|
121
|
+
/** Linearly interpolates between values passed in with wrapping
|
|
122
122
|
* @param {Number} percent
|
|
123
123
|
* @param {Number} valueA
|
|
124
124
|
* @param {Number} valueB
|
|
@@ -135,7 +135,7 @@ function lerpWrap(percent, valueA, valueB, wrapSize=1)
|
|
|
135
135
|
* @memberof Utilities */
|
|
136
136
|
function distanceAngle(angleA, angleB) { return distanceWrap(angleA, angleB, 2*PI); }
|
|
137
137
|
|
|
138
|
-
/** Linearly interpolates between the angles passed in with
|
|
138
|
+
/** Linearly interpolates between the angles passed in with wrapping
|
|
139
139
|
* @param {Number} percent
|
|
140
140
|
* @param {Number} angleA
|
|
141
141
|
* @param {Number} angleB
|
|
@@ -877,7 +877,7 @@ let tileSizeDefault = vec2(16);
|
|
|
877
877
|
* @type {Number}
|
|
878
878
|
* @default
|
|
879
879
|
* @memberof Settings */
|
|
880
|
-
let tileFixBleedScale = .
|
|
880
|
+
let tileFixBleedScale = .1;
|
|
881
881
|
|
|
882
882
|
///////////////////////////////////////////////////////////////////////////////
|
|
883
883
|
// Object settings
|
|
@@ -888,7 +888,7 @@ let tileFixBleedScale = .3;
|
|
|
888
888
|
* @memberof Settings */
|
|
889
889
|
let enablePhysicsSolver = true;
|
|
890
890
|
|
|
891
|
-
/** Default object mass for
|
|
891
|
+
/** Default object mass for collision calcuations (how heavy objects are)
|
|
892
892
|
* @type {Number}
|
|
893
893
|
* @default
|
|
894
894
|
* @memberof Settings */
|
|
@@ -971,7 +971,7 @@ let touchGamepadEnable = false;
|
|
|
971
971
|
* @memberof Settings */
|
|
972
972
|
let touchGamepadAnalog = true;
|
|
973
973
|
|
|
974
|
-
/** Size of
|
|
974
|
+
/** Size of virtual gamepad for touch devices in pixels
|
|
975
975
|
* @type {Number}
|
|
976
976
|
* @default
|
|
977
977
|
* @memberof Settings */
|
|
@@ -1258,7 +1258,7 @@ function setDebugKey(key) { debugKey = key; }
|
|
|
1258
1258
|
* - Automatically adds self to object list
|
|
1259
1259
|
* - Will be updated and rendered each frame
|
|
1260
1260
|
* - Renders as a sprite from a tilesheet by default
|
|
1261
|
-
* - Can have color and
|
|
1261
|
+
* - Can have color and additive color applied
|
|
1262
1262
|
* - 2D Physics and collision system
|
|
1263
1263
|
* - Sorted by renderOrder
|
|
1264
1264
|
* - Objects can have children attached
|
|
@@ -1537,7 +1537,7 @@ class EngineObject
|
|
|
1537
1537
|
}
|
|
1538
1538
|
|
|
1539
1539
|
/** Destroy this object, destroy it's children, detach it's parent, and mark it for removal */
|
|
1540
|
-
destroy()
|
|
1540
|
+
destroy()
|
|
1541
1541
|
{
|
|
1542
1542
|
if (this.destroyed)
|
|
1543
1543
|
return;
|
|
@@ -1726,13 +1726,9 @@ function tile(pos=vec2(), size=tileSizeDefault, textureIndex=0)
|
|
|
1726
1726
|
if (typeof pos === 'number')
|
|
1727
1727
|
{
|
|
1728
1728
|
const textureInfo = textureInfos[textureIndex];
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
pos = vec2((pos%cols)*size.x, (pos/cols|0)*size.y);
|
|
1733
|
-
}
|
|
1734
|
-
else
|
|
1735
|
-
pos = vec2();
|
|
1729
|
+
ASSERT(textureInfo, 'Texture not loaded');
|
|
1730
|
+
const cols = textureInfo.size.x / size.x |0;
|
|
1731
|
+
pos = vec2((pos%cols)*size.x, (pos/cols|0)*size.y);
|
|
1736
1732
|
}
|
|
1737
1733
|
|
|
1738
1734
|
// return a tile info object
|
|
@@ -1821,6 +1817,11 @@ function worldToScreen(worldPos)
|
|
|
1821
1817
|
);
|
|
1822
1818
|
}
|
|
1823
1819
|
|
|
1820
|
+
/** Get the camera's visible area in world space
|
|
1821
|
+
* @return {Vector2}
|
|
1822
|
+
* @memberof Draw */
|
|
1823
|
+
function getCameraSize() { return mainCanvasSize.scale(1/cameraScale); }
|
|
1824
|
+
|
|
1824
1825
|
/** Draw textured tile centered in world space, with color applied if using WebGL
|
|
1825
1826
|
* @param {Vector2} pos - Center of the tile in world space
|
|
1826
1827
|
* @param {Vector2} [size=(1,1)] - Size of the tile in world space
|
|
@@ -2498,7 +2499,7 @@ function createTouchGamepad()
|
|
|
2498
2499
|
touchGamepadStick = vec2();
|
|
2499
2500
|
|
|
2500
2501
|
const touchHandler = ontouchstart;
|
|
2501
|
-
ontouchstart = ontouchmove = ontouchend = (e)=>
|
|
2502
|
+
ontouchstart = ontouchmove = ontouchend = (e)=>
|
|
2502
2503
|
{
|
|
2503
2504
|
// clear touch gamepad input
|
|
2504
2505
|
touchGamepadStick = vec2();
|
|
@@ -2628,7 +2629,7 @@ function touchGamepadRender()
|
|
|
2628
2629
|
|
|
2629
2630
|
|
|
2630
2631
|
/**
|
|
2631
|
-
* Sound Object - Stores a
|
|
2632
|
+
* Sound Object - Stores a sound for later use and can be played positionally
|
|
2632
2633
|
*
|
|
2633
2634
|
* <a href=https://killedbyapixel.github.io/ZzFX/>Create sounds using the ZzFX Sound Designer.</a>
|
|
2634
2635
|
* @example
|
|
@@ -2643,7 +2644,7 @@ class Sound
|
|
|
2643
2644
|
/** Create a sound object and cache the zzfx samples for later use
|
|
2644
2645
|
* @param {Array} zzfxSound - Array of zzfx parameters, ex. [.5,.5]
|
|
2645
2646
|
* @param {Number} [range=soundDefaultRange] - World space max range of sound, will not play if camera is farther away
|
|
2646
|
-
* @param {Number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
|
|
2647
|
+
* @param {Number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
|
|
2647
2648
|
*/
|
|
2648
2649
|
constructor(zzfxSound, range=soundDefaultRange, taper=soundDefaultTaper)
|
|
2649
2650
|
{
|
|
@@ -2823,24 +2824,24 @@ class Music extends Sound
|
|
|
2823
2824
|
|
|
2824
2825
|
/** Play the music
|
|
2825
2826
|
* @param {Number} [volume=1] - How much to scale volume by
|
|
2826
|
-
* @param {Boolean} [loop
|
|
2827
|
+
* @param {Boolean} [loop] - True if the music should loop
|
|
2827
2828
|
* @return {AudioBufferSourceNode} - The audio source node
|
|
2828
2829
|
*/
|
|
2829
|
-
playMusic(volume, loop
|
|
2830
|
+
playMusic(volume, loop=false)
|
|
2830
2831
|
{ return super.play(undefined, volume, 1, 1, loop); }
|
|
2831
2832
|
}
|
|
2832
2833
|
|
|
2833
2834
|
/** Play an mp3, ogg, or wav audio from a local file or url
|
|
2834
|
-
* @param {String}
|
|
2835
|
+
* @param {String} filename - Location of sound file to play
|
|
2835
2836
|
* @param {Number} [volume] - How much to scale volume by
|
|
2836
2837
|
* @param {Boolean} [loop] - True if the music should loop
|
|
2837
2838
|
* @return {HTMLAudioElement} - The audio element for this sound
|
|
2838
2839
|
* @memberof Audio */
|
|
2839
|
-
function playAudioFile(
|
|
2840
|
+
function playAudioFile(filename, volume=1, loop=false)
|
|
2840
2841
|
{
|
|
2841
2842
|
if (!soundEnable) return;
|
|
2842
2843
|
|
|
2843
|
-
const audio = new Audio(
|
|
2844
|
+
const audio = new Audio(filename);
|
|
2844
2845
|
audio.volume = soundVolume * volume;
|
|
2845
2846
|
audio.loop = loop;
|
|
2846
2847
|
audio.play();
|
|
@@ -2892,6 +2893,11 @@ function getNoteFrequency(semitoneOffset, rootFrequency=220)
|
|
|
2892
2893
|
* @memberof Audio */
|
|
2893
2894
|
let audioContext = new AudioContext;
|
|
2894
2895
|
|
|
2896
|
+
/** Keep track if audio was suspended when last sound was played
|
|
2897
|
+
* @type {Boolean}
|
|
2898
|
+
* @memberof Audio */
|
|
2899
|
+
let audioSuspended = false;
|
|
2900
|
+
|
|
2895
2901
|
/** Play cached audio samples with given settings
|
|
2896
2902
|
* @param {Array} sampleChannels - Array of arrays of samples to play (for stereo playback)
|
|
2897
2903
|
* @param {Number} [volume] - How much to scale volume by
|
|
@@ -2906,11 +2912,15 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=false, sample
|
|
|
2906
2912
|
if (!soundEnable) return;
|
|
2907
2913
|
|
|
2908
2914
|
// prevent sounds from building up if they can't be played
|
|
2909
|
-
|
|
2915
|
+
const audioWasSuspended = audioSuspended;
|
|
2916
|
+
if (audioSuspended = audioContext.state != 'running')
|
|
2910
2917
|
{
|
|
2911
2918
|
// fix stalled audio
|
|
2912
2919
|
audioContext.resume();
|
|
2913
|
-
|
|
2920
|
+
|
|
2921
|
+
// prevent suspended sounds from building up
|
|
2922
|
+
if (audioWasSuspended)
|
|
2923
|
+
return;
|
|
2914
2924
|
}
|
|
2915
2925
|
|
|
2916
2926
|
// create buffer and source
|
|
@@ -3178,7 +3188,7 @@ function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
|
3178
3188
|
/**
|
|
3179
3189
|
* LittleJS Tile Layer System
|
|
3180
3190
|
* - Caches arrays of tiles to off screen canvas for fast rendering
|
|
3181
|
-
* -
|
|
3191
|
+
* - Unlimited numbers of layers, allocates canvases as needed
|
|
3182
3192
|
* - Interfaces with EngineObject for collision
|
|
3183
3193
|
* - Collision layer is separate from visible layers
|
|
3184
3194
|
* - It is recommended to have a visible layer that matches the collision
|
|
@@ -3230,7 +3240,7 @@ function getTileCollisionData(pos)
|
|
|
3230
3240
|
|
|
3231
3241
|
/** Check if collision with another object should occur
|
|
3232
3242
|
* @param {Vector2} pos
|
|
3233
|
-
* @param {Vector2} [size=(
|
|
3243
|
+
* @param {Vector2} [size=(0,0)]
|
|
3234
3244
|
* @param {EngineObject} [object]
|
|
3235
3245
|
* @return {Boolean}
|
|
3236
3246
|
* @memberof TileCollision */
|
|
@@ -3747,16 +3757,17 @@ class ParticleEmitter extends EngineObject
|
|
|
3747
3757
|
|
|
3748
3758
|
// build particle
|
|
3749
3759
|
const particle = new Particle(pos, this.tileInfo, angle, colorStart, colorEnd, particleTime, sizeStart, sizeEnd, this.fadeRate, this.additive, this.trailScale, this.localSpace && this, this.particleDestroyCallback);
|
|
3750
|
-
particle.velocity
|
|
3751
|
-
particle.
|
|
3752
|
-
particle.
|
|
3753
|
-
particle.
|
|
3754
|
-
particle.
|
|
3755
|
-
particle.
|
|
3756
|
-
particle.
|
|
3757
|
-
particle.
|
|
3758
|
-
particle.
|
|
3759
|
-
particle.
|
|
3760
|
+
particle.velocity = vec2().setAngle(velocityAngle, speed);
|
|
3761
|
+
particle.angleVelocity = angleSpeed;
|
|
3762
|
+
particle.fadeRate = this.fadeRate;
|
|
3763
|
+
particle.damping = this.damping;
|
|
3764
|
+
particle.angleDamping = this.angleDamping;
|
|
3765
|
+
particle.elasticity = this.elasticity;
|
|
3766
|
+
particle.friction = this.friction;
|
|
3767
|
+
particle.gravityScale = this.gravityScale;
|
|
3768
|
+
particle.collideTiles = this.collideTiles;
|
|
3769
|
+
particle.renderOrder = this.renderOrder;
|
|
3770
|
+
particle.mirror = !!randInt(2);
|
|
3760
3771
|
|
|
3761
3772
|
// call particle create callaback
|
|
3762
3773
|
this.particleCreateCallback && this.particleCreateCallback(particle);
|
|
@@ -4147,7 +4158,7 @@ class Newgrounds
|
|
|
4147
4158
|
}
|
|
4148
4159
|
|
|
4149
4160
|
// build the input object
|
|
4150
|
-
const input =
|
|
4161
|
+
const input =
|
|
4151
4162
|
{
|
|
4152
4163
|
'app_id': this.app_id,
|
|
4153
4164
|
'session_id': this.session_id,
|
|
@@ -4362,8 +4373,6 @@ function glCreateTexture(image)
|
|
|
4362
4373
|
const filter = canvasPixelated ? gl_NEAREST : gl_LINEAR;
|
|
4363
4374
|
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_MIN_FILTER, filter);
|
|
4364
4375
|
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_MAG_FILTER, filter);
|
|
4365
|
-
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_WRAP_S, gl_CLAMP_TO_EDGE);
|
|
4366
|
-
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_WRAP_T, gl_CLAMP_TO_EDGE);
|
|
4367
4376
|
|
|
4368
4377
|
return texture;
|
|
4369
4378
|
}
|
|
@@ -4441,7 +4450,7 @@ function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba, rgbaAdd
|
|
|
4441
4450
|
///////////////////////////////////////////////////////////////////////////////
|
|
4442
4451
|
// post processing - can be enabled to pass other canvases through a final shader
|
|
4443
4452
|
|
|
4444
|
-
let glPostShader,
|
|
4453
|
+
let glPostShader, glPostTexture, glPostIncludeOverlay;
|
|
4445
4454
|
|
|
4446
4455
|
/** Set up a post processing shader
|
|
4447
4456
|
* @param {String} shaderCode
|
|
@@ -4477,7 +4486,6 @@ function glInitPostProcess(shaderCode, includeOverlay=false)
|
|
|
4477
4486
|
);
|
|
4478
4487
|
|
|
4479
4488
|
// create buffer and texture
|
|
4480
|
-
glPostArrayBuffer = glContext.createBuffer();
|
|
4481
4489
|
glPostTexture = glCreateTexture(undefined);
|
|
4482
4490
|
glPostIncludeOverlay = includeOverlay;
|
|
4483
4491
|
|
|
@@ -4549,10 +4557,7 @@ gl_NEAREST = 9728,
|
|
|
4549
4557
|
gl_LINEAR = 9729,
|
|
4550
4558
|
gl_TEXTURE_MAG_FILTER = 10240,
|
|
4551
4559
|
gl_TEXTURE_MIN_FILTER = 10241,
|
|
4552
|
-
gl_TEXTURE_WRAP_S = 10242,
|
|
4553
|
-
gl_TEXTURE_WRAP_T = 10243,
|
|
4554
4560
|
gl_COLOR_BUFFER_BIT = 16384,
|
|
4555
|
-
gl_CLAMP_TO_EDGE = 33071,
|
|
4556
4561
|
gl_TEXTURE0 = 33984,
|
|
4557
4562
|
gl_ARRAY_BUFFER = 34962,
|
|
4558
4563
|
gl_STATIC_DRAW = 35044,
|
|
@@ -4569,7 +4574,7 @@ gl_MAX_INSTANCES = 1e4,
|
|
|
4569
4574
|
gl_INSTANCE_BYTE_STRIDE = gl_INDICIES_PER_INSTANCE * 4, // 11 * 4
|
|
4570
4575
|
gl_INSTANCE_BUFFER_SIZE = gl_MAX_INSTANCES * gl_INSTANCE_BYTE_STRIDE;
|
|
4571
4576
|
/**
|
|
4572
|
-
* LittleJS - The Tiny JavaScript Game Engine
|
|
4577
|
+
* LittleJS - The Tiny Fast JavaScript Game Engine
|
|
4573
4578
|
* MIT License - Copyright 2021 Frank Force
|
|
4574
4579
|
*
|
|
4575
4580
|
* Engine Features
|
|
@@ -4600,9 +4605,9 @@ const engineName = 'LittleJS';
|
|
|
4600
4605
|
* @type {String}
|
|
4601
4606
|
* @default
|
|
4602
4607
|
* @memberof Engine */
|
|
4603
|
-
const engineVersion = '1.9.
|
|
4608
|
+
const engineVersion = '1.9.3';
|
|
4604
4609
|
|
|
4605
|
-
/** Frames per second to update
|
|
4610
|
+
/** Frames per second to update
|
|
4606
4611
|
* @type {Number}
|
|
4607
4612
|
* @default
|
|
4608
4613
|
* @memberof Engine */
|
|
@@ -4619,7 +4624,7 @@ const timeDelta = 1/frameRate;
|
|
|
4619
4624
|
* @memberof Engine */
|
|
4620
4625
|
let engineObjects = [];
|
|
4621
4626
|
|
|
4622
|
-
/** Array
|
|
4627
|
+
/** Array with only objects set to collide with other objects this frame (for optimization)
|
|
4623
4628
|
* @type {Array}
|
|
4624
4629
|
* @memberof Engine */
|
|
4625
4630
|
let engineObjectsCollide = [];
|
|
@@ -4629,7 +4634,7 @@ let engineObjectsCollide = [];
|
|
|
4629
4634
|
* @memberof Engine */
|
|
4630
4635
|
let frame = 0;
|
|
4631
4636
|
|
|
4632
|
-
/** Current engine time since start in seconds
|
|
4637
|
+
/** Current engine time since start in seconds
|
|
4633
4638
|
* @type {Number}
|
|
4634
4639
|
* @memberof Engine */
|
|
4635
4640
|
let time = 0;
|
|
@@ -4655,12 +4660,12 @@ let frameTimeLastMS = 0, frameTimeBufferMS = 0, averageFPS = 0;
|
|
|
4655
4660
|
|
|
4656
4661
|
///////////////////////////////////////////////////////////////////////////////
|
|
4657
4662
|
|
|
4658
|
-
/**
|
|
4659
|
-
* @param {Function} gameInit
|
|
4660
|
-
* @param {Function} gameUpdate
|
|
4661
|
-
* @param {Function} gameUpdatePost
|
|
4662
|
-
* @param {Function} gameRender
|
|
4663
|
-
* @param {Function} gameRenderPost
|
|
4663
|
+
/** Startup LittleJS engine with your callback functions
|
|
4664
|
+
* @param {Function} gameInit - Called once after the engine starts up, setup the game
|
|
4665
|
+
* @param {Function} gameUpdate - Called every frame at 60 frames per second, handle input and update the game state
|
|
4666
|
+
* @param {Function} gameUpdatePost - Called after physics and objects are updated, setup camera and prepare for render
|
|
4667
|
+
* @param {Function} gameRender - Called before objects are rendered, draw any background effects that appear behind objects
|
|
4668
|
+
* @param {Function} gameRenderPost - Called after objects are rendered, draw effects or hud that appear above all objects
|
|
4664
4669
|
* @param {Array} [imageSources=['tiles.png']] - Image to load
|
|
4665
4670
|
* @memberof Engine */
|
|
4666
4671
|
function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources=['tiles.png'])
|
|
@@ -4683,32 +4688,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4683
4688
|
frameTimeBufferMS += paused ? 0 : frameTimeDeltaMS;
|
|
4684
4689
|
if (!debugSpeedUp)
|
|
4685
4690
|
frameTimeBufferMS = min(frameTimeBufferMS, 50); // clamp incase of slow framerate
|
|
4686
|
-
|
|
4687
|
-
if (canvasFixedSize.x)
|
|
4688
|
-
{
|
|
4689
|
-
// clear canvas and set fixed size
|
|
4690
|
-
mainCanvas.width = canvasFixedSize.x;
|
|
4691
|
-
mainCanvas.height = canvasFixedSize.y;
|
|
4692
|
-
|
|
4693
|
-
// fit to window by adding space on top or bottom if necessary
|
|
4694
|
-
const aspect = innerWidth / innerHeight;
|
|
4695
|
-
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
4696
|
-
(glCanvas||mainCanvas).style.width = mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
4697
|
-
(glCanvas||mainCanvas).style.height = mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
4698
|
-
}
|
|
4699
|
-
else
|
|
4700
|
-
{
|
|
4701
|
-
// clear canvas and set size to same as window
|
|
4702
|
-
mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
4703
|
-
mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
4704
|
-
}
|
|
4705
|
-
|
|
4706
|
-
// clear overlay canvas and set size
|
|
4707
|
-
overlayCanvas.width = mainCanvas.width;
|
|
4708
|
-
overlayCanvas.height = mainCanvas.height;
|
|
4709
|
-
|
|
4710
|
-
// save canvas size
|
|
4711
|
-
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
4691
|
+
updateCanvas();
|
|
4712
4692
|
|
|
4713
4693
|
if (paused)
|
|
4714
4694
|
{
|
|
@@ -4782,6 +4762,35 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4782
4762
|
requestAnimationFrame(engineUpdate);
|
|
4783
4763
|
}
|
|
4784
4764
|
|
|
4765
|
+
function updateCanvas()
|
|
4766
|
+
{
|
|
4767
|
+
if (canvasFixedSize.x)
|
|
4768
|
+
{
|
|
4769
|
+
// clear canvas and set fixed size
|
|
4770
|
+
mainCanvas.width = canvasFixedSize.x;
|
|
4771
|
+
mainCanvas.height = canvasFixedSize.y;
|
|
4772
|
+
|
|
4773
|
+
// fit to window by adding space on top or bottom if necessary
|
|
4774
|
+
const aspect = innerWidth / innerHeight;
|
|
4775
|
+
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
4776
|
+
(glCanvas||mainCanvas).style.width = mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
4777
|
+
(glCanvas||mainCanvas).style.height = mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
4778
|
+
}
|
|
4779
|
+
else
|
|
4780
|
+
{
|
|
4781
|
+
// clear canvas and set size to same as window
|
|
4782
|
+
mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
4783
|
+
mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
4784
|
+
}
|
|
4785
|
+
|
|
4786
|
+
// clear overlay canvas and set size
|
|
4787
|
+
overlayCanvas.width = mainCanvas.width;
|
|
4788
|
+
overlayCanvas.height = mainCanvas.height;
|
|
4789
|
+
|
|
4790
|
+
// save canvas size
|
|
4791
|
+
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
4792
|
+
}
|
|
4793
|
+
|
|
4785
4794
|
// setup html
|
|
4786
4795
|
const styleBody =
|
|
4787
4796
|
'margin:0;overflow:hidden;' + // fill the window
|
|
@@ -4806,6 +4815,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4806
4815
|
const styleCanvas = 'position:absolute;' + // position
|
|
4807
4816
|
'top:50%;left:50%;transform:translate(-50%,-50%)'; // center
|
|
4808
4817
|
(glCanvas||mainCanvas).style.cssText = mainCanvas.style.cssText = overlayCanvas.style.cssText = styleCanvas;
|
|
4818
|
+
updateCanvas();
|
|
4809
4819
|
|
|
4810
4820
|
// create promises for loading images
|
|
4811
4821
|
const promises = imageSources.map((src, textureIndex)=>
|
|
@@ -5002,9 +5012,9 @@ function drawEngineSplashScreen(t)
|
|
|
5002
5012
|
|
|
5003
5013
|
// big stack
|
|
5004
5014
|
rect(50,20,10,-10,color(0,1));
|
|
5005
|
-
rect(50,20,6,-10,color(0,2));
|
|
5006
|
-
rect(50,20,3,-10,color(0,3));
|
|
5007
|
-
rect(50,
|
|
5015
|
+
rect(50,20,6.5,-10,color(0,2));
|
|
5016
|
+
rect(50,20,3.5,-10,color(0,3));
|
|
5017
|
+
rect(50,20,10,-10);
|
|
5008
5018
|
circle(55,2,11.4,.5,PI-.5,color(3,3));
|
|
5009
5019
|
circle(55,2,11.4,.5,PI/2,color(3,2),1);
|
|
5010
5020
|
circle(55,2,11.4,.5,PI-.5);
|
|
@@ -5023,7 +5033,7 @@ function drawEngineSplashScreen(t)
|
|
|
5023
5033
|
|
|
5024
5034
|
// engine outline
|
|
5025
5035
|
circle(36,30,10,PI/2,PI*3/2);
|
|
5026
|
-
circle(
|
|
5036
|
+
circle(48,30,10,PI/2,PI*3/2);
|
|
5027
5037
|
circle(60,30,10);
|
|
5028
5038
|
line(36,20,60,20);
|
|
5029
5039
|
|
package/examples/logo.png
CHANGED
|
Binary file
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="256" height="64" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="1">
|
|
3
3
|
<editorsettings>
|
|
4
|
-
<export target="../
|
|
4
|
+
<export target="../gameLevelData.js" format="js"/>
|
|
5
5
|
</editorsettings>
|
|
6
|
-
<tileset firstgid="1" source="
|
|
6
|
+
<tileset firstgid="1" source="gameLevelData.tsx"/>
|
|
7
7
|
<layer id="2" name="Tile Layer 2" width="256" height="64" tintcolor="#4d7caf">
|
|
8
8
|
<data encoding="csv">
|
|
9
9
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,2,5,2,5,4,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,5,4,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5,2,0,0,0,0,0,0,0,0,0,0,0,4,0,0,2,0,0,0,0,0,2,2,0,0,0,0,5,0,0,5,0,0,5,0,0,0,0,0,2,0,0,0,4,0,0,0,0,0,0,2,2,0,0,0,0,0,0,5,0,0,5,0,0,0,0,0,0,0,0,0,0,5,5,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,5,2,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,0,0,0,0,0,0,0,0,4,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
104
104
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,5,5,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,5,4,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,5,5,0,0,0,0,0,0,0,0,5,5,5,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,4,0,0,0,20,20,20,20,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
105
105
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,5,5,0,0,0,0,0,0,18,0,5,5,0,0,0,0,0,0,5,5,0,0,18,0,0,0,0,0,0,5,4,5,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,5,5,5,0,0,0,0,0,0,5,5,5,5,0,0,5,5,5,0,0,0,0,0,0,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,18,18,0,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,4,0,0,0,20,20,20,20,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
106
|
-
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,0,0,19,0,4,0,0,0,5,5,0,0,0,0,0,18,18,0,5,5,0,0,19,0,0,0,5,5,0,18,18,18,0,19,
|
|
106
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,0,0,19,0,4,0,0,0,5,5,0,0,0,0,0,18,18,0,5,5,0,0,19,0,0,0,5,5,0,18,18,18,0,19,0,0,0,5,4,5,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,4,0,19,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,5,5,5,5,0,19,0,0,5,5,5,5,5,0,0,5,5,5,5,0,0,0,0,0,18,18,0,0,0,0,0,19,0,0,0,19,0,0,0,18,18,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,5,0,0,0,20,20,20,20,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
107
107
|
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,3,2,2,2,3,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,3,2,2,2,2,2,2,2,2,4,2,2,2,2,3,2,2,2,2,2,2,5,5,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
|
108
108
|
2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,3,2,2,3,2,3,2,2,2,4,2,2,2,2,2,2,2,2,3,2,2,5,5,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,3,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,
|
|
109
109
|
2,2,3,2,2,3,2,2,3,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,4,0,0,0,0,0,0,0,0,0,0,0,5,5,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,3,2,2,2,2,3,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,2,2,2,2,2,3,2,2,2,2,2,2,2,0,0,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
|
@@ -11,21 +11,39 @@
|
|
|
11
11
|
// show the LittleJS splash screen
|
|
12
12
|
setShowSplashScreen(true);
|
|
13
13
|
|
|
14
|
-
let score, deaths;
|
|
14
|
+
let spriteAtlas, score, deaths;
|
|
15
15
|
|
|
16
16
|
///////////////////////////////////////////////////////////////////////////////
|
|
17
17
|
function gameInit()
|
|
18
18
|
{
|
|
19
|
+
// create a table of all sprites
|
|
20
|
+
spriteAtlas =
|
|
21
|
+
{
|
|
22
|
+
// large tiles
|
|
23
|
+
circle: tile(0),
|
|
24
|
+
crate: tile(2),
|
|
25
|
+
player: tile(3),
|
|
26
|
+
enemy: tile(5),
|
|
27
|
+
coin: tile(6),
|
|
28
|
+
|
|
29
|
+
// small tiles
|
|
30
|
+
gun: tile(2,8),
|
|
31
|
+
grenade: tile(3,8),
|
|
32
|
+
};
|
|
33
|
+
|
|
19
34
|
// enable touch gamepad on touch devices
|
|
20
35
|
touchGamepadEnable = true;
|
|
21
36
|
|
|
22
|
-
// setup
|
|
37
|
+
// setup level
|
|
38
|
+
buildLevel();
|
|
39
|
+
|
|
40
|
+
// init game
|
|
23
41
|
score = deaths = 0;
|
|
24
42
|
gravity = -.01;
|
|
25
43
|
objectDefaultDamping = .99;
|
|
26
44
|
objectDefaultAngleDamping = .99;
|
|
27
45
|
cameraScale = 4*16;
|
|
28
|
-
|
|
46
|
+
cameraPos = getCameraTarget();
|
|
29
47
|
}
|
|
30
48
|
|
|
31
49
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -60,20 +78,23 @@ function gameUpdate()
|
|
|
60
78
|
}
|
|
61
79
|
|
|
62
80
|
///////////////////////////////////////////////////////////////////////////////
|
|
63
|
-
function
|
|
81
|
+
function getCameraTarget()
|
|
64
82
|
{
|
|
65
|
-
//
|
|
66
|
-
|
|
83
|
+
// camera is above player
|
|
84
|
+
const offset = 3*percent(mainCanvasSize.y, 300, 600);
|
|
85
|
+
return player.pos.add(vec2(0, offset));
|
|
86
|
+
}
|
|
67
87
|
|
|
68
|
-
|
|
69
|
-
|
|
88
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
89
|
+
function gameUpdatePost()
|
|
90
|
+
{
|
|
91
|
+
// update camera
|
|
92
|
+
cameraPos = cameraPos.lerp(getCameraTarget(), clamp(player.getAliveTime()/2));
|
|
70
93
|
}
|
|
71
94
|
|
|
72
95
|
///////////////////////////////////////////////////////////////////////////////
|
|
73
96
|
function gameRender()
|
|
74
97
|
{
|
|
75
|
-
drawSky();
|
|
76
|
-
drawStars();
|
|
77
98
|
}
|
|
78
99
|
|
|
79
100
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -210,15 +210,17 @@ class Character extends GameObject
|
|
|
210
210
|
// update mirror
|
|
211
211
|
if (moveInput.x && !this.dodgeTimer.active())
|
|
212
212
|
this.mirror = moveInput.x < 0;
|
|
213
|
-
|
|
214
|
-
// set tile to use
|
|
215
|
-
const tile = this.isDead() ? 3 :
|
|
216
|
-
this.climbingLadder || this.groundTimer.active() ? 3 + 2*this.walkCyclePercent|0 : 4;
|
|
217
|
-
this.tileInfo.pos.x = tile * 16;
|
|
218
213
|
}
|
|
219
214
|
|
|
220
215
|
render()
|
|
221
216
|
{
|
|
217
|
+
// update animation
|
|
218
|
+
const animationFrame = this.isDead() ? 0 :
|
|
219
|
+
this.climbingLadder || this.groundTimer.active() ?
|
|
220
|
+
2*this.walkCyclePercent|0 : 1;
|
|
221
|
+
const playerTile = spriteAtlas.player;
|
|
222
|
+
this.tileInfo.pos.x = playerTile.pos.x + playerTile.size.x*animationFrame;
|
|
223
|
+
|
|
222
224
|
let bodyPos = this.pos;
|
|
223
225
|
if (!this.isDead())
|
|
224
226
|
{
|
|
@@ -245,7 +247,7 @@ class Character extends GameObject
|
|
|
245
247
|
if (this.isDead())
|
|
246
248
|
return;
|
|
247
249
|
|
|
248
|
-
makeBlood(this.pos,
|
|
250
|
+
makeBlood(this.pos, 100);
|
|
249
251
|
sound_die.play(this.pos);
|
|
250
252
|
|
|
251
253
|
this.health = 0;
|