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.
@@ -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 (also returns 1 if 0)
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 wrappping
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 wrappping
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 = .3;
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 collison calcuations (how heavy objects are)
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 virutal gamepad for touch devices in pixels
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 addtive color applied
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
- if (textureInfo)
1730
- {
1731
- const cols = textureInfo.size.x / size.x |0;
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 zzfx sound for later use and can be played positionally
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 off
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=1] - True if the music should 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 = false)
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} url - Location of sound file to play
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(url, volume=1, loop=false)
2840
+ function playAudioFile(filename, volume=1, loop=false)
2840
2841
  {
2841
2842
  if (!soundEnable) return;
2842
2843
 
2843
- const audio = new Audio(url);
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
- if (audioContext.state != 'running')
2915
+ const audioWasSuspended = audioSuspended;
2916
+ if (audioSuspended = audioContext.state != 'running')
2910
2917
  {
2911
2918
  // fix stalled audio
2912
2919
  audioContext.resume();
2913
- return;
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
- * - Unlimted numbers of layers, allocates canvases as needed
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=(1,1)]
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 = vec2().setAngle(velocityAngle, speed);
3751
- particle.fadeRate = this.fadeRate;
3752
- particle.damping = this.damping;
3753
- particle.angleDamping = this.angleDamping;
3754
- particle.elasticity = this.elasticity;
3755
- particle.friction = this.friction;
3756
- particle.gravityScale = this.gravityScale;
3757
- particle.collideTiles = this.collideTiles;
3758
- particle.renderOrder = this.renderOrder;
3759
- particle.mirror = !!randInt(2);
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, glPostArrayBuffer, glPostTexture, glPostIncludeOverlay;
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 That Can!
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.2';
4608
+ const engineVersion = '1.9.3';
4604
4609
 
4605
- /** Frames per second to update objects
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 containing only objects that are set to collide with other objects this frame (for optimization)
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, derived from frame
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
- /** Start up LittleJS engine with your callback functions
4659
- * @param {Function} gameInit - Called once after the engine starts up, setup the game
4660
- * @param {Function} gameUpdate - Called every frame at 60 frames per second, handle input and update the game state
4661
- * @param {Function} gameUpdatePost - Called after physics and objects are updated, setup camera and prepare for render
4662
- * @param {Function} gameRender - Called before objects are rendered, draw any background effects that appear behind objects
4663
- * @param {Function} gameRenderPost - Called after objects are rendered, draw effects or hud that appear above all objects
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,10,10,10);
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(47,30,10,PI/2,PI*3/2);
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="../gameTileData.js" format="js"/>
4
+ <export target="../gameLevelData.js" format="js"/>
5
5
  </editorsettings>
6
- <tileset firstgid="1" source="gameTileData.tsx"/>
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,19,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,19,0,0,0,0,0,0,0,19,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,
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 game
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
- buildLevel();
46
+ cameraPos = getCameraTarget();
29
47
  }
30
48
 
31
49
  ///////////////////////////////////////////////////////////////////////////////
@@ -60,20 +78,23 @@ function gameUpdate()
60
78
  }
61
79
 
62
80
  ///////////////////////////////////////////////////////////////////////////////
63
- function gameUpdatePost()
81
+ function getCameraTarget()
64
82
  {
65
- // move camera to player
66
- cameraPos = cameraPos.lerp(player.pos, clamp(player.getAliveTime()/2));
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
- // update parallax background relative to camera
69
- updateParallaxLayers();
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, 300);
250
+ makeBlood(this.pos, 100);
249
251
  sound_die.play(this.pos);
250
252
 
251
253
  this.health = 0;