littlejsengine 1.4.8 → 1.4.91

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.
@@ -626,7 +626,7 @@ let cameraPos = vec2();
626
626
  /** Scale of camera in world space
627
627
  * @default
628
628
  * @memberof Settings */
629
- let cameraScale = 16;
629
+ let cameraScale = 32;
630
630
 
631
631
  ///////////////////////////////////////////////////////////////////////////////
632
632
  // Display settings
@@ -783,20 +783,20 @@ let vibrateEnable = 1;
783
783
  ///////////////////////////////////////////////////////////////////////////////
784
784
  // Audio settings
785
785
 
786
- /** Volume scale to apply to all sound, music and speech
786
+ /** All audio code can be disabled and removed from build
787
787
  * @default
788
788
  * @memberof Settings */
789
- let soundVolume = .5;
789
+ let soundEnable = 1;
790
790
 
791
- /** All audio code can be disabled and removed from build
791
+ /** Volume scale to apply to all sound, music and speech
792
792
  * @default
793
793
  * @memberof Settings */
794
- let soundEnable = 1;
794
+ let soundVolume = .5;
795
795
 
796
796
  /** Default range where sound no longer plays
797
797
  * @default
798
798
  * @memberof Settings */
799
- let soundDefaultRange = 30;
799
+ let soundDefaultRange = 40;
800
800
 
801
801
  /** Default range percent to start tapering off sound (0-1)
802
802
  * @default
@@ -816,20 +816,20 @@ let medalDisplayTime = 5;
816
816
  * @memberof Settings */
817
817
  let medalDisplaySlideTime = .5;
818
818
 
819
- /** Width of medal display
819
+ /** Size of medal display
820
820
  * @default
821
821
  * @memberof Settings */
822
- let medalDisplayWidth = 640;
822
+ let medalDisplaySize = vec2(640, 80);
823
823
 
824
- /** Height of medal display
824
+ /** Size of icon in medal display
825
825
  * @default
826
826
  * @memberof Settings */
827
- let medalDisplayHeight = 80;
827
+ let medalDisplayIconSize = 50;
828
828
 
829
- /** Size of icon in medal display
829
+ /** Set to stop medals from being unlockable (like if cheats are enabled)
830
830
  * @default
831
831
  * @memberof Settings */
832
- let medalDisplayIconSize = 50;
832
+ let medalsPreventUnlock;
833
833
  /*
834
834
  LittleJS - The Tiny JavaScript Game Engine That Can!
835
835
  MIT License - Copyright 2021 Frank Force
@@ -855,7 +855,7 @@ let medalDisplayIconSize = 50;
855
855
  const engineName = 'LittleJS';
856
856
 
857
857
  /** Version of engine */
858
- const engineVersion = '1.4.8';
858
+ const engineVersion = '1.4.9';
859
859
 
860
860
  /** Frames per second to update objects
861
861
  * @default */
@@ -1230,9 +1230,9 @@ class EngineObject
1230
1230
 
1231
1231
  // apply physics
1232
1232
  const oldPos = this.pos.copy();
1233
- this.pos.x += this.velocity.x = this.damping * this.velocity.x;
1234
- this.pos.y += this.velocity.y = this.damping * this.velocity.y + gravity * this.gravityScale;
1235
- this.angle += this.angleVelocity *= this.angleDamping;
1233
+ this.velocity.y += gravity * this.gravityScale;
1234
+ this.pos.x += this.velocity.x *= this.damping;
1235
+ this.pos.y += this.velocity.y *= this.damping;
1236
1236
 
1237
1237
  // physics sanity checks
1238
1238
  ASSERT(this.angleDamping >= 0 && this.angleDamping <= 1);
@@ -1290,7 +1290,7 @@ class EngineObject
1290
1290
  const isBlockedX = abs(oldPos.y - o.pos.y)*2 < sizeBoth.y;
1291
1291
  const isBlockedY = abs(oldPos.x - o.pos.x)*2 < sizeBoth.x;
1292
1292
 
1293
- if (smallStepUp || isBlockedY || !isBlockedX) // resolve y collision
1293
+ if (smallStepUp | isBlockedY | !isBlockedX) // resolve y collision
1294
1294
  {
1295
1295
  // push outside object collision
1296
1296
  this.pos.y = o.pos.y + (sizeBoth.y/2 + epsilon) * sign(oldPos.y - o.pos.y);
@@ -1320,7 +1320,7 @@ class EngineObject
1320
1320
  o.velocity.y = lerp(elasticity, inelastic, elastic1);
1321
1321
  }
1322
1322
  }
1323
- if (!smallStepUp && (isBlockedX || !isBlockedY)) // resolve x collision
1323
+ if (!smallStepUp & isBlockedX) // resolve x collision
1324
1324
  {
1325
1325
  // push outside collision
1326
1326
  this.pos.x = o.pos.x + (sizeBoth.x/2 + epsilon) * sign(oldPos.x - o.pos.x);
@@ -1358,7 +1358,7 @@ class EngineObject
1358
1358
  // test which side we bounced off (or both if a corner)
1359
1359
  const isBlockedY = tileCollisionTest(new Vector2(oldPos.x, this.pos.y), this.size, this);
1360
1360
  const isBlockedX = tileCollisionTest(new Vector2(this.pos.x, oldPos.y), this.size, this);
1361
- if (isBlockedY || !isBlockedX)
1361
+ if (isBlockedY | !isBlockedX)
1362
1362
  {
1363
1363
  // set if landed on ground
1364
1364
  this.groundObject = wasMovingDown;
@@ -1780,25 +1780,23 @@ function drawText(text, pos, size=1, color, lineWidth, lineColor, textAlign, fon
1780
1780
  * font.drawTextScreen("LittleJS\nHello World!", vec2(200, 50));
1781
1781
  */
1782
1782
 
1783
+ // default font image created by engine
1783
1784
  let engineFontImage;
1784
1785
 
1785
1786
  class FontImage
1786
1787
  {
1787
1788
  /** Create an image font
1788
- * @param {HTMLImageElement} [image] - The image the font is stored in, if undefined the default font is used
1789
- * @param {Vector2} [tileSize=vec2(8)] - The size of the font source tiles
1789
+ * @param {HTMLImageElement} [image] - Image for the font, if undefined default font is used
1790
+ * @param {Vector2} [tileSize=vec2(8)] - Size of the font source tiles
1790
1791
  * @param {Vector2} [paddingSize=vec2(0,1)] - How much extra space to add between characters
1791
1792
  * @param {Number} [startTileIndex=0] - Tile index in image where font starts
1792
1793
  * @param {CanvasRenderingContext2D} [context=overlayContext] - context to draw to
1793
1794
  */
1794
1795
  constructor(image, tileSize=vec2(8), paddingSize=vec2(0,1), startTileIndex=0, context=overlayContext)
1795
1796
  {
1797
+ // load default font image
1796
1798
  if (!engineFontImage)
1797
- {
1798
- // load default font image
1799
- engineFontImage = new Image;
1800
- engineFontImage.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAAYAQAAAAA9+x6JAAAAAnRSTlMAAHaTzTgAAAGiSURBVHjaZZABhxxBEIUf6ECLBdFY+Q0PMNgf0yCgsSAGZcT9sgIPtBWwIA5wgAPEoHUyJeeSlW+gjK+fegWwtROWpVQEyWh2npdpBmTUFVhb29RINgLIukoXr5LIAvYQ5ve+1FqWEMqNKTX3FAJHyQDRZvmKWubAACcv5z5Gtg2oyCWE+Yk/8JZQX1jTTCpKAFGIgza+dJCNBF2UskRlsgwitHbSV0QLgt9sTPtsRlvJjEr8C/FARWA2bJ/TtJ7lko34dNDn6usJUMzuErP89UUBJbWeozrwLLncXczd508deAjLWipLO4Q5XGPcJvPu92cNDaN0P5G1FL0nSOzddZOrJ6rNhbXGmeDvO3TF7DeJWl4bvaYQTNHCTeuqKZmbjHaSOFes+IX/+IhHrnAkXOAsfn24EM68XieIECoccD4KZLk/odiwzeo2rovYdhvb2HYFgyznJyDpYJdYOmfXgVdJTaUi4xA2uWYNYec9BLeqdl9EsoTw582mSFDX2DxVLbNt9U3YYoeatBad1c2Tj8t2akrjaIGJNywKB/7h75/gN3vCMSaadIUTAAAAAElFTkSuQmCC';
1801
- }
1799
+ (engineFontImage = new Image).src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAAYAQAAAAA9+x6JAAAAAnRSTlMAAHaTzTgAAAGiSURBVHjaZZABhxxBEIUf6ECLBdFY+Q0PMNgf0yCgsSAGZcT9sgIPtBWwIA5wgAPEoHUyJeeSlW+gjK+fegWwtROWpVQEyWh2npdpBmTUFVhb29RINgLIukoXr5LIAvYQ5ve+1FqWEMqNKTX3FAJHyQDRZvmKWubAACcv5z5Gtg2oyCWE+Yk/8JZQX1jTTCpKAFGIgza+dJCNBF2UskRlsgwitHbSV0QLgt9sTPtsRlvJjEr8C/FARWA2bJ/TtJ7lko34dNDn6usJUMzuErP89UUBJbWeozrwLLncXczd508deAjLWipLO4Q5XGPcJvPu92cNDaN0P5G1FL0nSOzddZOrJ6rNhbXGmeDvO3TF7DeJWl4bvaYQTNHCTeuqKZmbjHaSOFes+IX/+IhHrnAkXOAsfn24EM68XieIECoccD4KZLk/odiwzeo2rovYdhvb2HYFgyznJyDpYJdYOmfXgVdJTaUi4xA2uWYNYec9BLeqdl9EsoTw582mSFDX2DxVLbNt9U3YYoeatBad1c2Tj8t2akrjaIGJNywKB/7h75/gN3vCMSaadIUTAAAAAElFTkSuQmCC';
1802
1800
 
1803
1801
  this.image = image || engineFontImage;
1804
1802
  this.tileSize = tileSize;
@@ -3291,9 +3289,9 @@ class ParticleEmitter extends EngineObject
3291
3289
  {
3292
3290
  // spawn a particle
3293
3291
  let pos = this.emitSize.x != undefined ? // check if vec2 was used for size
3294
- (new Vector2(rand(-1,1), rand(-1,1)))
3295
- .multiply(this.emitSize/2).rotate(this.angle) // box emitter
3296
- : randInCircle(this.emitSize/2); // circle emitter
3292
+ (new Vector2(rand(-.5,.5), rand(-.5,.5)))
3293
+ .multiply(this.emitSize).rotate(this.angle) // box emitter
3294
+ : randInCircle(this.emitSize/2); // circle emitter
3297
3295
  let angle = rand(this.particleConeAngle, -this.particleConeAngle);
3298
3296
  if (!this.localSpace)
3299
3297
  {
@@ -3435,10 +3433,6 @@ class Particle extends EngineObject
3435
3433
  * @memberof Medals */
3436
3434
  const medals = [];
3437
3435
 
3438
- /** Set to stop medals from being unlockable (like if cheats are enabled)
3439
- * @memberof Medals */
3440
- let medalsPreventUnlock;
3441
-
3442
3436
  // Engine internal variables not exposed to documentation
3443
3437
  let medalsDisplayQueue = [], medalsSaveName, medalsDisplayTimeLast;
3444
3438
 
@@ -3486,9 +3480,8 @@ class Medal
3486
3480
  this.name = name;
3487
3481
  this.description = description;
3488
3482
  this.icon = icon;
3489
- this.image = new Image;
3490
3483
  if (src)
3491
- this.image.src = src;
3484
+ (this.image = new Image).src = src;
3492
3485
  }
3493
3486
 
3494
3487
  /** Unlocks a medal if not already unlocked */
@@ -3510,9 +3503,9 @@ class Medal
3510
3503
  render(hidePercent=0)
3511
3504
  {
3512
3505
  const context = overlayContext;
3513
- const width = min(medalDisplayWidth, mainCanvas.width);
3506
+ const width = min(medalDisplaySize.x, mainCanvas.width);
3514
3507
  const x = overlayCanvas.width - width;
3515
- const y = -medalDisplayHeight*hidePercent;
3508
+ const y = -medalDisplaySize.y*hidePercent;
3516
3509
 
3517
3510
  // draw containing rect and clip to that region
3518
3511
  context.save();
@@ -3520,12 +3513,12 @@ class Medal
3520
3513
  context.fillStyle = new Color(.9,.9,.9);
3521
3514
  context.strokeStyle = new Color(0,0,0);
3522
3515
  context.lineWidth = 3;
3523
- context.fill(context.rect(x, y, width, medalDisplayHeight));
3516
+ context.fill(context.rect(x, y, width, medalDisplaySize.y));
3524
3517
  context.stroke();
3525
3518
  context.clip();
3526
3519
 
3527
3520
  // draw the icon and text
3528
- this.renderIcon(vec2(x+15+medalDisplayIconSize/2, y+medalDisplayHeight/2));
3521
+ this.renderIcon(vec2(x+15+medalDisplayIconSize/2, y+medalDisplaySize.y/2));
3529
3522
  const pos = vec2(x+medalDisplayIconSize+30, y+28);
3530
3523
  drawTextScreen(this.name, pos, 38, new Color(0,0,0), 0, 0, 'left');
3531
3524
  pos.y += 32;
@@ -3603,25 +3596,19 @@ class Newgrounds
3603
3596
  {
3604
3597
  ASSERT(!newgrounds && app_id);
3605
3598
 
3606
- // create an instance of CryptoJS for encrypted calls
3607
- if (cipher)
3608
- {
3609
- ///////////////////////////////////////////////////////////////////////////////
3610
- // Crypto-JS - https://github.com/brix/crypto-js [The MIT License (MIT)]
3611
- // Copyright (c) 2009-2013 Jeff Mott Copyright (c) 2013-2016 Evan Vosberg
3612
-
3613
- this.cryptoJS = eval(Function("[M='GBMGXz^oVYPPKKbB`agTXU|LxPc_ZBcMrZvCr~wyGfWrwk@ATqlqeTp^N?p{we}jIpEnB_sEr`l?YDkDhWhprc|Er|XETG?pTl`e}dIc[_N~}fzRycIfpW{HTolvoPB_FMe_eH~BTMx]yyOhv?biWPCGc]kABencBhgERHGf{OL`Dj`c^sh@canhy[secghiyotcdOWgO{tJIE^JtdGQRNSCrwKYciZOa]Y@tcRATYKzv|sXpboHcbCBf`}SKeXPFM|RiJsSNaIb]QPc[D]Jy_O^XkOVTZep`ONmntLL`Qz~UupHBX_Ia~WX]yTRJIxG`ioZ{fefLJFhdyYoyLPvqgH?b`[TMnTwwfzDXhfM?rKs^aFr|nyBdPmVHTtAjXoYUloEziWDCw_suyYT~lSMksI~ZNCS[Bex~j]Vz?kx`gdYSEMCsHpjbyxQvw|XxX_^nQYue{sBzVWQKYndtYQMWRef{bOHSfQhiNdtR{o?cUAHQAABThwHPT}F{VvFmgN`E@FiFYS`UJmpQNM`X|tPKHlccT}z}k{sACHL?Rt@MkWplxO`ASgh?hBsuuP|xD~LSH~KBlRs]t|l|_tQAroDRqWS^SEr[sYdPB}TAROtW{mIkE|dWOuLgLmJrucGLpebrAFKWjikTUzS|j}M}szasKOmrjy[?hpwnEfX[jGpLt@^v_eNwSQHNwtOtDgWD{rk|UgASs@mziIXrsHN_|hZuxXlPJOsA^^?QY^yGoCBx{ekLuZzRqQZdsNSx@ezDAn{XNj@fRXIwrDX?{ZQHwTEfu@GhxDOykqts|n{jOeZ@c`dvTY?e^]ATvWpb?SVyg]GC?SlzteilZJAL]mlhLjYZazY__qcVFYvt@|bIQnSno@OXyt]OulzkWqH`rYFWrwGs`v|~XeTsIssLrbmHZCYHiJrX}eEzSssH}]l]IhPQhPoQ}rCXLyhFIT[clhzYOvyHqigxmjz`phKUU^TPf[GRAIhNqSOdayFP@FmKmuIzMOeoqdpxyCOwCthcLq?n`L`tLIBboNn~uXeFcPE{C~mC`h]jUUUQe^`UqvzCutYCgct|SBrAeiYQW?X~KzCz}guXbsUw?pLsg@hDArw?KeJD[BN?GD@wgFWCiHq@Ypp_QKFixEKWqRp]oJFuVIEvjDcTFu~Zz]a{IcXhWuIdMQjJ]lwmGQ|]g~c]Hl]pl`Pd^?loIcsoNir_kikBYyg?NarXZEGYspt_vLBIoj}LI[uBFvm}tbqvC|xyR~a{kob|HlctZslTGtPDhBKsNsoZPuH`U`Fqg{gKnGSHVLJ^O`zmNgMn~{rsQuoymw^JY?iUBvw_~mMr|GrPHTERS[MiNpY[Mm{ggHpzRaJaoFomtdaQ_?xuTRm}@KjU~RtPsAdxa|uHmy}n^i||FVL[eQAPrWfLm^ndczgF~Nk~aplQvTUpHvnTya]kOenZlLAQIm{lPl@CCTchvCF[fI{^zPkeYZTiamoEcKmBMfZhk_j_~Fjp|wPVZlkh_nHu]@tP|hS@^G^PdsQ~f[RqgTDqezxNFcaO}HZhb|MMiNSYSAnQWCDJukT~e|OTgc}sf[cnr?fyzTa|EwEtRG|I~|IO}O]S|rp]CQ}}DWhSjC_|z|oY|FYl@WkCOoPuWuqr{fJu?Brs^_EBI[@_OCKs}?]O`jnDiXBvaIWhhMAQDNb{U`bqVR}oqVAvR@AZHEBY@depD]OLh`kf^UsHhzKT}CS}HQKy}Q~AeMydXPQztWSSzDnghULQgMAmbWIZ|lWWeEXrE^EeNoZApooEmrXe{NAnoDf`m}UNlRdqQ@jOc~HLOMWs]IDqJHYoMziEedGBPOxOb?[X`KxkFRg@`mgFYnP{hSaxwZfBQqTm}_?RSEaQga]w[vxc]hMne}VfSlqUeMo_iqmd`ilnJXnhdj^EEFifvZyxYFRf^VaqBhLyrGlk~qowqzHOBlOwtx?i{m~`n^G?Yxzxux}b{LSlx]dS~thO^lYE}bzKmUEzwW^{rPGhbEov[Plv??xtyKJshbG`KuO?hjBdS@Ru}iGpvFXJRrvOlrKN?`I_n_tplk}kgwSXuKylXbRQ]]?a|{xiT[li?k]CJpwy^o@ebyGQrPfF`aszGKp]baIx~H?ElETtFh]dz[OjGl@C?]VDhr}OE@V]wLTc[WErXacM{We`F|utKKjgllAxvsVYBZ@HcuMgLboFHVZmi}eIXAIFhS@A@FGRbjeoJWZ_NKd^oEH`qgy`q[Tq{x?LRP|GfBFFJV|fgZs`MLbpPYUdIV^]mD@FG]pYAT^A^RNCcXVrPsgk{jTrAIQPs_`mD}rOqAZA[}RETFz]WkXFTz_m{N@{W@_fPKZLT`@aIqf|L^Mb|crNqZ{BVsijzpGPEKQQZGlApDn`ruH}cvF|iXcNqK}cxe_U~HRnKV}sCYb`D~oGvwG[Ca|UaybXea~DdD~LiIbGRxJ_VGheI{ika}KC[OZJLn^IBkPrQj_EuoFwZ}DpoBRcK]Q}?EmTv~i_Tul{bky?Iit~tgS|o}JL_VYcCQdjeJ_MfaA`FgCgc[Ii|CBHwq~nbJeYTK{e`CNstKfTKPzw{jdhp|qsZyP_FcugxCFNpKitlR~vUrx^NrSVsSTaEgnxZTmKc`R|lGJeX}ccKLsQZQhsFkeFd|ckHIVTlGMg`~uPwuHRJS_CPuN_ogXe{Ba}dO_UBhuNXby|h?JlgBIqMKx^_u{molgL[W_iavNQuOq?ap]PGB`clAicnl@k~pA?MWHEZ{HuTLsCpOxxrKlBh]FyMjLdFl|nMIvTHyGAlPogqfZ?PlvlFJvYnDQd}R@uAhtJmDfe|iJqdkYr}r@mEjjIetDl_I`TELfoR|qTBu@Tic[BaXjP?dCS~MUK[HPRI}OUOwAaf|_}HZzrwXvbnNgltjTwkBE~MztTQhtRSWoQHajMoVyBBA`kdgK~h`o[J`dm~pm]tk@i`[F~F]DBlJKklrkR]SNw@{aG~Vhl`KINsQkOy?WhcqUMTGDOM_]bUjVd|Yh_KUCCgIJ|LDIGZCPls{RzbVWVLEhHvWBzKq|^N?DyJB|__aCUjoEgsARki}j@DQXS`RNU|DJ^a~d{sh_Iu{ONcUtSrGWW@cvUjefHHi}eSSGrNtO?cTPBShLqzwMVjWQQCCFB^culBjZHEK_{dO~Q`YhJYFn]jq~XSnG@[lQr]eKrjXpG~L^h~tDgEma^AUFThlaR{xyuP@[^VFwXSeUbVetufa@dX]CLyAnDV@Bs[DnpeghJw^?UIana}r_CKGDySoRudklbgio}kIDpA@McDoPK?iYcG?_zOmnWfJp}a[JLR[stXMo?_^Ng[whQlrDbrawZeSZ~SJstIObdDSfAA{MV}?gNunLOnbMv_~KFQUAjIMj^GkoGxuYtYbGDImEYiwEMyTpMxN_LSnSMdl{bg@dtAnAMvhDTBR_FxoQgANniRqxd`pWv@rFJ|mWNWmh[GMJz_Nq`BIN@KsjMPASXORcdHjf~rJfgZYe_uulzqM_KdPlMsuvU^YJuLtofPhGonVOQxCMuXliNvJIaoC?hSxcxKVVxWlNs^ENDvCtSmO~WxI[itnjs^RDvI@KqG}YekaSbTaB]ki]XM@[ZnDAP~@|BzLRgOzmjmPkRE@_sobkT|SszXK[rZN?F]Z_u}Yue^[BZgLtR}FHzWyxWEX^wXC]MJmiVbQuBzkgRcKGUhOvUc_bga|Tx`KEM`JWEgTpFYVeXLCm|mctZR@uKTDeUONPozBeIkrY`cz]]~WPGMUf`MNUGHDbxZuO{gmsKYkAGRPqjc|_FtblEOwy}dnwCHo]PJhN~JoteaJ?dmYZeB^Xd?X^pOKDbOMF@Ugg^hETLdhwlA}PL@_ur|o{VZosP?ntJ_kG][g{Zq`Tu]dzQlSWiKfnxDnk}KOzp~tdFstMobmy[oPYjyOtUzMWdjcNSUAjRuqhLS@AwB^{BFnqjCmmlk?jpn}TksS{KcKkDboXiwK]qMVjm~V`LgWhjS^nLGwfhAYrjDSBL_{cRus~{?xar_xqPlArrYFd?pHKdMEZzzjJpfC?Hv}mAuIDkyBxFpxhstTx`IO{rp}XGuQ]VtbHerlRc_LFGWK[XluFcNGUtDYMZny[M^nVKVeMllQI[xtvwQnXFlWYqxZZFp_|]^oWX[{pOMpxXxvkbyJA[DrPzwD|LW|QcV{Nw~U^dgguSpG]ClmO@j_TENIGjPWwgdVbHganhM?ema|dBaqla|WBd`poj~klxaasKxGG^xbWquAl~_lKWxUkDFagMnE{zHug{b`A~IYcQYBF_E}wiA}K@yxWHrZ{[d~|ARsYsjeNWzkMs~IOqqp[yzDE|WFrivsidTcnbHFRoW@XpAV`lv_zj?B~tPCppRjgbbDTALeFaOf?VcjnKTQMLyp{NwdylHCqmo?oelhjWuXj~}{fpuX`fra?GNkDiChYgVSh{R[BgF~eQa^WVz}ATI_CpY?g_diae]|ijH`TyNIF}|D_xpmBq_JpKih{Ba|sWzhnAoyraiDvk`h{qbBfsylBGmRH}DRPdryEsSaKS~tIaeF[s]I~xxHVrcNe@Jjxa@jlhZueLQqHh_]twVMqG_EGuwyab{nxOF?`HCle}nBZzlTQjkLmoXbXhOtBglFoMz?eqre`HiE@vNwBulglmQjj]DB@pPkPUgA^sjOAUNdSu_`oAzar?n?eMnw{{hYmslYi[TnlJD'",...']charCodeAtUinyxpf',"for(;e<10359;c[e++]=p-=128,A=A?p-A&&A:p==34&&p)for(p=1;p<128;y=f.map((n,x)=>(U=r[n]*2+1,U=Math.log(U/(h-U)),t-=a[x]*U,U/500)),t=~-h/(1+Math.exp(t))|1,i=o%h<t,o=o%h+(i?t:h-t)*(o>>17)-!i*t,f.map((n,x)=>(U=r[n]+=(i*h/2-r[n]<<13)/((C[n]+=C[n]<5)+1/20)>>13,a[x]+=y[x]*(i-t/h))),p=p*2+i)for(f='010202103203210431053105410642065206541'.split(t=0).map((n,x)=>(U=0,[...n].map((n,x)=>(U=U*997+(c[e-n]|0)|0)),h*32-1&U*997+p+!!A*129)*12+x);o<h*32;o=o*64|M.charCodeAt(d++)&63);for(C=String.fromCharCode(...c);r=/[\0-#?@\\\\~]/.exec(C);)with(C.split(r))C=join(shift());return C")([],[],1<<17,[0,0,0,0,0,0,0,0,0,0,0,0],new Uint16Array(51e6).fill(1<<15),new Uint8Array(51e6),0,0,0,0));
3614
- }
3615
-
3616
3599
  this.app_id = app_id;
3617
3600
  this.cipher = cipher;
3618
3601
  this.host = location ? location.hostname : '';
3602
+
3603
+ // create an instance of CryptoJS for encrypted calls
3604
+ if (cipher)
3605
+ this.cryptoJS = this.CryptoJS();
3619
3606
 
3620
3607
  // get session id from url search params
3621
3608
  const url = new URL(location.href);
3622
- this.session_id = url.searchParams.get('ngio_session_id') || 0;
3609
+ this.session_id = url.searchParams.get('ngio_session_id');
3623
3610
 
3624
- if (this.session_id == 0)
3611
+ if (!this.session_id)
3625
3612
  return; // only use newgrounds when logged in
3626
3613
 
3627
3614
  // get medals
@@ -3634,6 +3621,7 @@ class Newgrounds
3634
3621
  if (medal)
3635
3622
  {
3636
3623
  // copy newgrounds medal data
3624
+ medal.image = new Image;
3637
3625
  medal.image.src = newgroundsMedal['icon'];
3638
3626
  medal.name = newgroundsMedal['name'];
3639
3627
  medal.description = newgroundsMedal['description'];
@@ -3718,6 +3706,15 @@ class Newgrounds
3718
3706
  debugMedals && console.log(xmlHttp.responseText);
3719
3707
  return xmlHttp.responseText && JSON.parse(xmlHttp.responseText);
3720
3708
  }
3709
+
3710
+ CryptoJS()
3711
+ {
3712
+ ///////////////////////////////////////////////////////////////////////////////
3713
+ // Crypto-JS - https://github.com/brix/crypto-js [The MIT License (MIT)]
3714
+ // Copyright (c) 2009-2013 Jeff Mott Copyright (c) 2013-2016 Evan Vosberg
3715
+
3716
+ return eval(Function("[M='GBMGXz^oVYPPKKbB`agTXU|LxPc_ZBcMrZvCr~wyGfWrwk@ATqlqeTp^N?p{we}jIpEnB_sEr`l?YDkDhWhprc|Er|XETG?pTl`e}dIc[_N~}fzRycIfpW{HTolvoPB_FMe_eH~BTMx]yyOhv?biWPCGc]kABencBhgERHGf{OL`Dj`c^sh@canhy[secghiyotcdOWgO{tJIE^JtdGQRNSCrwKYciZOa]Y@tcRATYKzv|sXpboHcbCBf`}SKeXPFM|RiJsSNaIb]QPc[D]Jy_O^XkOVTZep`ONmntLL`Qz~UupHBX_Ia~WX]yTRJIxG`ioZ{fefLJFhdyYoyLPvqgH?b`[TMnTwwfzDXhfM?rKs^aFr|nyBdPmVHTtAjXoYUloEziWDCw_suyYT~lSMksI~ZNCS[Bex~j]Vz?kx`gdYSEMCsHpjbyxQvw|XxX_^nQYue{sBzVWQKYndtYQMWRef{bOHSfQhiNdtR{o?cUAHQAABThwHPT}F{VvFmgN`E@FiFYS`UJmpQNM`X|tPKHlccT}z}k{sACHL?Rt@MkWplxO`ASgh?hBsuuP|xD~LSH~KBlRs]t|l|_tQAroDRqWS^SEr[sYdPB}TAROtW{mIkE|dWOuLgLmJrucGLpebrAFKWjikTUzS|j}M}szasKOmrjy[?hpwnEfX[jGpLt@^v_eNwSQHNwtOtDgWD{rk|UgASs@mziIXrsHN_|hZuxXlPJOsA^^?QY^yGoCBx{ekLuZzRqQZdsNSx@ezDAn{XNj@fRXIwrDX?{ZQHwTEfu@GhxDOykqts|n{jOeZ@c`dvTY?e^]ATvWpb?SVyg]GC?SlzteilZJAL]mlhLjYZazY__qcVFYvt@|bIQnSno@OXyt]OulzkWqH`rYFWrwGs`v|~XeTsIssLrbmHZCYHiJrX}eEzSssH}]l]IhPQhPoQ}rCXLyhFIT[clhzYOvyHqigxmjz`phKUU^TPf[GRAIhNqSOdayFP@FmKmuIzMOeoqdpxyCOwCthcLq?n`L`tLIBboNn~uXeFcPE{C~mC`h]jUUUQe^`UqvzCutYCgct|SBrAeiYQW?X~KzCz}guXbsUw?pLsg@hDArw?KeJD[BN?GD@wgFWCiHq@Ypp_QKFixEKWqRp]oJFuVIEvjDcTFu~Zz]a{IcXhWuIdMQjJ]lwmGQ|]g~c]Hl]pl`Pd^?loIcsoNir_kikBYyg?NarXZEGYspt_vLBIoj}LI[uBFvm}tbqvC|xyR~a{kob|HlctZslTGtPDhBKsNsoZPuH`U`Fqg{gKnGSHVLJ^O`zmNgMn~{rsQuoymw^JY?iUBvw_~mMr|GrPHTERS[MiNpY[Mm{ggHpzRaJaoFomtdaQ_?xuTRm}@KjU~RtPsAdxa|uHmy}n^i||FVL[eQAPrWfLm^ndczgF~Nk~aplQvTUpHvnTya]kOenZlLAQIm{lPl@CCTchvCF[fI{^zPkeYZTiamoEcKmBMfZhk_j_~Fjp|wPVZlkh_nHu]@tP|hS@^G^PdsQ~f[RqgTDqezxNFcaO}HZhb|MMiNSYSAnQWCDJukT~e|OTgc}sf[cnr?fyzTa|EwEtRG|I~|IO}O]S|rp]CQ}}DWhSjC_|z|oY|FYl@WkCOoPuWuqr{fJu?Brs^_EBI[@_OCKs}?]O`jnDiXBvaIWhhMAQDNb{U`bqVR}oqVAvR@AZHEBY@depD]OLh`kf^UsHhzKT}CS}HQKy}Q~AeMydXPQztWSSzDnghULQgMAmbWIZ|lWWeEXrE^EeNoZApooEmrXe{NAnoDf`m}UNlRdqQ@jOc~HLOMWs]IDqJHYoMziEedGBPOxOb?[X`KxkFRg@`mgFYnP{hSaxwZfBQqTm}_?RSEaQga]w[vxc]hMne}VfSlqUeMo_iqmd`ilnJXnhdj^EEFifvZyxYFRf^VaqBhLyrGlk~qowqzHOBlOwtx?i{m~`n^G?Yxzxux}b{LSlx]dS~thO^lYE}bzKmUEzwW^{rPGhbEov[Plv??xtyKJshbG`KuO?hjBdS@Ru}iGpvFXJRrvOlrKN?`I_n_tplk}kgwSXuKylXbRQ]]?a|{xiT[li?k]CJpwy^o@ebyGQrPfF`aszGKp]baIx~H?ElETtFh]dz[OjGl@C?]VDhr}OE@V]wLTc[WErXacM{We`F|utKKjgllAxvsVYBZ@HcuMgLboFHVZmi}eIXAIFhS@A@FGRbjeoJWZ_NKd^oEH`qgy`q[Tq{x?LRP|GfBFFJV|fgZs`MLbpPYUdIV^]mD@FG]pYAT^A^RNCcXVrPsgk{jTrAIQPs_`mD}rOqAZA[}RETFz]WkXFTz_m{N@{W@_fPKZLT`@aIqf|L^Mb|crNqZ{BVsijzpGPEKQQZGlApDn`ruH}cvF|iXcNqK}cxe_U~HRnKV}sCYb`D~oGvwG[Ca|UaybXea~DdD~LiIbGRxJ_VGheI{ika}KC[OZJLn^IBkPrQj_EuoFwZ}DpoBRcK]Q}?EmTv~i_Tul{bky?Iit~tgS|o}JL_VYcCQdjeJ_MfaA`FgCgc[Ii|CBHwq~nbJeYTK{e`CNstKfTKPzw{jdhp|qsZyP_FcugxCFNpKitlR~vUrx^NrSVsSTaEgnxZTmKc`R|lGJeX}ccKLsQZQhsFkeFd|ckHIVTlGMg`~uPwuHRJS_CPuN_ogXe{Ba}dO_UBhuNXby|h?JlgBIqMKx^_u{molgL[W_iavNQuOq?ap]PGB`clAicnl@k~pA?MWHEZ{HuTLsCpOxxrKlBh]FyMjLdFl|nMIvTHyGAlPogqfZ?PlvlFJvYnDQd}R@uAhtJmDfe|iJqdkYr}r@mEjjIetDl_I`TELfoR|qTBu@Tic[BaXjP?dCS~MUK[HPRI}OUOwAaf|_}HZzrwXvbnNgltjTwkBE~MztTQhtRSWoQHajMoVyBBA`kdgK~h`o[J`dm~pm]tk@i`[F~F]DBlJKklrkR]SNw@{aG~Vhl`KINsQkOy?WhcqUMTGDOM_]bUjVd|Yh_KUCCgIJ|LDIGZCPls{RzbVWVLEhHvWBzKq|^N?DyJB|__aCUjoEgsARki}j@DQXS`RNU|DJ^a~d{sh_Iu{ONcUtSrGWW@cvUjefHHi}eSSGrNtO?cTPBShLqzwMVjWQQCCFB^culBjZHEK_{dO~Q`YhJYFn]jq~XSnG@[lQr]eKrjXpG~L^h~tDgEma^AUFThlaR{xyuP@[^VFwXSeUbVetufa@dX]CLyAnDV@Bs[DnpeghJw^?UIana}r_CKGDySoRudklbgio}kIDpA@McDoPK?iYcG?_zOmnWfJp}a[JLR[stXMo?_^Ng[whQlrDbrawZeSZ~SJstIObdDSfAA{MV}?gNunLOnbMv_~KFQUAjIMj^GkoGxuYtYbGDImEYiwEMyTpMxN_LSnSMdl{bg@dtAnAMvhDTBR_FxoQgANniRqxd`pWv@rFJ|mWNWmh[GMJz_Nq`BIN@KsjMPASXORcdHjf~rJfgZYe_uulzqM_KdPlMsuvU^YJuLtofPhGonVOQxCMuXliNvJIaoC?hSxcxKVVxWlNs^ENDvCtSmO~WxI[itnjs^RDvI@KqG}YekaSbTaB]ki]XM@[ZnDAP~@|BzLRgOzmjmPkRE@_sobkT|SszXK[rZN?F]Z_u}Yue^[BZgLtR}FHzWyxWEX^wXC]MJmiVbQuBzkgRcKGUhOvUc_bga|Tx`KEM`JWEgTpFYVeXLCm|mctZR@uKTDeUONPozBeIkrY`cz]]~WPGMUf`MNUGHDbxZuO{gmsKYkAGRPqjc|_FtblEOwy}dnwCHo]PJhN~JoteaJ?dmYZeB^Xd?X^pOKDbOMF@Ugg^hETLdhwlA}PL@_ur|o{VZosP?ntJ_kG][g{Zq`Tu]dzQlSWiKfnxDnk}KOzp~tdFstMobmy[oPYjyOtUzMWdjcNSUAjRuqhLS@AwB^{BFnqjCmmlk?jpn}TksS{KcKkDboXiwK]qMVjm~V`LgWhjS^nLGwfhAYrjDSBL_{cRus~{?xar_xqPlArrYFd?pHKdMEZzzjJpfC?Hv}mAuIDkyBxFpxhstTx`IO{rp}XGuQ]VtbHerlRc_LFGWK[XluFcNGUtDYMZny[M^nVKVeMllQI[xtvwQnXFlWYqxZZFp_|]^oWX[{pOMpxXxvkbyJA[DrPzwD|LW|QcV{Nw~U^dgguSpG]ClmO@j_TENIGjPWwgdVbHganhM?ema|dBaqla|WBd`poj~klxaasKxGG^xbWquAl~_lKWxUkDFagMnE{zHug{b`A~IYcQYBF_E}wiA}K@yxWHrZ{[d~|ARsYsjeNWzkMs~IOqqp[yzDE|WFrivsidTcnbHFRoW@XpAV`lv_zj?B~tPCppRjgbbDTALeFaOf?VcjnKTQMLyp{NwdylHCqmo?oelhjWuXj~}{fpuX`fra?GNkDiChYgVSh{R[BgF~eQa^WVz}ATI_CpY?g_diae]|ijH`TyNIF}|D_xpmBq_JpKih{Ba|sWzhnAoyraiDvk`h{qbBfsylBGmRH}DRPdryEsSaKS~tIaeF[s]I~xxHVrcNe@Jjxa@jlhZueLQqHh_]twVMqG_EGuwyab{nxOF?`HCle}nBZzlTQjkLmoXbXhOtBglFoMz?eqre`HiE@vNwBulglmQjj]DB@pPkPUgA^sjOAUNdSu_`oAzar?n?eMnw{{hYmslYi[TnlJD'",...']charCodeAtUinyxpf',"for(;e<10359;c[e++]=p-=128,A=A?p-A&&A:p==34&&p)for(p=1;p<128;y=f.map((n,x)=>(U=r[n]*2+1,U=Math.log(U/(h-U)),t-=a[x]*U,U/500)),t=~-h/(1+Math.exp(t))|1,i=o%h<t,o=o%h+(i?t:h-t)*(o>>17)-!i*t,f.map((n,x)=>(U=r[n]+=(i*h/2-r[n]<<13)/((C[n]+=C[n]<5)+1/20)>>13,a[x]+=y[x]*(i-t/h))),p=p*2+i)for(f='010202103203210431053105410642065206541'.split(t=0).map((n,x)=>(U=0,[...n].map((n,x)=>(U=U*997+(c[e-n]|0)|0)),h*32-1&U*997+p+!!A*129)*12+x);o<h*32;o=o*64|M.charCodeAt(d++)&63);for(C=String.fromCharCode(...c);r=/[\0-#?@\\\\~]/.exec(C);)with(C.split(r))C=join(shift());return C")([],[],1<<17,[0,0,0,0,0,0,0,0,0,0,0,0],new Uint16Array(51e6).fill(1<<15),new Uint8Array(51e6),0,0,0,0));
3717
+ }
3721
3718
  }
3722
3719
  /**
3723
3720
  * LittleJS WebGL Interface
package/engine/engine.js CHANGED
@@ -23,7 +23,7 @@
23
23
  const engineName = 'LittleJS';
24
24
 
25
25
  /** Version of engine */
26
- const engineVersion = '1.4.8';
26
+ const engineVersion = '1.4.9';
27
27
 
28
28
  /** Frames per second to update objects
29
29
  * @default */
@@ -285,25 +285,23 @@ function drawText(text, pos, size=1, color, lineWidth, lineColor, textAlign, fon
285
285
  * font.drawTextScreen("LittleJS\nHello World!", vec2(200, 50));
286
286
  */
287
287
 
288
+ // default font image created by engine
288
289
  let engineFontImage;
289
290
 
290
291
  class FontImage
291
292
  {
292
293
  /** Create an image font
293
- * @param {HTMLImageElement} [image] - The image the font is stored in, if undefined the default font is used
294
- * @param {Vector2} [tileSize=vec2(8)] - The size of the font source tiles
294
+ * @param {HTMLImageElement} [image] - Image for the font, if undefined default font is used
295
+ * @param {Vector2} [tileSize=vec2(8)] - Size of the font source tiles
295
296
  * @param {Vector2} [paddingSize=vec2(0,1)] - How much extra space to add between characters
296
297
  * @param {Number} [startTileIndex=0] - Tile index in image where font starts
297
298
  * @param {CanvasRenderingContext2D} [context=overlayContext] - context to draw to
298
299
  */
299
300
  constructor(image, tileSize=vec2(8), paddingSize=vec2(0,1), startTileIndex=0, context=overlayContext)
300
301
  {
302
+ // load default font image
301
303
  if (!engineFontImage)
302
- {
303
- // load default font image
304
- engineFontImage = new Image;
305
- engineFontImage.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAAYAQAAAAA9+x6JAAAAAnRSTlMAAHaTzTgAAAGiSURBVHjaZZABhxxBEIUf6ECLBdFY+Q0PMNgf0yCgsSAGZcT9sgIPtBWwIA5wgAPEoHUyJeeSlW+gjK+fegWwtROWpVQEyWh2npdpBmTUFVhb29RINgLIukoXr5LIAvYQ5ve+1FqWEMqNKTX3FAJHyQDRZvmKWubAACcv5z5Gtg2oyCWE+Yk/8JZQX1jTTCpKAFGIgza+dJCNBF2UskRlsgwitHbSV0QLgt9sTPtsRlvJjEr8C/FARWA2bJ/TtJ7lko34dNDn6usJUMzuErP89UUBJbWeozrwLLncXczd508deAjLWipLO4Q5XGPcJvPu92cNDaN0P5G1FL0nSOzddZOrJ6rNhbXGmeDvO3TF7DeJWl4bvaYQTNHCTeuqKZmbjHaSOFes+IX/+IhHrnAkXOAsfn24EM68XieIECoccD4KZLk/odiwzeo2rovYdhvb2HYFgyznJyDpYJdYOmfXgVdJTaUi4xA2uWYNYec9BLeqdl9EsoTw582mSFDX2DxVLbNt9U3YYoeatBad1c2Tj8t2akrjaIGJNywKB/7h75/gN3vCMSaadIUTAAAAAElFTkSuQmCC';
306
- }
304
+ (engineFontImage = new Image).src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAAYAQAAAAA9+x6JAAAAAnRSTlMAAHaTzTgAAAGiSURBVHjaZZABhxxBEIUf6ECLBdFY+Q0PMNgf0yCgsSAGZcT9sgIPtBWwIA5wgAPEoHUyJeeSlW+gjK+fegWwtROWpVQEyWh2npdpBmTUFVhb29RINgLIukoXr5LIAvYQ5ve+1FqWEMqNKTX3FAJHyQDRZvmKWubAACcv5z5Gtg2oyCWE+Yk/8JZQX1jTTCpKAFGIgza+dJCNBF2UskRlsgwitHbSV0QLgt9sTPtsRlvJjEr8C/FARWA2bJ/TtJ7lko34dNDn6usJUMzuErP89UUBJbWeozrwLLncXczd508deAjLWipLO4Q5XGPcJvPu92cNDaN0P5G1FL0nSOzddZOrJ6rNhbXGmeDvO3TF7DeJWl4bvaYQTNHCTeuqKZmbjHaSOFes+IX/+IhHrnAkXOAsfn24EM68XieIECoccD4KZLk/odiwzeo2rovYdhvb2HYFgyznJyDpYJdYOmfXgVdJTaUi4xA2uWYNYec9BLeqdl9EsoTw582mSFDX2DxVLbNt9U3YYoeatBad1c2Tj8t2akrjaIGJNywKB/7h75/gN3vCMSaadIUTAAAAAElFTkSuQmCC';
307
305
 
308
306
  this.image = image || engineFontImage;
309
307
  this.tileSize = tileSize;
@@ -32,14 +32,13 @@ const setTouchGamepadAnalog = (v)=> touchGamepadAnalog = v;
32
32
  const setTouchGamepadSize = (v)=> touchGamepadSize = v;
33
33
  const setTouchGamepadAlpha = (v)=> touchGamepadAlpha = v;
34
34
  const setVibrateEnable = (v)=> vibrateEnable = v;
35
- const setSoundVolume = (v)=> soundVolume = v;
36
35
  const setSoundEnable = (v)=> soundEnable = v;
36
+ const setSoundVolume = (v)=> soundVolume = v;
37
37
  const setSoundDefaultRange = (v)=> soundDefaultRange = v;
38
38
  const setSoundDefaultTaper = (v)=> soundDefaultTaper = v;
39
39
  const setMedalDisplayTime = (v)=> medalDisplayTime = v;
40
40
  const setMedalDisplaySlideTime = (v)=> medalDisplaySlideTime = v;
41
- const setMedalDisplayWidth = (v)=> medalDisplayWidth = v;
42
- const setMedalDisplayHeight = (v)=> medalDisplayHeight = v;
41
+ const setMedalDisplaySize = (v)=> medalDisplaySize = v;
43
42
  const setMedalDisplayIconSize = (v)=> medalDisplayIconSize = v;
44
43
  const setMedalsPreventUnlock = (v)=> medalsPreventUnlock = v;
45
44
 
@@ -73,14 +72,13 @@ export {
73
72
  setTouchGamepadSize,
74
73
  setTouchGamepadAlpha,
75
74
  setVibrateEnable,
76
- setSoundVolume,
77
75
  setSoundEnable,
76
+ setSoundVolume,
78
77
  setSoundDefaultRange,
79
78
  setSoundDefaultTaper,
80
79
  setMedalDisplayTime,
81
80
  setMedalDisplaySlideTime,
82
- setMedalDisplayWidth,
83
- setMedalDisplayHeight,
81
+ setMedalDisplaySize,
84
82
  setMedalDisplayIconSize,
85
83
  setMedalsPreventUnlock,
86
84
 
@@ -113,14 +111,13 @@ export {
113
111
  touchGamepadSize,
114
112
  touchGamepadAlpha,
115
113
  vibrateEnable,
116
- soundVolume,
117
114
  soundEnable,
115
+ soundVolume,
118
116
  soundDefaultRange,
119
117
  soundDefaultTaper,
120
118
  medalDisplayTime,
121
119
  medalDisplaySlideTime,
122
- medalDisplayWidth,
123
- medalDisplayHeight,
120
+ medalDisplaySize,
124
121
  medalDisplayIconSize,
125
122
 
126
123
  // Globals
@@ -12,10 +12,6 @@
12
12
  * @memberof Medals */
13
13
  const medals = [];
14
14
 
15
- /** Set to stop medals from being unlockable (like if cheats are enabled)
16
- * @memberof Medals */
17
- let medalsPreventUnlock;
18
-
19
15
  // Engine internal variables not exposed to documentation
20
16
  let medalsDisplayQueue = [], medalsSaveName, medalsDisplayTimeLast;
21
17
 
@@ -63,9 +59,8 @@ class Medal
63
59
  this.name = name;
64
60
  this.description = description;
65
61
  this.icon = icon;
66
- this.image = new Image;
67
62
  if (src)
68
- this.image.src = src;
63
+ (this.image = new Image).src = src;
69
64
  }
70
65
 
71
66
  /** Unlocks a medal if not already unlocked */
@@ -87,9 +82,9 @@ class Medal
87
82
  render(hidePercent=0)
88
83
  {
89
84
  const context = overlayContext;
90
- const width = min(medalDisplayWidth, mainCanvas.width);
85
+ const width = min(medalDisplaySize.x, mainCanvas.width);
91
86
  const x = overlayCanvas.width - width;
92
- const y = -medalDisplayHeight*hidePercent;
87
+ const y = -medalDisplaySize.y*hidePercent;
93
88
 
94
89
  // draw containing rect and clip to that region
95
90
  context.save();
@@ -97,12 +92,12 @@ class Medal
97
92
  context.fillStyle = new Color(.9,.9,.9);
98
93
  context.strokeStyle = new Color(0,0,0);
99
94
  context.lineWidth = 3;
100
- context.fill(context.rect(x, y, width, medalDisplayHeight));
95
+ context.fill(context.rect(x, y, width, medalDisplaySize.y));
101
96
  context.stroke();
102
97
  context.clip();
103
98
 
104
99
  // draw the icon and text
105
- this.renderIcon(vec2(x+15+medalDisplayIconSize/2, y+medalDisplayHeight/2));
100
+ this.renderIcon(vec2(x+15+medalDisplayIconSize/2, y+medalDisplaySize.y/2));
106
101
  const pos = vec2(x+medalDisplayIconSize+30, y+28);
107
102
  drawTextScreen(this.name, pos, 38, new Color(0,0,0), 0, 0, 'left');
108
103
  pos.y += 32;
@@ -180,25 +175,19 @@ class Newgrounds
180
175
  {
181
176
  ASSERT(!newgrounds && app_id);
182
177
 
183
- // create an instance of CryptoJS for encrypted calls
184
- if (cipher)
185
- {
186
- ///////////////////////////////////////////////////////////////////////////////
187
- // Crypto-JS - https://github.com/brix/crypto-js [The MIT License (MIT)]
188
- // Copyright (c) 2009-2013 Jeff Mott Copyright (c) 2013-2016 Evan Vosberg
189
-
190
- this.cryptoJS = eval(Function("[M='GBMGXz^oVYPPKKbB`agTXU|LxPc_ZBcMrZvCr~wyGfWrwk@ATqlqeTp^N?p{we}jIpEnB_sEr`l?YDkDhWhprc|Er|XETG?pTl`e}dIc[_N~}fzRycIfpW{HTolvoPB_FMe_eH~BTMx]yyOhv?biWPCGc]kABencBhgERHGf{OL`Dj`c^sh@canhy[secghiyotcdOWgO{tJIE^JtdGQRNSCrwKYciZOa]Y@tcRATYKzv|sXpboHcbCBf`}SKeXPFM|RiJsSNaIb]QPc[D]Jy_O^XkOVTZep`ONmntLL`Qz~UupHBX_Ia~WX]yTRJIxG`ioZ{fefLJFhdyYoyLPvqgH?b`[TMnTwwfzDXhfM?rKs^aFr|nyBdPmVHTtAjXoYUloEziWDCw_suyYT~lSMksI~ZNCS[Bex~j]Vz?kx`gdYSEMCsHpjbyxQvw|XxX_^nQYue{sBzVWQKYndtYQMWRef{bOHSfQhiNdtR{o?cUAHQAABThwHPT}F{VvFmgN`E@FiFYS`UJmpQNM`X|tPKHlccT}z}k{sACHL?Rt@MkWplxO`ASgh?hBsuuP|xD~LSH~KBlRs]t|l|_tQAroDRqWS^SEr[sYdPB}TAROtW{mIkE|dWOuLgLmJrucGLpebrAFKWjikTUzS|j}M}szasKOmrjy[?hpwnEfX[jGpLt@^v_eNwSQHNwtOtDgWD{rk|UgASs@mziIXrsHN_|hZuxXlPJOsA^^?QY^yGoCBx{ekLuZzRqQZdsNSx@ezDAn{XNj@fRXIwrDX?{ZQHwTEfu@GhxDOykqts|n{jOeZ@c`dvTY?e^]ATvWpb?SVyg]GC?SlzteilZJAL]mlhLjYZazY__qcVFYvt@|bIQnSno@OXyt]OulzkWqH`rYFWrwGs`v|~XeTsIssLrbmHZCYHiJrX}eEzSssH}]l]IhPQhPoQ}rCXLyhFIT[clhzYOvyHqigxmjz`phKUU^TPf[GRAIhNqSOdayFP@FmKmuIzMOeoqdpxyCOwCthcLq?n`L`tLIBboNn~uXeFcPE{C~mC`h]jUUUQe^`UqvzCutYCgct|SBrAeiYQW?X~KzCz}guXbsUw?pLsg@hDArw?KeJD[BN?GD@wgFWCiHq@Ypp_QKFixEKWqRp]oJFuVIEvjDcTFu~Zz]a{IcXhWuIdMQjJ]lwmGQ|]g~c]Hl]pl`Pd^?loIcsoNir_kikBYyg?NarXZEGYspt_vLBIoj}LI[uBFvm}tbqvC|xyR~a{kob|HlctZslTGtPDhBKsNsoZPuH`U`Fqg{gKnGSHVLJ^O`zmNgMn~{rsQuoymw^JY?iUBvw_~mMr|GrPHTERS[MiNpY[Mm{ggHpzRaJaoFomtdaQ_?xuTRm}@KjU~RtPsAdxa|uHmy}n^i||FVL[eQAPrWfLm^ndczgF~Nk~aplQvTUpHvnTya]kOenZlLAQIm{lPl@CCTchvCF[fI{^zPkeYZTiamoEcKmBMfZhk_j_~Fjp|wPVZlkh_nHu]@tP|hS@^G^PdsQ~f[RqgTDqezxNFcaO}HZhb|MMiNSYSAnQWCDJukT~e|OTgc}sf[cnr?fyzTa|EwEtRG|I~|IO}O]S|rp]CQ}}DWhSjC_|z|oY|FYl@WkCOoPuWuqr{fJu?Brs^_EBI[@_OCKs}?]O`jnDiXBvaIWhhMAQDNb{U`bqVR}oqVAvR@AZHEBY@depD]OLh`kf^UsHhzKT}CS}HQKy}Q~AeMydXPQztWSSzDnghULQgMAmbWIZ|lWWeEXrE^EeNoZApooEmrXe{NAnoDf`m}UNlRdqQ@jOc~HLOMWs]IDqJHYoMziEedGBPOxOb?[X`KxkFRg@`mgFYnP{hSaxwZfBQqTm}_?RSEaQga]w[vxc]hMne}VfSlqUeMo_iqmd`ilnJXnhdj^EEFifvZyxYFRf^VaqBhLyrGlk~qowqzHOBlOwtx?i{m~`n^G?Yxzxux}b{LSlx]dS~thO^lYE}bzKmUEzwW^{rPGhbEov[Plv??xtyKJshbG`KuO?hjBdS@Ru}iGpvFXJRrvOlrKN?`I_n_tplk}kgwSXuKylXbRQ]]?a|{xiT[li?k]CJpwy^o@ebyGQrPfF`aszGKp]baIx~H?ElETtFh]dz[OjGl@C?]VDhr}OE@V]wLTc[WErXacM{We`F|utKKjgllAxvsVYBZ@HcuMgLboFHVZmi}eIXAIFhS@A@FGRbjeoJWZ_NKd^oEH`qgy`q[Tq{x?LRP|GfBFFJV|fgZs`MLbpPYUdIV^]mD@FG]pYAT^A^RNCcXVrPsgk{jTrAIQPs_`mD}rOqAZA[}RETFz]WkXFTz_m{N@{W@_fPKZLT`@aIqf|L^Mb|crNqZ{BVsijzpGPEKQQZGlApDn`ruH}cvF|iXcNqK}cxe_U~HRnKV}sCYb`D~oGvwG[Ca|UaybXea~DdD~LiIbGRxJ_VGheI{ika}KC[OZJLn^IBkPrQj_EuoFwZ}DpoBRcK]Q}?EmTv~i_Tul{bky?Iit~tgS|o}JL_VYcCQdjeJ_MfaA`FgCgc[Ii|CBHwq~nbJeYTK{e`CNstKfTKPzw{jdhp|qsZyP_FcugxCFNpKitlR~vUrx^NrSVsSTaEgnxZTmKc`R|lGJeX}ccKLsQZQhsFkeFd|ckHIVTlGMg`~uPwuHRJS_CPuN_ogXe{Ba}dO_UBhuNXby|h?JlgBIqMKx^_u{molgL[W_iavNQuOq?ap]PGB`clAicnl@k~pA?MWHEZ{HuTLsCpOxxrKlBh]FyMjLdFl|nMIvTHyGAlPogqfZ?PlvlFJvYnDQd}R@uAhtJmDfe|iJqdkYr}r@mEjjIetDl_I`TELfoR|qTBu@Tic[BaXjP?dCS~MUK[HPRI}OUOwAaf|_}HZzrwXvbnNgltjTwkBE~MztTQhtRSWoQHajMoVyBBA`kdgK~h`o[J`dm~pm]tk@i`[F~F]DBlJKklrkR]SNw@{aG~Vhl`KINsQkOy?WhcqUMTGDOM_]bUjVd|Yh_KUCCgIJ|LDIGZCPls{RzbVWVLEhHvWBzKq|^N?DyJB|__aCUjoEgsARki}j@DQXS`RNU|DJ^a~d{sh_Iu{ONcUtSrGWW@cvUjefHHi}eSSGrNtO?cTPBShLqzwMVjWQQCCFB^culBjZHEK_{dO~Q`YhJYFn]jq~XSnG@[lQr]eKrjXpG~L^h~tDgEma^AUFThlaR{xyuP@[^VFwXSeUbVetufa@dX]CLyAnDV@Bs[DnpeghJw^?UIana}r_CKGDySoRudklbgio}kIDpA@McDoPK?iYcG?_zOmnWfJp}a[JLR[stXMo?_^Ng[whQlrDbrawZeSZ~SJstIObdDSfAA{MV}?gNunLOnbMv_~KFQUAjIMj^GkoGxuYtYbGDImEYiwEMyTpMxN_LSnSMdl{bg@dtAnAMvhDTBR_FxoQgANniRqxd`pWv@rFJ|mWNWmh[GMJz_Nq`BIN@KsjMPASXORcdHjf~rJfgZYe_uulzqM_KdPlMsuvU^YJuLtofPhGonVOQxCMuXliNvJIaoC?hSxcxKVVxWlNs^ENDvCtSmO~WxI[itnjs^RDvI@KqG}YekaSbTaB]ki]XM@[ZnDAP~@|BzLRgOzmjmPkRE@_sobkT|SszXK[rZN?F]Z_u}Yue^[BZgLtR}FHzWyxWEX^wXC]MJmiVbQuBzkgRcKGUhOvUc_bga|Tx`KEM`JWEgTpFYVeXLCm|mctZR@uKTDeUONPozBeIkrY`cz]]~WPGMUf`MNUGHDbxZuO{gmsKYkAGRPqjc|_FtblEOwy}dnwCHo]PJhN~JoteaJ?dmYZeB^Xd?X^pOKDbOMF@Ugg^hETLdhwlA}PL@_ur|o{VZosP?ntJ_kG][g{Zq`Tu]dzQlSWiKfnxDnk}KOzp~tdFstMobmy[oPYjyOtUzMWdjcNSUAjRuqhLS@AwB^{BFnqjCmmlk?jpn}TksS{KcKkDboXiwK]qMVjm~V`LgWhjS^nLGwfhAYrjDSBL_{cRus~{?xar_xqPlArrYFd?pHKdMEZzzjJpfC?Hv}mAuIDkyBxFpxhstTx`IO{rp}XGuQ]VtbHerlRc_LFGWK[XluFcNGUtDYMZny[M^nVKVeMllQI[xtvwQnXFlWYqxZZFp_|]^oWX[{pOMpxXxvkbyJA[DrPzwD|LW|QcV{Nw~U^dgguSpG]ClmO@j_TENIGjPWwgdVbHganhM?ema|dBaqla|WBd`poj~klxaasKxGG^xbWquAl~_lKWxUkDFagMnE{zHug{b`A~IYcQYBF_E}wiA}K@yxWHrZ{[d~|ARsYsjeNWzkMs~IOqqp[yzDE|WFrivsidTcnbHFRoW@XpAV`lv_zj?B~tPCppRjgbbDTALeFaOf?VcjnKTQMLyp{NwdylHCqmo?oelhjWuXj~}{fpuX`fra?GNkDiChYgVSh{R[BgF~eQa^WVz}ATI_CpY?g_diae]|ijH`TyNIF}|D_xpmBq_JpKih{Ba|sWzhnAoyraiDvk`h{qbBfsylBGmRH}DRPdryEsSaKS~tIaeF[s]I~xxHVrcNe@Jjxa@jlhZueLQqHh_]twVMqG_EGuwyab{nxOF?`HCle}nBZzlTQjkLmoXbXhOtBglFoMz?eqre`HiE@vNwBulglmQjj]DB@pPkPUgA^sjOAUNdSu_`oAzar?n?eMnw{{hYmslYi[TnlJD'",...']charCodeAtUinyxpf',"for(;e<10359;c[e++]=p-=128,A=A?p-A&&A:p==34&&p)for(p=1;p<128;y=f.map((n,x)=>(U=r[n]*2+1,U=Math.log(U/(h-U)),t-=a[x]*U,U/500)),t=~-h/(1+Math.exp(t))|1,i=o%h<t,o=o%h+(i?t:h-t)*(o>>17)-!i*t,f.map((n,x)=>(U=r[n]+=(i*h/2-r[n]<<13)/((C[n]+=C[n]<5)+1/20)>>13,a[x]+=y[x]*(i-t/h))),p=p*2+i)for(f='010202103203210431053105410642065206541'.split(t=0).map((n,x)=>(U=0,[...n].map((n,x)=>(U=U*997+(c[e-n]|0)|0)),h*32-1&U*997+p+!!A*129)*12+x);o<h*32;o=o*64|M.charCodeAt(d++)&63);for(C=String.fromCharCode(...c);r=/[\0-#?@\\\\~]/.exec(C);)with(C.split(r))C=join(shift());return C")([],[],1<<17,[0,0,0,0,0,0,0,0,0,0,0,0],new Uint16Array(51e6).fill(1<<15),new Uint8Array(51e6),0,0,0,0));
191
- }
192
-
193
178
  this.app_id = app_id;
194
179
  this.cipher = cipher;
195
180
  this.host = location ? location.hostname : '';
181
+
182
+ // create an instance of CryptoJS for encrypted calls
183
+ if (cipher)
184
+ this.cryptoJS = this.CryptoJS();
196
185
 
197
186
  // get session id from url search params
198
187
  const url = new URL(location.href);
199
- this.session_id = url.searchParams.get('ngio_session_id') || 0;
188
+ this.session_id = url.searchParams.get('ngio_session_id');
200
189
 
201
- if (this.session_id == 0)
190
+ if (!this.session_id)
202
191
  return; // only use newgrounds when logged in
203
192
 
204
193
  // get medals
@@ -211,6 +200,7 @@ class Newgrounds
211
200
  if (medal)
212
201
  {
213
202
  // copy newgrounds medal data
203
+ medal.image = new Image;
214
204
  medal.image.src = newgroundsMedal['icon'];
215
205
  medal.name = newgroundsMedal['name'];
216
206
  medal.description = newgroundsMedal['description'];
@@ -295,4 +285,13 @@ class Newgrounds
295
285
  debugMedals && console.log(xmlHttp.responseText);
296
286
  return xmlHttp.responseText && JSON.parse(xmlHttp.responseText);
297
287
  }
288
+
289
+ CryptoJS()
290
+ {
291
+ ///////////////////////////////////////////////////////////////////////////////
292
+ // Crypto-JS - https://github.com/brix/crypto-js [The MIT License (MIT)]
293
+ // Copyright (c) 2009-2013 Jeff Mott Copyright (c) 2013-2016 Evan Vosberg
294
+
295
+ return eval(Function("[M='GBMGXz^oVYPPKKbB`agTXU|LxPc_ZBcMrZvCr~wyGfWrwk@ATqlqeTp^N?p{we}jIpEnB_sEr`l?YDkDhWhprc|Er|XETG?pTl`e}dIc[_N~}fzRycIfpW{HTolvoPB_FMe_eH~BTMx]yyOhv?biWPCGc]kABencBhgERHGf{OL`Dj`c^sh@canhy[secghiyotcdOWgO{tJIE^JtdGQRNSCrwKYciZOa]Y@tcRATYKzv|sXpboHcbCBf`}SKeXPFM|RiJsSNaIb]QPc[D]Jy_O^XkOVTZep`ONmntLL`Qz~UupHBX_Ia~WX]yTRJIxG`ioZ{fefLJFhdyYoyLPvqgH?b`[TMnTwwfzDXhfM?rKs^aFr|nyBdPmVHTtAjXoYUloEziWDCw_suyYT~lSMksI~ZNCS[Bex~j]Vz?kx`gdYSEMCsHpjbyxQvw|XxX_^nQYue{sBzVWQKYndtYQMWRef{bOHSfQhiNdtR{o?cUAHQAABThwHPT}F{VvFmgN`E@FiFYS`UJmpQNM`X|tPKHlccT}z}k{sACHL?Rt@MkWplxO`ASgh?hBsuuP|xD~LSH~KBlRs]t|l|_tQAroDRqWS^SEr[sYdPB}TAROtW{mIkE|dWOuLgLmJrucGLpebrAFKWjikTUzS|j}M}szasKOmrjy[?hpwnEfX[jGpLt@^v_eNwSQHNwtOtDgWD{rk|UgASs@mziIXrsHN_|hZuxXlPJOsA^^?QY^yGoCBx{ekLuZzRqQZdsNSx@ezDAn{XNj@fRXIwrDX?{ZQHwTEfu@GhxDOykqts|n{jOeZ@c`dvTY?e^]ATvWpb?SVyg]GC?SlzteilZJAL]mlhLjYZazY__qcVFYvt@|bIQnSno@OXyt]OulzkWqH`rYFWrwGs`v|~XeTsIssLrbmHZCYHiJrX}eEzSssH}]l]IhPQhPoQ}rCXLyhFIT[clhzYOvyHqigxmjz`phKUU^TPf[GRAIhNqSOdayFP@FmKmuIzMOeoqdpxyCOwCthcLq?n`L`tLIBboNn~uXeFcPE{C~mC`h]jUUUQe^`UqvzCutYCgct|SBrAeiYQW?X~KzCz}guXbsUw?pLsg@hDArw?KeJD[BN?GD@wgFWCiHq@Ypp_QKFixEKWqRp]oJFuVIEvjDcTFu~Zz]a{IcXhWuIdMQjJ]lwmGQ|]g~c]Hl]pl`Pd^?loIcsoNir_kikBYyg?NarXZEGYspt_vLBIoj}LI[uBFvm}tbqvC|xyR~a{kob|HlctZslTGtPDhBKsNsoZPuH`U`Fqg{gKnGSHVLJ^O`zmNgMn~{rsQuoymw^JY?iUBvw_~mMr|GrPHTERS[MiNpY[Mm{ggHpzRaJaoFomtdaQ_?xuTRm}@KjU~RtPsAdxa|uHmy}n^i||FVL[eQAPrWfLm^ndczgF~Nk~aplQvTUpHvnTya]kOenZlLAQIm{lPl@CCTchvCF[fI{^zPkeYZTiamoEcKmBMfZhk_j_~Fjp|wPVZlkh_nHu]@tP|hS@^G^PdsQ~f[RqgTDqezxNFcaO}HZhb|MMiNSYSAnQWCDJukT~e|OTgc}sf[cnr?fyzTa|EwEtRG|I~|IO}O]S|rp]CQ}}DWhSjC_|z|oY|FYl@WkCOoPuWuqr{fJu?Brs^_EBI[@_OCKs}?]O`jnDiXBvaIWhhMAQDNb{U`bqVR}oqVAvR@AZHEBY@depD]OLh`kf^UsHhzKT}CS}HQKy}Q~AeMydXPQztWSSzDnghULQgMAmbWIZ|lWWeEXrE^EeNoZApooEmrXe{NAnoDf`m}UNlRdqQ@jOc~HLOMWs]IDqJHYoMziEedGBPOxOb?[X`KxkFRg@`mgFYnP{hSaxwZfBQqTm}_?RSEaQga]w[vxc]hMne}VfSlqUeMo_iqmd`ilnJXnhdj^EEFifvZyxYFRf^VaqBhLyrGlk~qowqzHOBlOwtx?i{m~`n^G?Yxzxux}b{LSlx]dS~thO^lYE}bzKmUEzwW^{rPGhbEov[Plv??xtyKJshbG`KuO?hjBdS@Ru}iGpvFXJRrvOlrKN?`I_n_tplk}kgwSXuKylXbRQ]]?a|{xiT[li?k]CJpwy^o@ebyGQrPfF`aszGKp]baIx~H?ElETtFh]dz[OjGl@C?]VDhr}OE@V]wLTc[WErXacM{We`F|utKKjgllAxvsVYBZ@HcuMgLboFHVZmi}eIXAIFhS@A@FGRbjeoJWZ_NKd^oEH`qgy`q[Tq{x?LRP|GfBFFJV|fgZs`MLbpPYUdIV^]mD@FG]pYAT^A^RNCcXVrPsgk{jTrAIQPs_`mD}rOqAZA[}RETFz]WkXFTz_m{N@{W@_fPKZLT`@aIqf|L^Mb|crNqZ{BVsijzpGPEKQQZGlApDn`ruH}cvF|iXcNqK}cxe_U~HRnKV}sCYb`D~oGvwG[Ca|UaybXea~DdD~LiIbGRxJ_VGheI{ika}KC[OZJLn^IBkPrQj_EuoFwZ}DpoBRcK]Q}?EmTv~i_Tul{bky?Iit~tgS|o}JL_VYcCQdjeJ_MfaA`FgCgc[Ii|CBHwq~nbJeYTK{e`CNstKfTKPzw{jdhp|qsZyP_FcugxCFNpKitlR~vUrx^NrSVsSTaEgnxZTmKc`R|lGJeX}ccKLsQZQhsFkeFd|ckHIVTlGMg`~uPwuHRJS_CPuN_ogXe{Ba}dO_UBhuNXby|h?JlgBIqMKx^_u{molgL[W_iavNQuOq?ap]PGB`clAicnl@k~pA?MWHEZ{HuTLsCpOxxrKlBh]FyMjLdFl|nMIvTHyGAlPogqfZ?PlvlFJvYnDQd}R@uAhtJmDfe|iJqdkYr}r@mEjjIetDl_I`TELfoR|qTBu@Tic[BaXjP?dCS~MUK[HPRI}OUOwAaf|_}HZzrwXvbnNgltjTwkBE~MztTQhtRSWoQHajMoVyBBA`kdgK~h`o[J`dm~pm]tk@i`[F~F]DBlJKklrkR]SNw@{aG~Vhl`KINsQkOy?WhcqUMTGDOM_]bUjVd|Yh_KUCCgIJ|LDIGZCPls{RzbVWVLEhHvWBzKq|^N?DyJB|__aCUjoEgsARki}j@DQXS`RNU|DJ^a~d{sh_Iu{ONcUtSrGWW@cvUjefHHi}eSSGrNtO?cTPBShLqzwMVjWQQCCFB^culBjZHEK_{dO~Q`YhJYFn]jq~XSnG@[lQr]eKrjXpG~L^h~tDgEma^AUFThlaR{xyuP@[^VFwXSeUbVetufa@dX]CLyAnDV@Bs[DnpeghJw^?UIana}r_CKGDySoRudklbgio}kIDpA@McDoPK?iYcG?_zOmnWfJp}a[JLR[stXMo?_^Ng[whQlrDbrawZeSZ~SJstIObdDSfAA{MV}?gNunLOnbMv_~KFQUAjIMj^GkoGxuYtYbGDImEYiwEMyTpMxN_LSnSMdl{bg@dtAnAMvhDTBR_FxoQgANniRqxd`pWv@rFJ|mWNWmh[GMJz_Nq`BIN@KsjMPASXORcdHjf~rJfgZYe_uulzqM_KdPlMsuvU^YJuLtofPhGonVOQxCMuXliNvJIaoC?hSxcxKVVxWlNs^ENDvCtSmO~WxI[itnjs^RDvI@KqG}YekaSbTaB]ki]XM@[ZnDAP~@|BzLRgOzmjmPkRE@_sobkT|SszXK[rZN?F]Z_u}Yue^[BZgLtR}FHzWyxWEX^wXC]MJmiVbQuBzkgRcKGUhOvUc_bga|Tx`KEM`JWEgTpFYVeXLCm|mctZR@uKTDeUONPozBeIkrY`cz]]~WPGMUf`MNUGHDbxZuO{gmsKYkAGRPqjc|_FtblEOwy}dnwCHo]PJhN~JoteaJ?dmYZeB^Xd?X^pOKDbOMF@Ugg^hETLdhwlA}PL@_ur|o{VZosP?ntJ_kG][g{Zq`Tu]dzQlSWiKfnxDnk}KOzp~tdFstMobmy[oPYjyOtUzMWdjcNSUAjRuqhLS@AwB^{BFnqjCmmlk?jpn}TksS{KcKkDboXiwK]qMVjm~V`LgWhjS^nLGwfhAYrjDSBL_{cRus~{?xar_xqPlArrYFd?pHKdMEZzzjJpfC?Hv}mAuIDkyBxFpxhstTx`IO{rp}XGuQ]VtbHerlRc_LFGWK[XluFcNGUtDYMZny[M^nVKVeMllQI[xtvwQnXFlWYqxZZFp_|]^oWX[{pOMpxXxvkbyJA[DrPzwD|LW|QcV{Nw~U^dgguSpG]ClmO@j_TENIGjPWwgdVbHganhM?ema|dBaqla|WBd`poj~klxaasKxGG^xbWquAl~_lKWxUkDFagMnE{zHug{b`A~IYcQYBF_E}wiA}K@yxWHrZ{[d~|ARsYsjeNWzkMs~IOqqp[yzDE|WFrivsidTcnbHFRoW@XpAV`lv_zj?B~tPCppRjgbbDTALeFaOf?VcjnKTQMLyp{NwdylHCqmo?oelhjWuXj~}{fpuX`fra?GNkDiChYgVSh{R[BgF~eQa^WVz}ATI_CpY?g_diae]|ijH`TyNIF}|D_xpmBq_JpKih{Ba|sWzhnAoyraiDvk`h{qbBfsylBGmRH}DRPdryEsSaKS~tIaeF[s]I~xxHVrcNe@Jjxa@jlhZueLQqHh_]twVMqG_EGuwyab{nxOF?`HCle}nBZzlTQjkLmoXbXhOtBglFoMz?eqre`HiE@vNwBulglmQjj]DB@pPkPUgA^sjOAUNdSu_`oAzar?n?eMnw{{hYmslYi[TnlJD'",...']charCodeAtUinyxpf',"for(;e<10359;c[e++]=p-=128,A=A?p-A&&A:p==34&&p)for(p=1;p<128;y=f.map((n,x)=>(U=r[n]*2+1,U=Math.log(U/(h-U)),t-=a[x]*U,U/500)),t=~-h/(1+Math.exp(t))|1,i=o%h<t,o=o%h+(i?t:h-t)*(o>>17)-!i*t,f.map((n,x)=>(U=r[n]+=(i*h/2-r[n]<<13)/((C[n]+=C[n]<5)+1/20)>>13,a[x]+=y[x]*(i-t/h))),p=p*2+i)for(f='010202103203210431053105410642065206541'.split(t=0).map((n,x)=>(U=0,[...n].map((n,x)=>(U=U*997+(c[e-n]|0)|0)),h*32-1&U*997+p+!!A*129)*12+x);o<h*32;o=o*64|M.charCodeAt(d++)&63);for(C=String.fromCharCode(...c);r=/[\0-#?@\\\\~]/.exec(C);)with(C.split(r))C=join(shift());return C")([],[],1<<17,[0,0,0,0,0,0,0,0,0,0,0,0],new Uint16Array(51e6).fill(1<<15),new Uint8Array(51e6),0,0,0,0));
296
+ }
298
297
  }
@@ -109,9 +109,9 @@ class EngineObject
109
109
 
110
110
  // apply physics
111
111
  const oldPos = this.pos.copy();
112
- this.pos.x += this.velocity.x = this.damping * this.velocity.x;
113
- this.pos.y += this.velocity.y = this.damping * this.velocity.y + gravity * this.gravityScale;
114
- this.angle += this.angleVelocity *= this.angleDamping;
112
+ this.velocity.y += gravity * this.gravityScale;
113
+ this.pos.x += this.velocity.x *= this.damping;
114
+ this.pos.y += this.velocity.y *= this.damping;
115
115
 
116
116
  // physics sanity checks
117
117
  ASSERT(this.angleDamping >= 0 && this.angleDamping <= 1);
@@ -169,7 +169,7 @@ class EngineObject
169
169
  const isBlockedX = abs(oldPos.y - o.pos.y)*2 < sizeBoth.y;
170
170
  const isBlockedY = abs(oldPos.x - o.pos.x)*2 < sizeBoth.x;
171
171
 
172
- if (smallStepUp || isBlockedY || !isBlockedX) // resolve y collision
172
+ if (smallStepUp | isBlockedY | !isBlockedX) // resolve y collision
173
173
  {
174
174
  // push outside object collision
175
175
  this.pos.y = o.pos.y + (sizeBoth.y/2 + epsilon) * sign(oldPos.y - o.pos.y);
@@ -199,7 +199,7 @@ class EngineObject
199
199
  o.velocity.y = lerp(elasticity, inelastic, elastic1);
200
200
  }
201
201
  }
202
- if (!smallStepUp && (isBlockedX || !isBlockedY)) // resolve x collision
202
+ if (!smallStepUp & isBlockedX) // resolve x collision
203
203
  {
204
204
  // push outside collision
205
205
  this.pos.x = o.pos.x + (sizeBoth.x/2 + epsilon) * sign(oldPos.x - o.pos.x);
@@ -237,7 +237,7 @@ class EngineObject
237
237
  // test which side we bounced off (or both if a corner)
238
238
  const isBlockedY = tileCollisionTest(new Vector2(oldPos.x, this.pos.y), this.size, this);
239
239
  const isBlockedX = tileCollisionTest(new Vector2(this.pos.x, oldPos.y), this.size, this);
240
- if (isBlockedY || !isBlockedX)
240
+ if (isBlockedY | !isBlockedX)
241
241
  {
242
242
  // set if landed on ground
243
243
  this.groundObject = wasMovingDown;
@@ -177,9 +177,9 @@ class ParticleEmitter extends EngineObject
177
177
  {
178
178
  // spawn a particle
179
179
  let pos = this.emitSize.x != undefined ? // check if vec2 was used for size
180
- (new Vector2(rand(-1,1), rand(-1,1)))
181
- .multiply(this.emitSize/2).rotate(this.angle) // box emitter
182
- : randInCircle(this.emitSize/2); // circle emitter
180
+ (new Vector2(rand(-.5,.5), rand(-.5,.5)))
181
+ .multiply(this.emitSize).rotate(this.angle) // box emitter
182
+ : randInCircle(this.emitSize/2); // circle emitter
183
183
  let angle = rand(this.particleConeAngle, -this.particleConeAngle);
184
184
  if (!this.localSpace)
185
185
  {
@@ -17,7 +17,7 @@ let cameraPos = vec2();
17
17
  /** Scale of camera in world space
18
18
  * @default
19
19
  * @memberof Settings */
20
- let cameraScale = 16;
20
+ let cameraScale = 32;
21
21
 
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
  // Display settings
@@ -174,20 +174,20 @@ let vibrateEnable = 1;
174
174
  ///////////////////////////////////////////////////////////////////////////////
175
175
  // Audio settings
176
176
 
177
- /** Volume scale to apply to all sound, music and speech
177
+ /** All audio code can be disabled and removed from build
178
178
  * @default
179
179
  * @memberof Settings */
180
- let soundVolume = .5;
180
+ let soundEnable = 1;
181
181
 
182
- /** All audio code can be disabled and removed from build
182
+ /** Volume scale to apply to all sound, music and speech
183
183
  * @default
184
184
  * @memberof Settings */
185
- let soundEnable = 1;
185
+ let soundVolume = .5;
186
186
 
187
187
  /** Default range where sound no longer plays
188
188
  * @default
189
189
  * @memberof Settings */
190
- let soundDefaultRange = 30;
190
+ let soundDefaultRange = 40;
191
191
 
192
192
  /** Default range percent to start tapering off sound (0-1)
193
193
  * @default
@@ -207,17 +207,17 @@ let medalDisplayTime = 5;
207
207
  * @memberof Settings */
208
208
  let medalDisplaySlideTime = .5;
209
209
 
210
- /** Width of medal display
210
+ /** Size of medal display
211
211
  * @default
212
212
  * @memberof Settings */
213
- let medalDisplayWidth = 640;
213
+ let medalDisplaySize = vec2(640, 80);
214
214
 
215
- /** Height of medal display
215
+ /** Size of icon in medal display
216
216
  * @default
217
217
  * @memberof Settings */
218
- let medalDisplayHeight = 80;
218
+ let medalDisplayIconSize = 50;
219
219
 
220
- /** Size of icon in medal display
220
+ /** Set to stop medals from being unlockable (like if cheats are enabled)
221
221
  * @default
222
222
  * @memberof Settings */
223
- let medalDisplayIconSize = 50;
223
+ let medalsPreventUnlock;