littlejsengine 1.2.0 → 1.2.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 -8
- package/engine/engine.all.js +82 -79
- package/engine/engine.all.min.js +1 -1
- package/engine/engine.all.release.js +81 -78
- package/engine/engine.js +8 -31
- package/engine/engineDebug.js +1 -1
- package/engine/engineDraw.js +8 -5
- package/engine/engineFont.png +0 -0
- package/engine/engineInput.js +22 -6
- package/engine/engineMedals.js +3 -3
- package/engine/engineParticles.js +5 -3
- package/engine/engineSettings.js +5 -0
- package/engine/engineWebGL.js +30 -30
- package/engine/index.d.ts +14 -9
- package/examples/breakout/gameObjects.js +2 -2
- package/examples/breakout/index.html +3 -3
- package/examples/platformer/game.js +4 -4
- package/examples/platformer/gameEffects.js +3 -3
- package/examples/platformer/gameObjects.js +2 -2
- package/examples/platformer/index.html +6 -6
- package/examples/puzzle/game.js +1 -1
- package/examples/puzzle/index.html +2 -2
- package/examples/screenshot.jpg +0 -0
- package/examples/stress/index.html +2 -2
- package/game.js +4 -4
- package/index.html +13 -13
- package/package.json +1 -1
|
@@ -659,6 +659,11 @@ let inputWASDEmulateDirection = 1;
|
|
|
659
659
|
* @memberof Settings */
|
|
660
660
|
let touchGamepadEnable = 0;
|
|
661
661
|
|
|
662
|
+
/** True if touch gamepad should be analog stick or false to use if 8 way dpad
|
|
663
|
+
* @default
|
|
664
|
+
* @memberof Settings */
|
|
665
|
+
let touchGamepadAnalog = 1;
|
|
666
|
+
|
|
662
667
|
/** Size of virutal gamepad for touch devices in pixels
|
|
663
668
|
* @default
|
|
664
669
|
* @memberof Settings */
|
|
@@ -748,7 +753,7 @@ let medalDisplayIconSize = 50;
|
|
|
748
753
|
const engineName = 'LittleJS';
|
|
749
754
|
|
|
750
755
|
/** Version of engine */
|
|
751
|
-
const engineVersion = '1.2.
|
|
756
|
+
const engineVersion = '1.2.3';
|
|
752
757
|
|
|
753
758
|
/** Frames per second to update objects
|
|
754
759
|
* @default */
|
|
@@ -785,7 +790,7 @@ let averageFPS, drawCount;
|
|
|
785
790
|
// css text used for elements created by engine
|
|
786
791
|
const styleBody = 'margin:0;overflow:hidden;background:#000' +
|
|
787
792
|
';touch-action:none;user-select:none;-webkit-user-select:none;-moz-user-select:none';
|
|
788
|
-
const styleCanvas = 'position:absolute';
|
|
793
|
+
const styleCanvas = 'position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)';
|
|
789
794
|
|
|
790
795
|
///////////////////////////////////////////////////////////////////////////////
|
|
791
796
|
|
|
@@ -886,24 +891,13 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
886
891
|
|
|
887
892
|
// fit to window by adding space on top or bottom if necessary
|
|
888
893
|
const aspect = innerWidth / innerHeight;
|
|
889
|
-
const fixedAspect =
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
mainCanvas.style.height = overlayCanvas.style.height =
|
|
894
|
-
mainCanvas.style.top = overlayCanvas.style.top =
|
|
895
|
-
mainCanvas.style.left = overlayCanvas.style.left = '';
|
|
896
|
-
|
|
897
|
-
// letterbox center canvas
|
|
898
|
-
if (aspect < fixedAspect)
|
|
899
|
-
{
|
|
900
|
-
mainCanvas.style.width = overlayCanvas.style.width = innerWidth;
|
|
901
|
-
mainCanvas.style.top = overlayCanvas.style.top = (innerHeight - innerWidth/fixedAspect)/2;
|
|
902
|
-
}
|
|
903
|
-
else
|
|
894
|
+
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
895
|
+
mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
896
|
+
mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
897
|
+
if (glCanvas)
|
|
904
898
|
{
|
|
905
|
-
|
|
906
|
-
|
|
899
|
+
glCanvas.style.width = mainCanvas.style.width;
|
|
900
|
+
glCanvas.style.height = mainCanvas.style.height;
|
|
907
901
|
}
|
|
908
902
|
}
|
|
909
903
|
else
|
|
@@ -911,18 +905,6 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
911
905
|
// clear and set size to same as window
|
|
912
906
|
mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
913
907
|
mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
914
|
-
|
|
915
|
-
// center canvas
|
|
916
|
-
overlayCanvas.style.top = mainCanvas.style.top = (innerHeight - mainCanvas.height)/2;
|
|
917
|
-
overlayCanvas.style.left = mainCanvas.style.left = (innerWidth - mainCanvas.width)/2;
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
if (glEnable)
|
|
921
|
-
{
|
|
922
|
-
glCanvas.style.width = mainCanvas.style.width;
|
|
923
|
-
glCanvas.style.height = mainCanvas.style.height;
|
|
924
|
-
glCanvas.style.top = mainCanvas.style.top;
|
|
925
|
-
glCanvas.style.left = mainCanvas.style.left;
|
|
926
908
|
}
|
|
927
909
|
|
|
928
910
|
// render sort then render while removing destroyed objects
|
|
@@ -1642,6 +1624,9 @@ function drawText(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new
|
|
|
1642
1624
|
* // draw text
|
|
1643
1625
|
* font.drawTextScreen("LittleJS\nHello World!", vec2(200, 50));
|
|
1644
1626
|
*/
|
|
1627
|
+
|
|
1628
|
+
let engineFontImage;
|
|
1629
|
+
|
|
1645
1630
|
class FontImage
|
|
1646
1631
|
{
|
|
1647
1632
|
/** Create an image font
|
|
@@ -1653,14 +1638,14 @@ class FontImage
|
|
|
1653
1638
|
*/
|
|
1654
1639
|
constructor(image, tileSize=vec2(8), paddingSize=vec2(0,1), startTileIndex=0, context=overlayContext)
|
|
1655
1640
|
{
|
|
1656
|
-
if (!image)
|
|
1641
|
+
if (!image && !engineFontImage)
|
|
1657
1642
|
{
|
|
1658
|
-
//
|
|
1659
|
-
|
|
1660
|
-
|
|
1643
|
+
// load default font image
|
|
1644
|
+
engineFontImage = new Image();
|
|
1645
|
+
engineFontImage.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAAYAQAAAAA9+x6JAAAAAnRSTlMAAHaTzTgAAAGiSURBVHjaZZABhxxBEIUf6ECLBdFY+Q0PMNgf0yCgsSAGZcT9sgIPtBWwIA5wgAPEoHUyJeeSlW+gjK+fegWwtROWpVQEyWh2npdpBmTUFVhb29RINgLIukoXr5LIAvYQ5ve+1FqWEMqNKTX3FAJHyQDRZvmKWubAACcv5z5Gtg2oyCWE+Yk/8JZQX1jTTCpKAFGIgza+dJCNBF2UskRlsgwitHbSV0QLgt9sTPtsRlvJjEr8C/FARWA2bJ/TtJ7lko34dNDn6usJUMzuErP89UUBJbWeozrwLLncXczd508deAjLWipLO4Q5XGPcJvPu92cNDaN0P5G1FL0nSOzddZOrJ6rNhbXGmeDvO3TF7DeJWl4bvaYQTNHCTeuqKZmbjHaSOFes+IX/+IhHrnAkXOAsfn24EM68XieIECoccD4KZLk/odiwzeo2rovYdhvb2HYFgyznJyDpYJdYOmfXgVdJTaUi4xA2uWYNYec9BLeqdl9EsoTw582mSFDX2DxVLbNt9U3YYoeatBad1c2Tj8t2akrjaIGJNywKB/7h75/gN3vCMSaadIUTAAAAAElFTkSuQmCC';
|
|
1661
1646
|
}
|
|
1662
1647
|
|
|
1663
|
-
this.image = image;
|
|
1648
|
+
this.image = image || engineFontImage;
|
|
1664
1649
|
this.tileSize = tileSize;
|
|
1665
1650
|
this.paddingSize = paddingSize;
|
|
1666
1651
|
this.startTileIndex = startTileIndex;
|
|
@@ -2027,7 +2012,7 @@ if (isTouchDevice)
|
|
|
2027
2012
|
// touch gamepad, virtual on screen gamepad emulator for touch devices
|
|
2028
2013
|
|
|
2029
2014
|
// touch input internal variables
|
|
2030
|
-
let touchGamepadTimer = new Timer, touchGamepadButtons = [], touchGamepadStick = vec2()
|
|
2015
|
+
let touchGamepadTimer = new Timer, touchGamepadButtons = [], touchGamepadStick = vec2();
|
|
2031
2016
|
|
|
2032
2017
|
// create the touch gamepad, called automatically by the engine
|
|
2033
2018
|
function touchGamepadCreate()
|
|
@@ -2074,7 +2059,7 @@ function touchGamepadCreate()
|
|
|
2074
2059
|
{
|
|
2075
2060
|
// virtual analog stick
|
|
2076
2061
|
if (touchGamepadAnalog)
|
|
2077
|
-
touchGamepadStick = touchPos.subtract(stickCenter).
|
|
2062
|
+
touchGamepadStick = touchPos.subtract(stickCenter).scale(2/touchGamepadSize).clampLength();
|
|
2078
2063
|
else
|
|
2079
2064
|
{
|
|
2080
2065
|
// 8 way dpad
|
|
@@ -2115,12 +2100,28 @@ function touchGamepadRender()
|
|
|
2115
2100
|
overlayContext.lineWidth = 3;
|
|
2116
2101
|
|
|
2117
2102
|
// draw left analog stick
|
|
2118
|
-
overlayContext.fillStyle =
|
|
2103
|
+
overlayContext.fillStyle = touchGamepadStick.lengthSquared() > 0 ? '#fff' : '#000';
|
|
2119
2104
|
overlayContext.beginPath();
|
|
2120
|
-
overlayContext.arc(touchGamepadSize, mainCanvasSize.y-touchGamepadSize, touchGamepadSize/2, 0,9);
|
|
2121
|
-
overlayContext.fill();
|
|
2122
|
-
overlayContext.stroke();
|
|
2123
2105
|
|
|
2106
|
+
const leftCenter = vec2(touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
|
|
2107
|
+
if (touchGamepadAnalog)
|
|
2108
|
+
{
|
|
2109
|
+
overlayContext.arc(leftCenter.x, leftCenter.y, touchGamepadSize/2, 0, 9);
|
|
2110
|
+
overlayContext.fill();
|
|
2111
|
+
overlayContext.stroke();
|
|
2112
|
+
}
|
|
2113
|
+
else // draw cross shaped gamepad
|
|
2114
|
+
{
|
|
2115
|
+
for(let i=10; i--;)
|
|
2116
|
+
{
|
|
2117
|
+
const angle = i*PI/4;
|
|
2118
|
+
overlayContext.arc(leftCenter.x, leftCenter.y,touchGamepadSize*.6, angle + PI/8, angle + PI/8);
|
|
2119
|
+
i%2 && overlayContext.arc(leftCenter.x, leftCenter.y, touchGamepadSize*.33, angle, angle);
|
|
2120
|
+
i==1 && overlayContext.fill();
|
|
2121
|
+
}
|
|
2122
|
+
overlayContext.stroke();
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2124
2125
|
// draw right face buttons
|
|
2125
2126
|
const rightCenter = vec2(mainCanvasSize.x-touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
|
|
2126
2127
|
for (let i=4; i--;)
|
|
@@ -2966,9 +2967,9 @@ class TileLayer extends EngineObject
|
|
|
2966
2967
|
* let pos = vec2(2,3);
|
|
2967
2968
|
* let particleEmiter = new ParticleEmitter
|
|
2968
2969
|
* (
|
|
2969
|
-
* pos, 1, 0, 500, PI, // pos, emitSize, emitTime, emitRate, emiteCone
|
|
2970
|
+
* pos, 0, 1, 0, 500, PI, // pos, angle, emitSize, emitTime, emitRate, emiteCone
|
|
2970
2971
|
* 0, vec2(16), // tileIndex, tileSize
|
|
2971
|
-
* new Color,
|
|
2972
|
+
* new Color(1,1,1), new Color(0,0,0), // colorStartA, colorStartB
|
|
2972
2973
|
* new Color(1,1,1,0), new Color(0,0,0,0), // colorEndA, colorEndB
|
|
2973
2974
|
* 2, .2, .2, .1, .05, // particleTime, sizeStart, sizeEnd, particleSpeed, particleAngleSpeed
|
|
2974
2975
|
* .99, 1, 1, PI, .05, // damping, angleDamping, gravityScale, particleCone, fadeRate,
|
|
@@ -2979,6 +2980,7 @@ class ParticleEmitter extends EngineObject
|
|
|
2979
2980
|
{
|
|
2980
2981
|
/** Create a particle system with the given settings
|
|
2981
2982
|
* @param {Vector2} position - World space position of the emitter
|
|
2983
|
+
* @param {Number} [angle=0] - Angle to rotate the object
|
|
2982
2984
|
* @param {Number} [emitSize=0] - World space size of the emitter (float for circle diameter, vec2 for rect)
|
|
2983
2985
|
* @param {Number} [emitTime=0] - How long to stay alive (0 is forever)
|
|
2984
2986
|
* @param {Number} [emitRate=100] - How many particles per second to spawn, does not emit if 0
|
|
@@ -3008,6 +3010,7 @@ class ParticleEmitter extends EngineObject
|
|
|
3008
3010
|
constructor
|
|
3009
3011
|
(
|
|
3010
3012
|
pos,
|
|
3013
|
+
angle,
|
|
3011
3014
|
emitSize = 0,
|
|
3012
3015
|
emitTime = 0,
|
|
3013
3016
|
emitRate = 100,
|
|
@@ -3035,7 +3038,7 @@ class ParticleEmitter extends EngineObject
|
|
|
3035
3038
|
renderOrder = additive ? 1e9 : 0
|
|
3036
3039
|
)
|
|
3037
3040
|
{
|
|
3038
|
-
super(pos, new Vector2, tileIndex, tileSize,
|
|
3041
|
+
super(pos, new Vector2, tileIndex, tileSize, angle, undefined, renderOrder);
|
|
3039
3042
|
|
|
3040
3043
|
// emitter settings
|
|
3041
3044
|
/** @property {Number} - World space size of the emitter (float for circle diameter, vec2 for rect) */
|
|
@@ -3468,9 +3471,6 @@ class Newgrounds
|
|
|
3468
3471
|
* @param {Number} value - The score value */
|
|
3469
3472
|
postScore(id, value) { return this.call('ScoreBoard.postScore', {'id':id, 'value':value}, 1); }
|
|
3470
3473
|
|
|
3471
|
-
/** Send message to log a view */
|
|
3472
|
-
logView() { return this.call('App.logView', {'host':this.host}, 1); }
|
|
3473
|
-
|
|
3474
3474
|
/** Get scores from a scoreboard
|
|
3475
3475
|
* @param {Number} id - The scoreboard id
|
|
3476
3476
|
* @param {String} [user=0] - A user's id or name
|
|
@@ -3482,6 +3482,9 @@ class Newgrounds
|
|
|
3482
3482
|
getScores(id, user=0, social=0, skip=0, limit=10)
|
|
3483
3483
|
{ return this.call('ScoreBoard.getScores', {'id':id, 'user':user, 'social':social, 'skip':skip, 'limit':limit}); }
|
|
3484
3484
|
|
|
3485
|
+
/** Send message to log a view */
|
|
3486
|
+
logView() { return this.call('App.logView', {'host':this.host}, 1); }
|
|
3487
|
+
|
|
3485
3488
|
/** Send a message to call a component of the Newgrounds API
|
|
3486
3489
|
* @param {String} component - Name of the component
|
|
3487
3490
|
* @param {Object} [parameters=0] - Parameters to use for call
|
|
@@ -3578,24 +3581,24 @@ function glInit()
|
|
|
3578
3581
|
|
|
3579
3582
|
// setup vertex and fragment shaders
|
|
3580
3583
|
glShader = glCreateProgram(
|
|
3581
|
-
'precision highp float;'+
|
|
3582
|
-
'uniform mat4 m;'+
|
|
3583
|
-
'attribute vec2 p,t;'+
|
|
3584
|
-
'attribute vec4 c,a;'+
|
|
3585
|
-
'varying vec2 v;'+
|
|
3586
|
-
'varying vec4 d,e;'+
|
|
3587
|
-
'void main(){'+
|
|
3588
|
-
'gl_Position=m*vec4(p,1,1);'
|
|
3589
|
-
'v=t;d=c;e=a;'+
|
|
3590
|
-
'}'
|
|
3584
|
+
'precision highp float;'+ // use highp for better accuracy, lowp for better perf
|
|
3585
|
+
'uniform mat4 m;'+ // transform matrix
|
|
3586
|
+
'attribute vec2 p,t;'+ // position, uv
|
|
3587
|
+
'attribute vec4 c,a;'+ // color, additiveColor
|
|
3588
|
+
'varying vec2 v;'+ // return uv
|
|
3589
|
+
'varying vec4 d,e;'+ // return color, additiveColor
|
|
3590
|
+
'void main(){'+ // shader entry point
|
|
3591
|
+
'gl_Position=m*vec4(p,1,1);'+ // transform position
|
|
3592
|
+
'v=t;d=c;e=a;'+ // pass stuff to fragment shader
|
|
3593
|
+
'}' // end of shader
|
|
3591
3594
|
,
|
|
3592
|
-
'precision highp float;'+
|
|
3593
|
-
'varying vec2 v;'+
|
|
3594
|
-
'varying vec4 d,e;'+
|
|
3595
|
-
'uniform sampler2D
|
|
3596
|
-
'void main(){'+
|
|
3597
|
-
'gl_FragColor=texture2D(
|
|
3598
|
-
'}'
|
|
3595
|
+
'precision highp float;'+ // use highp for better accuracy, lowp for better perf
|
|
3596
|
+
'varying vec2 v;'+ // uv
|
|
3597
|
+
'varying vec4 d,e;'+ // color, additiveColor
|
|
3598
|
+
'uniform sampler2D s;'+ // texture
|
|
3599
|
+
'void main(){'+ // shader entry point
|
|
3600
|
+
'gl_FragColor=texture2D(s,v)*d+e;'+ // modulate texture by color plus additive
|
|
3601
|
+
'}' // end of shader
|
|
3599
3602
|
);
|
|
3600
3603
|
|
|
3601
3604
|
// init buffers
|
|
@@ -3807,44 +3810,44 @@ function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba=0xffffff
|
|
|
3807
3810
|
|
|
3808
3811
|
// prepare to create the verts from size and angle
|
|
3809
3812
|
const c = Math.cos(angle)/2, s = Math.sin(angle)/2;
|
|
3810
|
-
const
|
|
3813
|
+
const cx = c*sizeX, cy = c*sizeY, sx = s*sizeX, sy = s*sizeY;
|
|
3811
3814
|
|
|
3812
3815
|
// setup 2 triangles to form a quad
|
|
3813
3816
|
let offset = glBatchCount++ * gl_VERTICES_PER_QUAD * gl_INDICIES_PER_VERT;
|
|
3814
3817
|
|
|
3815
3818
|
// vertex 0
|
|
3816
|
-
glPositionData[offset++] = x -
|
|
3817
|
-
glPositionData[offset++] = y -
|
|
3819
|
+
glPositionData[offset++] = x - cx - sy;
|
|
3820
|
+
glPositionData[offset++] = y - cy + sx;
|
|
3818
3821
|
glPositionData[offset++] = uv0X; glPositionData[offset++] = uv1Y;
|
|
3819
3822
|
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
3820
3823
|
|
|
3821
3824
|
// vertex 1
|
|
3822
|
-
glPositionData[offset++] = x +
|
|
3823
|
-
glPositionData[offset++] = y +
|
|
3825
|
+
glPositionData[offset++] = x + cx + sy;
|
|
3826
|
+
glPositionData[offset++] = y + cy - sx;
|
|
3824
3827
|
glPositionData[offset++] = uv1X; glPositionData[offset++] = uv0Y;
|
|
3825
3828
|
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
3826
3829
|
|
|
3827
3830
|
// vertex 2
|
|
3828
|
-
glPositionData[offset++] = x -
|
|
3829
|
-
glPositionData[offset++] = y +
|
|
3831
|
+
glPositionData[offset++] = x - cx + sy;
|
|
3832
|
+
glPositionData[offset++] = y + cy + sx;
|
|
3830
3833
|
glPositionData[offset++] = uv0X; glPositionData[offset++] = uv0Y;
|
|
3831
3834
|
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
3832
3835
|
|
|
3833
3836
|
// vertex 0
|
|
3834
|
-
glPositionData[offset++] = x -
|
|
3835
|
-
glPositionData[offset++] = y -
|
|
3837
|
+
glPositionData[offset++] = x - cx - sy;
|
|
3838
|
+
glPositionData[offset++] = y - cy + sx;
|
|
3836
3839
|
glPositionData[offset++] = uv0X; glPositionData[offset++] = uv1Y;
|
|
3837
3840
|
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
3838
3841
|
|
|
3839
3842
|
// vertex 3
|
|
3840
|
-
glPositionData[offset++] = x +
|
|
3841
|
-
glPositionData[offset++] = y -
|
|
3843
|
+
glPositionData[offset++] = x + cx - sy;
|
|
3844
|
+
glPositionData[offset++] = y - cy - sx;
|
|
3842
3845
|
glPositionData[offset++] = uv1X; glPositionData[offset++] = uv1Y;
|
|
3843
3846
|
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
3844
3847
|
|
|
3845
3848
|
// vertex 1
|
|
3846
|
-
glPositionData[offset++] = x +
|
|
3847
|
-
glPositionData[offset++] = y +
|
|
3849
|
+
glPositionData[offset++] = x + cx + sy;
|
|
3850
|
+
glPositionData[offset++] = y + cy - sx;
|
|
3848
3851
|
glPositionData[offset++] = uv1X; glPositionData[offset++] = uv0Y;
|
|
3849
3852
|
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
3850
3853
|
}
|
package/engine/engine.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
const engineName = 'LittleJS';
|
|
23
23
|
|
|
24
24
|
/** Version of engine */
|
|
25
|
-
const engineVersion = '1.2.
|
|
25
|
+
const engineVersion = '1.2.3';
|
|
26
26
|
|
|
27
27
|
/** Frames per second to update objects
|
|
28
28
|
* @default */
|
|
@@ -59,7 +59,7 @@ let averageFPS, drawCount;
|
|
|
59
59
|
// css text used for elements created by engine
|
|
60
60
|
const styleBody = 'margin:0;overflow:hidden;background:#000' +
|
|
61
61
|
';touch-action:none;user-select:none;-webkit-user-select:none;-moz-user-select:none';
|
|
62
|
-
const styleCanvas = 'position:absolute';
|
|
62
|
+
const styleCanvas = 'position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)';
|
|
63
63
|
|
|
64
64
|
///////////////////////////////////////////////////////////////////////////////
|
|
65
65
|
|
|
@@ -160,24 +160,13 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
160
160
|
|
|
161
161
|
// fit to window by adding space on top or bottom if necessary
|
|
162
162
|
const aspect = innerWidth / innerHeight;
|
|
163
|
-
const fixedAspect =
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
mainCanvas.style.height = overlayCanvas.style.height =
|
|
168
|
-
mainCanvas.style.top = overlayCanvas.style.top =
|
|
169
|
-
mainCanvas.style.left = overlayCanvas.style.left = '';
|
|
170
|
-
|
|
171
|
-
// letterbox center canvas
|
|
172
|
-
if (aspect < fixedAspect)
|
|
173
|
-
{
|
|
174
|
-
mainCanvas.style.width = overlayCanvas.style.width = innerWidth;
|
|
175
|
-
mainCanvas.style.top = overlayCanvas.style.top = (innerHeight - innerWidth/fixedAspect)/2;
|
|
176
|
-
}
|
|
177
|
-
else
|
|
163
|
+
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
164
|
+
mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
165
|
+
mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
166
|
+
if (glCanvas)
|
|
178
167
|
{
|
|
179
|
-
|
|
180
|
-
|
|
168
|
+
glCanvas.style.width = mainCanvas.style.width;
|
|
169
|
+
glCanvas.style.height = mainCanvas.style.height;
|
|
181
170
|
}
|
|
182
171
|
}
|
|
183
172
|
else
|
|
@@ -185,18 +174,6 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
185
174
|
// clear and set size to same as window
|
|
186
175
|
mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
187
176
|
mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
188
|
-
|
|
189
|
-
// center canvas
|
|
190
|
-
overlayCanvas.style.top = mainCanvas.style.top = (innerHeight - mainCanvas.height)/2;
|
|
191
|
-
overlayCanvas.style.left = mainCanvas.style.left = (innerWidth - mainCanvas.width)/2;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (glEnable)
|
|
195
|
-
{
|
|
196
|
-
glCanvas.style.width = mainCanvas.style.width;
|
|
197
|
-
glCanvas.style.height = mainCanvas.style.height;
|
|
198
|
-
glCanvas.style.top = mainCanvas.style.top;
|
|
199
|
-
glCanvas.style.left = mainCanvas.style.left;
|
|
200
177
|
}
|
|
201
178
|
|
|
202
179
|
// render sort then render while removing destroyed objects
|
package/engine/engineDebug.js
CHANGED
package/engine/engineDraw.js
CHANGED
|
@@ -254,6 +254,9 @@ function drawText(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new
|
|
|
254
254
|
* // draw text
|
|
255
255
|
* font.drawTextScreen("LittleJS\nHello World!", vec2(200, 50));
|
|
256
256
|
*/
|
|
257
|
+
|
|
258
|
+
let engineFontImage;
|
|
259
|
+
|
|
257
260
|
class FontImage
|
|
258
261
|
{
|
|
259
262
|
/** Create an image font
|
|
@@ -265,14 +268,14 @@ class FontImage
|
|
|
265
268
|
*/
|
|
266
269
|
constructor(image, tileSize=vec2(8), paddingSize=vec2(0,1), startTileIndex=0, context=overlayContext)
|
|
267
270
|
{
|
|
268
|
-
if (!image)
|
|
271
|
+
if (!image && !engineFontImage)
|
|
269
272
|
{
|
|
270
|
-
//
|
|
271
|
-
|
|
272
|
-
|
|
273
|
+
// load default font image
|
|
274
|
+
engineFontImage = new Image();
|
|
275
|
+
engineFontImage.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAAYAQAAAAA9+x6JAAAAAnRSTlMAAHaTzTgAAAGiSURBVHjaZZABhxxBEIUf6ECLBdFY+Q0PMNgf0yCgsSAGZcT9sgIPtBWwIA5wgAPEoHUyJeeSlW+gjK+fegWwtROWpVQEyWh2npdpBmTUFVhb29RINgLIukoXr5LIAvYQ5ve+1FqWEMqNKTX3FAJHyQDRZvmKWubAACcv5z5Gtg2oyCWE+Yk/8JZQX1jTTCpKAFGIgza+dJCNBF2UskRlsgwitHbSV0QLgt9sTPtsRlvJjEr8C/FARWA2bJ/TtJ7lko34dNDn6usJUMzuErP89UUBJbWeozrwLLncXczd508deAjLWipLO4Q5XGPcJvPu92cNDaN0P5G1FL0nSOzddZOrJ6rNhbXGmeDvO3TF7DeJWl4bvaYQTNHCTeuqKZmbjHaSOFes+IX/+IhHrnAkXOAsfn24EM68XieIECoccD4KZLk/odiwzeo2rovYdhvb2HYFgyznJyDpYJdYOmfXgVdJTaUi4xA2uWYNYec9BLeqdl9EsoTw582mSFDX2DxVLbNt9U3YYoeatBad1c2Tj8t2akrjaIGJNywKB/7h75/gN3vCMSaadIUTAAAAAElFTkSuQmCC';
|
|
273
276
|
}
|
|
274
277
|
|
|
275
|
-
this.image = image;
|
|
278
|
+
this.image = image || engineFontImage;
|
|
276
279
|
this.tileSize = tileSize;
|
|
277
280
|
this.paddingSize = paddingSize;
|
|
278
281
|
this.startTileIndex = startTileIndex;
|
|
Binary file
|
package/engine/engineInput.js
CHANGED
|
@@ -281,7 +281,7 @@ if (isTouchDevice)
|
|
|
281
281
|
// touch gamepad, virtual on screen gamepad emulator for touch devices
|
|
282
282
|
|
|
283
283
|
// touch input internal variables
|
|
284
|
-
let touchGamepadTimer = new Timer, touchGamepadButtons = [], touchGamepadStick = vec2()
|
|
284
|
+
let touchGamepadTimer = new Timer, touchGamepadButtons = [], touchGamepadStick = vec2();
|
|
285
285
|
|
|
286
286
|
// create the touch gamepad, called automatically by the engine
|
|
287
287
|
function touchGamepadCreate()
|
|
@@ -328,7 +328,7 @@ function touchGamepadCreate()
|
|
|
328
328
|
{
|
|
329
329
|
// virtual analog stick
|
|
330
330
|
if (touchGamepadAnalog)
|
|
331
|
-
touchGamepadStick = touchPos.subtract(stickCenter).
|
|
331
|
+
touchGamepadStick = touchPos.subtract(stickCenter).scale(2/touchGamepadSize).clampLength();
|
|
332
332
|
else
|
|
333
333
|
{
|
|
334
334
|
// 8 way dpad
|
|
@@ -369,12 +369,28 @@ function touchGamepadRender()
|
|
|
369
369
|
overlayContext.lineWidth = 3;
|
|
370
370
|
|
|
371
371
|
// draw left analog stick
|
|
372
|
-
overlayContext.fillStyle =
|
|
372
|
+
overlayContext.fillStyle = touchGamepadStick.lengthSquared() > 0 ? '#fff' : '#000';
|
|
373
373
|
overlayContext.beginPath();
|
|
374
|
-
overlayContext.arc(touchGamepadSize, mainCanvasSize.y-touchGamepadSize, touchGamepadSize/2, 0,9);
|
|
375
|
-
overlayContext.fill();
|
|
376
|
-
overlayContext.stroke();
|
|
377
374
|
|
|
375
|
+
const leftCenter = vec2(touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
|
|
376
|
+
if (touchGamepadAnalog)
|
|
377
|
+
{
|
|
378
|
+
overlayContext.arc(leftCenter.x, leftCenter.y, touchGamepadSize/2, 0, 9);
|
|
379
|
+
overlayContext.fill();
|
|
380
|
+
overlayContext.stroke();
|
|
381
|
+
}
|
|
382
|
+
else // draw cross shaped gamepad
|
|
383
|
+
{
|
|
384
|
+
for(let i=10; i--;)
|
|
385
|
+
{
|
|
386
|
+
const angle = i*PI/4;
|
|
387
|
+
overlayContext.arc(leftCenter.x, leftCenter.y,touchGamepadSize*.6, angle + PI/8, angle + PI/8);
|
|
388
|
+
i%2 && overlayContext.arc(leftCenter.x, leftCenter.y, touchGamepadSize*.33, angle, angle);
|
|
389
|
+
i==1 && overlayContext.fill();
|
|
390
|
+
}
|
|
391
|
+
overlayContext.stroke();
|
|
392
|
+
}
|
|
393
|
+
|
|
378
394
|
// draw right face buttons
|
|
379
395
|
const rightCenter = vec2(mainCanvasSize.x-touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
|
|
380
396
|
for (let i=4; i--;)
|
package/engine/engineMedals.js
CHANGED
|
@@ -235,9 +235,6 @@ class Newgrounds
|
|
|
235
235
|
* @param {Number} value - The score value */
|
|
236
236
|
postScore(id, value) { return this.call('ScoreBoard.postScore', {'id':id, 'value':value}, 1); }
|
|
237
237
|
|
|
238
|
-
/** Send message to log a view */
|
|
239
|
-
logView() { return this.call('App.logView', {'host':this.host}, 1); }
|
|
240
|
-
|
|
241
238
|
/** Get scores from a scoreboard
|
|
242
239
|
* @param {Number} id - The scoreboard id
|
|
243
240
|
* @param {String} [user=0] - A user's id or name
|
|
@@ -249,6 +246,9 @@ class Newgrounds
|
|
|
249
246
|
getScores(id, user=0, social=0, skip=0, limit=10)
|
|
250
247
|
{ return this.call('ScoreBoard.getScores', {'id':id, 'user':user, 'social':social, 'skip':skip, 'limit':limit}); }
|
|
251
248
|
|
|
249
|
+
/** Send message to log a view */
|
|
250
|
+
logView() { return this.call('App.logView', {'host':this.host}, 1); }
|
|
251
|
+
|
|
252
252
|
/** Send a message to call a component of the Newgrounds API
|
|
253
253
|
* @param {String} component - Name of the component
|
|
254
254
|
* @param {Object} [parameters=0] - Parameters to use for call
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
* let pos = vec2(2,3);
|
|
16
16
|
* let particleEmiter = new ParticleEmitter
|
|
17
17
|
* (
|
|
18
|
-
* pos, 1, 0, 500, PI, // pos, emitSize, emitTime, emitRate, emiteCone
|
|
18
|
+
* pos, 0, 1, 0, 500, PI, // pos, angle, emitSize, emitTime, emitRate, emiteCone
|
|
19
19
|
* 0, vec2(16), // tileIndex, tileSize
|
|
20
|
-
* new Color,
|
|
20
|
+
* new Color(1,1,1), new Color(0,0,0), // colorStartA, colorStartB
|
|
21
21
|
* new Color(1,1,1,0), new Color(0,0,0,0), // colorEndA, colorEndB
|
|
22
22
|
* 2, .2, .2, .1, .05, // particleTime, sizeStart, sizeEnd, particleSpeed, particleAngleSpeed
|
|
23
23
|
* .99, 1, 1, PI, .05, // damping, angleDamping, gravityScale, particleCone, fadeRate,
|
|
@@ -28,6 +28,7 @@ class ParticleEmitter extends EngineObject
|
|
|
28
28
|
{
|
|
29
29
|
/** Create a particle system with the given settings
|
|
30
30
|
* @param {Vector2} position - World space position of the emitter
|
|
31
|
+
* @param {Number} [angle=0] - Angle to rotate the object
|
|
31
32
|
* @param {Number} [emitSize=0] - World space size of the emitter (float for circle diameter, vec2 for rect)
|
|
32
33
|
* @param {Number} [emitTime=0] - How long to stay alive (0 is forever)
|
|
33
34
|
* @param {Number} [emitRate=100] - How many particles per second to spawn, does not emit if 0
|
|
@@ -57,6 +58,7 @@ class ParticleEmitter extends EngineObject
|
|
|
57
58
|
constructor
|
|
58
59
|
(
|
|
59
60
|
pos,
|
|
61
|
+
angle,
|
|
60
62
|
emitSize = 0,
|
|
61
63
|
emitTime = 0,
|
|
62
64
|
emitRate = 100,
|
|
@@ -84,7 +86,7 @@ class ParticleEmitter extends EngineObject
|
|
|
84
86
|
renderOrder = additive ? 1e9 : 0
|
|
85
87
|
)
|
|
86
88
|
{
|
|
87
|
-
super(pos, new Vector2, tileIndex, tileSize,
|
|
89
|
+
super(pos, new Vector2, tileIndex, tileSize, angle, undefined, renderOrder);
|
|
88
90
|
|
|
89
91
|
// emitter settings
|
|
90
92
|
/** @property {Number} - World space size of the emitter (float for circle diameter, vec2 for rect) */
|
package/engine/engineSettings.js
CHANGED
|
@@ -145,6 +145,11 @@ let inputWASDEmulateDirection = 1;
|
|
|
145
145
|
* @memberof Settings */
|
|
146
146
|
let touchGamepadEnable = 0;
|
|
147
147
|
|
|
148
|
+
/** True if touch gamepad should be analog stick or false to use if 8 way dpad
|
|
149
|
+
* @default
|
|
150
|
+
* @memberof Settings */
|
|
151
|
+
let touchGamepadAnalog = 1;
|
|
152
|
+
|
|
148
153
|
/** Size of virutal gamepad for touch devices in pixels
|
|
149
154
|
* @default
|
|
150
155
|
* @memberof Settings */
|
package/engine/engineWebGL.js
CHANGED
|
@@ -47,24 +47,24 @@ function glInit()
|
|
|
47
47
|
|
|
48
48
|
// setup vertex and fragment shaders
|
|
49
49
|
glShader = glCreateProgram(
|
|
50
|
-
'precision highp float;'+
|
|
51
|
-
'uniform mat4 m;'+
|
|
52
|
-
'attribute vec2 p,t;'+
|
|
53
|
-
'attribute vec4 c,a;'+
|
|
54
|
-
'varying vec2 v;'+
|
|
55
|
-
'varying vec4 d,e;'+
|
|
56
|
-
'void main(){'+
|
|
57
|
-
'gl_Position=m*vec4(p,1,1);'
|
|
58
|
-
'v=t;d=c;e=a;'+
|
|
59
|
-
'}'
|
|
50
|
+
'precision highp float;'+ // use highp for better accuracy, lowp for better perf
|
|
51
|
+
'uniform mat4 m;'+ // transform matrix
|
|
52
|
+
'attribute vec2 p,t;'+ // position, uv
|
|
53
|
+
'attribute vec4 c,a;'+ // color, additiveColor
|
|
54
|
+
'varying vec2 v;'+ // return uv
|
|
55
|
+
'varying vec4 d,e;'+ // return color, additiveColor
|
|
56
|
+
'void main(){'+ // shader entry point
|
|
57
|
+
'gl_Position=m*vec4(p,1,1);'+ // transform position
|
|
58
|
+
'v=t;d=c;e=a;'+ // pass stuff to fragment shader
|
|
59
|
+
'}' // end of shader
|
|
60
60
|
,
|
|
61
|
-
'precision highp float;'+
|
|
62
|
-
'varying vec2 v;'+
|
|
63
|
-
'varying vec4 d,e;'+
|
|
64
|
-
'uniform sampler2D
|
|
65
|
-
'void main(){'+
|
|
66
|
-
'gl_FragColor=texture2D(
|
|
67
|
-
'}'
|
|
61
|
+
'precision highp float;'+ // use highp for better accuracy, lowp for better perf
|
|
62
|
+
'varying vec2 v;'+ // uv
|
|
63
|
+
'varying vec4 d,e;'+ // color, additiveColor
|
|
64
|
+
'uniform sampler2D s;'+ // texture
|
|
65
|
+
'void main(){'+ // shader entry point
|
|
66
|
+
'gl_FragColor=texture2D(s,v)*d+e;'+ // modulate texture by color plus additive
|
|
67
|
+
'}' // end of shader
|
|
68
68
|
);
|
|
69
69
|
|
|
70
70
|
// init buffers
|
|
@@ -276,44 +276,44 @@ function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba=0xffffff
|
|
|
276
276
|
|
|
277
277
|
// prepare to create the verts from size and angle
|
|
278
278
|
const c = Math.cos(angle)/2, s = Math.sin(angle)/2;
|
|
279
|
-
const
|
|
279
|
+
const cx = c*sizeX, cy = c*sizeY, sx = s*sizeX, sy = s*sizeY;
|
|
280
280
|
|
|
281
281
|
// setup 2 triangles to form a quad
|
|
282
282
|
let offset = glBatchCount++ * gl_VERTICES_PER_QUAD * gl_INDICIES_PER_VERT;
|
|
283
283
|
|
|
284
284
|
// vertex 0
|
|
285
|
-
glPositionData[offset++] = x -
|
|
286
|
-
glPositionData[offset++] = y -
|
|
285
|
+
glPositionData[offset++] = x - cx - sy;
|
|
286
|
+
glPositionData[offset++] = y - cy + sx;
|
|
287
287
|
glPositionData[offset++] = uv0X; glPositionData[offset++] = uv1Y;
|
|
288
288
|
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
289
289
|
|
|
290
290
|
// vertex 1
|
|
291
|
-
glPositionData[offset++] = x +
|
|
292
|
-
glPositionData[offset++] = y +
|
|
291
|
+
glPositionData[offset++] = x + cx + sy;
|
|
292
|
+
glPositionData[offset++] = y + cy - sx;
|
|
293
293
|
glPositionData[offset++] = uv1X; glPositionData[offset++] = uv0Y;
|
|
294
294
|
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
295
295
|
|
|
296
296
|
// vertex 2
|
|
297
|
-
glPositionData[offset++] = x -
|
|
298
|
-
glPositionData[offset++] = y +
|
|
297
|
+
glPositionData[offset++] = x - cx + sy;
|
|
298
|
+
glPositionData[offset++] = y + cy + sx;
|
|
299
299
|
glPositionData[offset++] = uv0X; glPositionData[offset++] = uv0Y;
|
|
300
300
|
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
301
301
|
|
|
302
302
|
// vertex 0
|
|
303
|
-
glPositionData[offset++] = x -
|
|
304
|
-
glPositionData[offset++] = y -
|
|
303
|
+
glPositionData[offset++] = x - cx - sy;
|
|
304
|
+
glPositionData[offset++] = y - cy + sx;
|
|
305
305
|
glPositionData[offset++] = uv0X; glPositionData[offset++] = uv1Y;
|
|
306
306
|
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
307
307
|
|
|
308
308
|
// vertex 3
|
|
309
|
-
glPositionData[offset++] = x +
|
|
310
|
-
glPositionData[offset++] = y -
|
|
309
|
+
glPositionData[offset++] = x + cx - sy;
|
|
310
|
+
glPositionData[offset++] = y - cy - sx;
|
|
311
311
|
glPositionData[offset++] = uv1X; glPositionData[offset++] = uv1Y;
|
|
312
312
|
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
313
313
|
|
|
314
314
|
// vertex 1
|
|
315
|
-
glPositionData[offset++] = x +
|
|
316
|
-
glPositionData[offset++] = y +
|
|
315
|
+
glPositionData[offset++] = x + cx + sy;
|
|
316
|
+
glPositionData[offset++] = y + cy - sx;
|
|
317
317
|
glPositionData[offset++] = uv1X; glPositionData[offset++] = uv0Y;
|
|
318
318
|
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
319
319
|
}
|