littlejsengine 1.5.2 → 1.6.4
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 +155 -33
- package/{engine/index.d.ts → build/littlejs.d.ts} +14 -6
- package/{engine/engine.all.module.js → build/littlejs.esm.js} +110 -99
- package/build/littlejs.esm.min.js +1 -0
- package/{engine/engine.all.js → build/littlejs.js} +102 -97
- package/build/littlejs.min.js +1 -0
- package/{engine/engine.all.release.js → build/littlejs.release.js} +95 -95
- package/examples/breakout/game.js +5 -0
- package/examples/breakout/gameObjects.js +41 -48
- package/examples/breakout/index.html +5 -4
- package/examples/breakoutTutorial/README.md +514 -0
- package/examples/breakoutTutorial/game.js +181 -0
- package/examples/breakoutTutorial/images/1.png +0 -0
- package/examples/breakoutTutorial/images/10.png +0 -0
- package/examples/breakoutTutorial/images/11.png +0 -0
- package/examples/breakoutTutorial/images/2.png +0 -0
- package/examples/breakoutTutorial/images/3.png +0 -0
- package/examples/breakoutTutorial/images/4.png +0 -0
- package/examples/breakoutTutorial/images/5.png +0 -0
- package/examples/breakoutTutorial/images/6.png +0 -0
- package/examples/breakoutTutorial/images/7.png +0 -0
- package/examples/breakoutTutorial/images/8.png +0 -0
- package/examples/breakoutTutorial/images/9.png +0 -0
- package/examples/breakoutTutorial/index.html +10 -0
- package/examples/electron/build.bat +52 -0
- package/{electron → examples/electron}/electron.js +18 -21
- package/{game.js → examples/electron/game.js} +1 -1
- package/examples/electron/index.html +2 -0
- package/examples/electron/package.json +20 -0
- package/examples/empty/game.js +11 -1
- package/examples/empty/index.html +2 -2
- package/examples/module/game.js +1 -1
- package/examples/module/index.html +3 -2
- package/examples/particles/index.html +3 -2
- package/examples/platformer/gameLevel.js +1 -1
- package/examples/platformer/gamePlayer.js +1 -1
- package/examples/platformer/index.html +8 -7
- package/examples/puzzle/index.html +4 -3
- package/{build.bat → examples/starter/build.bat} +17 -17
- package/examples/starter/game.js +111 -0
- package/examples/starter/index.html +27 -0
- package/examples/starter/tiles.png +0 -0
- package/examples/stress/index.html +3 -2
- package/examples/typescript/game.js +89 -89
- package/examples/typescript/game.ts +11 -11
- package/examples/typescript/index.html +3 -2
- package/package.json +4 -4
- package/{engine → src}/engine.js +1 -2
- package/{engine → src}/engineAudio.js +11 -11
- package/src/engineBuild.bat +132 -0
- package/{engine → src}/engineDebug.js +8 -2
- package/{engine → src}/engineDraw.js +19 -15
- package/{engine → src}/engineExport.js +8 -2
- package/{engine → src}/engineInput.js +54 -58
- package/{engine → src}/engineMedals.js +1 -1
- package/{engine → src}/engineObject.js +4 -4
- package/{engine → src}/engineRelease.js +1 -0
- package/{engine → src}/engineUtilities.js +4 -4
- package/electron/electronBuild.bat +0 -32
- package/electron/electronSetup.bat +0 -2
- package/electron/package.json +0 -21
- package/engine/engine.all.min.js +0 -1
- package/engine/engine.all.module.min.js +0 -1
- package/engine/engineBuild.bat +0 -127
- package/index.html +0 -26
- /package/{tiles.png → examples/electron/tiles.png} +0 -0
- /package/{favicon.png → examples/favicon.png} +0 -0
- /package/{engine → src}/engineFont.png +0 -0
- /package/{engine → src}/engineParticles.js +0 -0
- /package/{engine → src}/engineSettings.js +0 -0
- /package/{engine → src}/engineTileLayer.js +0 -0
- /package/{engine → src}/engineWebGL.js +0 -0
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
let showWatermark = 0;
|
|
12
12
|
let godMode = 0;
|
|
13
|
+
let debugKeyCode = 0;
|
|
13
14
|
const debug = 0;
|
|
14
15
|
const debugOverlay = 0;
|
|
15
16
|
const debugPhysics = 0;
|
|
@@ -381,7 +382,7 @@ class Vector2
|
|
|
381
382
|
* @return {Color}
|
|
382
383
|
* @memberof Utilities
|
|
383
384
|
*/
|
|
384
|
-
const
|
|
385
|
+
const rgb = (r, g, b, a)=> new Color(r, g, b, a);
|
|
385
386
|
|
|
386
387
|
/**
|
|
387
388
|
* Create a color object with HSLA values
|
|
@@ -392,7 +393,7 @@ const colorRGBA = (r, g, b, a)=> new Color(r, g, b, a);
|
|
|
392
393
|
* @return {Color}
|
|
393
394
|
* @memberof Utilities
|
|
394
395
|
*/
|
|
395
|
-
const
|
|
396
|
+
const hsl = (h, s, l, a)=> new Color().setHSLA(h, s, l, a);
|
|
396
397
|
|
|
397
398
|
/**
|
|
398
399
|
* Color object (red, green, blue, alpha) with some helpful functions
|
|
@@ -400,8 +401,8 @@ const colorHSLA = (h, s, l, a)=> new Color().setHSLA(h, s, l, a);
|
|
|
400
401
|
* let a = new Color; // white
|
|
401
402
|
* let b = new Color(1, 0, 0); // red
|
|
402
403
|
* let c = new Color(0, 0, 0, 0); // transparent black
|
|
403
|
-
* let d =
|
|
404
|
-
* let e =
|
|
404
|
+
* let d = RGB(0, 0, 1); // blue using rgb color
|
|
405
|
+
* let e = HSL(.3, 1, .5); // green using hsl color
|
|
405
406
|
*/
|
|
406
407
|
class Color
|
|
407
408
|
{
|
|
@@ -898,7 +899,7 @@ const engineName = 'LittleJS';
|
|
|
898
899
|
* @type {String}
|
|
899
900
|
* @default
|
|
900
901
|
* @memberof Engine */
|
|
901
|
-
const engineVersion = '1.
|
|
902
|
+
const engineVersion = '1.6.4';
|
|
902
903
|
|
|
903
904
|
/** Frames per second to update objects
|
|
904
905
|
* @type {Number}
|
|
@@ -989,7 +990,6 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
989
990
|
(glCanvas||mainCanvas).style = mainCanvas.style = overlayCanvas.style = styleCanvas;
|
|
990
991
|
|
|
991
992
|
gameInit();
|
|
992
|
-
touchGamepadCreate();
|
|
993
993
|
engineUpdate();
|
|
994
994
|
};
|
|
995
995
|
|
|
@@ -1300,6 +1300,7 @@ class EngineObject
|
|
|
1300
1300
|
this.velocity.y += gravity * this.gravityScale;
|
|
1301
1301
|
this.pos.x += this.velocity.x *= this.damping;
|
|
1302
1302
|
this.pos.y += this.velocity.y *= this.damping;
|
|
1303
|
+
this.angle += this.angleVelocity *= this.angleDamping;
|
|
1303
1304
|
|
|
1304
1305
|
// physics sanity checks
|
|
1305
1306
|
ASSERT(this.angleDamping >= 0 && this.angleDamping <= 1);
|
|
@@ -1356,6 +1357,7 @@ class EngineObject
|
|
|
1356
1357
|
const smallStepUp = (oldPos.y - o.pos.y)*2 > sizeBoth.y + gravity; // prefer to push up if small delta
|
|
1357
1358
|
const isBlockedX = abs(oldPos.y - o.pos.y)*2 < sizeBoth.y;
|
|
1358
1359
|
const isBlockedY = abs(oldPos.x - o.pos.x)*2 < sizeBoth.x;
|
|
1360
|
+
const elasticity = max(this.elasticity, o.elasticity);
|
|
1359
1361
|
|
|
1360
1362
|
if (smallStepUp | isBlockedY | !isBlockedX) // resolve y collision
|
|
1361
1363
|
{
|
|
@@ -1368,7 +1370,7 @@ class EngineObject
|
|
|
1368
1370
|
this.groundObject = o;
|
|
1369
1371
|
|
|
1370
1372
|
// bounce if other object is fixed or grounded
|
|
1371
|
-
this.velocity.y *= -
|
|
1373
|
+
this.velocity.y *= -elasticity;
|
|
1372
1374
|
}
|
|
1373
1375
|
else if (o.mass)
|
|
1374
1376
|
{
|
|
@@ -1382,7 +1384,6 @@ class EngineObject
|
|
|
1382
1384
|
+ this.velocity.y * 2 * this.mass / (this.mass + o.mass);
|
|
1383
1385
|
|
|
1384
1386
|
// lerp betwen elastic or inelastic based on elasticity
|
|
1385
|
-
const elasticity = max(this.elasticity, o.elasticity);
|
|
1386
1387
|
this.velocity.y = lerp(elasticity, inelastic, elastic0);
|
|
1387
1388
|
o.velocity.y = lerp(elasticity, inelastic, elastic1);
|
|
1388
1389
|
}
|
|
@@ -1403,12 +1404,11 @@ class EngineObject
|
|
|
1403
1404
|
+ this.velocity.x * 2 * this.mass / (this.mass + o.mass);
|
|
1404
1405
|
|
|
1405
1406
|
// lerp betwen elastic or inelastic based on elasticity
|
|
1406
|
-
const elasticity = max(this.elasticity, o.elasticity);
|
|
1407
1407
|
this.velocity.x = lerp(elasticity, inelastic, elastic0);
|
|
1408
1408
|
o.velocity.x = lerp(elasticity, inelastic, elastic1);
|
|
1409
1409
|
}
|
|
1410
1410
|
else // bounce if other object is fixed
|
|
1411
|
-
this.velocity.x *= -
|
|
1411
|
+
this.velocity.x *= -elasticity;
|
|
1412
1412
|
}
|
|
1413
1413
|
debugOverlay && debugPhysics && debugAABB(this.pos, this.size, o.pos, o.size, '#f0f');
|
|
1414
1414
|
}
|
|
@@ -1790,6 +1790,23 @@ function setBlendMode(additive, useWebGL=glEnable)
|
|
|
1790
1790
|
mainContext.globalCompositeOperation = additive ? 'lighter' : 'source-over';
|
|
1791
1791
|
}
|
|
1792
1792
|
|
|
1793
|
+
/** Draw text on overlay canvas in world space
|
|
1794
|
+
* Automatically splits new lines into rows
|
|
1795
|
+
* @param {String} text
|
|
1796
|
+
* @param {Vector2} pos
|
|
1797
|
+
* @param {Number} [size=1]
|
|
1798
|
+
* @param {Color} [color=Color()]
|
|
1799
|
+
* @param {Number} [lineWidth=0]
|
|
1800
|
+
* @param {Color} [lineColor=Color(0,0,0)]
|
|
1801
|
+
* @param {String} [textAlign='center']
|
|
1802
|
+
* @param {String} [font=fontDefault]
|
|
1803
|
+
* @param {CanvasRenderingContext2D} [context=overlayContext]
|
|
1804
|
+
* @memberof Draw */
|
|
1805
|
+
function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, font, context)
|
|
1806
|
+
{
|
|
1807
|
+
drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth*cameraScale, lineColor, textAlign, font, context);
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1793
1810
|
/** Draw text on overlay canvas in screen space
|
|
1794
1811
|
* Automatically splits new lines into rows
|
|
1795
1812
|
* @param {String} text
|
|
@@ -1799,6 +1816,8 @@ function setBlendMode(additive, useWebGL=glEnable)
|
|
|
1799
1816
|
* @param {Number} [lineWidth=0]
|
|
1800
1817
|
* @param {Color} [lineColor=Color(0,0,0)]
|
|
1801
1818
|
* @param {String} [textAlign='center']
|
|
1819
|
+
* @param {String} [font=fontDefault]
|
|
1820
|
+
* @param {CanvasRenderingContext2D} [context=overlayContext]
|
|
1802
1821
|
* @memberof Draw */
|
|
1803
1822
|
function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), textAlign='center', font=fontDefault, context=overlayContext)
|
|
1804
1823
|
{
|
|
@@ -1819,21 +1838,6 @@ function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineCol
|
|
|
1819
1838
|
});
|
|
1820
1839
|
}
|
|
1821
1840
|
|
|
1822
|
-
/** Draw text on overlay canvas in world space
|
|
1823
|
-
* Automatically splits new lines into rows
|
|
1824
|
-
* @param {String} text
|
|
1825
|
-
* @param {Vector2} pos
|
|
1826
|
-
* @param {Number} [size=1]
|
|
1827
|
-
* @param {Color} [color=Color()]
|
|
1828
|
-
* @param {Number} [lineWidth=0]
|
|
1829
|
-
* @param {Color} [lineColor=Color(0,0,0)]
|
|
1830
|
-
* @param {String} [textAlign='center']
|
|
1831
|
-
* @memberof Draw */
|
|
1832
|
-
function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, font)
|
|
1833
|
-
{
|
|
1834
|
-
drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth*cameraScale, lineColor, textAlign, font, mainContext);
|
|
1835
|
-
}
|
|
1836
|
-
|
|
1837
1841
|
///////////////////////////////////////////////////////////////////////////////
|
|
1838
1842
|
|
|
1839
1843
|
let engineFontImage;
|
|
@@ -2087,15 +2091,15 @@ function inputUpdatePost()
|
|
|
2087
2091
|
onkeydown = (e)=>
|
|
2088
2092
|
{
|
|
2089
2093
|
if (debug && e.target != document.body) return;
|
|
2090
|
-
e.repeat || (inputData[isUsingGamepad = 0][
|
|
2094
|
+
e.repeat || (inputData[isUsingGamepad = 0][remapKey(e.which)] = 3);
|
|
2091
2095
|
preventDefaultInput && e.preventDefault();
|
|
2092
2096
|
}
|
|
2093
2097
|
onkeyup = (e)=>
|
|
2094
2098
|
{
|
|
2095
2099
|
if (debug && e.target != document.body) return;
|
|
2096
|
-
inputData[0][
|
|
2100
|
+
inputData[0][remapKey(e.which)] = 4;
|
|
2097
2101
|
}
|
|
2098
|
-
const
|
|
2102
|
+
const remapKey = (c)=> inputWASDEmulateDirection ? c==87?38 : c==83?40 : c==65?37 : c==68?39 : c : c;
|
|
2099
2103
|
|
|
2100
2104
|
///////////////////////////////////////////////////////////////////////////////
|
|
2101
2105
|
// Mouse event handlers
|
|
@@ -2237,6 +2241,9 @@ if (isTouchDevice)
|
|
|
2237
2241
|
return true;
|
|
2238
2242
|
}
|
|
2239
2243
|
|
|
2244
|
+
// try to create touch game pad
|
|
2245
|
+
touchGamepadEnable && touchGamepadCreate();
|
|
2246
|
+
|
|
2240
2247
|
return ontouchstart(e);
|
|
2241
2248
|
}
|
|
2242
2249
|
}
|
|
@@ -2250,76 +2257,69 @@ let touchGamepadTimer = new Timer, touchGamepadButtons, touchGamepadStick;
|
|
|
2250
2257
|
// create the touch gamepad, called automatically by the engine
|
|
2251
2258
|
function touchGamepadCreate()
|
|
2252
2259
|
{
|
|
2253
|
-
if (!touchGamepadEnable || !isTouchDevice)
|
|
2254
|
-
return;
|
|
2255
|
-
|
|
2256
2260
|
// touch input internal variables
|
|
2257
2261
|
touchGamepadButtons = [];
|
|
2258
2262
|
touchGamepadStick = vec2();
|
|
2259
2263
|
|
|
2260
|
-
|
|
2261
|
-
ontouchstart = (e)=>
|
|
2264
|
+
let touchHandler = ontouchstart;
|
|
2265
|
+
ontouchstart = ontouchmove = ontouchend = (e)=>
|
|
2262
2266
|
{
|
|
2263
|
-
//
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
+
// clear touch gamepad input
|
|
2268
|
+
touchGamepadStick = vec2();
|
|
2269
|
+
touchGamepadButtons = [];
|
|
2270
|
+
|
|
2271
|
+
const touching = e.touches.length;
|
|
2272
|
+
if (touching)
|
|
2267
2273
|
{
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
touchGamepadButtons = [];
|
|
2271
|
-
|
|
2272
|
-
const touching = e.touches.length;
|
|
2273
|
-
if (touching)
|
|
2274
|
+
touchGamepadTimer.set();
|
|
2275
|
+
if (paused)
|
|
2274
2276
|
{
|
|
2275
|
-
//
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
if (paused)
|
|
2280
|
-
{
|
|
2281
|
-
// touch anywhere to press start when paused
|
|
2282
|
-
touchGamepadButtons[9] = 1;
|
|
2283
|
-
return;
|
|
2284
|
-
}
|
|
2277
|
+
// touch anywhere to press start when paused
|
|
2278
|
+
touchGamepadButtons[9] = 1;
|
|
2279
|
+
return;
|
|
2285
2280
|
}
|
|
2281
|
+
}
|
|
2286
2282
|
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2283
|
+
// get center of left and right sides
|
|
2284
|
+
const stickCenter = vec2(touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
|
|
2285
|
+
const buttonCenter = mainCanvasSize.subtract(vec2(touchGamepadSize, touchGamepadSize));
|
|
2286
|
+
const startCenter = mainCanvasSize.scale(.5);
|
|
2291
2287
|
|
|
2292
|
-
|
|
2293
|
-
|
|
2288
|
+
// check each touch point
|
|
2289
|
+
for (const touch of e.touches)
|
|
2290
|
+
{
|
|
2291
|
+
const touchPos = mouseToScreen(vec2(touch.clientX, touch.clientY));
|
|
2292
|
+
if (touchPos.distance(stickCenter) < touchGamepadSize)
|
|
2294
2293
|
{
|
|
2295
|
-
|
|
2296
|
-
if (
|
|
2294
|
+
// virtual analog stick
|
|
2295
|
+
if (touchGamepadAnalog)
|
|
2296
|
+
touchGamepadStick = touchPos.subtract(stickCenter).scale(2/touchGamepadSize).clampLength();
|
|
2297
|
+
else
|
|
2297
2298
|
{
|
|
2298
|
-
//
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
else
|
|
2302
|
-
{
|
|
2303
|
-
// 8 way dpad
|
|
2304
|
-
const angle = touchPos.subtract(stickCenter).angle();
|
|
2305
|
-
touchGamepadStick.setAngle((angle * 4 / PI + 8.5 | 0) * PI / 4);
|
|
2306
|
-
}
|
|
2307
|
-
}
|
|
2308
|
-
else if (touchPos.distance(buttonCenter) < touchGamepadSize)
|
|
2309
|
-
{
|
|
2310
|
-
// virtual face buttons
|
|
2311
|
-
const button = touchPos.subtract(buttonCenter).direction();
|
|
2312
|
-
touchGamepadButtons[button] = 1;
|
|
2313
|
-
}
|
|
2314
|
-
else if (touchPos.distance(startCenter) < touchGamepadSize)
|
|
2315
|
-
{
|
|
2316
|
-
// virtual start button in center
|
|
2317
|
-
touchGamepadButtons[9] = 1;
|
|
2299
|
+
// 8 way dpad
|
|
2300
|
+
const angle = touchPos.subtract(stickCenter).angle();
|
|
2301
|
+
touchGamepadStick.setAngle((angle * 4 / PI + 8.5 | 0) * PI / 4);
|
|
2318
2302
|
}
|
|
2319
2303
|
}
|
|
2304
|
+
else if (touchPos.distance(buttonCenter) < touchGamepadSize)
|
|
2305
|
+
{
|
|
2306
|
+
// virtual face buttons
|
|
2307
|
+
const button = touchPos.subtract(buttonCenter).direction();
|
|
2308
|
+
touchGamepadButtons[button] = 1;
|
|
2309
|
+
}
|
|
2310
|
+
else if (touchPos.distance(startCenter) < touchGamepadSize)
|
|
2311
|
+
{
|
|
2312
|
+
// virtual start button in center
|
|
2313
|
+
touchGamepadButtons[9] = 1;
|
|
2314
|
+
}
|
|
2320
2315
|
}
|
|
2321
2316
|
|
|
2322
|
-
|
|
2317
|
+
// call default touch handler and set to using gamepad
|
|
2318
|
+
touchHandler(e);
|
|
2319
|
+
isUsingGamepad = 1;
|
|
2320
|
+
|
|
2321
|
+
// must return true so the document will get focus
|
|
2322
|
+
return true;
|
|
2323
2323
|
}
|
|
2324
2324
|
}
|
|
2325
2325
|
|
|
@@ -2345,7 +2345,7 @@ function touchGamepadRender()
|
|
|
2345
2345
|
overlayContext.beginPath();
|
|
2346
2346
|
|
|
2347
2347
|
const leftCenter = vec2(touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
|
|
2348
|
-
if (touchGamepadAnalog)
|
|
2348
|
+
if (touchGamepadAnalog) // draw circle shaped gamepad
|
|
2349
2349
|
{
|
|
2350
2350
|
overlayContext.arc(leftCenter.x, leftCenter.y, touchGamepadSize/2, 0, 9);
|
|
2351
2351
|
overlayContext.fill();
|
|
@@ -2650,7 +2650,7 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=0)
|
|
|
2650
2650
|
}
|
|
2651
2651
|
|
|
2652
2652
|
///////////////////////////////////////////////////////////////////////////////
|
|
2653
|
-
// ZzFXMicro - Zuper Zmall Zound Zynth - v1.
|
|
2653
|
+
// ZzFXMicro - Zuper Zmall Zound Zynth - v1.2.0 by Frank Force
|
|
2654
2654
|
|
|
2655
2655
|
/** Generate and play a ZzFX sound
|
|
2656
2656
|
* <br>
|
|
@@ -2676,11 +2676,11 @@ function zzfxG
|
|
|
2676
2676
|
bitCrush = 0, delay = 0, sustainVolume = 1, decay = 0, tremolo = 0
|
|
2677
2677
|
)
|
|
2678
2678
|
{
|
|
2679
|
-
//
|
|
2679
|
+
// locals
|
|
2680
2680
|
let PI2 = PI*2, startSlide = slide *= 500 * PI2 / zzfxR / zzfxR, b=[],
|
|
2681
2681
|
startFrequency = frequency *= (1 + randomness*rand(-1,1)) * PI2 / zzfxR,
|
|
2682
|
-
t=0, tm=0, i=0, j=1, r=0, c=0, s=0, f, length
|
|
2683
|
-
|
|
2682
|
+
t=0, tm=0, i=0, j=1, r=0, c=0, s=0, f, length
|
|
2683
|
+
|
|
2684
2684
|
// scale by sample rate
|
|
2685
2685
|
attack = attack * zzfxR + 9; // minimum attack to prevent pop
|
|
2686
2686
|
decay *= zzfxR;
|
|
@@ -2730,18 +2730,18 @@ function zzfxG
|
|
|
2730
2730
|
Math.cos(modulation*tm++); // modulation
|
|
2731
2731
|
t += f - f*noise*(1 - (Math.sin(i)+1)*1e9%2); // noise
|
|
2732
2732
|
|
|
2733
|
-
if (j && ++j > pitchJumpTime)
|
|
2733
|
+
if (j && ++j > pitchJumpTime) // pitch jump
|
|
2734
2734
|
{
|
|
2735
|
-
frequency += pitchJump;
|
|
2736
|
-
startFrequency += pitchJump;
|
|
2737
|
-
j = 0;
|
|
2735
|
+
frequency += pitchJump; // apply pitch jump
|
|
2736
|
+
startFrequency += pitchJump; // also apply to start
|
|
2737
|
+
j = 0; // reset pitch jump time
|
|
2738
2738
|
}
|
|
2739
2739
|
|
|
2740
2740
|
if (repeatTime && !(++r % repeatTime)) // repeat
|
|
2741
2741
|
{
|
|
2742
|
-
frequency = startFrequency;
|
|
2743
|
-
slide = startSlide;
|
|
2744
|
-
j
|
|
2742
|
+
frequency = startFrequency; // reset frequency
|
|
2743
|
+
slide = startSlide; // reset slide
|
|
2744
|
+
j ||= 1; // reset pitch jump time
|
|
2745
2745
|
}
|
|
2746
2746
|
}
|
|
2747
2747
|
|
|
@@ -3509,7 +3509,7 @@ class Particle extends EngineObject
|
|
|
3509
3509
|
* LittleJS Medal System
|
|
3510
3510
|
* <br> - Tracks and displays medals
|
|
3511
3511
|
* <br> - Saves medals to local storage
|
|
3512
|
-
* <br> - Newgrounds
|
|
3512
|
+
* <br> - Newgrounds integration
|
|
3513
3513
|
* @namespace Medals
|
|
3514
3514
|
*/
|
|
3515
3515
|
|
|
@@ -26,6 +26,11 @@ function gameInit()
|
|
|
26
26
|
for (pos.y = 12; pos.y <= levelSize.y-2; pos.y += 1)
|
|
27
27
|
new Brick(pos);
|
|
28
28
|
|
|
29
|
+
// create walls
|
|
30
|
+
new Wall(vec2(-.5,levelSize.y/2), vec2(1,100)) // top
|
|
31
|
+
new Wall(vec2(levelSize.x+.5,levelSize.y/2), vec2(1,100)) // left
|
|
32
|
+
new Wall(vec2(levelSize.x/2,levelSize.y+.5), vec2(100,1)) // right
|
|
33
|
+
|
|
29
34
|
initPostProcess(); // set up a post processing shader
|
|
30
35
|
}
|
|
31
36
|
|
|
@@ -5,31 +5,36 @@
|
|
|
5
5
|
'use strict';
|
|
6
6
|
|
|
7
7
|
///////////////////////////////////////////////////////////////////////////////
|
|
8
|
-
class
|
|
8
|
+
class Wall extends EngineObject
|
|
9
|
+
{
|
|
10
|
+
constructor(pos, size)
|
|
11
|
+
{
|
|
12
|
+
super(pos, size);
|
|
13
|
+
|
|
14
|
+
this.mass = 0; // make object have static physics
|
|
15
|
+
this.setCollision(); // make object collide
|
|
16
|
+
this.color = new Color(0,0,0,0); // make object invisible
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
21
|
+
class Paddle extends EngineObject
|
|
9
22
|
{
|
|
10
23
|
constructor(pos)
|
|
11
24
|
{
|
|
12
25
|
super(pos, vec2(5,.5));
|
|
13
|
-
|
|
14
|
-
//
|
|
15
|
-
this.setCollision();
|
|
16
|
-
this.mass = 0;
|
|
26
|
+
|
|
27
|
+
this.mass = 0; // make object have static physics
|
|
28
|
+
this.setCollision(); // make object collide
|
|
17
29
|
}
|
|
18
30
|
|
|
19
31
|
update()
|
|
20
32
|
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
else
|
|
27
|
-
{
|
|
28
|
-
// move to mouse
|
|
29
|
-
this.pos.x = mousePos.x;
|
|
30
|
-
}
|
|
33
|
+
// control with gamepad or mouse
|
|
34
|
+
this.pos.x = isUsingGamepad ? this.pos.x + gamepadStick(0).x : mousePos.x;
|
|
35
|
+
|
|
36
|
+
// keep paddle in bounds of level
|
|
31
37
|
this.pos.x = clamp(this.pos.x, this.size.x/2, levelSize.x - this.size.x/2);
|
|
32
|
-
super.update();
|
|
33
38
|
}
|
|
34
39
|
}
|
|
35
40
|
|
|
@@ -39,11 +44,10 @@ class Brick extends EngineObject
|
|
|
39
44
|
constructor(pos)
|
|
40
45
|
{
|
|
41
46
|
super(pos, vec2(2,1), 1, vec2(32,16), 0, randColor());
|
|
42
|
-
|
|
43
|
-
// set to collide
|
|
44
|
-
this.setCollision();
|
|
45
|
-
this.mass = 0;
|
|
46
47
|
++brickCount;
|
|
48
|
+
|
|
49
|
+
this.mass = 0; // make object have static physics
|
|
50
|
+
this.setCollision(); // make object collide
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
collideWithObject(o)
|
|
@@ -54,6 +58,7 @@ class Brick extends EngineObject
|
|
|
54
58
|
--brickCount;
|
|
55
59
|
sound_break.play(this.pos);
|
|
56
60
|
|
|
61
|
+
// make explosion effect
|
|
57
62
|
const color1 = this.color;
|
|
58
63
|
const color2 = color1.lerp(new Color, .5);
|
|
59
64
|
new ParticleEmitter(
|
|
@@ -62,7 +67,7 @@ class Brick extends EngineObject
|
|
|
62
67
|
0, vec2(16), // tileIndex, tileSize
|
|
63
68
|
color1, color2, // colorStartA, colorStartB
|
|
64
69
|
color1.scale(1,0), color2.scale(1,0), // colorEndA, colorEndB
|
|
65
|
-
.
|
|
70
|
+
.1, .3, 1, .05, .05,// time, sizeStart, sizeEnd, speed, angleSpeed
|
|
66
71
|
.99, .95, .4, PI, // damping, angleDamping, gravityScale, cone
|
|
67
72
|
.1, .5, 0, 1 // fadeRate, randomness, collide, additive
|
|
68
73
|
);
|
|
@@ -82,55 +87,43 @@ class Ball extends EngineObject
|
|
|
82
87
|
this.setCollision();
|
|
83
88
|
this.velocity = vec2(randSign(), -1).scale(.1);
|
|
84
89
|
this.elasticity = 1;
|
|
85
|
-
this.damping = 1;
|
|
86
90
|
}
|
|
87
91
|
|
|
88
92
|
update()
|
|
89
93
|
{
|
|
90
|
-
if (this.pos.y <
|
|
94
|
+
if (this.pos.y < -1)
|
|
91
95
|
{
|
|
92
96
|
// destroy ball if it goes below the level
|
|
93
97
|
ball = 0;
|
|
94
98
|
this.destroy();
|
|
95
99
|
}
|
|
96
100
|
|
|
97
|
-
// bounce on sides and top
|
|
98
|
-
const nextPos = this.pos.x + this.velocity.x;
|
|
99
|
-
if (nextPos - this.size.x/2 < 0 || nextPos + this.size.x/2 > levelSize.x)
|
|
100
|
-
{
|
|
101
|
-
this.velocity.x *= -1;
|
|
102
|
-
this.bounce();
|
|
103
|
-
}
|
|
104
|
-
if (this.pos.y + this.velocity.y > levelSize.y)
|
|
105
|
-
{
|
|
106
|
-
this.velocity.y *= -1;
|
|
107
|
-
this.bounce();
|
|
108
|
-
}
|
|
109
|
-
|
|
110
101
|
// update physics
|
|
111
102
|
super.update();
|
|
112
103
|
}
|
|
113
104
|
|
|
114
105
|
collideWithObject(o)
|
|
115
106
|
{
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// put english on the ball when it collides with paddle
|
|
119
|
-
this.velocity = this.velocity.rotate(.2 * (this.pos.x - o.pos.x));
|
|
120
|
-
this.velocity.y = max(-this.velocity.y, .2);
|
|
121
|
-
this.bounce();
|
|
107
|
+
// prevent colliding with paddle if moving upwards
|
|
108
|
+
if (o == paddle && this.velocity.y > 0)
|
|
122
109
|
return 0;
|
|
123
|
-
}
|
|
124
|
-
return 1;
|
|
125
|
-
}
|
|
126
110
|
|
|
127
|
-
bounce()
|
|
128
|
-
{
|
|
129
111
|
// speed up
|
|
130
|
-
const speed = min(1.
|
|
112
|
+
const speed = min(1.04*this.velocity.length(), .5);
|
|
131
113
|
this.velocity = this.velocity.normalize(speed);
|
|
132
114
|
|
|
133
115
|
// scale bounce sound pitch by speed
|
|
134
116
|
sound_bounce.play(this.pos, 1, speed);
|
|
117
|
+
|
|
118
|
+
if (o == paddle)
|
|
119
|
+
{
|
|
120
|
+
// put english on the ball when it collides with paddle
|
|
121
|
+
this.velocity = this.velocity.rotate(.2 * (this.pos.x - o.pos.x));
|
|
122
|
+
this.velocity.y = max(-this.velocity.y, .2);
|
|
123
|
+
return 0;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// prevent default collision with paddle
|
|
127
|
+
return 1;
|
|
135
128
|
}
|
|
136
129
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<html><head>
|
|
2
|
+
<title>Little JS Breakout Game Demo</title>
|
|
2
3
|
<meta name=viewport content=width=device-width,height=device-height,initial-scale=1,maximum-scale=1>
|
|
3
4
|
<meta name=apple-mobile-web-app-capable content=yes>
|
|
4
5
|
<meta name=mobile-web-app-capable content=yes>
|
|
5
|
-
<link rel=icon type=image/png href
|
|
6
|
+
<link rel=icon type=image/png href=../favicon.png>
|
|
6
7
|
</head><body>
|
|
7
8
|
|
|
8
|
-
<script src=../../
|
|
9
|
-
<script src=gameObjects.js?
|
|
10
|
-
<script src=game.js?
|
|
9
|
+
<script src=../../build/littlejs.js?126></script>
|
|
10
|
+
<script src=gameObjects.js?126></script>
|
|
11
|
+
<script src=game.js?126></script>
|