From 7b6beddc0c65d24ca7cf3d3b011a38cffed78f64 Mon Sep 17 00:00:00 2001 From: Sean Date: Fri, 14 Jun 2013 08:34:03 +0800 Subject: [PATCH 1/6] Fix assets path. --- Tests/demoscene/ballmover.js | 2 +- Tests/demoscene/ballmover.ts | 2 +- Tests/demoscene/colorwhirl.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/demoscene/ballmover.js b/Tests/demoscene/ballmover.js index e45c4c6d..689f60bb 100644 --- a/Tests/demoscene/ballmover.js +++ b/Tests/demoscene/ballmover.js @@ -3,7 +3,7 @@ (function () { var game = new Phaser.Game(this, 'demo1', 320, 200, init, create, update); function init() { - game.load.image('balls', '../assets/sprites/balls.png'); + game.load.image('balls', 'assets/sprites/balls.png'); game.load.start(); } var scroller; diff --git a/Tests/demoscene/ballmover.ts b/Tests/demoscene/ballmover.ts index d1775dae..d210f244 100644 --- a/Tests/demoscene/ballmover.ts +++ b/Tests/demoscene/ballmover.ts @@ -7,7 +7,7 @@ function init() { - game.load.image('balls', '../assets/sprites/balls.png'); + game.load.image('balls', 'assets/sprites/balls.png'); game.load.start(); } diff --git a/Tests/demoscene/colorwhirl.js b/Tests/demoscene/colorwhirl.js index 51595fdd..520b412b 100644 --- a/Tests/demoscene/colorwhirl.js +++ b/Tests/demoscene/colorwhirl.js @@ -3,7 +3,7 @@ var game = new Phaser.Game(this, 'game', 320, 200, init, create); function init() { // Using Phasers asset loader we load up a PNG from the assets folder - game.load.image('swirl', '../assets/pics/color_wheel_swirl.png'); + game.load.image('swirl', 'assets/pics/color_wheel_swirl.png'); game.load.start(); } var swirl; From 1bcbf91398458bc695df08196beb10eddefad126 Mon Sep 17 00:00:00 2001 From: Sean Date: Fri, 14 Jun 2013 08:36:20 +0800 Subject: [PATCH 2/6] Add assets for tests and a simple camera scroll test. --- Tests/assets/tests/cloud-big-2x.png | Bin 0 -> 2465 bytes Tests/assets/tests/cloud-big.png | Bin 0 -> 1548 bytes Tests/assets/tests/cloud-narrow-2x.png | Bin 0 -> 1210 bytes Tests/assets/tests/cloud-narrow.png | Bin 0 -> 1000 bytes Tests/assets/tests/cloud-small-2x.png | Bin 0 -> 1517 bytes Tests/assets/tests/cloud-small.png | Bin 0 -> 1176 bytes Tests/assets/tests/ground-2x.png | Bin 0 -> 1227 bytes Tests/assets/tests/ground.png | Bin 0 -> 593 bytes Tests/assets/tests/river-2x.png | Bin 0 -> 794 bytes Tests/assets/tests/river.png | Bin 0 -> 346 bytes Tests/assets/tests/sky-2x.png | Bin 0 -> 2939 bytes Tests/assets/tests/sky.png | Bin 0 -> 1078 bytes Tests/assets/tiles/ground-tile.png | Bin 0 -> 1007 bytes Tests/cameras/scrollfactor-compare.js | 44 +++++++++++++++++++++++++ 14 files changed, 44 insertions(+) create mode 100644 Tests/assets/tests/cloud-big-2x.png create mode 100644 Tests/assets/tests/cloud-big.png create mode 100644 Tests/assets/tests/cloud-narrow-2x.png create mode 100644 Tests/assets/tests/cloud-narrow.png create mode 100644 Tests/assets/tests/cloud-small-2x.png create mode 100644 Tests/assets/tests/cloud-small.png create mode 100644 Tests/assets/tests/ground-2x.png create mode 100644 Tests/assets/tests/ground.png create mode 100644 Tests/assets/tests/river-2x.png create mode 100644 Tests/assets/tests/river.png create mode 100644 Tests/assets/tests/sky-2x.png create mode 100644 Tests/assets/tests/sky.png create mode 100644 Tests/assets/tiles/ground-tile.png create mode 100644 Tests/cameras/scrollfactor-compare.js diff --git a/Tests/assets/tests/cloud-big-2x.png b/Tests/assets/tests/cloud-big-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bdc5d1eae39295e87ef0932fcc0d2c804abf5208 GIT binary patch literal 2465 zcmZuy4K!3)9KXYunJ{*$Q5NOZo;GEw(J?#{b1@rR>`ZGMs*R!O;~2dprKU8P#P&hE zeUNHw+OxEF+tW@cDk(*jA~r0cq4c%c+P32DdyN@y&d!_PyYJoK@BY8;yZ6o>amXUJ zrM)EpfE^SVuoM7u4gfU3GA9_WJW2t8**o!)P!T8wptzW9h=-JXm68`u{G>QeHXk3v zD{08(A_&6c@lX^Mi9`~KL?)AA7^YMzb8~YG3kx+GO?`cRZ*T9%@i+vy0^n7EFeXri z0|gEs;fN|wSkr<+fge}kRSLXIf#W2)a77iaIF1_&6xOt$(crZjyj_D2YH*yyAg*c0 zHMO|0Kw(V_0AP*)LjfiQ7)C;h0Tcs{n6W@%O$#WBiBL?6VlouNNXRf$ilHLRSfH?` z1&IWUkYF+iwpM~+B-UaQ877Iqj0Fm7S^xlY07L-f0|-g*AwVGDKx2WznidcQIwO#e zKoo(H1PT#8M4X|qKw(V_JRaoppc@Z*^B^SQ4S8;m$A`uOg*7b@>-PT_u|BhMn_~!p zwrOd|*FdOkizPeJix&leOp7UjL}%QFz=%WutR|8-4dflOBS_|^pkNWRlfh=vIWcvM zZvwzTf&yUZmIu!|gEqGFITqrspqY1v=jBLe&rgd$G9L~HPgrzlPQ{6mWo$EF-&f%) z50_0hqjRPUGr_c6<;yC%CC!XQU_25~${HCNp0dYfh7e5C;ng@qb!9_HD)7^xQGVPv zdqGP;t92ib!9`LzA8|mD-+$Zh_AckO#d9cZrE9aYtlBxgPOTe8v8h3&DXbd9K8-Ot_?dU8-hgJKlf9YIuGVUNd&0usUO}%*wLuKe+K2UKs zj?OUm(p5vW5e_v2DzE!d>(5!}9i6J&vTbrL5BXB1jAC(wIs{Hhf6(KsxV25KubQa+ z+1`Z5>VXAnec?n>J3KD8I&CQp_qXa^$}By+efX#=pwT(P(I)*vJ0HrtOKaFY9+^rY$4U-BHJWl+2V}z8&Jfw5s@`z>OAyd$Ft4G+F&giOz_y z&n(CvSns+bySqIj`E0OdEX-*?a_f!_=~m}}Wv5;4_D^2}oWt~0*(bDEjO9bOj>&5a z_kZuE>Tocdk-!b-vM3^F*vd8OU{hyT;^0uf@SI$O=)XCw#+nt@7FZT{*5|drFW8N% zFOaZaQ+OhwB95L@Q9hed-EEY|^Q)ZqiPyE2^mLWOSbmv*@Xzd1F5bi1|py zXxd}}nK>N4hJHDJ+3r|%13R|TM@*Sc*A%;CFJ<$*G}|3P6q;5OXf5vB9pke7MX^04 zOcUbPvR>X8dyh6YHOLo*DCXMbl55+wqHOM+&=yJ|9R>GP8-HpozbZ(jWW+MBaJAc< zvX|vCZwU*4&-^n*0xB&a}A0E~3E;{GOlQ-hS9cLdJpWV4G?_pl; z^-1;DR(?haDD=*V&Vb)MjhW$q`X&u29$$|vkDj}A>i5=Tb=C}AoE%b$HL`1~76zXF z`}2bP+VibLhK+dRIr}xsZK1oUKEAKzhfF~eWg>2+%KCe5Ph$=5l>d6@U3iddi5I1! zs3Vtl?Gw}&IpH5JiPK8*4BLYk6CG(?1fus#JSpD5*_kSPJDVwEC)kkqqI};v;?&T4 z^&3%#KYDqs1I|jmA|?(*!w0^Rw>Rk~Eo)(x6N4D5KeO%#tqkXhlXVGOyUg9vAOgQ9 zRwM6Tw8(8z*x%Msg7gFcb^hA0&d~1H!qAD7*_;X5;>~*}bPKMr85COhRPi=tfW0dr y+be9KoXre%pok^z4GTP)lC8C&<0-6z_7gd0bB_P(mb=8?2M7{{1eE$kDgOftH%8h3 literal 0 HcmV?d00001 diff --git a/Tests/assets/tests/cloud-big.png b/Tests/assets/tests/cloud-big.png new file mode 100644 index 0000000000000000000000000000000000000000..b8498800348ccea8220f6d612ac3a4fae1620084 GIT binary patch literal 1548 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 literal 0 HcmV?d00001 diff --git a/Tests/assets/tests/cloud-small-2x.png b/Tests/assets/tests/cloud-small-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b2fe625b93c85e9a4d0289aedd1de97c242c9ca8 GIT binary patch literal 1517 zcmZvce@v4{7{{N|uH{!*RV7fj@gpwCZJ6NT z#im0BF(k@}1Vlu1(}6D8vNre!g<+H|s6)0n2N;Mbo2yQZ%VaRPJ+E7qHtW6LzIV^} zbNAe}y}QP|+$?SAs!#yXnzM~t0TkF&K(G?4U1#3R2MBtcmy>UTo}M0n9;~c#(<&E+ zkCid`^`yckj*5(oU27ro1444yWMX0$jHdd%*>Pii~y5> zc>o8aJPafT1QYoJA2%?NB-SZ0kHn@V#$-(~$-|^h<_~<_z`*Th!)`X=W?naAvb@Ya z!Q8{lANaU|0RW8wDgdZHU#zJ~ zR$=76tuCxSk<_uMn)@Xz7MG*^YH~DDyOXtNQd>u;U8N(@%w29-}>j21~|ds zEq*=B;C;OJR(S-#dUa_*U&mq^CQFYl8VDJyel*h;we7uxC~yqI%XOUxx+cAcUyIX% zp~5lVbSN2?mT>05_8(THmqcWK>Pf(n*M3r23QpIoFaIVCzkxHTCBE-f^|9?n%Ml%3 zIpGJ7-2JUnwdJEz^|(YR+GRUkqe%-_$P>6WT}n~oG8_*fS&dLG4I%o)%{p*!@QLNB zO*vKAr9CGGVV}E~8&|@)0ldPdmz2wT->sj`s0=}WgJ#|N9dQcK#dQ4~RJLOD!DYPf zAa!5WDy;5r3%m8)2Xpgg9R`+Vi)&71#7;KhkLuXF;Bwv5*uoiAF4Mx~{~6`ioL zaG`BEMoSWR^HN8lFMwXzSpK`^<@28f{QZzyH)<%GjZmz0}G1yqpKq`&&TFq0x+9$jh|;0IsXPv C{W3TJ literal 0 HcmV?d00001 diff --git a/Tests/assets/tests/cloud-small.png b/Tests/assets/tests/cloud-small.png new file mode 100644 index 0000000000000000000000000000000000000000..14f5f8ae8a8319eda908910ad7d5338b0d22b099 GIT binary patch literal 1176 zcmZvaTS!zv7{|Y@yr)T;nio8Z(rPDnDXUW%?AUI)-tf4txnk(5NTPw0l4Ko1!^juG zOJPx4n1*eXMsm8rYIrMs*vJPXt0k5)FcW;~f;G+Y=`5X@|9szk|KEJ`Fid-XUPhpQ zq(1-z8Z-3;H0z}0yOG8lk6XS0Z1|I(Q)mFN(+PIF6lgL_TeCC>on}I$u%76a_J)Rr zG7Q7AEXQ#MgMsIHtJR7zZf$Mt>gww2>k~zBc6Qe7cCVi&2#5g00koOQK|mmY=tXiM zbCrQ05Su_80&xk1NOBRuK?ED|1Tt3{h$5L5$%06hL_#Dj5pjWt)5H_VTx9@&qXBb( z&495aGX@SrH1-5CR~c{|HgMR?VJnBRBrE33m@{BcAaj)g&tnUZtvs&bF_u(=c`N2E z*b~THWdMMJ0WpBIfRH3D0tP`a@&qzh888e|Gf2xIjzLHghZrql)W{RaTxGzrNXw#B z7NxNWNlHU(Dq^+B6Uba;K>zLkgZ|Gf&Ce_fRE-6BCeVF(TP+n8*%^Acb!fj;4Tjd35NX-}w8j|z*&m#<`R9cMNlX&7vZcah-S z8O^4OsNzO`q~?w($zE62QRyBXYun~1E$=*^JUn%C-^1j3w=-#MSa*D++u5s2d3S6v zRU46>Qc~qx88kEWDjB&~clTJr%HvgcU*`Db&u?i8d7Th!TiekRuEML`zwB+JWxq>? ztziK{%{lip{T|<kKv?91c-78P5^NQd>dJTl!FPY7)bOYUdewmnO56O+h{ZG zV?FPwKhMnf|2&&t_j&gHKhM&g`43yz@GOQ1*f$G9?6|#E&u9Nz$@-quUVg3Z$G^VQ zi+Nx0=V$UmyR>tu5S=hX>JR^1e*fElnXsRK66<5$*F}{5pFYcaI>f;LcduJQ+_~i_ z>$Pk5&+2baol`gav*3D|cAy(T%=yOuwWI&%PWx*x&(FB#$ZM$kHd{b-Zz`+azW?{{ z&;Py^U-!Q0{`cR>sNY`7^*>L?|NAt3|DUJ&^*^is+0=vC`_0rrk;%}pZT0M(C$C&E zT^}#MUOsN$zH3$W-h1=%=U#j5&zJxH^OX#HL%U+?Y9SKGxt9~|2Y{X_W%2*awcw|!3`O^ zf9>wx%eMaNo~y6#*qn{dUw5rsC;Ih#sRPdG^V}|nn|D6XGM{tU_4mr_k*h7I;WW@2 zVc@Qp*4s04V)NGq|F8f1J}$X3&)9Oi;hVRs|NZ}a_p__{p6fT(ZQWn|z8lrst_W|( zPudSnS=#3J*B$#FXR!TdjQ9J`ua4!tEO(v$uK4x&y|H(?D8gCb z5n0T@z%2~Ij105pNB{-dOFVsD+3&J(@N#med35#wjk@RQ;uunK>+PM>xlD!vYzg{{ z8m1gDJRV~ibSa4ArLty&(6?Da8j7+LyxGJyAA7dY#pAxZ>&Z>`B>z7%sPuUG?RPCx zL-tu2Mg}$x81k6?Zu9T!`_H^yzyIH_*Z+?*FWFkSecc-AJnoesf%X4Cf0=*x(u;W$ zu6_XWfI{}J|MhB@ENl9!w)Feg+ShV{%I}t6340y*WO{tv&!_gL{b!G~`K_C-`StM2 z=EuL2H=4y8*V)$X>6-QT*_XPw$2s;lORvn@V}8{-dis5^mg)O#|KD7{VcD`X4;Mb% zD6G45%B4>`ZmyF4U0>?)-k6TK>_RdM!fw>s;mP62s;`u?@=Z!$18i2V~6gM~0S qs3jB_kWoSd12Sr0WIFKp4?~}D^Pr}dEyS#JK54FFS%|Vt@75q=Ps(bR$fufP6UwKr}(67~1%*K%gC)e@}S^YX(-b(w$veA{yb!_d8P_11g2i@@q8EvvN46@T)b-G3eXeQYY7;VRFG zKiPd+wf660{a2V)*E7S_?TecLcCteQ%nqI>V7pW#PcVWQ9!3xa6H*k|L41Xi4tyZm qVN#c|mjz!LK?POTgVj+RfLAn|ndb6Mw<&;$T)A>T~^ literal 0 HcmV?d00001 diff --git a/Tests/assets/tests/river.png b/Tests/assets/tests/river.png new file mode 100644 index 0000000000000000000000000000000000000000..a9d366b24c0721c99e48cabf6f1ae35569d4f2b1 GIT binary patch literal 346 zcmeAS@N?(olHy`uVBq!ia0y~yU}^xe6*$;{WRu^?CqRlV$=lt9;Xep2*t>i(P=vF< zBeIx*fm;}a85w5HkpK#^mw5WRvfpLn;AW6@zx-PbDD>RZ#WAGf*4rB!c@G(gxL$mo zbEsos`BXWx6Iqf^gCi7Jcm!q^&(hdc)D`0I2UL#=ET(V$6*qOw($~Az0nz#Ex2ruS z?Yn>M^~9XprYHBl1dG1@{N@~ literal 0 HcmV?d00001 diff --git a/Tests/assets/tests/sky-2x.png b/Tests/assets/tests/sky-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d7aae77da62c73fac44c6d3ae2f228b96de3d817 GIT binary patch literal 2939 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i1B%QlYbpRzY)RhkE)4%caKYZ?lYt_f z1s;*b3=G`DAk4@xYmNj^kiEpy*OmP)8!wxo?7oiqUx7lBC9V-A&iT2ysd*&~&PAz- zC8;S2<(VZJ3hti10pX2&;tUL2k3C%+Ln>~)y}414$xwjBalyF|J|m8YK`OSairp+v zn%x=lW&W>vCva`{t>2%&{<{M-m&?WnNOA};FgP?|WiYWorBE0G3P8mm5fnxP10zHP zmBGTnzyKCOVJJ8NjR1+@U@$U4rBE0kmok7vP#9EjJKQ&@ZU^}f)9r8(s5?351;KoTQu!bQk49UjpITD0`>fu*kB(pVW77PPRl3~-`IFecTb;zBoPivqKY zkQ}TyK`Ar9DT4~};-`8n22a{-m``pxI3Ry?#%W;r?ZC+oE0#bhzaWCRyg=`iPluua zd;C!=B1ta%!I=6v@SA6BLGsfjOGAH(~aIm(1Qkj#T#N9J^Z520qb}MPgg&e IbxsLQ042)##Q*>R literal 0 HcmV?d00001 diff --git a/Tests/assets/tests/sky.png b/Tests/assets/tests/sky.png new file mode 100644 index 0000000000000000000000000000000000000000..b187718d922cd1a6428bb754afa8fc57c690f7f7 GIT binary patch literal 1078 zcmeAS@N?(olHy`uVBq!ia0y~yV4MKNIvi|3k+<8Q9s*KqN#5=*3}Fn589r~Eb+8*K z!dc)ESF|9LImQm?EfKC`h~EOA59eVgzd+tcQNJ!)C_fY!0Et;zSvCh<*?e)THbw z4a*kl5Gk<{!6J5O8J3_$2=SnT7yD=7LGU7-mM$H7z2|9$=DqLye(!xgZw3b5M1MNf z*l?f$02+JGCNr`#`LxxCWSyI8-U|?d{__Kd+yWHkgkn(@*(|lR)DUu7La4IaDx1Qo2xnIKg@*69a5sdzB>cidg9QLZfjE!_ zL@E{mCy0_?cxbTToD5DDCz}(g*u*X32Kj}D1`E@qL6dBgMol7>Q8H~Z2gxryG*|#& z7?1(#fT*G)FoZDrg@*(hNrpY;0VzSL~%mzR;7uh_D=OTy+%4Ye|k9g500CGc>n+a literal 0 HcmV?d00001 diff --git a/Tests/cameras/scrollfactor-compare.js b/Tests/cameras/scrollfactor-compare.js new file mode 100644 index 00000000..867ae52e --- /dev/null +++ b/Tests/cameras/scrollfactor-compare.js @@ -0,0 +1,44 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + function init() { + game.world.setSize(1280, 600, true); + game.load.image('ground', 'assets/tests/ground-2x.png'); + game.load.image('river', 'assets/tests/river-2x.png'); + game.load.image('sky', 'assets/tests/sky-2x.png'); + game.load.image('cloud0', 'assets/tests/cloud-big-2x.png'); + game.load.image('cloud1', 'assets/tests/cloud-narrow-2x.png'); + game.load.image('cloud2', 'assets/tests/cloud-small-2x.png'); + game.load.start(); + } + function create() { + // background sky, which does not move at all + game.add.sprite(0, 0, 'sky') + .scrollFactor.setTo(0, 0); + + // clouds with different scroll factor which moves slower than camera + game.add.sprite(200, 120, 'cloud0') + .scrollFactor.setTo(0.3, 0.3); + game.add.sprite(-60, 120, 'cloud1') + .scrollFactor.setTo(0.5, 0.3); + game.add.sprite(900, 170, 'cloud2') + .scrollFactor.setTo(0.7, 0.3); + + // forground objects which moves equal or faster than camera + game.add.sprite(0, 360, 'ground') + .scrollFactor.setTo(0.5, 0.5); + game.add.sprite(0, 400, 'river') + .scrollFactor.setTo(1.3, 1.3); + } + function update() { + if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { + game.camera.scroll.x -= 3; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { + game.camera.scroll.x += 3; + } + } + function render() { + // game.camera.renderDebugInfo(32, 32); + } +})(); From 6d21d39b198ad53f084406e0aa1424b04fda41cd Mon Sep 17 00:00:00 2001 From: Sean Date: Sat, 13 Jul 2013 08:41:05 +0800 Subject: [PATCH 3/6] Fix scrollfactor test for using new component based sprite. --- Tests/cameras/scrollfactor-compare.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Tests/cameras/scrollfactor-compare.js b/Tests/cameras/scrollfactor-compare.js index 867ae52e..07b499a1 100644 --- a/Tests/cameras/scrollfactor-compare.js +++ b/Tests/cameras/scrollfactor-compare.js @@ -14,28 +14,28 @@ function create() { // background sky, which does not move at all game.add.sprite(0, 0, 'sky') - .scrollFactor.setTo(0, 0); + .transform.scrollFactor.setTo(0, 0); // clouds with different scroll factor which moves slower than camera game.add.sprite(200, 120, 'cloud0') - .scrollFactor.setTo(0.3, 0.3); + .transform.scrollFactor.setTo(0.3, 0.3); game.add.sprite(-60, 120, 'cloud1') - .scrollFactor.setTo(0.5, 0.3); + .transform.scrollFactor.setTo(0.5, 0.3); game.add.sprite(900, 170, 'cloud2') - .scrollFactor.setTo(0.7, 0.3); + .transform.scrollFactor.setTo(0.7, 0.3); // forground objects which moves equal or faster than camera game.add.sprite(0, 360, 'ground') - .scrollFactor.setTo(0.5, 0.5); + .transform.scrollFactor.setTo(0.5, 0.5); game.add.sprite(0, 400, 'river') - .scrollFactor.setTo(1.3, 1.3); + .transform.scrollFactor.setTo(1.3, 1.3); } function update() { if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { - game.camera.scroll.x -= 3; + game.camera.x -= 3; } else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { - game.camera.scroll.x += 3; + game.camera.x += 3; } } function render() { From 945c9c1a0d4db7e84f3860aecc56b95217710f3d Mon Sep 17 00:00:00 2001 From: Sean Date: Sat, 13 Jul 2013 08:43:08 +0800 Subject: [PATCH 4/6] Add assets and code template of camera fx tests. --- Tests/assets/sprites/asteroids_ship_white.png | Bin 0 -> 198 bytes Tests/assets/tests/blue-circle.png | Bin 0 -> 7481 bytes Tests/assets/tests/magenta-circle.png | Bin 0 -> 7225 bytes Tests/assets/tests/radar-surface.png | Bin 0 -> 9225 bytes Tests/assets/tests/yellow-circle.png | Bin 0 -> 7459 bytes Tests/cameras/camera fade.js | 35 +++++++++++++ Tests/cameras/camera texture.js | 47 ++++++++++++++++++ Tests/cameras/edit-template.js | 47 ++++++++++++++++++ 8 files changed, 129 insertions(+) create mode 100644 Tests/assets/sprites/asteroids_ship_white.png create mode 100644 Tests/assets/tests/blue-circle.png create mode 100644 Tests/assets/tests/magenta-circle.png create mode 100644 Tests/assets/tests/radar-surface.png create mode 100644 Tests/assets/tests/yellow-circle.png create mode 100644 Tests/cameras/camera fade.js create mode 100644 Tests/cameras/camera texture.js create mode 100644 Tests/cameras/edit-template.js diff --git a/Tests/assets/sprites/asteroids_ship_white.png b/Tests/assets/sprites/asteroids_ship_white.png new file mode 100644 index 0000000000000000000000000000000000000000..6863fafde172ce30711e28bcff5cf592e25617d9 GIT binary patch literal 198 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 literal 0 HcmV?d00001 diff --git a/Tests/assets/tests/magenta-circle.png b/Tests/assets/tests/magenta-circle.png new file mode 100644 index 0000000000000000000000000000000000000000..f94db91c54ce42b313716cf35fa2b7f652815c26 GIT binary patch literal 7225 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 literal 0 HcmV?d00001 diff --git a/Tests/assets/tests/yellow-circle.png b/Tests/assets/tests/yellow-circle.png new file mode 100644 index 0000000000000000000000000000000000000000..5f7ad7b6b70270bed637ce548f2f8ddf3a5b899b GIT binary patch literal 7459 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 literal 0 HcmV?d00001 diff --git a/Tests/cameras/camera fade.js b/Tests/cameras/camera fade.js new file mode 100644 index 00000000..42ba6cf1 --- /dev/null +++ b/Tests/cameras/camera fade.js @@ -0,0 +1,35 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var circle1, circle2, circle3; + var fx; + + function init() { + game.world.setSize(800, 600, true); + game.load.image('blue', 'assets/tests/blue-circle.png'); + game.load.image('yellow', 'assets/tests/yellow-circle.png'); + game.load.image('magenta', 'assets/tests/magenta-circle.png'); + + game.load.start(); + } + function create() { + circle1 = game.add.sprite(114, 34, 'blue'); + circle2 = game.add.sprite(426, 86, 'yellow'); + circle3 = game.add.sprite(221, 318, 'magenta'); + + circle1.input.start(0, false, true); + + fx = game.camera.fx.add(Phaser.FX.Camera.Shake); + } + function update() { + if (circle1.input.justReleased(0, 20)) { + console.log('pressed'); + fx.start(0.05, 0.5, function() { + console.log('fin'); + }); + } + } + function render() { + } +})(); diff --git a/Tests/cameras/camera texture.js b/Tests/cameras/camera texture.js new file mode 100644 index 00000000..5608b2e6 --- /dev/null +++ b/Tests/cameras/camera texture.js @@ -0,0 +1,47 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var radar; + var ships = []; + + var button; + + function init() { + game.world.setSize(800, 600, true); + game.load.image('radar-surface', 'assets/tests/radar-surface.png'); + game.load.image('ship', 'assets/sprites/asteroids_ship_white.png'); + game.load.image('enemy-ship', 'assets/sprites/asteroids_ship.png'); + + game.load.image('button', 'assets/tests/320x200.png'); + + game.load.start(); + } + function create() { + for (var i = 0; i < 4; i++) { + ships.push(game.add.sprite(100 + i * 10, 300 + i * 16, 'ship')); + } + ships.push(game.add.sprite(160, 320, 'enemy-ship')); + radar = game.add.sprite(0, 0, 'radar-surface'); + + game.camera.setSize(400, 600); + var camera2 = game.add.camera(0, 0, 400, 600); + camera2.x = 400; + + button = game.add.sprite(500, 100, 'button'); + button.input.start(0, false, true); + } + function update() { + if (button.input.justReleased(0, 20)) { + } + + for (var i = 0; i < ships.length; i++) { + ships[i].x += 1; + if (ships[i].x > 400) { + ships[i].x = 40; + } + } + } + function render() { + } +})(); diff --git a/Tests/cameras/edit-template.js b/Tests/cameras/edit-template.js new file mode 100644 index 00000000..ab18e7aa --- /dev/null +++ b/Tests/cameras/edit-template.js @@ -0,0 +1,47 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var circle1, circle2, circle3; + var button; + + function init() { + game.world.setSize(800, 600, true); + game.load.image('blue', 'assets/tests/blue-circle.png'); + game.load.image('yellow', 'assets/tests/yellow-circle.png'); + game.load.image('magenta', 'assets/tests/magenta-circle.png'); + + game.load.image('button', 'assets/tests/320x200.png'); + + game.load.start(); + } + function create() { + circle1 = game.add.sprite(114, 34, 'blue'); + circle2 = game.add.sprite(426, 86, 'yellow'); + circle3 = game.add.sprite(221, 318, 'magenta'); + + circle1.input.start(0, false, true); + circle1.input.enableDrag(false); + + circle2.input.start(0, false, true); + circle2.input.enableDrag(false); + + circle3.input.start(0, false, true); + circle3.input.enableDrag(false); + + button = game.add.sprite(500, 100, 'button'); + button.input.start(0, false, true); + } + function update() { + if (button.input.justReleased(0, 20)) { + console.log('<1>: (' + circle1.x + ', ' + circle1.y + ')'); + console.log('<2>: (' + circle2.x + ', ' + circle2.y + ')'); + console.log('<3>: (' + circle3.x + ', ' + circle3.y + ')'); + } + } + function render() { + circle1.input.renderDebugInfo(32, 32); + circle2.input.renderDebugInfo(32, 160); + circle3.input.renderDebugInfo(32, 296); + } +})(); From d620fc7796e74636498aea980d6335e32e15a4d9 Mon Sep 17 00:00:00 2001 From: Sean Date: Sat, 13 Jul 2013 22:47:32 +0800 Subject: [PATCH 5/6] Camera tests, some of them not finished because of bugs. --- Tests/assets/buttons/baddie-buttons.png | Bin 0 -> 2514 bytes Tests/assets/buttons/follow-style-button.png | Bin 0 -> 8461 bytes Tests/cameras/basic follow.js | 64 +++++++++++ Tests/cameras/camera fade.js | 21 ++-- Tests/cameras/camera texture.js | 40 ++----- Tests/cameras/edit-template.js | 47 --------- Tests/cameras/follow styles.js | 99 ++++++++++++++++++ Tests/cameras/multi camera.js | 63 +++++++++++ Tests/cameras/radar template.js | 47 +++++++++ ...tor-compare.js => scrollfactor compare.js} | 0 10 files changed, 293 insertions(+), 88 deletions(-) create mode 100644 Tests/assets/buttons/baddie-buttons.png create mode 100644 Tests/assets/buttons/follow-style-button.png create mode 100644 Tests/cameras/basic follow.js delete mode 100644 Tests/cameras/edit-template.js create mode 100644 Tests/cameras/follow styles.js create mode 100644 Tests/cameras/multi camera.js create mode 100644 Tests/cameras/radar template.js rename Tests/cameras/{scrollfactor-compare.js => scrollfactor compare.js} (100%) diff --git a/Tests/assets/buttons/baddie-buttons.png b/Tests/assets/buttons/baddie-buttons.png new file mode 100644 index 0000000000000000000000000000000000000000..a16940fcb62d2721bca22d1efa7cefe9e64535e7 GIT binary patch literal 2514 zcma);X*e7B7RJ+((b1|dIxbpOY6(MCk%`=hsx4&_gIJrYy@=X^5Tr~os%WYywKQsN zs3nM$P(=r|)DnrEcI?EyFX5W|^qKo*?sM;lbAIQ2&-wU&-sc}{iZm1w6c+>l073{O zJ+mWzIjScojvw{8V725Uh~f0DapvBxxF82V7r;$tZ$}p?gqMSxifpPt`F!fknhXIa1RrKT%={1j)JN+7 zv>#@csw&vm)P<-{Jkmv~P3rBrE(-QR$lCHh`2Rs81UEsVi@a4!cs!({yGpy2&6k2R z6}bMI;4<2$tG_ulr;o-(?deIPLU)YYRO}Up4u`}Da*T@jw>A>^rLgIKCaaPGhb!-` zEsO-NU%0H*S+0r**r4I-Z3cb;oks znhf%(pJuhl1ME$lBTH`RdHv27!EY~6LJH>ObYV>e#s`DF*%PYo|!>gv!(n` zNfb*Ay&s9*akt9C9kv#lv!r^|1}kM3Hav_cbt?9Y811FO5+`3MoCvYMG3Z=?nl@ns zdtuY>dnq#_IbdrjUp@*-wfJn&H+#)U1~RcU=NEZ1JHQuPn?hUrkY-*csWtO)9O^gk-rpeZ4Uo$#}r}8Uerfv`er*qEcBao6hPjOIFdMJ4oJ8 zR*+V%4i?mu>v@+T=h+}v6gOqmRPd{J+p7<;=gl=dKk~y535M}#fl>7sQA5H7#>9(9 zY4{b{B(JC@ZenZ06Jjw~KSn4TYrUZ;ElFU69v(Ef`CaQD8!DW2zSBG0LV+PRyzrWsW$mxDPF;7mu_WtS~ zpYqwFN%_Gc_6z!}nh?fJ>1)$GhqhMf&SPAl1SsDSM{ITg{=yt_=IapR$NXbk(d!9G zObk*M7vk;aX4A7FlQJTiK9{NPal0D3&%AJIqzO?Qo-gZYf;O_u>8+Nx;}f~0`7+g( z2I>)oWYm6XFWtdqtOf-YR%)hdf(4L4zOy(9jb|c=zca{SX`^5p13OeYAyaxI+l%N(yKBHyamB1TZ-TiKXci3pK zha-hRIR`Z!rgqZS?W-0+?N-3?{QEyaXALIS8fbBB!IKFI26X;uEJ?k`*WY zm^Z7PMBSG@3zSScgVCTrO|^X(m(VzumsUh(<#d9BgbMCa1$%xp4++^-RB>iliXW)4Wn zVTv}Y@`_N={VD%&c2uyc4cD_hvhlNT3-aN*a3wvq;FkMN4-26{!U~R0?jd+mA=>5>MF}vDQkB9NlX5kN65w0OQ*>LVFxqofVU*!fS?Q97jP`i|H_Q+CPbe9R1#$2#GRTv&OBWhUhbH?0B7FQ=>j4M0rC7ju+eVfq)JTLaT_S5I&`!$o6$t% z5I5knv9JK)wwBF;r+M|BYzKPo6lptt@Ub9Tv?}vHJt;Nc;M`bcC$YJXAz9CN5_678)Q}0c*ad2PY0{71+6$v&%46^L=ad8_ zhC$Pn!F}&gBo*f{GBHY?JoK}f$Hbj}%WkToz7Viif^xuBv2x_cEE`3RT;3Yot7TMA zNhVxef4)Sen(L{@ZVwyAjD!7{26troTrPV|4aYMLrbdgER(t*X7vwIX6Q{x}^jGk| z*Bw&l%)QuvAD`XkFM5P4M}G)Ad|lnx7z@37SkOA0fh<|G98|AW(!{sNx7rn$9CTb$ zfE#_JoGLc0+IiDi_qvB-r(dfjGA4Gnh|w$|-YIKH@l%QzsJS81hwB-|P`gi#J1IXH z$i(l*7j#jg9g{}{&dSW{uc&*_LX#@ScQw|ytnnT8+%8nbfXtzD#hY) zG7F5k6!6>V;0Ejc4EuMV@ohLFC@xIZT{7^qpu6o8(a?L4<|`~8%CD)Xo-VixS3n#{ zp*1H2bMOFuAU{yY^c(&?=$QVc|IVJ2IdZ?<=$Kkd?V}zZ1595RSH@@fzdQP*0TB8~ Ky<**ak^ce(n#gzn literal 0 HcmV?d00001 diff --git a/Tests/assets/buttons/follow-style-button.png b/Tests/assets/buttons/follow-style-button.png new file mode 100644 index 0000000000000000000000000000000000000000..74a0481ca5a766ebfab09e1f559aad8f58fa08ee GIT binary patch literal 8461 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 +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + + var ufo; + var speed = 4; + + function init() { + game.world.setSize(1280, 600, true); + game.load.image('ground', 'assets/tests/ground-2x.png'); + game.load.image('river', 'assets/tests/river-2x.png'); + game.load.image('sky', 'assets/tests/sky-2x.png'); + game.load.image('cloud0', 'assets/tests/cloud-big-2x.png'); + game.load.image('cloud1', 'assets/tests/cloud-narrow-2x.png'); + game.load.image('cloud2', 'assets/tests/cloud-small-2x.png'); + + game.load.spritesheet('ufo', 'assets/sprites/ufo.png', 24, 21); + + game.load.start(); + } + function create() { + // background images + game.add.sprite(0, 0, 'sky') + .transform.scrollFactor.setTo(0, 0); + game.add.sprite(0, 360, 'ground') + .transform.scrollFactor.setTo(0.5, 0.5); + game.add.sprite(0, 400, 'river') + .transform.scrollFactor.setTo(1.3, 1.3); + game.add.sprite(200, 120, 'cloud0') + .transform.scrollFactor.setTo(0.3, 0.3); + game.add.sprite(-60, 120, 'cloud1') + .transform.scrollFactor.setTo(0.5, 0.3); + game.add.sprite(900, 170, 'cloud2') + .transform.scrollFactor.setTo(0.7, 0.3); + + // ufo spirte + ufo = game.add.sprite(320, 240, 'ufo'); + ufo.animations.add('fly', null, 30, false); + ufo.animations.play('fly'); + ufo.transform.origin.setTo(0.5, 0.5); + + // make camera follows ufo + game.camera.follow(ufo); + } + function update() { + if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { + ufo.x -= speed; + ufo.rotation = -15; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { + ufo.x += speed; + ufo.rotation = 15; + } + else { + ufo.rotation = 0; + } + if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) { + ufo.y -= speed; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) { + ufo.y += speed; + } + } +})(); diff --git a/Tests/cameras/camera fade.js b/Tests/cameras/camera fade.js index 42ba6cf1..b86cbcc2 100644 --- a/Tests/cameras/camera fade.js +++ b/Tests/cameras/camera fade.js @@ -19,17 +19,24 @@ circle3 = game.add.sprite(221, 318, 'magenta'); circle1.input.start(0, false, true); + circle1.events.onInputUp.add(fade1, this); - fx = game.camera.fx.add(Phaser.FX.Camera.Shake); + fx = game.camera.fx.add(Phaser.FX.Camera.Fade); } function update() { - if (circle1.input.justReleased(0, 20)) { - console.log('pressed'); - fx.start(0.05, 0.5, function() { - console.log('fin'); - }); - } } function render() { + game.camera.fx.render(game.camera, + game.camera.x, game.camera.y, + game.camera.width, game.camera.height); + game.camera.fx.postRender(game.camera, + game.camera.x, game.camera.y, + game.camera.width, game.camera.height); + } + function fade1(pointer) { + console.log('pressed'); + fx.start(0.05, 0.5, function() { + console.log('fin'); + }); } })(); diff --git a/Tests/cameras/camera texture.js b/Tests/cameras/camera texture.js index 5608b2e6..5a95701a 100644 --- a/Tests/cameras/camera texture.js +++ b/Tests/cameras/camera texture.js @@ -1,47 +1,19 @@ /// (function () { - var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); - - var radar; - var ships = []; - - var button; + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); function init() { game.world.setSize(800, 600, true); - game.load.image('radar-surface', 'assets/tests/radar-surface.png'); - game.load.image('ship', 'assets/sprites/asteroids_ship_white.png'); - game.load.image('enemy-ship', 'assets/sprites/asteroids_ship.png'); - - game.load.image('button', 'assets/tests/320x200.png'); + game.load.image('background', 'assets/misc/water_texture.jpg'); game.load.start(); } function create() { - for (var i = 0; i < 4; i++) { - ships.push(game.add.sprite(100 + i * 10, 300 + i * 16, 'ship')); - } - ships.push(game.add.sprite(160, 320, 'enemy-ship')); - radar = game.add.sprite(0, 0, 'radar-surface'); - - game.camera.setSize(400, 600); - var camera2 = game.add.camera(0, 0, 400, 600); - camera2.x = 400; - - button = game.add.sprite(500, 100, 'button'); - button.input.start(0, false, true); - } - function update() { - if (button.input.justReleased(0, 20)) { - } - - for (var i = 0; i < ships.length; i++) { - ships[i].x += 1; - if (ships[i].x > 400) { - ships[i].x = 40; - } - } + game.camera.texture.loadImage('background', false); } function render() { + Phaser.DebugUtils.context.fillStyle = 'rgb(255, 255, 255)'; + Phaser.DebugUtils.context.fillText('Draw background image using camera.texture property.', + 196, 320); } })(); diff --git a/Tests/cameras/edit-template.js b/Tests/cameras/edit-template.js deleted file mode 100644 index ab18e7aa..00000000 --- a/Tests/cameras/edit-template.js +++ /dev/null @@ -1,47 +0,0 @@ -/// -(function () { - var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); - - var circle1, circle2, circle3; - var button; - - function init() { - game.world.setSize(800, 600, true); - game.load.image('blue', 'assets/tests/blue-circle.png'); - game.load.image('yellow', 'assets/tests/yellow-circle.png'); - game.load.image('magenta', 'assets/tests/magenta-circle.png'); - - game.load.image('button', 'assets/tests/320x200.png'); - - game.load.start(); - } - function create() { - circle1 = game.add.sprite(114, 34, 'blue'); - circle2 = game.add.sprite(426, 86, 'yellow'); - circle3 = game.add.sprite(221, 318, 'magenta'); - - circle1.input.start(0, false, true); - circle1.input.enableDrag(false); - - circle2.input.start(0, false, true); - circle2.input.enableDrag(false); - - circle3.input.start(0, false, true); - circle3.input.enableDrag(false); - - button = game.add.sprite(500, 100, 'button'); - button.input.start(0, false, true); - } - function update() { - if (button.input.justReleased(0, 20)) { - console.log('<1>: (' + circle1.x + ', ' + circle1.y + ')'); - console.log('<2>: (' + circle2.x + ', ' + circle2.y + ')'); - console.log('<3>: (' + circle3.x + ', ' + circle3.y + ')'); - } - } - function render() { - circle1.input.renderDebugInfo(32, 32); - circle2.input.renderDebugInfo(32, 160); - circle3.input.renderDebugInfo(32, 296); - } -})(); diff --git a/Tests/cameras/follow styles.js b/Tests/cameras/follow styles.js new file mode 100644 index 00000000..223286e3 --- /dev/null +++ b/Tests/cameras/follow styles.js @@ -0,0 +1,99 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var ufo, + speed = 4; + + var btn0, btn1, btn2, btn3; + var style = 'default'; + + function init() { + game.world.setSize(1280, 800, true); + game.load.image('ground', 'assets/tests/ground-2x.png'); + game.load.image('river', 'assets/tests/river-2x.png'); + game.load.image('sky', 'assets/tests/sky-2x.png'); + game.load.image('cloud0', 'assets/tests/cloud-big-2x.png'); + game.load.image('cloud1', 'assets/tests/cloud-narrow-2x.png'); + game.load.image('cloud2', 'assets/tests/cloud-small-2x.png'); + + game.load.spritesheet('button', 'assets/buttons/follow-style-button.png', 224, 70); + + game.load.spritesheet('ufo', 'assets/sprites/ufo.png', 24, 21); + + game.load.start(); + } + function create() { + // background images + game.add.sprite(0, 0, 'sky') + .transform.scrollFactor.setTo(0, 0); + game.add.sprite(0, 360, 'ground') + .transform.scrollFactor.setTo(0.5, 0.1); + game.add.sprite(0, 400, 'river') + .transform.scrollFactor.setTo(1.3, 0.16); + game.add.sprite(200, 120, 'cloud0') + .transform.scrollFactor.setTo(0.3, 0.1); + game.add.sprite(-60, 120, 'cloud1') + .transform.scrollFactor.setTo(0.5, 0.1); + game.add.sprite(900, 170, 'cloud2') + .transform.scrollFactor.setTo(0.7, 0.1); + // ufo spirte + ufo = game.add.sprite(360, 240, 'ufo'); + ufo.animations.add('fly', null, 30, false); + ufo.animations.play('fly'); + ufo.transform.origin.setTo(0.5, 0.5); + + // make camera follows ufo + game.camera.follow(ufo); + + // follow style switch buttons + btn0 = game.add.button(16, 40, 'button', lockonFollow, 0, 0, 0); + btn1 = game.add.button(16, 120, 'button', platformerFollow, 1, 1, 1); + btn2 = game.add.button(16, 200, 'button', topdownFollow, 2, 2, 2); + btn3 = game.add.button(16, 280, 'button', topdownTightFollow, 3, 3, 3); + } + function update() { + if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { + ufo.x -= speed; + ufo.rotation = -15; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { + ufo.x += speed; + ufo.rotation = 15; + } + else { + ufo.rotation = 0; + } + if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) { + ufo.y -= speed; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) { + ufo.y += speed; + } + } + function render() { + if (game.camera.deadzone) { + Phaser.DebugUtils.renderRectangle(game.camera.deadzone, 'rgba(240, 112, 111, 0.4)'); + } + // game.camera.renderDebugInfo(400, 16); + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Click buttons to switch between different styles.', 360, 32); + Phaser.DebugUtils.context.fillText('Current style: ' + style, 360, 48); + } + function lockonFollow() { + game.camera.follow(ufo, Phaser.Camera.STYLE_LOCKON); + style = 'STYLE_LOCKON'; + } + function platformerFollow() { + game.camera.follow(ufo, Phaser.Camera.STYLE_PLATFORMER); + style = 'STYLE_PLATFORMER'; + } + function topdownFollow() { + game.camera.follow(ufo, Phaser.Camera.STYLE_TOPDOWN); + style = 'STYLE_TOPDOWN'; + } + function topdownTightFollow() { + game.camera.follow(ufo, Phaser.Camera.STYLE_TOPDOWN_TIGHT); + style = 'STYLE_TOPDOWN_TIGHT'; + } +})(); diff --git a/Tests/cameras/multi camera.js b/Tests/cameras/multi camera.js new file mode 100644 index 00000000..7554e1f3 --- /dev/null +++ b/Tests/cameras/multi camera.js @@ -0,0 +1,63 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var zombieCamera; + + var zombie; + var walkSpeed = 2, + direction = 1; + + function init() { + game.world.setSize(1280, 600, true); + game.load.image('ground', 'assets/tests/ground-2x.png'); + game.load.image('river', 'assets/tests/river-2x.png'); + game.load.image('sky', 'assets/tests/sky-2x.png'); + + game.load.spritesheet('zombie', 'assets/sprites/metalslug_monster39x40.png', 39, 40); + + game.load.start(); + } + function create() { + // background images + game.add.sprite(0, 0, 'sky'); + game.add.sprite(0, 360, 'ground'); + game.add.sprite(0, 400, 'river'); + + // zombie spirte + zombie = game.add.sprite(480, 336, 'zombie'); + zombie.animations.add('walk', null, 30, true); + zombie.animations.play('walk'); + + // create a small camera which looks at the zombie + zombieCamera = game.add.camera(0, 0, 800, 600); + zombieCamera.x = 420; + zombieCamera.y = 240; + zombieCamera.setPosition(0, 0); + zombieCamera.setSize(200, 200); + } + function update() { + if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { + zombieCamera.x -= 2; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { + zombieCamera.x += 2; + } + if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) { + zombieCamera.y -= 2; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) { + zombieCamera.y += 2; + } + // zombie wandering update + zombie.x += walkSpeed * direction; + if (zombie.x > 540 || zombie.x < 440) { + direction *= -1; + zombie.transform.scale.setTo(direction, 1); + } + } + function render() { + game.camera.renderDebugInfo(32, 32); + zombieCamera.renderDebugInfo(32, 128); + } +})(); diff --git a/Tests/cameras/radar template.js b/Tests/cameras/radar template.js new file mode 100644 index 00000000..5608b2e6 --- /dev/null +++ b/Tests/cameras/radar template.js @@ -0,0 +1,47 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var radar; + var ships = []; + + var button; + + function init() { + game.world.setSize(800, 600, true); + game.load.image('radar-surface', 'assets/tests/radar-surface.png'); + game.load.image('ship', 'assets/sprites/asteroids_ship_white.png'); + game.load.image('enemy-ship', 'assets/sprites/asteroids_ship.png'); + + game.load.image('button', 'assets/tests/320x200.png'); + + game.load.start(); + } + function create() { + for (var i = 0; i < 4; i++) { + ships.push(game.add.sprite(100 + i * 10, 300 + i * 16, 'ship')); + } + ships.push(game.add.sprite(160, 320, 'enemy-ship')); + radar = game.add.sprite(0, 0, 'radar-surface'); + + game.camera.setSize(400, 600); + var camera2 = game.add.camera(0, 0, 400, 600); + camera2.x = 400; + + button = game.add.sprite(500, 100, 'button'); + button.input.start(0, false, true); + } + function update() { + if (button.input.justReleased(0, 20)) { + } + + for (var i = 0; i < ships.length; i++) { + ships[i].x += 1; + if (ships[i].x > 400) { + ships[i].x = 40; + } + } + } + function render() { + } +})(); diff --git a/Tests/cameras/scrollfactor-compare.js b/Tests/cameras/scrollfactor compare.js similarity index 100% rename from Tests/cameras/scrollfactor-compare.js rename to Tests/cameras/scrollfactor compare.js From 9f30f656bc99bc7c6da90ca5a1575f64e6dab6d7 Mon Sep 17 00:00:00 2001 From: Sean Date: Thu, 18 Jul 2013 15:13:58 +0800 Subject: [PATCH 6/6] 46 tests with assets and javascript code. --- Tests/assets/buttons/arrow-button.png | Bin 0 -> 2341 bytes Tests/assets/buttons/baddie-buttons.png | Bin 2514 -> 4447 bytes Tests/assets/buttons/follow-style-button.png | Bin 8461 -> 10151 bytes Tests/assets/buttons/number-buttons-90x90.png | Bin 0 -> 4364 bytes Tests/assets/buttons/number-buttons.png | Bin 0 -> 8982 bytes Tests/assets/buttons/revive-button.png | Bin 0 -> 1547 bytes Tests/assets/buttons/spacebar.png | Bin 0 -> 3620 bytes Tests/assets/sprites/robot/arm-l.png | Bin 0 -> 2751 bytes Tests/assets/sprites/robot/arm-r.png | Bin 0 -> 2773 bytes Tests/assets/sprites/robot/body.png | Bin 0 -> 10524 bytes Tests/assets/sprites/robot/eye.png | Bin 0 -> 2949 bytes Tests/assets/sprites/robot/leg-l.png | Bin 0 -> 3789 bytes Tests/assets/sprites/robot/leg-r.png | Bin 0 -> 4175 bytes Tests/assets/sprites/space-baddie-purple.png | Bin 0 -> 559 bytes Tests/assets/sprites/x.png | Bin 0 -> 2559 bytes Tests/assets/tests/blue-circle.png | Bin 7481 -> 9165 bytes Tests/assets/tests/cloud-big-2x.png | Bin 2465 -> 4149 bytes Tests/assets/tests/cloud-big.png | Bin 1548 -> 3232 bytes Tests/assets/tests/cloud-narrow-2x.png | Bin 1210 -> 2894 bytes Tests/assets/tests/cloud-narrow.png | Bin 1000 -> 2684 bytes Tests/assets/tests/cloud-small-2x.png | Bin 1517 -> 3201 bytes Tests/assets/tests/cloud-small.png | Bin 1176 -> 2860 bytes Tests/assets/tests/ground-2x.png | Bin 1227 -> 2911 bytes Tests/assets/tests/ground.png | Bin 593 -> 2277 bytes Tests/assets/tests/magenta-circle.png | Bin 7225 -> 8909 bytes Tests/assets/tests/radar-surface.png | Bin 9225 -> 10909 bytes Tests/assets/tests/river-2x.png | Bin 794 -> 2478 bytes Tests/assets/tests/river.png | Bin 346 -> 2030 bytes Tests/assets/tests/sky-2x.png | Bin 2939 -> 4623 bytes Tests/assets/tests/sky.png | Bin 1078 -> 2762 bytes Tests/assets/tests/tween/PHASER.png | Bin 0 -> 3967 bytes Tests/assets/tests/tween/ribbon.png | Bin 0 -> 1165 bytes Tests/assets/tests/tween/shadow.png | Bin 0 -> 1251 bytes Tests/assets/tests/yellow-circle.png | Bin 7459 -> 9143 bytes Tests/assets/tiles/ground-tile.png | Bin 1007 -> 2697 bytes Tests/cameras/camera fade.js | 42 ----- Tests/cameras/camera fx 1.js | 43 +++++ Tests/cameras/camera fx 2.js | 44 +++++ Tests/cameras/camera fx 3.js | 44 +++++ Tests/cameras/camera scale.js | 72 +++++++++ Tests/cameras/hide from camera.js | 53 ++++++ Tests/cameras/multi camera.js | 17 +- Tests/cameras/radar template.js | 47 ------ Tests/groups/add to group 1.js | 40 +++++ Tests/groups/add to group 2.js | 37 +++++ Tests/groups/bring to top.js | 30 ++++ Tests/groups/call all.js | 37 +++++ Tests/groups/direct render.js | 38 +++++ Tests/groups/for each.js | 35 ++++ Tests/groups/get first 1.js | 44 +++++ Tests/groups/get first 2.js | 49 ++++++ Tests/groups/get first 3.js | 58 +++++++ Tests/groups/group as layer.js | 74 +++++++++ Tests/groups/group texture.js | 21 +++ Tests/groups/group transform 1.js | 65 ++++++++ Tests/groups/group transform 2.js | 48 ++++++ Tests/groups/group transform 3.js | 51 ++++++ Tests/groups/recycle 1.js | 46 ++++++ Tests/groups/recycle 2.js | 49 ++++++ Tests/groups/remove.js | 65 ++++++++ Tests/groups/replace.js | 66 ++++++++ Tests/groups/set all.js | 31 ++++ Tests/groups/sort 1.js | 46 ++++++ Tests/groups/sort 2.js | 57 +++++++ Tests/groups/sub groups.js | 60 +++++++ Tests/input/drop limitation.js | 46 ++++++ Tests/input/keyboard 1.js | 79 +++++++++ Tests/input/keyboard 2.js | 106 ++++++++++++ Tests/misc/color utils 1.js | 49 ++++++ Tests/misc/color utils 2.js | 57 +++++++ Tests/misc/color utils 3.js | 151 ++++++++++++++++++ Tests/misc/dynamic texture 1.js | 23 +++ Tests/misc/dynamic texture 2.js | 27 ++++ Tests/misc/dynamic texture 3.js | 32 ++++ Tests/misc/rectangle utils 1.js | 10 ++ Tests/sprites/out of screen.js | 29 ++++ Tests/sprites/rotate around.js | 40 +++++ Tests/tweens/easing example 1.js | 22 +++ Tests/tweens/easing example 2.js | 27 ++++ Tests/tweens/easing example 3.js | 27 ++++ Tests/tweens/easing example 4.js | 37 +++++ Tests/tweens/easing example 5.js | 38 +++++ Tests/tweens/easing example 6.js | 53 ++++++ 83 files changed, 2168 insertions(+), 94 deletions(-) create mode 100644 Tests/assets/buttons/arrow-button.png create mode 100644 Tests/assets/buttons/number-buttons-90x90.png create mode 100644 Tests/assets/buttons/number-buttons.png create mode 100644 Tests/assets/buttons/revive-button.png create mode 100644 Tests/assets/buttons/spacebar.png create mode 100644 Tests/assets/sprites/robot/arm-l.png create mode 100644 Tests/assets/sprites/robot/arm-r.png create mode 100644 Tests/assets/sprites/robot/body.png create mode 100644 Tests/assets/sprites/robot/eye.png create mode 100644 Tests/assets/sprites/robot/leg-l.png create mode 100644 Tests/assets/sprites/robot/leg-r.png create mode 100644 Tests/assets/sprites/space-baddie-purple.png create mode 100644 Tests/assets/sprites/x.png create mode 100644 Tests/assets/tests/tween/PHASER.png create mode 100644 Tests/assets/tests/tween/ribbon.png create mode 100644 Tests/assets/tests/tween/shadow.png delete mode 100644 Tests/cameras/camera fade.js create mode 100644 Tests/cameras/camera fx 1.js create mode 100644 Tests/cameras/camera fx 2.js create mode 100644 Tests/cameras/camera fx 3.js create mode 100644 Tests/cameras/camera scale.js create mode 100644 Tests/cameras/hide from camera.js delete mode 100644 Tests/cameras/radar template.js create mode 100644 Tests/groups/add to group 1.js create mode 100644 Tests/groups/add to group 2.js create mode 100644 Tests/groups/bring to top.js create mode 100644 Tests/groups/call all.js create mode 100644 Tests/groups/direct render.js create mode 100644 Tests/groups/for each.js create mode 100644 Tests/groups/get first 1.js create mode 100644 Tests/groups/get first 2.js create mode 100644 Tests/groups/get first 3.js create mode 100644 Tests/groups/group as layer.js create mode 100644 Tests/groups/group texture.js create mode 100644 Tests/groups/group transform 1.js create mode 100644 Tests/groups/group transform 2.js create mode 100644 Tests/groups/group transform 3.js create mode 100644 Tests/groups/recycle 1.js create mode 100644 Tests/groups/recycle 2.js create mode 100644 Tests/groups/remove.js create mode 100644 Tests/groups/replace.js create mode 100644 Tests/groups/set all.js create mode 100644 Tests/groups/sort 1.js create mode 100644 Tests/groups/sort 2.js create mode 100644 Tests/groups/sub groups.js create mode 100644 Tests/input/drop limitation.js create mode 100644 Tests/input/keyboard 1.js create mode 100644 Tests/input/keyboard 2.js create mode 100644 Tests/misc/color utils 1.js create mode 100644 Tests/misc/color utils 2.js create mode 100644 Tests/misc/color utils 3.js create mode 100644 Tests/misc/dynamic texture 1.js create mode 100644 Tests/misc/dynamic texture 2.js create mode 100644 Tests/misc/dynamic texture 3.js create mode 100644 Tests/misc/rectangle utils 1.js create mode 100644 Tests/sprites/out of screen.js create mode 100644 Tests/sprites/rotate around.js create mode 100644 Tests/tweens/easing example 1.js create mode 100644 Tests/tweens/easing example 2.js create mode 100644 Tests/tweens/easing example 3.js create mode 100644 Tests/tweens/easing example 4.js create mode 100644 Tests/tweens/easing example 5.js create mode 100644 Tests/tweens/easing example 6.js diff --git a/Tests/assets/buttons/arrow-button.png b/Tests/assets/buttons/arrow-button.png new file mode 100644 index 0000000000000000000000000000000000000000..48dedb62256e3f950e23f97b7b7aba19836806e8 GIT binary patch literal 2341 zcmV+=3EK9FP)a(=+a>uI{eBRMr1WEk|)OkgD_foT~FzHDeG2LAEK1qP}>>7>8&~V}Xc( znhLlj@$5vgFdoOEFZP!=tRFJ4FC{vQ$By*GUTpc=qroM_Bw>=YWJEM<&) z9y|l_WhkD^K-hh7#5R9=!VaFldh>U_ximk3LcRkyHy+>KKmK*_-rMZv7iZbvf|Ro( z@!SwYxC;RN3YvZlUS=t@|MXvWyEU2}0%P0Kn1!k_bL3OE)f^QI)0JVpu}}=uWx0LrapZ?~fk;EwbL@Y1ygu zc>u5yfQhIa9bP^s%F|P_KSEh>-Sx7RI~*863|>ETcAvkRf_LY)XT?4j02%=>(b^~P zPeG&&8;M3Sh)$NJJqH6~DK0lBGWe*}T>b9X!tg=nMRP!NL31Jz&EdpVHw||Tz5$zU zvIMfprmUB4D-`~3EM!1vA)pFoz_cg}QZ}Tls3=P}U20o!N5G?Y!cbLiuHSu>*;W96 z-2w18<()gtcCMVyD@&b@cOKzi^Yj@JLd<0X#lz+ zSKTz+BJcuM(ZvD)?U!qA8g2=EAv54&0f27EB{vQ4ICxZU8gsD#K)2+An}&B3ynxl< zVgZ0|%4RoBuVdgTT`Wmk0WKCOEt}mmyhHE}nBs7(2^R}8p!?Er({$<(Fz*0(jk#C= zpg*$3P19=;yy+G1OyOdoj0YDBR7Q!LhGHnkP1EX?`n)ChT5+);1Nx~hyJ>jC;Psip z#X@ZbT1X?~0l>P-QtBTn+7^wwX?R261u=M;7qj}}VgZ2NkcOM)P7LCK^=rVmtuU6s zM=qA-TMqyq)R-vNDCQ{kBwCBthoQ9@FusPIvR)u7H`nhz^uDct4A`z{mvraKM|o}< z%7%BW01z$~0BEDya?@~w;L#RSvb&kN&fEU^=``(QcM|}1QM4u`gZK4|XH@IMO769l&S(@XfIba120do!T0tOcg0EFgb%1y&n>pV7VD@gBRp^S&N0s!>6 zETy&uWkf|;y3G`A3od~VE*1a?X{w5whG&$UaIpYDsD#S6X?jVy8DH_Pyo-glWC0%p zNfv#A4UH@HC+REodAz%MTei+axrq!2)l!zyn(*shyj{8-|HesV#Rpu!_-TIiU6QL(tI0Jq5ESBod={37SA%99m_vDxez_Y#$SCl{hvhJ0&=O`q?o4ImcW-B zMOrR;c~j{V@n~Bh1Nxw%ZH1z$d?yUr768yiHT6zS1BT0;0AS1N(yPfD1uz9- zpP_9502@|QZH1z0{2lSrLx`NO(m$4ExM^sB_P+cy?@Dk8DzMHwKaD8~e938r)u!QV zB?D%x57D+j2CPMGv=yuZFa;vo768zg+H5OW31A9Dv@HN&#d5RVwu03Frpi*>$PECs zW#Wcv0C*C_fGOG*lm!Vy-`W-ca9-3_An+9BW}|HdX8=rrNb5r7TbX=11PlOY(mWiy z-p0;m5%s!0&~e*>4gqJjEpQ0fzj9OKaO{ovaO|k_@om*l|JnMG%F;pR$a~rtB^{k%k z*}&8Ka7$LQOs-u}x!$3Uisp>wP5~dy`LfOMS)TzHvSF^9X8rD?%4I1sV7(cT%FP@f z@Q8K9#o~PiT*!v|;<+k*xz1)=&~u^*B}4A*s~^MU-9gcu(A>}*N#=*QAnHJ}rgdrm0Ufwlu~x)~2s`M+UU3EG=#F zMg}aG0c|%;13>eE(`O}2-T<%|fUcOPQG%K;OJVY^x!iQgG!51JQ+!E0JCQ_(FJ4E3 zA09?*_uh%`VeA&hLyQrP6^)rfJ8`QBg67Lo@r-3rGyd}*0GI<{))=L~9hd$PqztMJ zN_>%qFjiVRjNhIGL50fFApool;1J~|R3*Sx#Ipwg3j??p8{{F#NT3a}%2JF=X1O^) z#6WeGr6B;60vMv)gqjGtASp{R7RTjgfXINF4!$*v0mh(;{uf{XHk&8>D+`sU00000 LNkvXXu0mjfk-9Tf literal 0 HcmV?d00001 diff --git a/Tests/assets/buttons/baddie-buttons.png b/Tests/assets/buttons/baddie-buttons.png index a16940fcb62d2721bca22d1efa7cefe9e64535e7..278274186c89cf94c6030c47e629146a56e066fa 100644 GIT binary patch delta 1957 zcmb_d&649Z5avd)S8kky=K=+`Y{yPwmp!{P$!zUZVc41(YNm>lA}fh%{D-7WGP4KQ zz5#E*E3jt{yaO-5Bk&5e?8G=BEKr3{mel>V`s+{Kzkd9i@xw{|;ah%lr|y!kLR#h) zNy{0tHhJ}d{-WobiqLze(2Om35gWh%{ELBj8XLEMVkgyvE%~b_!LFaazM)U|G)Rr- zr_Z8I2mm=#1a0!Hkl`ja8r%^6^)@z8W1{Y3qdwCS(OvQyO-jL#Z}}#*9S@BH%kiDD z?SF|}+ZkZn!**agZfK7~*FoFQIDLj9kC0_2SjEOtsVc;Hy7K&`lqLwEbqXn5VNd>PIFAJnW$*f$d*f8K6?Q+ShE52AN*~KX2mNnoH zZ%Bn5%f_Oy!3Um4eCnRlfpwA`vG1AZ`5wMh7Y}gRZRSUBC2t-phOd|`SAw#O2Ue*1 zq#re<9YD1bSwmb(G0RvEwh~fv_F`UEih59NUAoQ_2&9dtR4MLTG|V)TXhFd7s&0r1 z6C&;z=;|fOBx`O2hhYL@Nr@s;q5xjYz_drEdy<3{WDbkH&|MeD1sCqsaIU8Qam zLdTLmRAFcQ-lTgu*Z(%@2Jm&Lqn9>=~7zsL#CZc9gT4 delta 11 ScmcbwbV+!E^5zZf>p1}*YXrOi diff --git a/Tests/assets/buttons/follow-style-button.png b/Tests/assets/buttons/follow-style-button.png index 74a0481ca5a766ebfab09e1f559aad8f58fa08ee..e6ba55626067be5a6db1f1e709580c41c84cb0a3 100644 GIT binary patch delta 1712 zcmb7F&2Hm15bmjmyhBk|L4g*nM9Hy}l^}bY*jcQBs=G*1Bv+ao%S7~7l8&8R^aNe( zTlCy>4}GBmeSsc2qAb_;2D_+EB02NT$B!R}zh3mtn;kU(R%1u+z9`hY3dLgV(y1decn_gcgb5aE)|f0H*mQh^vPN11%u#)Klq;X z{NRN8ed>p9(2M*RQ7<5y&lw$&Sc!RbHF>qEhNGdgFs6zqU9DE$>clHmN`o*Aso$f$ zo{JH#ek=@IyG5;!8;llY0-7sX8Ce#j0cEptX@-u2>!jODUR}v_Vf3~}p*O0bess+$ z8hAccHiqtI3cgLLmMXKP1g|M%kV9cK<^_8R)5`EZD%t3=O+|LxrfMVTZiFps_1*)) z{B7=YOzXqwB>8AO&GWqsZ7v^BqK)3qRiOIju>yJpx?Cy_mk+qvV=D}DyQ-~FQNq+c zps!xBOhdOAC1@7G44W{63N$uw{WCY{-!vZZqm#jR_~ZLse3C@dLK{|am`;Wc!h2GR zsPDtstOuuV5Cows!v4SwPtgWvry=SOAVermb}%L-Up6PwVTey*dN#4F3qw3wH6cl$B&GG{WoEfqGEO0FTRBri1z^F!J!cz8SQ8I%3A zTK=pySsM>4Hk(OkK=Jit4`ld6Un4yM~J-|5i-VhGITV1 z0MRn&mL!_B{$FnG+_6_-wE)Eb`0YS5wRChjH!G&#JVl2Oo%7nZ-wP#03S>Mc-`vVV zlq>!1K2?t1N}CHxn+D$8$&D)H&|@E{)CTOdR+O%t!=63*`Y5K`_X6LJ?TZ5iR#W(% OOuzW&%iq8Hi~I|?UJ$zg delta 11 ScmZ4P-|I9%dGlVjR|)_gjs*Dt diff --git a/Tests/assets/buttons/number-buttons-90x90.png b/Tests/assets/buttons/number-buttons-90x90.png new file mode 100644 index 0000000000000000000000000000000000000000..f4179877ce3b6be2c9bff6f666eab8e4ff3be95b GIT binary patch literal 4364 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 BFAx9# literal 0 HcmV?d00001 diff --git a/Tests/assets/buttons/number-buttons.png b/Tests/assets/buttons/number-buttons.png new file mode 100644 index 0000000000000000000000000000000000000000..8cf84b8fbca9707c72e079a0172a6786d34ec6ac GIT binary patch literal 8982 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 Bvibl3 literal 0 HcmV?d00001 diff --git a/Tests/assets/buttons/revive-button.png b/Tests/assets/buttons/revive-button.png new file mode 100644 index 0000000000000000000000000000000000000000..13ce5d7a59aa85d679402d56c71d4f7ceb668eaf GIT binary patch literal 1547 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 literal 0 HcmV?d00001 diff --git a/Tests/assets/sprites/robot/arm-r.png b/Tests/assets/sprites/robot/arm-r.png new file mode 100644 index 0000000000000000000000000000000000000000..a10b33511dd9ad2c268d675e057f78ca4d6beb0d GIT binary patch literal 2773 zcmZ9OdpwivAICk+VvC00FAnlXpaZ(@#fK4s>x)-WOxrk*Jk!z!nBa26x#XQWIf z%R{A%oJKjH>S04l&$Bs%=y&V+?{~jm*L_{D@AbVt*ZcFmuGjs#Z+f~rLZmdLL_|a& zPG~!Cpw9u?)*dkM_Th5ufKHuck0trUgpn>0;)o)s(3oH%)G3+}PV^=cLdmgRM5Ks_ z)Fmf7)Tuwlzub4bIF43IvoF&MRY}Y%R1XVdiq0yh*1lYkZJ}@*dOBs%nClIqol5FJt;>9Bhou3HktM?wqtd4e@CVV zs9GZ&n-jh28Gll}GPsnP7~q0XDU(m^Gw=RP%vIZCNh~2(J=~AdXv{LMS+S!z$c15a z4x-nugb^b(Q%L<;KA7`%wBbI!khf#sDN-i4_e=QYvW?5e)=BGN>$B98TW%l;0OebNIMPWOAW?BT+Ptk>sauj zf+HL*_Bbl#nQMOngT^}yNg<``1dM_rrV7^LSrvyw>3Z^<(bo6 zOVkOgU69>83W=+8IfZl;#dd|EL+C;OH~&LMspS`q^dRao1#5L1Iz_y@Ei3jmoK6RJ zMit2@mETM`J{DM8_MCV2ZN#pxbW~BiH7H^h3Sl2S?g_|KfYIJPg9x)RN*%~mskZAh zLwVtyFRP*Ep?J3h#1_a7cBodLGNN@fmn{se zO5|tG89KS|c$ z+fmGSXR@EKjrbRLOrAP<3;w)=b=bFu0l&XzJ7Pxa zviV4_!Sf4W*yVTV3GUN(S1Ea|jqqH8CA1%AO$@eFv)_t6aq3ExBw<>g-vJE}{ z(vSggYQVP9rdi z0_VO}nV{F~BUy|E?~7Vh#6{IZegP}}Tgrcp?4A^f=$V9}OBWV}=V`ECVvydg%A&iq zW~1_>f+tLYP{jiK`E&D4jVxJP?vO62YnhWaq0d68E*MP*Uxu)(N7~KaW9>7OoKg7@ zcG#88UAqAQgFbgi>O4;P^jUsyY3CwFSnxFO}azP5*h>F9?rs`(6Zm zqGhPg_Pj_#wJRV0n~umH-aLQuSr9x2qfO3APd`;^O@4G0%Mom$#qU_^h5q>d&+N`Q zQ}(SKZ7W7=FSXt6W@iH#Ui0HwC`;Mlk@}8XgJUwjLo=%R2{KOF#Xu!P^M?7Hd#}$b zFGl&>b^Rtnv)^mv@`o3VSwH6rsF3dB-iP0JwlBxV#d&8sJlG!5xhu&p7ii{BivHLT z&Oe$tgPbng$UV?+58SjZM?^pf>uj7H2N{JuX=OFzr@hZKmw}jA8hP@qclb)y7$$%~ ze*C>$V&nce5D%ohyGU$DP8B<iZwG16r1QP%*F38=8mdpTUjApfr-76(z+5WV z6OI4)bTX)9#ozwn`|5%9zWMmC-##Hdtc99O4fR7$@NFqO0|gv6EauKvn6%I{fr*gk z*N+_KqnxNbF8}t!q#iL=riq$N9l}G0&^*xF3mL8W{05(7=;1(67s}@$Gvy*YWe9Ui|z*2_7 zil<$8HYdY_3OGKz2rAM42L0GZk7a?bHI{`t1s$HGkdbLT7TE?yP9Yni^5_-!P1&_b z!DaM?4y0r{PYoj!_$C?V%ss1reL`1)I3!ut){=7$U;^?= zBFM_4&M?@ylG#_tR33HiW*72goZRlhst`{vE88Cmbv1JLQ)SzkU%na^_b&farBLt$ z;nCmDRC7%43O#a9nsE1M#`h??O)0_~pu=z}kU(T@f u8yd&!8a~*fzz-yaV28Bm0{m}a5%>kd?@eDK4S@et5hr_hyE>aQDgOhLEIE(> literal 0 HcmV?d00001 diff --git a/Tests/assets/sprites/robot/body.png b/Tests/assets/sprites/robot/body.png new file mode 100644 index 0000000000000000000000000000000000000000..527a84b9decbba05654e2c560577433b7bdb1377 GIT binary patch literal 10524 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 obNd#*OKaXj;sQ>@~ literal 0 HcmV?d00001 diff --git a/Tests/assets/sprites/robot/eye.png b/Tests/assets/sprites/robot/eye.png new file mode 100644 index 0000000000000000000000000000000000000000..d872e67647fca3b9c94d3f21179b2d1c922b7b96 GIT binary patch literal 2949 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 literal 0 HcmV?d00001 diff --git a/Tests/assets/sprites/robot/leg-l.png b/Tests/assets/sprites/robot/leg-l.png new file mode 100644 index 0000000000000000000000000000000000000000..b1c8529eff2bdb75f8afd893481a2fe7cb550fd1 GIT binary patch literal 3789 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 DVnIUL literal 0 HcmV?d00001 diff --git a/Tests/assets/sprites/robot/leg-r.png b/Tests/assets/sprites/robot/leg-r.png new file mode 100644 index 0000000000000000000000000000000000000000..10f0d0bbe5e2c501ec9b92c7467e4cac42f2a000 GIT binary patch literal 4175 zcmV-V5U}rwP)@kvBMRCwC#olk5WcNNFSs~`o6lr5ra zl0&m0m!L|`THz3>px6?WQa}_zAa*SgPDE>0 zYRQ4H8xBbjNH!9JNF0XWTg|wW&Ft=bzxn`ONqGd++yel7z#HNYk_~ zj+Qt!#W4^^ldnn`ASYv$uaZA7m&CCyj$S%Hc4xiU0$)zMAjJgzrUY!Ivwnvtq8E&F?I^9E9?|d8pGi*6#&zAyPY-~jkI2`r>9S! zPT|yhJ@hGef=`|dbP808%!5CUp)?b@~E^5x4(x7$q)4i3huU0On! z%2Lp6EU3~od(A-tB=`xy@({`#g9La&sh{^ch}QsI_;;aN>_;sMJ3a_bv6&q$xePK7 zfC%brHk)I(lL4?H;P2u6iqPk%HY~6(W+{HOZGCrbHGk>n9%lN z0w6*g34qG%76TS@;}ky1*vJ`W#09G{b@bFuBLpH`gp=k8X4TI}5^){?FT z*fD^G^F)G$Ia75Q#yjO9R8VTuRghqzsv=iDp`Fd`xa*r@H>psejapn>G%MA)&bF`LS0^7_PU(QVPdoKyzHrY0<}$r3JK87n>Q;ZLbk0qZ)YK( z89@dNdNgXDKLcHMJla0|1L7^Y|U|~Qne~5wXBcU$AGMOObR#3b83$|tq(xg*VnC{yXy8e2MbUM0||s`ZFIoAWVb3efu`4RdNPw zHqVz_tAbKPsa4CMLa9Tw;o{<~nq{cXtgIo|sxCrRl{^(~m{1q*6@RH&gxW|X2Fn4e ztF@}CawqQ!m9=4OU}ZZX0BA@Z5M==q*z&wV)`o2=mONMvKwU3uR9JD|#8k0iD`2x) zl{{F!wzlTH+EiF^)oj=b*eZkNE|oQ|+ptlvJ`I-3go;s}+=k)32=7-q0$(!-)tkX` zTakZPf?7*$*a+CHR^1GxR@K$M!i@}8Ol)5dCRef>0b3X>C)cWk$y-5W#Cg&L77Q6N zGIpl@kD5lP^~`>w9xSJ}uPSU<8(7(i-7XB4%SM#}0M$0EQ?cY)73L}VJg!;=tZEz9 z0#xch+t*1Vx2Z@1uR&P${F)M24urJZCEK-N@g6IYNMC`%Vuwo|6ENZ9t%8j$GcL|V)NRAMz($oBV@Gz1of5ijn621gNMyqh zeV4$FV#T^?x-?7V4_p{W*=6|2}R#0ABoEkxx`p+4Af)m7>)fE~pE z7SogzXCj)iVVz)6nep}O*MkRZ!-m<44TOq4o7jpSPMl2Iur{!i%$PWfz^hUxpNVMN zhIJ~I?KqL10@HULZ18qG&x&;{k8}ZS@R{)}E6#0L3 zTEWJW8J9&q6Va9p>sD;gc08+nRlR4Ei(rGb<5?N8Z5uWLHi|xD*KC-rxI#=D0LZgp z8=Vqt#Tvm%%tRzDk8}cTY?*OB6H({#NLLgatR0snPr6sBy9V|+M6hM$jw?273M^`y z7~eBv=ofayhE0J*FVyncie0i{Q(#dEly6f}C#_ibW+BdjrJTI4^NjPEh_2YMDaE4g z*p~!q@;oJHO6-LIb`-K=C0D8ULja4)jIUg|;#K1vMO^`rSvn20-EOD5ySr(HXoUtAhtSzDQ=!3?HdRX==$^CL@lYWK@I=n+!N^vl zX87}*-x*aRX@W8i9{shru&@BfmWr(ge5zw1V3cRBJ)Jpo#@YoTjL-nkHQC)sLsRU? zWyJziLTAK|t5BT$LKiq*N62Uf-r`lP!oM};NNc-nlYqou8d_a#Jwso}tqRxm-Gsd82Y zakAQgiQ&O6NlhXWrHKml5+|#*nV5!>M~8YT9sXRq8UkBYy~NtJ!=&h7cdNpcQSavF zCgmfRn3U%1Se1H1u3cU1J06%&FL678b*AHqdWjwWT)X<9UgBi6U8doQdSSl^u3ZCE zZ)lU%SiSV%+SNDpBBRMyJUsPshku~zUF9nrrh2)=m9&A=h07O_})yxiTy9OJPz=9~)x1#I99)+=69ZU!8V4vJUn3dn*n$u2V zvaT5B)DC+FYzAm2H6KSj_g4?ldbTCH?HI6n)wZEWsXGyL>0(Nyoz&fEGbLiVlXboI zvU0`cSP^B>HlxKsH97s0m1{z=nNo*@P6br__kaIRp8o4m>Hj--=2G&-FMOGms|&13 z`~B-b568!&e;kg10@zvc=DD|%H_yMFTz%u6Djy3^)i_|VFN1|uXRRtQ|Md7?^4Zh- zb3smvSHE;NdH1a!jX_HUbU|K>u`6<622_|lEj1VD!QbvBzy0%v$%l=!@PfAU<4-;i_WK)SCoKs#Dob9ds@A)||KZqzO@}1h zWdXMz1K3(g+lq$zs|W8}ftowTuOIxJnr%lj$7ym~TlAwCKNTg6N&B6itbIWFlSVAP zQj=iYc(uIm#20{@3vMz(+=&Wob|<6Co6ny9QM$uHM}TSx=hKW~JA$HO(T`#@QPxlb zIzsM0`iNCK1uQCQ0^3vBqogYS@RyIodHo&x@>UdJDT{s|Jih1T7Xd3KBy;sx6nhSBs7&3-1{DGA`ag&VxNIvE%~g0>e!HbM)z=l3-uQzVsjlup`V1sdIV3f?Y~Gn;btN95%0wawokd3 zxmqbf0Dz9~Ae(_`6`S=yq1qqVe+l5qSgXp+7~F$!4pHq;eyZe-ZetWH3+Qz99oJ5h zHlkxhW5bhHjIQwjs%#>3=`}S86lCHAYd?-{`@Ko9T^~*wZYrpq32`@xEM5ScwLu5E zp;WctTUUQd`4jj~TTz3}V#nnZh9N;>c6~R-y%cMvOM)u%pTK^J-G|WAw4Ov5FM*|$ zJ+f9RYvI(oS;R^bX-u1?=u{GwZ;nZftyp$pqkz@g&QcO6Q24Z28M7={92-f*Q3^J* zVm$}>(Hxjd{+kQLCje&MX?aurcVf<-YS`wJSUF1U8RBDk+{I7q2|fbh;bspN_19q zEkIp~xn7l3ECm+a0FMnr-Qefg$%EY?fJIqxF)OYBbvxF6U?pHPJI2(7`w4mt(Cby9 zLRrHZa7D#pRZB`2qY|UP? zr1@Fwbta+Kis#vJZo_p}s()a+2(V3t>KWMV!ggn5#H>_L6+6q0M-0_turo${Mhw+& z#g?|Ug}&Mg3eKs^Q07w)hCqo)Y$I$v4)U^mNvRDjy%tLg^W zMgdAI`?tCT(4!ch4Cx!(K?bLp{Z8#p>~R;Nn_yS-KH}{67PqJ2*zut7`#J*XF!X22 zg#x!-`0vg zK~y-)jgvoU+dve?f0t&+kilRIRyw4F7L>tLmt=F2#UU9i3LUg{3x;k9cnNg$9`M>t zL!ron45pC8gTaO(GH6l%jYTO`jc8f|A>}&QcRtA(`lfgHzW2TF-g_tT9JIN<g4+q=*7lL1i{({p{PNCch(t}k15lg6`s0Lq(| zPF9wV6Vg!vKsO9%#~tt-v1lfjH>VY+z#PFS(eVb8LT$Gr1t14oZ?!ytYRT4Wly$=( z7q442YUeL_0KBd&JtWFv+|>qu{@(EM*H^Bte)5;o>Ii*2u{Ad0ib0!sav(VR?*yR72j~%|ql9i4 zOqw=ruo@*W8RzBMY>Xyr@A3?jRDp{awF|OkH|11`1mvqHFZKDpJ2NMzpjxtX)$UVZ zV(=WXpd=md9L@s3(fR>V787MLN9zY#c9g{&?;Orgp&JIXce%doCj(8Ul;Am{=lZf5 x+L~ZN1=MblCcEP6YXEvdfueDP4{G_PanEZLmHwPbS-*OEbpYwtGqj^MUG?h2xJi_e?& zD@@>5Fh@p>r-a}umDep202|mb2hA7E#s2+=x#b=J*ShiQvajmjI%Yx>CH!3=Iw|G1nbNNLxCuXhpXzA zDSGuLVYO__uwGs;w^v(VRH>wMK0A64v=T_XiL_m-(YWKbF!8>~tP5|_hY$Ga-t#23 z?Nx%1_S-x+6sK2^ZQ(S$VA~7B){Z-`83z7nG7q+m&d!^EFan@*LkN`{!jMg%k#7^t_uGsee7a~h ziWrc&=rS7@4eyR;4Z&+<7ZN8Uy@r+U?!(`2&lgNrZ;hDOiigVVN*AK?_~qmhebhPp zDOHSFByv7QCR9uHa9R05L$ca|ukY@;uf8U6QS7$Hla9VQ#gV&mg#OpNWurEqD6Tbi zreIt_W^G)x-L$>x;g-yHr2kx0pmJQpG*I1Z_%}VJ2}|w4*PuD!HldKmVv?qVIm$M!n&9W95)U|CGA&X* zyJR7;+h_`YySDILVRZkN#Eav;vcoo8%h5`r;Esl!-WZ1HiA&QAP>sPHD2f2v8vgK{`cP}LOnavZ|^NDLfBO^l9JtN?i zeeJ5ATFs~<)h+}zDXTGoj+dXZFKclN&7~(4@O*7zY6h@P=BlRmrG=_qsXB3tCsh~8 z4zzR6Ydl|z>GJKz{U;7r;`Ex%x;nj@=rw{pAbzuaM0Vb&x3 zCEUyCm^}sjxUEbwDSazxnzO!0?4j&?hC;mHTUH2Ku-VQ9@{lUFwGuZj0u2I=+qm`A zU>dt2-!&P0DTz0;J&~6%xuTM3w^xWE;Tmht@xJ%vyGpt8yuqdzh6{Nln|>p_Gp%AF zID-+7M~c7A+N}&)`r+3Ang+z&qXawNia}N&A1wMrT{_^KR^Xw0Cd9AOLUqfCM9!skk zc-_&9Z596yiN zAp#Vj8Ce&3sls*aSlkf*n`!D08=`Mwr#Ued$#wFMOezUv=nY-&2Lm!1d%-X`@`pc> zo*(q7KcN2D4SJz}6!rqrea`W763KKPo=;zO)o>I$3$5#r($#9^t@>UiGa8J?W9s*4 zujgWftL{q8)^6FT1B20mOhIueYAvdg7*IB=mO6GETqm2o6!p2t7Fum@x%zvC-jZ*z^wP!4Af>;!ATJ8;tY|Fdjg>#lsgR%fAS! zdBDeF8AFmNR@BF1iACw5br$M@SfATmsXT+#z)VzweVez5rH|m(_xmkCo`+ z8)9qh;zhf*4kvA;NrnB&^;tQuY&Y)5h|_|J{Hl_8qts#zc`bOQu>Q}PS@5tm?HQ8? zX}`&)%jyg)*=&ZQG0mAaS=6C+R}uON9rju%-1Xg4+qUcov3(IDW4udZN3mN-TLzmY z(VDgSUvAwx4gJwpSSW6)v z9M3N^tx3(*ZMw0O1P{&_XLIfm{f|U#z|N(Ly0vq7TjM)H@fG;CeJOCXeQTh^Y7$?P N)$A{L|J~Q$d;;B<4*~!H delta 11 ScmX@>zSC-g^5*SqVzK}qX#`#X diff --git a/Tests/assets/tests/cloud-big-2x.png b/Tests/assets/tests/cloud-big-2x.png index bdc5d1eae39295e87ef0932fcc0d2c804abf5208..e3ec533f575832f7f6cf9789e9f88b6e935cf507 100644 GIT binary patch delta 1706 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 delta 11 ScmX>nwu^Iu^5*Sq(^&u<^aN%A diff --git a/Tests/assets/tests/cloud-narrow.png b/Tests/assets/tests/cloud-narrow.png index b2f112308f64912800158120f9a783f271b83fad..fb0428edc2b41a1766a1751563f279a563786eb9 100644 GIT binary patch literal 2684 zcmbtVZHOC17#`cI$Cbhr>JPQ*xGlC~lHH^^vRRUArm|F{ z-ML=wXs{f#w*EY;h|v3Szsf93LLqy{`MAZUDf#!GY8Wdmm>1p03qwymIu#_W`)?m_9a6$1{5r)hvau zX68w#QYteXfW-Dn8LLx-!aOPHMpC%`!C3+7T2k2Gn~^f*eln>K%-LjgZfH!Mn^NPN zu)VK4QBjzI5}_DYN=3s_DoMe!tFUj*76s^u(5a+=xI;Le8HW9)O<-@RH>gVCD2&BJ z;oh(;^#))>3U3pos3^sQ;fNy1N+b*$kI>f*6Sg*?jHGrooUvI_n5492?g%A0ZRYWbQ6rDz%w+X!;;4P@~u#9XMmNWg?Cc z$DFoRl0L|C-Q+oC-s+W9GT5FXtfhA0qC=XPl3{(KVTx0jvix}q1f^Io93A89zwIeD zN>WoelTii@hhjq|gQ=vzOowz`Q*cC%5hBNf@ra}au^Np8aZJU*7{M`|&tnqH_xenv zOm&*CMbm`#?@jDw3$Giv_@7PjUW5rvRkYi^=<(_uii)&8t51tMZ%d_!jRMO$sF4Xg zU8F+aXxY{&fqDrShyy1~8xBumhuDx9EIa}!ai|kYh`h;*dc(dqYdT1X9b({dsW!pX zw0$v+601F?zEOe=xYL}(Mkg0ddC!I4T*BYbN`Ku^zsdHgN(YSz)7ysaGJ3j%_2Pch zW(P@GuaII{S51ex-%;Q|i0w&lf#Dr$IlH0MXkDAN1FIOODyCdX6htqlgtsS@0o`Fa z&)zL*FE|Lj9igy**%^`)9DI;y^#GcX{(t(E^+w&n%p_sv@3JXcl8!k+XRu9BfpvEC zwB2dzT7kg+ez6a>~+^!6J5qd;{5-%-k{R_C!J zn%xaz>vCX|*7ZUR=FDc7$KLVS5&)~g@Sd@>cLgnjWdN3!`M_Q|{+Z*C%YHf6<%9QP zpGcYSmq=x+_)pQq^@iU2>}{ZgtUZ2YlSlK&|GUueld%?zNiha=PZ$ zF1oezZad)Pb_M{jHUdiqRt{Jer`Faz^@+Uu$n!nx&m7lBH(z=1?CZZjx^evT z7uM`sN}hSE=hMaY3%8uE#JOMf*TAVSKFO}SzZ`h!%Cj_wbi+wYlj}*{n@jpu3ueQGr#NR1FO#6*pqwu%OhQz|2q03?*H@McP_ex pxjf&V)_IcE{dA07zlXR{_Y9z2S7% zWq+mXF8Txcl}r}-fnI==BDo$<%7sP%?mhS5;9TJS*S~-J=U)5OAL8OlU!|`jT9+PS z^^AL~viZV%@$*$f=rz}9#&c06&WFGMagbn%b2&`?w3+a^IJuMj{O*?vdUs97%z1wJ zBwj@TP;yPssw^rMtrExLM)2QEV+Yv~eVsV%k*SET(zj?*OOA%#(4~GbKnG(l7zQJM z_!NbHu#f!#_Q!4zM*b)Y1Jr-c;S&@~mPKdNmwh!DCC*&yCc=2RTzboWua-Fu#^W*e zLmY-KM7Zj<(q!dUt=cmf9mtd`Dn+A3T_FQXX7xfRjsxpxy_d2%6Zu@LO^r(Rs)2rZ zMH(D?qn!^d;=2odOuVFtBc!)<1?=6g{1uW1~$8Ag#m77traRt ziM;0EtCyrue7zW@U=~I+nGy{O7#q0$fg21ij0g6Af?wZX2d8OtS}9E`%1@_>1K6Gr zETVMAMj@kaFw8b%|+hsf>i$Xhx=ZzGaBT(Y4$nb+>H^(B@xACE#XFK#EKV*|S1q6iv diff --git a/Tests/assets/tests/cloud-small.png b/Tests/assets/tests/cloud-small.png index 14f5f8ae8a8319eda908910ad7d5338b0d22b099..d046639080d77db99d59917402821907f7818e99 100644 GIT binary patch literal 2860 zcmbtWYitxn9G{}{D1t-~5h08V#DaIXd&iY-*E{I8chCb4d%d2t1S8Ykx$CBPySI;W zrFt=7F!F^&d_;|+K`>aOVkGB-q+oa{e5jER7*QM3C?<#`e(@1?o!M*4o?J-Oz5hPu z|NFn^KQp(xZR6S*wexEM05f8(k#_QKqW9FB$n)j*cl-#z3D{=lHY-sfP z>-{`e?|}i%zk=n0EZ6Au2Lz560)9AlF{^4}$dJ=Qdt}X+GcpP@J(iUhShi3o_zEk0 znvr4sjg5^g7hnScFOl$?+f@todsTBWHBq(^!KP#=c}vk$NNu8St#tBsj^@G%cBROE_MgVpkX;`V+cU19eA8gyZoWi|29`=1nWQjTC6C*i{{v9ozGm zZO5k8XGl1@jpVx6aZ0?ED=Ea0(Thn-twC86k7Gid^ofit6hRirpSFOPYw-Gm9d!Oz z+((`qH!d8H3o+HSkSgI=B+L-gK1GoQf0|3nIEcLUT)^+;P%!A_r8Mtt@HaO2(@2&B zLBGpHM3egHT#TEL|GkL^$iyou%Km3lv=?DWmIV1)FFL$(hl*LNJSq>f3T;avi_{Fs z+AHHU>dRWps$||!EDV(#%3u?wH3PQwAQKx9t0X)OEo@q*FT~O&&njc~ozb|15L+b% z8kb~XWNC&grX4^peS7?*ckxXp#!4K1{k9kpm=ok~_rO>53Ftdvor zIizGaX$ILy@=8C><`qdZiTkDu1$<;pIui{4p_Venl*U@uK;7M>V#tz^MU_~Fb#e+h zYeHyMOp^2V8zt=o2cfef1QIaWL&A)Swqdy(z&ND*pFSnMQFc)1!NmLx7R7|5simy~ zGO(B-ojtzWHXDkZ!LX$T)@@Q$Su2>!Dx;Lh+-2yRWa)NIm*H4JV0lKb&Ea(gDhs%_ zQc|@tk8IK8Y+xr22QrvAUa(4>8RYQT^6c#^0hsh>+lG!P0E6TQ1_$Ybyi)WtMK7ED zQnpPW&Wn7K(`wF~IV5k7$HVh{G#X7L5(pt(*LUvRxp(j0{rmTqN~Lq>&W(>{v-08u71WP_p&L}JJdxVY7UV$t4Lw1P*HgTXcwMK2 zbUvl?QN0pyajOG~gx;0VQ9@S|x=u;a6G%^V>6L(sTO9yEoCQP(L=K1|B~AoT1hd3S zz{RZ&Kq%Hhk%J-+MUfIOLQaHrVkO|>RtG#Dk@JW_j~McZBBhY%35p(0tOQ)#>Hz(l zb=^h!a~=EZI>N89+BYUa)AwJb>7aZ4+6Z{^mW8ckFfHHOWdbmLHoa@Wi!aS1%qdnZ z9-Z>_tq`Cl(PqI!|1AZvE{i;H@p@p#n2v&x)UAZ|=Uk(@GpsUQaF? z%x3pUqsNZ#x?^a|)~6m@e)#k&E8kt7A01wH{BYAlN1h&jzRCCHrb|I?UbAnrJXM-` z_MK0ci=#gWp6Qyqm8p5-lMU0_F5Fg_{n?UP`~J9h$DK9$&rkn0xa-)%zi&Q_=1!kE zu;ER1>kII&OAG^}#28n6c~1J=R@o?qioe z73UtFe)7SlMZ34nTd*&AO1}TVFR%4p?39tV*u?{}n&Hl) z$DSWp(KxyHeB{|_7v!IYKi|!-K;IAGvz^^y%4) Y(j#9PUEP;Xk&=N}bYtZ0=B+#b21&cllmGw# delta 11 ScmZ1@HiL75^5*Sqr7Qp%2m}BC diff --git a/Tests/assets/tests/ground-2x.png b/Tests/assets/tests/ground-2x.png index 9588e6b2cb4e8c5aced055e693879a92b2653f5b..981a78b8de81b34d4579c2cea096cff127545970 100644 GIT binary patch literal 2911 zcmds3drT8|96ybK;+QU)#ThfsBhfi+uLTP9Yh6QdCXiLqpx79hxoFX1?SWF&k>cW*d_AdzdB{6ewNI+vh0 zr<$ZW8&G?kF1U^$hBS|hq{@JZ+JK#5jab_;ABHlt5i8JHHC9(9C}py%c#u~$FQ2L^ zqx3YEmKtsF5D>r#L=yEl9jrijjF^l|z_BF8F;rF&%ZyltSOnP(0%j8IDCIOwz`ci$)BC z>u5L$x*VUAkz3i4cV)l>_H&VzRz|@q5~O1Wvlhs>Q3h%ctJE*zyyVo zJ){F6ztRQp1wi1+c?y^-V61VnQ|L{}Bw;1_G5}j@Ht7&Rc#W{aKA}mGG?5~VUuprB zCRwFT%$Mq)FdaTMny|9fN?2GyBv}erOhybss~LtSbV)irse{E%($R@33M8heY$-sm zvX#WsNhKO83D~Fs5GIZ)mueA)p#M2UE-XC5l8%23CG{d|pecgx??qXrbZCY{RA$Q5 z!ANaMI7rqGqgK(Nge-T6SZbb&XGDN9PSOqpw1nf)`K6=)coeXZ9zaDPh=SUHOHJ-z zLiqA5?7)Bz!9n6h@qiRLegLOD@aAAnsd<28(OFz6$qwZrtS`G52xl1B&_t%9iW++=qm*bOLJ~v+F+IxtesujlelzTOWQD% z5LBsXe+~bVAVp!oQ3|uB$lwtT?*_c@a)6V*>jkjT84oXysXLx-ffrAtEho!_1f}ne z#@(BsWRxp=k$@nh$4S3o$ky!>pfF0bSj|zlB4eV)j=So-Fa=(3g%(przUPPgH@|-E zM*4(^V(00I&qr*~-#PmcwlQ_?P!8Zjq3>g?oddtu?i!|!^wtn|NUq3b(Z zuH4aciWLOS1;@8m&Mk{ zE^TURuJYzIvfL-lf!yc0w)U%~Nk95;WOek4buC?6dzy|2?&d&aKcIx|$Gn$nTXSV6 ztvB6a;6P(B8`p8~>15%jg0ADMj`;UnFLK=O^!79@UtGELV4X}T%*_XSYtk;&$}-=n zQ8OfNJ9W9mkDFGc6a-3 z+}gB#?z?{ULnYJ@a>IFldu!(=NfzvQ4#y?CG&}jgj@&j$aGhG+Zd+>YCj% ziUPG0Ph{F_W?v~tUfa4ndHYFo*PfO|d-c_S3z*Xnc=Ybf2F9_3+m{#g_OvafD%k{m zgZ8)kdwYXDx7y9g$6LOyJLD7E)(sBZ+#mL`jlNK4O;7gMo$gqwX}G>Pr>*_oY4)z$ zy!n9;xYYQ2YV(~3MSbOzVhoSh(c{Re8DF8%-j delta 11 ScmcaFcA9g7^5*SqD_8&?Y6O`8 diff --git a/Tests/assets/tests/ground.png b/Tests/assets/tests/ground.png index c4e678ec640255d089d7538eabb44924f5d2b2fb..52debe6064e07df1314ca3f0daf093faaea2bfef 100644 GIT binary patch literal 2277 zcmbtV3v3f*9KX$^j4dOEDWD*nw}=pFuh+HPdbF#fEwo|>bVG*dw(H%u?$Y+|xVx_H z;>H4ruc(lSSu#b0un`_IkSzEBOX6c8gBW>)OnHRN4RH=+0tN@n@2(FzT}agSdg=H7 z{{P?q_kVrg8_O$}imA9H{I7^{3{_R+fE6oO9HP~p<*1z(0cz5jw6vZuq9tY> zVIoTPrUj@$PZZ&LBd#}V2?MDwB@G0c{9t9ds6}MzNv~sZ(ivP?u?ATdNF0wuBDzSC zju-tnVK$p_y#Y5Ev`|AU#WoWbnjQA)rGogNoe9X!*Lq0=TpSPZJ17#asb5CWVmK{H~UzFUxKBTS=` zm9!-!N2`{S%;1?Cs#i7H<3ON&+IB*snGB(_$MazIP-q;yBs&{nf|ALe(1BDH69Dc7 z5+4?6;B17k7OGC6w?rmM4R zeCzcoWsiq+bCOJPG;lkt7=+fbEJG5-rBrc=u~b`B46RK@qe<)27n`(zHWilwU|<+? zCWM2h!%8hu5X`@aSOyEva#Zj?Ln*z8S{RyS?)Rc9OLS;?P)@88%OIf-6lPWRv*nD&@d}PryOp zMT>xvc`<`iC0IM2Q&}aTICK%;KyeefNa?FCGT|(l4Nck;j_f>~Q(AU&^}ITU<8@eP zh+>1Qco7~X0viQEfu(r~x_{QMZ0O)jCOZ6YW-G;{QL=SK%IAX_qhy+r6(bzO)tD^m zOpq>Cf-%P)6tqeXMb(KQAz^riSTTue1WbZJYK#3peF}Rc;ULlgAp8S{BCRR$^>Ty~ zLAf7xcIvcUB(jVjpmsYtZxzcid_{bBfAZz!91SW|~@Z{2*9=y}QP zJ?YK4QaHbL>aF&v^PYTS(^Ac}gWnErbGR-(?L79$g~!GQ^)c6#Tcgd{t$`D>vJg#9 z>T$h)_2B5)`0=5x_`N@e#(Eyw(Y^N2zP&TKyj_Z*YwY(MThE{T`NK_TeuFD0vN^|e z%{w~R-<{j>$Ia%U*((aK?mYd%(2AehYFlm(*i0KweEn+0zP9-{zq+!af0RB@TwBy) zZ8`jA``y7CEj9f?TVMEe`{9x^3)i$=R889A*0H{>{hgi1FKxSYpg`NP`Q*r_eY z3v+G{D4<=vwvB_|*X@q&T^;)F?0a)-zPuhiGNso}_QN6AyR{oXCrl|Ke-vjWEy z^xkzZ--`u5f28RZYfV9I&*eLH&%H)Gx}Ymu`m5(QGE&mnQN!X1BDGuNYmVq{b$_EB zx$L96cfGhLHgvGtj)Tog_-*lzuk|5Wt<&yJpO(t7n(7%SlKIrNBAHKXR`${UJIFf) W8@8|P%YPddA8|V?9Qzj4t^W&l9ubNF delta 11 ScmaDVc#&m-^5*SqdQ1Qvk^~(nz1vO0Hb!0q)3*fNm?c%Q7TEtPBz+h z*>zXF!Yl`~m=p9Yy+S`J*|pOkm}+5|5Fwk=nXe$#tR`c@9z&EJtSD>U5)ZEZzg;pUf(NzasT5by}zL`^IjZ3 zOVu1cwsb>=zT1peD;>>(FoZZfYuu@%vE{uWJY#nC7j`814%=qL`NQ8W%m z-=jeo9pZ3^!`P1oNjOdh5$Zqh_!&wSn_gGU*0twpL1O=73HV5u-OAA3~)Pdolr?m z)C~t;y&|RNo5dstvoK=Flo(LJ+Q1Kw{AhS-J#hFP{D$EsIM0(asSS~opG`9lumd4j zGAH9G91fY!<|Ovx!7%p6b2j#m=<_&=4r$AuACVo5X-${*I5rsU6EGe?`~-(DBq=`$ zs(rx6VOc|>l+lF!Ye+ZO+4Q6|-KZOu!g@0)i7a5>KI3z;ERA=3(I{a!5)~=9M)O*s zw+o`VLRz_P7yQ?KQpXpZNc6H^5cyb% zKE6e+#x7pEYwKjvRhrb$uhg8$dF{G!KSrEZM3h&xf*Yj~YhE^j)*9;nP}qe4TGO2| zdXV3UfAQ~~07@LJX>~@ucpTJ?Sg@#?y3=BU^5*SqVln_9LH6}chTSJuD_5AkWwVa<4L*D2*ADP9vqwt{C@Js`;U9gli$R}mA*>ehP)~~mR3{n zRz>}d`Jz{=n(=GUWD1!mW9PrW|8a;&W9M?1_(?s6xj4C#aDMmW1;4xIqttnI_%vFD z2vC4#WL4y)3RkgXaYOuXrl~`0h`x@U=EzheSIIjvt|XA5H*~ol49Nb-3x>ggKm4Bb z{Gd<$0rf|2&DU z2A)r)jiK9_Dc_{j3z=I|DQ_s`P(Y~_<^?+mr?ut-RMP0ONkw+trYfD%?Fd`e>b(Pk z`J3E_m^SyLljPBOS`<4ON*~{#M4jFbRiNtPwg!3zs#-`6$2YjyJu3`yJ8P^^VZ!7! zps(JrT)}!VOwcST(`>>tDqw8j`ulD$xG)~*zrbJLUk4{icv>pWN)D%!*gk2QK(5aC_-s=(6cca1Z#9^HCp~K8J%Xj7h~8<~Y_E=~rOfgZK##Uz9BWDyZfj zAB$xSNurd8>1RXQxz?sfxo$`8Fc-#~Vb017_wA-IV~bonhv&5v8i*)Z28zroN#4zw z0!g4men2!Rtr{<)#_GA~3fR%QLPQ@RVTf@FOjmM?)H!_EC3ScXtR%0iIV&G3(Zx5! z*4W02wrw4b+e+gK`<3g{a#q=H+>H^(1rzyYCGke7#R~FT@JeC*A2PGxVQbnmCil|b z%cjff3@q7nilQ;inKoI}p>|gh`UxF&A{6fW_OWeSc7)iz2$3<~C9$K}4WuoD^^$1K z+WarKZk&exXe%t|fcTHJ#wJo#GreRIjxw}&?6mjp>qd$+12P_y=a-^PtEKvGmnX;b z%S>xhb9I|;>?Fa1Gsan;dqlsGs14YN~|XFCHeK| MU;g~-+kf{y0f#^l2LJ#7 delta 11 ScmbOm+UYStdGmI*XUYH`O9b!$ diff --git a/Tests/assets/tests/river-2x.png b/Tests/assets/tests/river-2x.png index abed28ac6fb34bc9697cc16a6604a9e83b0d807e..1e287c238bf6e740ee8d154ccd30970354aaeb39 100644 GIT binary patch literal 2478 zcmd^AU1%Id9N!pvX;ULe3ymT;Y^$hsZ}+}>x%Do+%wzWRk%5hv%W9 zjrjwSK!+505(K3{NR+~&6cYkLS?Z930Z{$$ovk2lYk9dpeV{5vM+v@2h$V|+xm@;_ zLw?gPh=EuvCQ3mu7!)W%a3&1`D}v$dW)vPr8ab+sErLx0Fiw~=$4P?c={l(Gq-6Eu zLXkLi3B#$zj7CqaKuZkxCDC>SgKU5d>K+0FImGeDMONfGuJXI1nm}CKzz61+Y9mNYyTPXc z^x|5dItLImK(|?h#zqn~yerX27jGta?lM-_&WHrCdamev_uCBONnO%Fsq#1zOp))3)2jS^jLBf8jeyLHE)g{(e!Q*>z4x^ z)UOw0P%)cc9`F8iYlvPvzTDFX)7)+LeQROKSo3Zu<`QYvNviqn%E+kgSqv z`OeqYvU8^&y?Kn|?wQY~y9O&4uV4H~`SfsmX7Q5#$qPESu=nPNP47>h>}%g~f6_P0 zFDB+^=Wac^dLha#!vFMhyC6?5{TlwFefipQyZXwHm#?lazjn1e^Y*vbR;Ct4KWKQY zuB?=sUGd{*M;1?ie&n=xPXGV_ delta 11 ScmZ1{Jd16D^5*Sq-4NQ+5BHM}gXvgtLSF09QI&9!ASWl8(S z2hvR)0BTea+^pFS*P9tB#MR+H5GxW6O~i6Wng{~oC1Va}U7zA)EGe6+mcXN_n3mMW z)a0W$u4==Ino!h~ti^S8Opj~0bxGp`IPF_yeLlCp6%0lhsVao0D@vo$h&6^|u3u5K zR4S#YaU~v?!9wP%jv!6h;d=sz2qQZnq+9=(gmf3Of>b@OvvP^~Av_>7l!An@0<|%jUzDe^dFxNd{ zP>2>~Qa6adOrfOq6PwevPB)-VEFwsb2$+9R0 z!ZU~1{~0Q%MVz)w-MU_jp)9J<30p*?XlS#bEOnbW6_~Yb(K4yqLKpalyFYzuqX6s#$nE@+f6zohjG{uIuM3EBqMRM zLam5ETgCoQokDFy0UA{b@Y^&+$CA5c(I7sZs6b`6ciTyySrv-2S-f|VIhNbt5BIV( zVeKkGPb$H79kgL9Avjvm>udP01Vsj2TPb8MlED@YXM@r?9AMBnUZ?}Xd^kL+pFj2m z96bG{C#G`f@8Ev#%!hA*j|R`FcjYf^*yj$v-#GHX$X74ib7f%(-+KEU@9?90Py4SHXJ^2^_ZoZq z<3FD}a^i!{)2HD1di~N%({G-={N?5w_NC38TLLN~t0)^8b_y^Q)! R?l1!Wh5StJ)Z~Ff{{U>8dv5>$ delta 11 ScmaFIe~W2?^5*Sq=8OOyGXymN diff --git a/Tests/assets/tests/sky-2x.png b/Tests/assets/tests/sky-2x.png index d7aae77da62c73fac44c6d3ae2f228b96de3d817..a86d96b03d0c07de82bdac0e2f9617db25eaa216 100644 GIT binary patch literal 4623 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 diff --git a/Tests/assets/tests/tween/PHASER.png b/Tests/assets/tests/tween/PHASER.png new file mode 100644 index 0000000000000000000000000000000000000000..09178f50c377ac9aeee42997ed545c9c3236a55a GIT binary patch literal 3967 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 AD*ylh literal 0 HcmV?d00001 diff --git a/Tests/assets/tests/tween/ribbon.png b/Tests/assets/tests/tween/ribbon.png new file mode 100644 index 0000000000000000000000000000000000000000..674a55aed6a0bf970571b25aface04a5206c0a18 GIT binary patch literal 1165 zcmV;81akX{P)>Q{B@+}+5HdmO1SK2vu0CpofI%R^Nqj!<-9y;?5a2w2b3Vj% z0RR9OXfl~p;iODs5ym`xZQka6TzQ%S02pvkuVQ)>#+xw4>3rOthVeOEX4=*LUwa7v z0O)Z{zo~_EJiS>vzitu6hZx%7y34NjPizAKkZVX+X|o>A<8)f4v9CCL{W09;?39l| zYy$vrs(7wPbA9`!w%s(Mcli{?hj8DEb3A6T4FJF);k+KjRc-riis>%mxfhWwwgCVx zJC--CX|C4Jk89i8)Hw_*wm}FFPx?0U*Di zEsFhTV|T^v%D(ptxr(3mc-Q4etBY*_D0Z&1-KJ`I`Ei5G9{lGbd_d{{DM5K@qizjpCtgGO~3SgW;@2wd#@t^02z7=u^pF^Ec>|g zKY9HC0LWNe{`t_?ofq2x0Oam=GMPMzZ2$le++rI5fL;dopXumgVjBPeT2_VeB?R}V z4?8Qi0RZTmG6na&*aiTAZak!AC8gK~0D$&YMaHw-VjBQ}zKd^|jI-Qd(x;<~Z2$mh zS$xxETvqa!%hD3D4FJH<+!oJEOD5+&OrY2X0APq>WWNvNuX9GX*aiSVbc<~O0B9w; zA5OKVTWkXWaB0zfpQ8JZu8&@F?fC`(;6lBNBLw#%oPG@BQ`la%c?V{;0RXskWf%`( z{F7$8Z`-aIRM~v z(qZ$;4sLps!uA+%54eq{k7ty|eJ#G@_!>{c`Tu{fU&SMP7thBWgmXJI?*IyB;wLV#z*&eoi{{+78ENIghp0|DY8~}hb#`bFM_BKC!Pi%K%k;ZEg z{Oy=XHlqpvkiScd?QJu&F^vCiaQXkPV?8MV0DX?_O|iRaR(Q7Ix|T2i05JI2UKHOi zsd#$jduEFP0J!+rp4DP`wfv&K&e*In003h9m6(pP{Iz&l%CStx5Ci}K_KfXWEwC-) f004lN{42l!ny4un;|CTv00000NkvXXu0mjfJt!>b literal 0 HcmV?d00001 diff --git a/Tests/assets/tests/tween/shadow.png b/Tests/assets/tests/tween/shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..60096788772d7f8d969793d35cfdd2a83bc59938 GIT binary patch literal 1251 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 I_8gu23vv60i2wiq delta 11 ScmeAaea}8YdGlVjGt2-SK?IEe diff --git a/Tests/cameras/camera fade.js b/Tests/cameras/camera fade.js deleted file mode 100644 index b86cbcc2..00000000 --- a/Tests/cameras/camera fade.js +++ /dev/null @@ -1,42 +0,0 @@ -/// -(function () { - var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); - - var circle1, circle2, circle3; - var fx; - - function init() { - game.world.setSize(800, 600, true); - game.load.image('blue', 'assets/tests/blue-circle.png'); - game.load.image('yellow', 'assets/tests/yellow-circle.png'); - game.load.image('magenta', 'assets/tests/magenta-circle.png'); - - game.load.start(); - } - function create() { - circle1 = game.add.sprite(114, 34, 'blue'); - circle2 = game.add.sprite(426, 86, 'yellow'); - circle3 = game.add.sprite(221, 318, 'magenta'); - - circle1.input.start(0, false, true); - circle1.events.onInputUp.add(fade1, this); - - fx = game.camera.fx.add(Phaser.FX.Camera.Fade); - } - function update() { - } - function render() { - game.camera.fx.render(game.camera, - game.camera.x, game.camera.y, - game.camera.width, game.camera.height); - game.camera.fx.postRender(game.camera, - game.camera.x, game.camera.y, - game.camera.width, game.camera.height); - } - function fade1(pointer) { - console.log('pressed'); - fx.start(0.05, 0.5, function() { - console.log('fin'); - }); - } -})(); diff --git a/Tests/cameras/camera fx 1.js b/Tests/cameras/camera fx 1.js new file mode 100644 index 00000000..7b8cd30f --- /dev/null +++ b/Tests/cameras/camera fx 1.js @@ -0,0 +1,43 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + var btn1, btn2, btn3; + var fx; + + function init() { + game.world.setSize(800, 600, true); + game.load.image('blue', 'assets/tests/blue-circle.png'); + game.load.image('yellow', 'assets/tests/yellow-circle.png'); + game.load.image('magenta', 'assets/tests/magenta-circle.png'); + + game.load.start(); + } + function create() { + btn1 = game.add.button(114, 34, 'blue', simpleFade, this); + btn2 = game.add.button(426, 86, 'yellow', forceFade, this); + btn3 = game.add.button(221, 318, 'magenta', fadeWithCallback, this); + + fx = game.camera.fx.add(Phaser.FX.Camera.Fade); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Press to fade.', 114 + 90, 34 + 130); + Phaser.DebugUtils.context.fillText('Force to fade every time you press it.', 426 + 20, 86 + 130); + Phaser.DebugUtils.context.fillText('Popup a window when fade finished.', 221 + 30, 318 + 130); + } + function simpleFade() { + // Simply fade to black in 0.5 seconds. + fx.start(0x330033, 0.5); + } + function forceFade() { + // Force restart fade effect each time you pressed the button. + fx.start(0x003333, 0.5, null, true); + } + function fadeWithCallback() { + // Popup a alert window when fade finished. + fx.start(0x333300, 0.5, function() { + alert('Fade finished!'); + }); + } +})(); diff --git a/Tests/cameras/camera fx 2.js b/Tests/cameras/camera fx 2.js new file mode 100644 index 00000000..f700830e --- /dev/null +++ b/Tests/cameras/camera fx 2.js @@ -0,0 +1,44 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + var btn1, btn2, btn3; + var fx; + + function init() { + game.world.setSize(800, 600, true); + game.load.image('blue', 'assets/tests/blue-circle.png'); + game.load.image('yellow', 'assets/tests/yellow-circle.png'); + game.load.image('magenta', 'assets/tests/magenta-circle.png'); + + game.load.start(); + } + function create() { + btn1 = game.add.button(114, 34, 'blue', simpleFlash, this); + btn2 = game.add.button(426, 86, 'yellow', forceFlash, this); + btn3 = game.add.button(221, 318, 'magenta', flashWithCallback, this); + + // Usage of flash fx is the same as fade. + fx = game.camera.fx.add(Phaser.FX.Camera.Flash); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Press to flash.', 114 + 90, 34 + 130); + Phaser.DebugUtils.context.fillText('Force to flash every time you press it.', 426 + 20, 86 + 130); + Phaser.DebugUtils.context.fillText('Popup a window when flash finished.', 221 + 30, 318 + 130); + } + function simpleFlash() { + // Simply flash to black in 0.5 seconds. + fx.start(0x330033, 0.5); + } + function forceFlash() { + // Force restart flash effect each time you pressed the button. + fx.start(0x003333, 0.5, null, true); + } + function flashWithCallback() { + // Popup a alert window when flash finished. + fx.start(0x333300, 0.5, function() { + alert('Flash finished!'); + }); + } +})(); diff --git a/Tests/cameras/camera fx 3.js b/Tests/cameras/camera fx 3.js new file mode 100644 index 00000000..b15a0652 --- /dev/null +++ b/Tests/cameras/camera fx 3.js @@ -0,0 +1,44 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + var btn1, btn2, btn3; + var fx; + + function init() { + game.world.setSize(800, 600, true); + game.load.image('blue', 'assets/tests/blue-circle.png'); + game.load.image('yellow', 'assets/tests/yellow-circle.png'); + game.load.image('magenta', 'assets/tests/magenta-circle.png'); + + game.load.start(); + } + function create() { + btn1 = game.add.button(114, 34, 'blue', simpleShake, this); + btn2 = game.add.button(426, 86, 'yellow', forceShake, this); + btn3 = game.add.button(221, 318, 'magenta', shakeWithCallback, this); + + // Usage of shake fx is the same as fade and flash. + fx = game.camera.fx.add(Phaser.FX.Camera.Shake); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Press to shake.', 114 + 90, 34 + 130); + Phaser.DebugUtils.context.fillText('Force to shake every time you press it.', 426 + 20, 86 + 130); + Phaser.DebugUtils.context.fillText('Popup a window when shake finished.', 221 + 30, 318 + 130); + } + function simpleShake() { + // Simply shake to black in 0.5 seconds. + fx.start(0x330033, 0.5); + } + function forceShake() { + // Force restart shake effect each time you pressed the button. + fx.start(0x003333, 0.5, null, true); + } + function shakeWithCallback() { + // Popup a alert window when shake finished. + fx.start(0x333300, 0.5, function() { + alert('Shake finished!'); + }); + } +})(); diff --git a/Tests/cameras/camera scale.js b/Tests/cameras/camera scale.js new file mode 100644 index 00000000..dd132d85 --- /dev/null +++ b/Tests/cameras/camera scale.js @@ -0,0 +1,72 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var zombieCamera; + + var zombie; + var walkSpeed = 2, + direction = 1; + + function init() { + game.world.setSize(1280, 600, true); + game.load.image('ground', 'assets/tests/ground-2x.png'); + game.load.image('river', 'assets/tests/river-2x.png'); + game.load.image('sky', 'assets/tests/sky-2x.png'); + + game.load.spritesheet('zombie', 'assets/sprites/metalslug_monster39x40.png', 39, 40); + + game.load.start(); + } + function create() { + // Add background images. + game.add.sprite(0, 0, 'sky'); + game.add.sprite(0, 360, 'ground'); + game.add.sprite(0, 400, 'river'); + + // Create zombie spirte + zombie = game.add.sprite(480, 336, 'zombie'); + zombie.animations.add('walk', null, 30, true); + zombie.animations.play('walk'); + + // Create a small camera which looks at the zombie. + // Use the same settings as the default camera. + zombieCamera = game.add.camera(0, 0, 800, 600); + // Use x and y properties to set the target area. + zombieCamera.x = 420; + zombieCamera.y = 240; + // Resize the camera so that it will only look at 200x200 area. + zombieCamera.setSize(200, 200); + // Scale the camera to 2.0, now its target will be 100x100. + zombieCamera.transform.scale.setTo(2.0, 2.0); + // Use setPosition() method to set where the camera rendered + // on the screen. + zombieCamera.setPosition(0, 0); + } + function update() { + if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { + zombieCamera.x -= 2; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { + zombieCamera.x += 2; + } + if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) { + zombieCamera.y -= 2; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) { + zombieCamera.y += 2; + } + // zombie wandering update + zombie.x += walkSpeed * direction; + if (zombie.x > 540 || zombie.x < 440) { + // Change walk direction. + direction *= -1; + // Flip zombie's animation. + zombie.texture.flippedX = !zombie.texture.flippedX; + } + } + function render() { + game.camera.renderDebugInfo(32, 32); + zombieCamera.renderDebugInfo(32, 128); + } +})(); diff --git a/Tests/cameras/hide from camera.js b/Tests/cameras/hide from camera.js new file mode 100644 index 00000000..231d1125 --- /dev/null +++ b/Tests/cameras/hide from camera.js @@ -0,0 +1,53 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var radar; + var ships = []; + + var enemyCamera; + + function init() { + game.world.setSize(800, 600, true); + game.load.image('radar-surface', 'assets/tests/radar-surface.png'); + game.load.image('ship', 'assets/sprites/asteroids_ship_white.png'); + game.load.image('enemy-ship', 'assets/sprites/asteroids_ship.png'); + + game.load.start(); + } + function create() { + // Add enemies and our ship the the world. + for (var i = 0; i < 4; i++) { + ships.push(game.add.sprite(100 + i * 10, 280 + i * 16, 'enemy-ship')); + } + var ourShip = game.add.sprite(160, 300, 'ship'); + ships.push(ourShip); + + // Radar sprite is a HUD. + radar = game.add.sprite(0, 0, 'radar-surface'); + radar.transform.scrollFactor.setTo(0, 0); + + // Make the default camera rendered on the left half screen. + game.camera.setSize(400, 600); + // Add a new camera and render it on the right half screen. + // The newly created is the enemies' camera, which cannot "see" our ship. + enemyCamera = game.add.camera(0, 0, 800, 600); + enemyCamera.setSize(400, 600); + enemyCamera.setPosition(400, 0); + + // Hide our ship on the enemies' camera. + enemyCamera.hide(ourShip); + } + function update() { + for (var i = 0; i < ships.length; i++) { + ships[i].x += 1; + if (ships[i].x > 400) { + ships[i].x = 40; + } + } + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Left is the player\'s camera, and right is the enemies\' camera.', 32, 100); + } +})(); diff --git a/Tests/cameras/multi camera.js b/Tests/cameras/multi camera.js index 7554e1f3..d98d8244 100644 --- a/Tests/cameras/multi camera.js +++ b/Tests/cameras/multi camera.js @@ -19,22 +19,27 @@ game.load.start(); } function create() { - // background images + // Add background images. game.add.sprite(0, 0, 'sky'); game.add.sprite(0, 360, 'ground'); game.add.sprite(0, 400, 'river'); - // zombie spirte + // Create zombie spirte zombie = game.add.sprite(480, 336, 'zombie'); zombie.animations.add('walk', null, 30, true); zombie.animations.play('walk'); - // create a small camera which looks at the zombie + // Create a small camera which looks at the zombie. + // Use the same settings as the default camera. zombieCamera = game.add.camera(0, 0, 800, 600); + // Use x and y properties to set the target area. zombieCamera.x = 420; zombieCamera.y = 240; - zombieCamera.setPosition(0, 0); + // Resize the camera so that it will only look at 200x200 area. zombieCamera.setSize(200, 200); + // Use setPosition() method to set where the camera rendered + // on the screen. + zombieCamera.setPosition(0, 0); } function update() { if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { @@ -52,8 +57,10 @@ // zombie wandering update zombie.x += walkSpeed * direction; if (zombie.x > 540 || zombie.x < 440) { + // Change walk direction. direction *= -1; - zombie.transform.scale.setTo(direction, 1); + // Flip zombie's animation. + zombie.texture.flippedX = !zombie.texture.flippedX; } } function render() { diff --git a/Tests/cameras/radar template.js b/Tests/cameras/radar template.js deleted file mode 100644 index 5608b2e6..00000000 --- a/Tests/cameras/radar template.js +++ /dev/null @@ -1,47 +0,0 @@ -/// -(function () { - var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); - - var radar; - var ships = []; - - var button; - - function init() { - game.world.setSize(800, 600, true); - game.load.image('radar-surface', 'assets/tests/radar-surface.png'); - game.load.image('ship', 'assets/sprites/asteroids_ship_white.png'); - game.load.image('enemy-ship', 'assets/sprites/asteroids_ship.png'); - - game.load.image('button', 'assets/tests/320x200.png'); - - game.load.start(); - } - function create() { - for (var i = 0; i < 4; i++) { - ships.push(game.add.sprite(100 + i * 10, 300 + i * 16, 'ship')); - } - ships.push(game.add.sprite(160, 320, 'enemy-ship')); - radar = game.add.sprite(0, 0, 'radar-surface'); - - game.camera.setSize(400, 600); - var camera2 = game.add.camera(0, 0, 400, 600); - camera2.x = 400; - - button = game.add.sprite(500, 100, 'button'); - button.input.start(0, false, true); - } - function update() { - if (button.input.justReleased(0, 20)) { - } - - for (var i = 0; i < ships.length; i++) { - ships[i].x += 1; - if (ships[i].x > 400) { - ships[i].x = 40; - } - } - } - function render() { - } -})(); diff --git a/Tests/groups/add to group 1.js b/Tests/groups/add to group 1.js new file mode 100644 index 00000000..44bff9a3 --- /dev/null +++ b/Tests/groups/add to group 1.js @@ -0,0 +1,40 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + var friendAndFoe, + enemies; + + function init() { + game.load.image('ufo', 'assets/sprites/ufo.png'); + game.load.image('baddie', 'assets/sprites/space-baddie.png'); + game.load.start(); + } + function create() { + // Create some local groups for later use. + friendAndFoe = game.add.group(); + enemies = game.add.group(); + + // Use game.add (GameObjectFactory) to create sprites, those + // newly created ones will be added to game.world.group + // automatically. While you can still use new to allocate and + // only add them to your own groups. + var ufo = game.add.sprite(200, 240, 'ufo'); + friendAndFoe.add(ufo); + + // Create some enemies using new keyword. + // (Don't forget to pass game as the first parameter.) + var enemy; + for (var i = 0; i < 16; i++) { + enemy = new Phaser.Sprite(game, + 360 + Math.random() * 200, 120 + Math.random() * 200, + 'baddie'); + enemies.add(enemy); + } + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('ufo added to game.world.group and "friendAndFoe" group', 16, 24); + Phaser.DebugUtils.context.fillText('others ONLY added to "enemies" group', 16, 40); + } +})(); diff --git a/Tests/groups/add to group 2.js b/Tests/groups/add to group 2.js new file mode 100644 index 00000000..1d7b0ead --- /dev/null +++ b/Tests/groups/add to group 2.js @@ -0,0 +1,37 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + function init() { + game.load.image('ufo', 'assets/sprites/ufo.png'); + game.load.image('baddie', 'assets/sprites/space-baddie.png'); + game.load.start(); + } + function create() { + // Create some local groups for later use. + friendAndFoe = game.add.group(); + enemies = game.add.group(); + + // You can directly create sprite and add it to a group + // using just one line. (One thing you should know is, the body type + // of this sprite is set to BODY_DINAMIC by default, while it's + // BODY_DISABLED by default using other creating methods.) + friendAndFoe.addNewSprite(200, 240, 'ufo', null, Phaser.Types.BODY_DISABLED); + + // Create some enemies. + for (var i = 0; i < 8; i++) { + createBaddie(); + } + + // Tap to create new baddie sprites. + game.input.onTap.add(createBaddie, this); + } + function createBaddie() { + enemies.addNewSprite(360 + Math.random() * 200, 120 + Math.random() * 200, + 'baddie', null, + Phaser.Types.BODY_DISABLED); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Tap screen or click to create new baddies.', 16, 24); + } +})(); diff --git a/Tests/groups/bring to top.js b/Tests/groups/bring to top.js new file mode 100644 index 00000000..c28b68a9 --- /dev/null +++ b/Tests/groups/bring to top.js @@ -0,0 +1,30 @@ +(function() { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + var container; + + function init() { + game.load.spritesheet('button', 'assets/buttons/number-buttons.png', 160, 160); + game.load.start(); + } + function create() { + // Container for sorting the buttons, which we'll use to make buttons + // to the top later. + container = game.add.group(); + + // Add buttons to container. + container.add(game.add.button(200, 100, 'button', bringMeToTop, this, 0, 0, 0)); + container.add(game.add.button(300, 100, 'button', bringMeToTop, this, 1, 1, 1)); + container.add(game.add.button(100, 200, 'button', bringMeToTop, this, 2, 2, 2)); + container.add(game.add.button(400, 200, 'button', bringMeToTop, this, 3, 3, 3)); + container.add(game.add.button(300, 300, 'button', bringMeToTop, this, 4, 4, 4)); + container.add(game.add.button(200, 300, 'button', bringMeToTop, this, 5, 5, 5)); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Tap or click buttons to bring it to the top.', 32, 32); + } + function bringMeToTop(btn) { + container.bringToTop(btn); + } +})(); diff --git a/Tests/groups/call all.js b/Tests/groups/call all.js new file mode 100644 index 00000000..12b78583 --- /dev/null +++ b/Tests/groups/call all.js @@ -0,0 +1,37 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + function init() { + game.load.spritesheet('item', 'assets/buttons/number-buttons-90x90.png', 90, 90); + game.load.image('reviveBtn', 'assets/buttons/revive-button.png'); + game.load.start(); + } + function create() { + // Add some items. + var item; + for (var i = 0; i < 3; i++) { + // Give the items a different alpha increase speed. + item = game.add.sprite(290, 98 * (i + 1), 'item', i); + // Enable input. + item.input.start(0, false, true); + item.events.onInputUp.add(kill); + // An item besides the left one. + item = game.add.sprite(388, 98 * (i + 1), 'item', i + 3); + item.input.start(0, false, true); + item.events.onInputUp.add(kill); + } + // Add a button to revive all the items. + game.add.button(270, 400, 'reviveBtn', reviveAll, this, 0, 0, 0); + } + function kill(item) { + item.kill(); + } + function reviveAll() { + game.world.group.callAll('revive'); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Tap or click an item to kill it, and press the revive button to revive them all.', 160, 500); + } +})(); diff --git a/Tests/groups/direct render.js b/Tests/groups/direct render.js new file mode 100644 index 00000000..96457e01 --- /dev/null +++ b/Tests/groups/direct render.js @@ -0,0 +1,38 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + // Left and right group. + var left, right; + // The first selected item. + var selected = null; + + function init() { + game.load.spritesheet('item', 'assets/buttons/number-buttons-90x90.png', 90, 90); + game.load.start(); + } + function create() { + left = game.add.group(); + right = new Phaser.Group(game); + // Add some items to left side, and set a onDragStop listener + // to limit its location when dropped. + var item; + for (var i = 0; i < 3; i++) { + // Directly create sprites from the left group. + item = left.addNewSprite(250, 98 * (i + 1), 'item', i, Phaser.Types.BODY_DISABLED); + // Add another to the right group. + item = right.addNewSprite(348, 98 * (i + 1), 'item', i + 3, Phaser.Types.BODY_DISABLED); + } + + exCamera = game.add.camera(0, 0, 800, 600); + exCamera.setPosition(120, 0); + } + function render() { + right.directRender(exCamera); + + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Left Group', 300, 80); + Phaser.DebugUtils.context.fillText('Right Group', 400, 80); + Phaser.DebugUtils.context.fillText('Left group is normally rendered, while the right one is ONLY rendered directly to another camera.', 120, 480); + } +})(); diff --git a/Tests/groups/for each.js b/Tests/groups/for each.js new file mode 100644 index 00000000..6c4b3821 --- /dev/null +++ b/Tests/groups/for each.js @@ -0,0 +1,35 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var baseAlphaIncSpeed = 0.006; + + function init() { + game.load.spritesheet('item', 'assets/buttons/number-buttons-90x90.png', 90, 90); + game.load.start(); + } + function create() { + // Add some items. + for (var i = 0; i < 3; i++) { + game.add.sprite(290, 98 * (i + 1), 'item', i) + .alphaIncSpeed = baseAlphaIncSpeed * (i + 1); + game.add.sprite(388, 98 * (i + 1), 'item', i + 3) + .alphaIncSpeed = baseAlphaIncSpeed * (i + 4); + } + } + function update() { + // Animating alpha property of each item using forEach() method. + game.world.group.forEach(function(item) { + // Update alpha first. + item.alpha -= item.alphaIncSpeed; + // Check for switch between increasing and descreasing. + if (item.alpha < 0.001 || item.alpha > 0.999) { + item.alphaIncSpeed *= -1; + } + }); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Alpha of items is always changing.', 280, 480); + } +})(); diff --git a/Tests/groups/get first 1.js b/Tests/groups/get first 1.js new file mode 100644 index 00000000..13abf0b4 --- /dev/null +++ b/Tests/groups/get first 1.js @@ -0,0 +1,44 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var timer, cycle; + + function init() { + game.load.spritesheet('item', 'assets/buttons/number-buttons-90x90.png', 90, 90); + game.load.image('reviveBtn', 'assets/buttons/revive-button.png'); + game.load.start(); + } + function create() { + // Add some items. + var item; + for (var i = 0; i < 3; i++) { + // Give the items a different alpha increase speed. + item = game.add.sprite(290, 98 * (i + 1), 'item', i); + // An item besides the left one. + item = game.add.sprite(388, 98 * (i + 1), 'item', i + 3); + } + + // Set a timer so we can perform an action after a delay. + timer = 0; + cycle = 1000; + } + function update() { + // Update timer. + timer += game.time.delta; + if (timer > cycle) { + timer -= cycle; + // Get the first alive item and kill it. + var item = game.world.group.getFirstAlive(); + if (item) { + item.kill(); + } + } + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('One item will be killed each second.', 280, 420); + // Get living and dead number of a group. + Phaser.DebugUtils.context.fillText('Living: ' + game.world.group.countLiving() + ', Dead: ' + game.world.group.countDead(), 330, 440); + } +})(); diff --git a/Tests/groups/get first 2.js b/Tests/groups/get first 2.js new file mode 100644 index 00000000..b83c8161 --- /dev/null +++ b/Tests/groups/get first 2.js @@ -0,0 +1,49 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var timer, cycle; + + function init() { + game.load.spritesheet('item', 'assets/buttons/number-buttons-90x90.png', 90, 90); + game.load.image('reviveBtn', 'assets/buttons/revive-button.png'); + game.load.start(); + } + function create() { + // Add some items. + var item; + for (var i = 0; i < 3; i++) { + // Give the items a different alpha increase speed. + item = game.add.sprite(290, 98 * (i + 1), 'item', i); + // An item besides the left one. + item = game.add.sprite(388, 98 * (i + 1), 'item', i + 3); + } + + // Set a timer so we can perform an action after a delay. + timer = 0; + cycle = 1000; + } + function update() { + // Update timer. + timer += game.time.delta; + if (timer > cycle) { + timer -= cycle; + // Get an alive item from the group randomly, so it may not + // be the first to be killed. + // Also you can specific a range, only items between that range + // will be found and return. + // Set a range of (0, 5), so the first item will not be kill at all. + var item = game.world.group.getRandom(1, 5); + if (item) { + item.kill(); + } + } + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('One item will be killed each second.', 280, 420); + Phaser.DebugUtils.context.fillText('Yet the first one will NEVER be killed since we use a range from 1 to 5 for selection.', 140, 432); + // Get living and dead number of a group. + Phaser.DebugUtils.context.fillText('Living: ' + game.world.group.countLiving() + ', Dead: ' + game.world.group.countDead(), 330, 460); + } +})(); diff --git a/Tests/groups/get first 3.js b/Tests/groups/get first 3.js new file mode 100644 index 00000000..ab09aedf --- /dev/null +++ b/Tests/groups/get first 3.js @@ -0,0 +1,58 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var killTimer, reviveTimer, cycle; + + function init() { + game.load.spritesheet('item', 'assets/buttons/number-buttons-90x90.png', 90, 90); + game.load.image('reviveBtn', 'assets/buttons/revive-button.png'); + game.load.start(); + } + function create() { + // Add some items. + var item; + for (var i = 0; i < 3; i++) { + // Give the items a different alpha increase speed. + item = game.add.sprite(290, 98 * (i + 1), 'item', i); + // An item besides the left one. + item = game.add.sprite(388, 98 * (i + 1), 'item', i + 3); + } + + // Set a timer so we can perform an action after a delay. + killTimer = 0; + // Another timer for reviving. + reviveTimer = 0; + cycle = 1000; + } + function update() { + // Update timers. + killTimer += game.time.delta; + reviveTimer += game.time.delta; + + // Kill first alive item every "cycle" duration. + if (killTimer > cycle) { + killTimer -= cycle; + // Get an alive item from the group and kill it. + var item = game.world.group.getFirstAlive(); + if (item) { + item.kill(); + } + } + // Revive first dead item every 1.5 "cycle" duration. + if (reviveTimer > cycle * 1.5) { + reviveTimer -= cycle * 1.5; + // Get a dead item from the group and revive it. + var item = game.world.group.getFirstDead(); + if (item) { + item.revive(); + } + } + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('One item will be killed each second and revived later.', 240, 420); + // Get living and dead number of a group. + Phaser.DebugUtils.context.fillText('Living: ' + game.world.group.countLiving() + ', Dead: ' + game.world.group.countDead(), 330, 440); + } +})(); diff --git a/Tests/groups/group as layer.js b/Tests/groups/group as layer.js new file mode 100644 index 00000000..1ba93a6f --- /dev/null +++ b/Tests/groups/group as layer.js @@ -0,0 +1,74 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + function init() { + game.world.setSize(1280, 800, true); + + game.load.image('ground', 'assets/tests/ground-2x.png'); + game.load.image('river', 'assets/tests/river-2x.png'); + game.load.image('sky', 'assets/tests/sky-2x.png'); + game.load.image('cloud0', 'assets/tests/cloud-big-2x.png'); + game.load.image('cloud1', 'assets/tests/cloud-narrow-2x.png'); + game.load.image('cloud2', 'assets/tests/cloud-small-2x.png'); + + game.load.spritesheet('ufo', 'assets/sprites/ufo.png', 24, 21); + + game.load.start(); + } + function create() { + // Create the sky layer, behind everything and donot move. + var skyLayer = game.add.group(); + skyLayer.z = 0; + // Create the cloud layer, only beyond the sky. + var cloudLayer = game.add.group(); + cloudLayer.z = 1; + // Create the ground, behind the river and beyond clouds. + var groundLayer = game.add.group(); + groundLayer.z = 2; + // Create the sprite layer. This should behind the river, + // and beyond the ground, cloud and sky layer. + var spriteLayer = game.add.group(); + spriteLayer.z = 3; + // Create the river layer, beyond everything. + var riverLayer = game.add.group(); + riverLayer.z = 4; + + // Add sky background to skyLayer. + var sky = new Phaser.Sprite(game, 0, 0, 'sky'); + sky.transform.scrollFactor.setTo(0, 0); + skyLayer.add(sky); + // Add clouds to cloudLayer. + var cloud0 = new Phaser.Sprite(game, 200, 120, 'cloud0'); + cloud0.transform.scrollFactor.setTo(0.3, 0.1); + var cloud1 = new Phaser.Sprite(game, -60, 120, 'cloud1'); + cloud1.transform.scrollFactor.setTo(0.5, 0.1); + var cloud2 = new Phaser.Sprite(game, 900, 170, 'cloud2'); + cloud2.transform.scrollFactor.setTo(0.7, 0.1); + cloudLayer.add(cloud0); + cloudLayer.add(cloud1); + cloudLayer.add(cloud2); + // Add ground sprite to groundLayer. + var ground = new Phaser.Sprite(game, 0, 360, 'ground'); + ground.transform.scrollFactor.setTo(0.5, 0.1); + groundLayer.add(ground); + // Add river to riverLayer. + var river = new Phaser.Sprite(game, 0, 400, 'river'); + river.transform.scrollFactor.setTo(1.3, 0.16); + riverLayer.add(river); + + // Add animating sprites to spriteLayer. + var ufo = new Phaser.Sprite(game, 360, 240, 'ufo'); + ufo.animations.add('fly', null, 0, false); + ufo.animations.play('fly'); + ufo.transform.origin.setTo(0.5, 0.5); + spriteLayer.add(ufo); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('sky layer: z = 0', 16, 20); + Phaser.DebugUtils.context.fillText('cloud layer: z = 1', 16, 36); + Phaser.DebugUtils.context.fillText('ground layer: z = 2', 16, 52); + Phaser.DebugUtils.context.fillText('sprite layer: z = 3', 16, 68); + Phaser.DebugUtils.context.fillText('river layer: z = 4', 16, 84); + } +})(); diff --git a/Tests/groups/group texture.js b/Tests/groups/group texture.js new file mode 100644 index 00000000..d4acd821 --- /dev/null +++ b/Tests/groups/group texture.js @@ -0,0 +1,21 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + var robot; + var eye, body, leftArm, rightArm, leftLeg, rightLeg; + + function init() { + game.load.spritesheet('buttons', 'assets/buttons/number-buttons.png', 90, 90); + game.load.start(); + } + function create() { + // Add 6 groups and childs. + var item = game.add.group(); + item.texture.loadImage('buttons'); + } + function render() { + Phaser.DebugUtils.context.fillStyle = 'rgb(0, 160, 213)'; + Phaser.DebugUtils.context.fillText('Group can have a texture too, so you can use it just like a simple sprite.', 180, 380); + } +})(); diff --git a/Tests/groups/group transform 1.js b/Tests/groups/group transform 1.js new file mode 100644 index 00000000..ceb1f0fe --- /dev/null +++ b/Tests/groups/group transform 1.js @@ -0,0 +1,65 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var robot; + var eye, body, leftArm, rightArm, leftLeg, rightLeg; + + function init() { + game.load.image('eye', 'assets/sprites/robot/eye.png'); + game.load.image('body', 'assets/sprites/robot/body.png'); + game.load.image('arm-l', 'assets/sprites/robot/arm-l.png'); + game.load.image('arm-r', 'assets/sprites/robot/arm-r.png'); + game.load.image('leg-l', 'assets/sprites/robot/leg-l.png'); + game.load.image('leg-r', 'assets/sprites/robot/leg-r.png'); + game.load.start(); + } + function create() { + // Add some items. + var item; + for (var i = 0; i < 3; i++) { + // Give the items a different alpha increase speed. + item = game.add.sprite(290, 98 * (i + 1), 'item', i); + // An item besides the left one. + item = game.add.sprite(388, 98 * (i + 1), 'item', i + 3); + } + // Use groups of sprites to create a big robot. + // Robot itself, you can subclass group class in a real game. + robot = game.add.group(); + // Robot components. + leftArm = robot.addNewSprite(90, 175, 'arm-l', 0, Phaser.Types.BODY_DISABLED); + rightArm = robot.addNewSprite(549, 175, 'arm-r', 0, Phaser.Types.BODY_DISABLED); + leftLeg = robot.addNewSprite(270, 325, 'leg-l', 0, Phaser.Types.BODY_DISABLED); + rightLeg = robot.addNewSprite(410, 325, 'leg-r', 0, Phaser.Types.BODY_DISABLED); + body = robot.addNewSprite(219, 32, 'body', 0, Phaser.Types.BODY_DISABLED); + eye = robot.addNewSprite(335, 173,'eye', 0, Phaser.Types.BODY_DISABLED); + + leftArm.input.start(0, false, true); + leftArm.input.enableDrag(); + rightArm.input.start(0, false, true); + rightArm.input.enableDrag(); + leftLeg.input.start(0, false, true); + leftLeg.input.enableDrag(); + rightLeg.input.start(0, false, true); + rightLeg.input.enableDrag(); + body.input.start(0, false, true); + body.input.enableDrag(); + eye.input.start(0, false, true); + eye.input.enableDrag(); + } + function update() { + } + function render() { + Phaser.DebugUtils.renderSpriteInfo(leftArm, 32, 32); + Phaser.DebugUtils.renderSpriteInfo(rightArm, 32, 152); + Phaser.DebugUtils.renderSpriteInfo(leftLeg, 32, 272); + Phaser.DebugUtils.renderSpriteInfo(rightLeg, 32, 392); + Phaser.DebugUtils.renderSpriteInfo(rightLeg, 450, 32); + Phaser.DebugUtils.renderSpriteInfo(rightLeg, 450, 152); + + Phaser.DebugUtils.context.fillStyle = 'rgb(0, 160, 213)'; + Phaser.DebugUtils.context.fillText('The robot is a group and every component is a sprite.', 240, 580); + // Phaser.DebugUtils.context.fillText('Drag each part to re-position them.', 288, 592); + Phaser.DebugUtils.context.fillText('Drag each part to re-position them. ', 288, 592); + } +})(); diff --git a/Tests/groups/group transform 2.js b/Tests/groups/group transform 2.js new file mode 100644 index 00000000..710b6a04 --- /dev/null +++ b/Tests/groups/group transform 2.js @@ -0,0 +1,48 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var robot; + var eye, body, leftArm, rightArm, leftLeg, rightLeg; + var draggable; + + function init() { + game.load.image('eye', 'assets/sprites/robot/eye.png'); + game.load.image('body', 'assets/sprites/robot/body.png'); + game.load.image('arm-l', 'assets/sprites/robot/arm-l.png'); + game.load.image('arm-r', 'assets/sprites/robot/arm-r.png'); + game.load.image('leg-l', 'assets/sprites/robot/leg-l.png'); + game.load.image('leg-r', 'assets/sprites/robot/leg-r.png'); + + game.load.start(); + } + function create() { + // Add some items. + var item; + for (var i = 0; i < 3; i++) { + // Give the items a different alpha increase speed. + item = game.add.sprite(290, 98 * (i + 1), 'item', i); + // An item besides the left one. + item = game.add.sprite(388, 98 * (i + 1), 'item', i + 3); + } + // Use groups of sprites to create a big robot. + // Robot itself, you can subclass group class in a real game. + robot = game.add.group(); + // Robot components. + leftArm = robot.addNewSprite(90, 175, 'arm-l', 0, Phaser.Types.BODY_DISABLED); + rightArm = robot.addNewSprite(549, 175, 'arm-r', 0, Phaser.Types.BODY_DISABLED); + leftLeg = robot.addNewSprite(270, 325, 'leg-l', 0, Phaser.Types.BODY_DISABLED); + rightLeg = robot.addNewSprite(410, 325, 'leg-r', 0, Phaser.Types.BODY_DISABLED); + body = robot.addNewSprite(219, 32, 'body', 0, Phaser.Types.BODY_DISABLED); + eye = robot.addNewSprite(335, 173,'eye', 0, Phaser.Types.BODY_DISABLED); + } + function update() { + // Change parent's rotation to change all the childs. + // robot.transform.rotation += 2; + game.world.group.transform.rotation += 2; + } + function render() { + Phaser.DebugUtils.context.fillStyle = 'rgb(0, 160, 213)'; + Phaser.DebugUtils.context.fillText('The robot is a group and every component is a sprite.', 240, 580); + } +})(); diff --git a/Tests/groups/group transform 3.js b/Tests/groups/group transform 3.js new file mode 100644 index 00000000..5031c814 --- /dev/null +++ b/Tests/groups/group transform 3.js @@ -0,0 +1,51 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var robot; + var eye, body, leftArm, rightArm, leftLeg, rightLeg; + var draggable; + + function init() { + game.load.image('eye', 'assets/sprites/robot/eye.png'); + game.load.image('body', 'assets/sprites/robot/body.png'); + game.load.image('arm-l', 'assets/sprites/robot/arm-l.png'); + game.load.image('arm-r', 'assets/sprites/robot/arm-r.png'); + game.load.image('leg-l', 'assets/sprites/robot/leg-l.png'); + game.load.image('leg-r', 'assets/sprites/robot/leg-r.png'); + + game.load.start(); + } + function create() { + // Add some items. + var item; + for (var i = 0; i < 3; i++) { + // Give the items a different alpha increase speed. + item = game.add.sprite(290, 98 * (i + 1), 'item', i); + // An item besides the left one. + item = game.add.sprite(388, 98 * (i + 1), 'item', i + 3); + } + // Use groups of sprites to create a big robot. + // Robot itself, you can subclass group class in a real game. + robot = game.add.group(); + // Robot components. + leftArm = robot.addNewSprite(90, 175, 'arm-l', 0, Phaser.Types.BODY_DISABLED); + rightArm = robot.addNewSprite(549, 175, 'arm-r', 0, Phaser.Types.BODY_DISABLED); + leftLeg = robot.addNewSprite(270, 325, 'leg-l', 0, Phaser.Types.BODY_DISABLED); + rightLeg = robot.addNewSprite(410, 325, 'leg-r', 0, Phaser.Types.BODY_DISABLED); + body = robot.addNewSprite(219, 32, 'body', 0, Phaser.Types.BODY_DISABLED); + eye = robot.addNewSprite(335, 173,'eye', 0, Phaser.Types.BODY_DISABLED); + + // Tween the robot's size, so all the components also scaled. + // game.add.tween(robot.transform.scale) + game.add.tween(game.world.group.transform.scale) + .to({x: 1.2, y: 1.2}, 1000, Phaser.Easing.Back.InOut, true, 0, false) + .yoyo(true); + } + function update() { + } + function render() { + Phaser.DebugUtils.context.fillStyle = 'rgb(0, 160, 213)'; + Phaser.DebugUtils.context.fillText('The robot is a group and every component is a sprite.', 240, 580); + } +})(); diff --git a/Tests/groups/recycle 1.js b/Tests/groups/recycle 1.js new file mode 100644 index 00000000..965faeb0 --- /dev/null +++ b/Tests/groups/recycle 1.js @@ -0,0 +1,46 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + function init() { + game.load.image('ufo', 'assets/sprites/ufo.png'); + game.load.image('baddie', 'assets/sprites/space-baddie.png'); + game.load.spritesheet('button', 'assets/buttons/baddie-buttons.png', 224, 70); + game.load.start(); + } + function create() { + // Create some local groups for later use. + friendAndFoe = game.add.group(); + enemies = game.add.group(); + + // Create a ufo. + friendAndFoe.addNewSprite(200, 240, 'ufo', null, Phaser.Types.BODY_DISABLED); + + // Create some enemies. + for (var i = 0; i < 8; i++) { + createBaddie(); + } + + // Create buttons to create and kill baddies. + game.add.button(16, 50, 'button', createBaddie, 0, 0, 0); + game.add.button(16, 130, 'button', killBaddie, 1, 1, 1); + } + function killBaddie() { + var baddie = enemies.getFirstAlive(); + if (baddie) baddie.kill(); + } + function createBaddie() { + // Group's recycle() method will always return a valid object unless + // you did not pass an objectClass parameter. + // It will create new object instance of the given class if no "dead" + // object can be found inside the group. + var enemy = enemies.recycle(Phaser.Sprite); + enemy.texture.loadImage('baddie', false); + enemy.texture.opaque = false; + enemy.x = 360 + Math.random() * 200; + enemy.y = 120 + Math.random() * 200; + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Add new baddies using recyle() instead of allocating new object every time.', 16, 24); + } +})(); diff --git a/Tests/groups/recycle 2.js b/Tests/groups/recycle 2.js new file mode 100644 index 00000000..12d7b220 --- /dev/null +++ b/Tests/groups/recycle 2.js @@ -0,0 +1,49 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + function init() { + game.load.image('ufo', 'assets/sprites/ufo.png'); + game.load.image('baddie', 'assets/sprites/space-baddie.png'); + game.load.spritesheet('button', 'assets/buttons/baddie-buttons.png', 224, 70); + game.load.start(); + } + function create() { + // Create some local groups for later use. + friendAndFoe = game.add.group(); + enemies = game.add.group(); + + // Create a ufo. + friendAndFoe.addNewSprite(200, 240, 'ufo', null, Phaser.Types.BODY_DISABLED); + + // Create some enemies. + for (var i = 0; i < 8; i++) { + // Since the getFirstAvailable() which we'll use for recycling + // cannot allocate new objects, create them manually here. + enemies.addNewSprite(360 + Math.random() * 200, 120 + Math.random() * 200, + 'baddie', null, Phaser.Types.BODY_DISABLED); + } + + // Create buttons to create and kill baddies. + game.add.button(16, 50, 'button', createBaddie, 0, 0, 0); + game.add.button(16, 130, 'button', killBaddie, 1, 1, 1); + } + function killBaddie() { + var baddie = enemies.getFirstAlive(); + if (baddie) baddie.kill(); + } + function createBaddie() { + // Recycle using getFirstAvailable() as an alternative to recycle(). + // Notice that this method will not create new objects if there's no one + // available, and it won't change size of this group. + var enemy = enemies.getFirstAvailable(); + if (enemy) { + enemy.revive(); + } + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Recycle baddies from a group using getFirstAvailable() instead of recycle().', 16, 24); + Phaser.DebugUtils.context.fillText('Notice that you cannot add more than 8 baddies since we only create 8 instance.', 16, 36); + Phaser.DebugUtils.context.fillText('Living baddies: ' + enemies.countLiving(), 340, 420); + } +})(); diff --git a/Tests/groups/remove.js b/Tests/groups/remove.js new file mode 100644 index 00000000..d7d789ff --- /dev/null +++ b/Tests/groups/remove.js @@ -0,0 +1,65 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + // Group contains items. + var items; + + function init() { + game.load.spritesheet('item', 'assets/buttons/number-buttons-90x90.png', 90, 90); + game.load.image('rect', 'assets/tests/200x100corners.png'); + game.load.image('rect2', 'assets/tests/200x100corners2.png'); + game.load.start(); + } + function create() { + // Create item container group. + items = game.add.group(); + + // Add some items and add them to the container group, + // then you can drag and drop them to remove. + var item; + for (var i = 0; i < 6; i++) { + // Directly create sprites from the group. + item = items.addNewSprite(90, 90 * i, 'item', i, Phaser.Types.BODY_DISABLED); + // Enable input detection, then it's possible be dragged. + item.input.start(0, false, true); + // Make this item draggable. + item.input.enableDrag(); + // Then we make it snap to 90x90 grids. + item.input.enableSnap(90, 90, false, true); + // Add a handler to remove it using different options when dropped. + item.events.onDragStop.add(dropHandler); + } + + // Create 2 rectangles, drop it at these rectangle to + // remove it from origin group normally or + // cut it from the group's array entirely. + var rect = game.add.sprite(400, 0, 'rect'); + rect.transform.scale.setTo(2.0, 3.0); + var rect2 = game.add.sprite(400, 300, 'rect2'); + rect2.transform.scale.setTo(2.0, 3.0); + } + function update() { + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Size of group: ' + items.length, 100, 560); + Phaser.DebugUtils.context.fillText('Drop here to cut items from groups entirely.', 450, 24); + Phaser.DebugUtils.context.fillText('Drop here to remove it normally.', 450, 324); + } + function dropHandler(item, pointer) { + if (item.x < 90) { + item.x = 90; + } + else if (item.x > 400) { // So it is dropped in one rectangle. + if (item.y < 300) { + // Remove it from group normally, so the group's size does not change. + items.remove(item, true); + } + else { + // Remove it from group and cut from it, so the group's size decreases. + items.remove(item); + } + } + } +})(); diff --git a/Tests/groups/replace.js b/Tests/groups/replace.js new file mode 100644 index 00000000..fae0ea29 --- /dev/null +++ b/Tests/groups/replace.js @@ -0,0 +1,66 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + // Left and right group. + var left, right; + // The first selected item. + var selected = null; + + function init() { + game.load.spritesheet('item', 'assets/buttons/number-buttons-90x90.png', 90, 90); + game.load.start(); + } + function create() { + left = game.add.group(); + right = game.add.group(); + // Add some items to left side, and set a onDragStop listener + // to limit its location when dropped. + var item; + for (var i = 0; i < 3; i++) { + // Directly create sprites from the left group. + item = left.addNewSprite(290, 98 * (i + 1), 'item', i, Phaser.Types.BODY_DISABLED); + // Enable input. + item.input.start(0, false, true); + item.events.onInputUp.add(select); + // Add another to the right group. + item = right.addNewSprite(388, 98 * (i + 1), 'item', i + 3, Phaser.Types.BODY_DISABLED); + // Enable input. + item.input.start(0, false, true); + item.events.onInputUp.add(select); + } + } + function select(item, pointer) { + // If there's no one selected, mark it as selected. + if (!selected) { + selected = item; + selected.alpha = 0.5; + } + else { + // Items from different group selected, replace with each other; + // Something like a swap action, maybe better done with + // group.swap() method. + if (selected.group !== item.group) { + // Move the later selected to the first selected item's position. + item.x = selected.x; + item.y = selected.y; + // Replace first selected with the second one. + selected.group.replace(selected, item); + } + else { + selected.alpha = 1; + } + + // After checking, now clear the helper var. + selected = null; + } + } + function update() { + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Left Group', 300, 80); + Phaser.DebugUtils.context.fillText('Right Group', 400, 80); + Phaser.DebugUtils.context.fillText('Click an item and one from another group to replace it.', 240, 480); + } +})(); diff --git a/Tests/groups/set all.js b/Tests/groups/set all.js new file mode 100644 index 00000000..b59555ae --- /dev/null +++ b/Tests/groups/set all.js @@ -0,0 +1,31 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + var baseIncSpeed = 0.006; + + function init() { + game.load.spritesheet('item', 'assets/buttons/number-buttons-90x90.png', 90, 90); + game.load.start(); + } + function create() { + // Add some items. + for (var i = 0; i < 3; i++) { + // Give the items a different alpha increase speed. + game.add.sprite(290, 98 * (i + 1), 'item', i) + .alphaIncSpeed = baseIncSpeed * (i + 1); + game.add.sprite(388, 98 * (i + 1), 'item', i + 3) + .alphaIncSpeed = baseIncSpeed * (i + 4); + } + + game.input.onTap.add(resetAlpha); + } + function resetAlpha() { + // Set "alpha" value of all the childs. + game.world.group.setAll('alpha', Math.random()); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Tap or click to set random alpha of all the items.', 240, 480); + } +})(); diff --git a/Tests/groups/sort 1.js b/Tests/groups/sort 1.js new file mode 100644 index 00000000..839971ee --- /dev/null +++ b/Tests/groups/sort 1.js @@ -0,0 +1,46 @@ +(function() { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var xTop, yTop, zTop; + + function init() { + game.load.image('cell', 'assets/sprites/diamond.png'); + game.load.start(); + } + function create() { + // Create 3 groups which will have different sort "index". + xTop = game.add.group(); + yTop = game.add.group(); + zTop = game.add.group(); + + var i; + for (i = 0; i < 64; i++) { + xTop.addNewSprite(160 + 48 * Math.cos(i * Math.PI / 8), 540 - i * 8, + 'cell', 0, + Phaser.Types.BODY_DISABLED); + } + for (i = 0; i < 64; i++) { + yTop.addNewSprite(340 + 48 * Math.cos(i * Math.PI / 8), 540 - i * 8, + 'cell', 0, + Phaser.Types.BODY_DISABLED); + } + for (i = 0; i < 64; i++) { + zTop.addNewSprite(520 + 48 * Math.cos(i * Math.PI / 8), 540 - i * 8, + 'cell', 0, + Phaser.Types.BODY_DISABLED); + } + } + function update() { + // Sort 3 groups using different methods, all of them are + // ascending by default. + xTop.sort('x'); + yTop.sort('y'); + zTop.sort('z'); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Left group sorted by x.', 16, 18); + Phaser.DebugUtils.context.fillText('Middle group sorted by y.', 16, 36); + Phaser.DebugUtils.context.fillText('Right group sorted by z.', 16, 54); + } +})(); diff --git a/Tests/groups/sort 2.js b/Tests/groups/sort 2.js new file mode 100644 index 00000000..9bde00b3 --- /dev/null +++ b/Tests/groups/sort 2.js @@ -0,0 +1,57 @@ +(function() { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + // Wabbits inside this group is sorted by its "dead" property. + // Dead wabbits behinds the others. + var wabbits; + + function init() { + game.load.image('wabbit', 'assets/sprites/wabbit.png'); + game.load.start(); + } + function create() { + // Create container group. + wabbits = game.add.group(); + + // Create wabbit and add to the container. + var wabbe; + for (var i = 0; i < 64; i++) { + wabbe = wabbits.addNewSprite(Math.random() * 480 + 64, Math.random() * 480 + 32, + 'wabbit', 0, + Phaser.Types.BODY_DISABLED); + wabbe.transform.scale.setTo(2, 2); + wabbe.transform.origin.setTo(0.5, 0.5); + + // Give wabbie a flag of living or not. + wabbe.dead = false; + + wabbe.input.start(0, false, true); + wabbe.events.onInputUp.add(killMe, this); + } + } + function update() { + // sort wabbies by "exists", so killed ones will + wabbits.sort('dead', Phaser.Group.DESCENDING); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Tap or click wabbits to kill them.', 32, 32); + } + function killMe(wabbe) { + // Disable input. + wabbe.input.stop(); + + // Do not call the kill method, set its "dead" property instead. + wabbe.dead = true; + + // Kill effects. + game.add.tween(wabbe) + .to({x: wabbe.x - 48}, 2000, Phaser.Easing.Linear.None, true, 0, false); + game.add.tween(wabbe) + .to({y: 640}, 2000 - wabbe.y, Phaser.Easing.Back.In, true, 0, false); + game.add.tween(wabbe) + .to({rotation: 240}, 1000, Phaser.Easing.Back.In, true, 0, false); + game.add.tween(wabbe.transform.scale) + .to({x: 2, y: 2}, 1000, Phaser.Easing.Bounce.In, true, 0, false); + } +})(); diff --git a/Tests/groups/sub groups.js b/Tests/groups/sub groups.js new file mode 100644 index 00000000..0b069d3c --- /dev/null +++ b/Tests/groups/sub groups.js @@ -0,0 +1,60 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + // Groups for storing friends and enemies, may use for collision later. + var friendAndFoe, + enemies; + + // Groups for teaming up stuff. + var normalBaddies, + purpleBaddies; + + function init() { + game.load.image('ufo', 'assets/sprites/ufo.png'); + game.load.image('baddie', 'assets/sprites/space-baddie.png'); + game.load.image('purple-baddie', 'assets/sprites/space-baddie-purple.png'); + game.load.start(); + } + function create() { + // Create some local groups for later use. + friendAndFoe = game.add.group(); + enemies = game.add.group(); + normalBaddies = game.add.group(); + purpleBaddies = game.add.group(); + + // Add both teams to enemies group. + enemies.add(normalBaddies); + enemies.add(purpleBaddies); + + // Create a ufo as a friend sprite. + friendAndFoe.addNewSprite(200, 240, 'ufo', null, Phaser.Types.BODY_DISABLED); + + // Create some enemies. + for (var i = 0; i < 16; i++) { + createBaddie(); + } + + // Tap to create new baddie sprites. + game.input.onTap.add(createBaddie, this); + } + function createBaddie() { + var baddie; + if (Math.random() > 0.5) { + baddie = purpleBaddies.addNewSprite(360 + Math.random() * 200, 120 + Math.random() * 200, + 'purple-baddie', null, Phaser.Types.BODY_DISABLED); + } + else { + baddie = normalBaddies.addNewSprite(360 + Math.random() * 200, 120 + Math.random() * 200, + 'baddie', null, Phaser.Types.BODY_DISABLED); + } + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Tap screen or click to create new baddies.', 16, 24); + Phaser.DebugUtils.context.fillText('enemies: ' + enemies.length + ' (actually ' + enemies.length + ' groups)', 16, 48); + Phaser.DebugUtils.context.fillText('normal baddies: ' + normalBaddies.length, 16, 60); + Phaser.DebugUtils.context.fillText('purple baddies: ' + purpleBaddies.length, 16, 72); + Phaser.DebugUtils.context.fillText('friends: ' + friendAndFoe.length, 16, 96); + } +})(); diff --git a/Tests/input/drop limitation.js b/Tests/input/drop limitation.js new file mode 100644 index 00000000..69c382fc --- /dev/null +++ b/Tests/input/drop limitation.js @@ -0,0 +1,46 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + function init() { + game.load.spritesheet('item', 'assets/buttons/number-buttons-90x90.png', 90, 90); + game.load.start(); + } + function create() { + // Add some items to left side, and set a onDragStop listener + // to limit its location when dropped. + var item; + for (var i = 0; i < 6; i++) { + // Directly create sprites from the left group. + item = game.add.sprite(90, 90 * i, 'item', i); + // Enable input detection, then it's possible be dragged. + item.input.start(0, false, true); + // Make this item draggable. + item.input.enableDrag(); + // Then we make it snap to left and right side, + // also make it only snaps when released. + item.input.enableSnap(90, 90, false, true); + // Limit drop location to only the 2 columns. + item.events.onDragStop.add(fixLocation); + } + } + function update() { + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Group Left.', 100, 560); + Phaser.DebugUtils.context.fillText('Group Right.', 280, 560); + } + function fixLocation(item) { + // Move the items when it is already dropped. + if (item.x < 90) { + item.x = 90; + } + else if (item.x > 180 && item.x < 270) { + item.x = 180; + } + else if (item.x > 360) { + item.x = 270; + } + } +})(); diff --git a/Tests/input/keyboard 1.js b/Tests/input/keyboard 1.js new file mode 100644 index 00000000..04811a15 --- /dev/null +++ b/Tests/input/keyboard 1.js @@ -0,0 +1,79 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + + var ufo, leftBtn, rightBtn; + var speed = 4; + + function init() { + game.world.setSize(1280, 600, true); + game.load.image('ground', 'assets/tests/ground-2x.png'); + game.load.image('river', 'assets/tests/river-2x.png'); + game.load.image('sky', 'assets/tests/sky-2x.png'); + game.load.image('cloud0', 'assets/tests/cloud-big-2x.png'); + game.load.image('cloud1', 'assets/tests/cloud-narrow-2x.png'); + game.load.image('cloud2', 'assets/tests/cloud-small-2x.png'); + + game.load.spritesheet('button', 'assets/buttons/arrow-button.png', 112, 95); + + game.load.spritesheet('ufo', 'assets/sprites/ufo.png', 24, 21); + + game.load.start(); + } + function create() { + // background images + game.add.sprite(0, 0, 'sky') + .transform.scrollFactor.setTo(0, 0); + game.add.sprite(0, 360, 'ground') + .transform.scrollFactor.setTo(0.5, 0.5); + game.add.sprite(0, 400, 'river') + .transform.scrollFactor.setTo(1.3, 1.3); + game.add.sprite(200, 120, 'cloud0') + .transform.scrollFactor.setTo(0.3, 0.3); + game.add.sprite(-60, 120, 'cloud1') + .transform.scrollFactor.setTo(0.5, 0.3); + game.add.sprite(900, 170, 'cloud2') + .transform.scrollFactor.setTo(0.7, 0.3); + + // Create a ufo spirte as player. + ufo = game.add.sprite(320, 240, 'ufo'); + ufo.animations.add('fly', null, 30, false); + ufo.animations.play('fly'); + ufo.transform.origin.setTo(0.5, 0.5); + + // Make the default camera follow the ufo. + game.camera.follow(ufo); + + // Add 2 sprite to display hold direction. + leftBtn = game.add.sprite(160 - 112, 200, 'button', 0); + leftBtn.transform.scrollFactor.setTo(0, 0); + leftBtn.alpha = 0; + rightBtn = game.add.sprite(640 - 112, 200, 'button', 1); + rightBtn.alpha = 0; + rightBtn.transform.scrollFactor.setTo(0, 0); + } + function update() { + // Check key states every frame. + // Move ONLY one of the left and right key is hold. + if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT) && + !game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { + ufo.x -= speed; + ufo.rotation = -15; + leftBtn.alpha = 0.6; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT) && + !game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { + ufo.x += speed; + ufo.rotation = 15; + rightBtn.alpha = 0.6; + } + else { + ufo.rotation = 0; + leftBtn.alpha = rightBtn.alpha = 0; + } + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Hold left/right to move the ufo.'); + } +})(); diff --git a/Tests/input/keyboard 2.js b/Tests/input/keyboard 2.js new file mode 100644 index 00000000..813551b1 --- /dev/null +++ b/Tests/input/keyboard 2.js @@ -0,0 +1,106 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update); + + var ufo, leftBtn, rightBtn, spaceBtn; + var speed = 4; + + function init() { + game.world.setSize(1280, 600, true); + game.load.image('ground', 'assets/tests/ground-2x.png'); + game.load.image('river', 'assets/tests/river-2x.png'); + game.load.image('sky', 'assets/tests/sky-2x.png'); + game.load.image('cloud0', 'assets/tests/cloud-big-2x.png'); + game.load.image('cloud1', 'assets/tests/cloud-narrow-2x.png'); + game.load.image('cloud2', 'assets/tests/cloud-small-2x.png'); + + game.load.spritesheet('button', 'assets/buttons/arrow-button.png', 112, 95); + game.load.image('spacebar', 'assets/buttons/spacebar.png'); + + game.load.spritesheet('ufo', 'assets/sprites/ufo.png', 24, 21); + + game.load.start(); + } + function create() { + // background images + game.add.sprite(0, 0, 'sky') + .transform.scrollFactor.setTo(0, 0); + game.add.sprite(0, 360, 'ground') + .transform.scrollFactor.setTo(0.5, 0.5); + game.add.sprite(0, 400, 'river') + .transform.scrollFactor.setTo(1.3, 1.3); + game.add.sprite(200, 120, 'cloud0') + .transform.scrollFactor.setTo(0.3, 0.3); + game.add.sprite(-60, 120, 'cloud1') + .transform.scrollFactor.setTo(0.5, 0.3); + game.add.sprite(900, 170, 'cloud2') + .transform.scrollFactor.setTo(0.7, 0.3); + + // Create a ufo spirte as player. + ufo = game.add.sprite(320, 240, 'ufo'); + ufo.animations.add('fly', null, 30, false); + ufo.animations.play('fly'); + ufo.transform.origin.setTo(0.5, 0.5); + + // Make the default camera follow the ufo. + game.camera.follow(ufo); + + // Add 2 sprite to display hold direction. + leftBtn = game.add.sprite(160 - 112 / 2, 200, 'button', 0); + leftBtn.transform.scrollFactor.setTo(0, 0); + leftBtn.alpha = 0; + rightBtn = game.add.sprite(640 - 112 / 2, 200, 'button', 1); + rightBtn.alpha = 0; + rightBtn.transform.scrollFactor.setTo(0, 0); + // Add a sprite to display spacebar press. + spaceBtn = game.add.sprite(400 - 112, 100, 'spacebar'); + spaceBtn.transform.scrollFactor.setTo(0, 0); + spaceBtn.alpha = 0; + + // Prevent directions and space key events bubbling up to browser, + // since these keys will make web page scroll which is not + // expected. + game.input.keyboard.addKeyCapture([ + Phaser.Keyboard.LEFT, + Phaser.Keyboard.RIGHT, + Phaser.Keyboard.UP, + Phaser.Keyboard.DOWN, + Phaser.Keyboard.SPACEBAR + ]); + } + function update() { + // Check key states every frame. + // Move ONLY one of the left and right key is hold. + if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT) && + !game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) { + ufo.x -= speed; + ufo.rotation = -15; + leftBtn.alpha = 0.6; + } + else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT) && + !game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) { + ufo.x += speed; + ufo.rotation = 15; + rightBtn.alpha = 0.6; + } + else { + ufo.rotation = 0; + leftBtn.alpha = rightBtn.alpha = 0; + } + + // 50 is a good choice if you are running 60FPS. + if (game.input.keyboard.justPressed(Phaser.Keyboard.SPACEBAR, 50)) { + console.log('space bar pressed'); + spaceBtn.alpha = 1; + } + if (spaceBtn.alpha > 0) { + spaceBtn.alpha -= 0.03; + } + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Hold left/right to move the ufo.', 16, 32); + Phaser.DebugUtils.context.fillText('Direction and Space key events are stopped by Phaser now, which will no longer be sent to the browser.', 16, 48); + Phaser.DebugUtils.context.fillText('Now you can press UP/DOWN or SPACE to see what happened.', 16, 64); + } +})(); diff --git a/Tests/misc/color utils 1.js b/Tests/misc/color utils 1.js new file mode 100644 index 00000000..8943d4d0 --- /dev/null +++ b/Tests/misc/color utils 1.js @@ -0,0 +1,49 @@ +(function() { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + var colorWheel, selected, color = '#CCA22B'; + var offset = { + x: 300 - 578 / 2, + y: 300 - 550 / 2 + }; + var rect, rectSize = 24; + + function init() { + game.load.image('color-wheel', 'assets/pics/color-wheel.png'); + game.load.start(); + } + function create() { + // Create color wheel texture. + colorWheel = game.add.dynamicTexture(578, 550); + colorWheel.pasteImage('color-wheel'); + + // Create a rectangle shows the color you just selected. + rect = new Phaser.Rectangle(0, 0, rectSize, rectSize); + selected = game.add.sprite(600, 430); + selected.width = rectSize; + selected.height = rectSize; + selected.texture.loadDynamicTexture(game.add.dynamicTexture(rectSize, rectSize)); + selected.texture.dynamicTexture.fillRect(rect, color); + + // Get the color under the position you tapped or clicked. + var pos = {}; + game.input.onTap.add(function(pointer) { + pos.x = pointer.position.x - offset.x; + pos.y = pointer.position.y - offset.y; + color = Phaser.ColorUtils.RGBtoWebstring(colorWheel.getPixel32(pos.x, pos.y)); + + // Set the rectangle's color to new selected one. + selected.texture.dynamicTexture.fillRect(rect, color); + }); + + // Set the background color to white. + game.stage.backgroundColor = '#fff'; +} + function render() { + colorWheel.render(offset.x, offset.y); + + Phaser.DebugUtils.context.fillStyle = '#000'; + Phaser.DebugUtils.context.fillText('Tap or click the color wheel to select a color.', 480, 52); + Phaser.DebugUtils.context.fillText(color, 646, 452); + } +})(); diff --git a/Tests/misc/color utils 2.js b/Tests/misc/color utils 2.js new file mode 100644 index 00000000..08d11e06 --- /dev/null +++ b/Tests/misc/color utils 2.js @@ -0,0 +1,57 @@ +(function() { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + var colorWheel, selected, + color = 0xAACCA22B, colorStr = '#CCA22B'; + var offset = { + x: 300 - 578 / 2, + y: 300 - 550 / 2 + }; + var rect, rectSize = 24; + + function init() { + game.load.image('color-wheel', 'assets/pics/color-wheel.png'); + game.load.start(); + } + function create() { + // Create color wheel texture. + colorWheel = game.add.dynamicTexture(578, 550); + colorWheel.pasteImage('color-wheel'); + + // Create a rectangle shows the color you just selected. + rect = new Phaser.Rectangle(0, 0, rectSize, rectSize); + selected = game.add.sprite(600, 430); + selected.width = rectSize; + selected.height = rectSize; + selected.texture.loadDynamicTexture(game.add.dynamicTexture(rectSize, rectSize)); + selected.texture.dynamicTexture.fillRect(rect, colorStr); + + // Get the color under the position you tapped or clicked. + var pos = {}; + game.input.onTap.add(function(pointer) { + pos.x = pointer.position.x - offset.x; + pos.y = pointer.position.y - offset.y; + color = colorWheel.getPixel32(pos.x, pos.y); + colorStr = Phaser.ColorUtils.RGBtoWebstring(color); + + // Set the rectangle's color to new selected one. + selected.texture.dynamicTexture.fillRect(rect, colorStr); + }); + + // Set the background color to white. + game.stage.backgroundColor = '#fff'; +} + function render() { + colorWheel.render(offset.x, offset.y); + + Phaser.DebugUtils.context.fillStyle = '#000'; + Phaser.DebugUtils.context.fillText('Tap or click the color wheel to select a color.', 480, 52); + + // Display more color formated infos here. You can also get a + // string contains everything using getColorInfo(); + Phaser.DebugUtils.context.fillText('Web String: ' + colorStr, 600, 492); + Phaser.DebugUtils.context.fillText('Hex String: ' + Phaser.ColorUtils.RGBtoHexstring(color), 600, 508); + var hsv = Phaser.ColorUtils.RGBtoHSV(color); + Phaser.DebugUtils.context.fillText('HSV: (' + hsv.hue.toFixed() + ', ' + hsv.saturation.toFixed(2) + ', ' + hsv.value.toFixed(2) + ')', 600, 524); + } +})(); diff --git a/Tests/misc/color utils 3.js b/Tests/misc/color utils 3.js new file mode 100644 index 00000000..ae638d32 --- /dev/null +++ b/Tests/misc/color utils 3.js @@ -0,0 +1,151 @@ +(function() { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + var colorWheel, + selected, + compHarmony, + analoHarmony, analoHarmony1, + splitHarmony, splitHarmony1, + triaHarmony, triaHarmony1, + color = 0xAACCA22B, colorStr = '#CCA22B', + compHColor, + analoColor, splitColor, triaColor, + analoColor1, splitColor1, triaColor1; + + var offset = { + x: 300 - 578 / 2, + y: 300 - 550 / 2 + }; + var rect, rectSize = 24; + + function init() { + game.load.image('color-wheel', 'assets/pics/color-wheel.png'); + game.load.start(); + } + function create() { + // Create color wheel texture. + colorWheel = game.add.dynamicTexture(578, 550); + colorWheel.pasteImage('color-wheel'); + + // Create a rectangle shows the color you just selected. + rect = new Phaser.Rectangle(0, 0, rectSize, rectSize); + selected = game.add.sprite(700, 290); + selected.width = rectSize; + selected.height = rectSize; + selected.texture.loadDynamicTexture(game.add.dynamicTexture(rectSize, rectSize)); + selected.texture.dynamicTexture.fillRect(rect, colorStr); + + // Create rectangles to show the harmony colors to the selected one. + compHColor = Phaser.ColorUtils.getComplementHarmony(color), + analoColor = Phaser.ColorUtils.getAnalogousHarmony(color), + splitColor = Phaser.ColorUtils.getSplitComplementHarmony(color), + triaColor = Phaser.ColorUtils.getTriadicHarmony(color); + + // Complement + compHarmony = game.add.sprite(700, 390); + compHarmony.width = rectSize; + compHarmony.height = rectSize; + compHarmony.texture.loadDynamicTexture(game.add.dynamicTexture(rectSize, rectSize)); + compHarmony.texture.dynamicTexture.fillRect(rect, Phaser.ColorUtils.RGBtoWebstring(compHColor)); + + // Analogous + analoHarmony = game.add.sprite(700, 434); + analoHarmony.width = rectSize; + analoHarmony.height = rectSize; + analoHarmony.texture.loadDynamicTexture(game.add.dynamicTexture(rectSize, rectSize)); + analoHarmony.texture.dynamicTexture.fillRect(rect, Phaser.ColorUtils.RGBtoWebstring(analoColor.color2)); + + analoHarmony1 = game.add.sprite(744, 434); + analoHarmony1.width = rectSize; + analoHarmony1.height = rectSize; + analoHarmony1.texture.loadDynamicTexture(game.add.dynamicTexture(rectSize, rectSize)); + analoHarmony1.texture.dynamicTexture.fillRect(rect, Phaser.ColorUtils.RGBtoWebstring(analoColor.color3)); + + // Split Complement + splitHarmony = game.add.sprite(700, 478); + splitHarmony.width = rectSize; + splitHarmony.height = rectSize; + splitHarmony.texture.loadDynamicTexture(game.add.dynamicTexture(rectSize, rectSize)); + splitHarmony.texture.dynamicTexture.fillRect(rect, Phaser.ColorUtils.RGBtoWebstring(splitColor.color2)); + + splitHarmony1 = game.add.sprite(744, 478); + splitHarmony1.width = rectSize; + splitHarmony1.height = rectSize; + splitHarmony1.texture.loadDynamicTexture(game.add.dynamicTexture(rectSize, rectSize)); + splitHarmony1.texture.dynamicTexture.fillRect(rect, Phaser.ColorUtils.RGBtoWebstring(splitColor.color3)); + + // Triadic + triaHarmony = game.add.sprite(700, 522); + triaHarmony.width = rectSize; + triaHarmony.height = rectSize; + triaHarmony.texture.loadDynamicTexture(game.add.dynamicTexture(rectSize, rectSize)); + triaHarmony.texture.dynamicTexture.fillRect(rect, Phaser.ColorUtils.RGBtoWebstring(triaColor.color2)); + + triaHarmony1 = game.add.sprite(744, 522); + triaHarmony1.width = rectSize; + triaHarmony1.height = rectSize; + triaHarmony1.texture.loadDynamicTexture(game.add.dynamicTexture(rectSize, rectSize)); + triaHarmony1.texture.dynamicTexture.fillRect(rect, Phaser.ColorUtils.RGBtoWebstring(triaColor.color3)); + + // Get the color under the position you tapped or clicked. + var pos = {}; + game.input.onTap.add(function(pointer) { + pos.x = pointer.position.x - offset.x; + pos.y = pointer.position.y - offset.y; + + // Update colors. + color = colorWheel.getPixel32(pos.x, pos.y); + compHColor = Phaser.ColorUtils.getComplementHarmony(color), + analoColor = Phaser.ColorUtils.getAnalogousHarmony(color).color2, + analoColor1 = Phaser.ColorUtils.getAnalogousHarmony(color).color3, + splitColor = Phaser.ColorUtils.getSplitComplementHarmony(color).color2, + splitColor1 = Phaser.ColorUtils.getSplitComplementHarmony(color).color3, + triaColor = Phaser.ColorUtils.getTriadicHarmony(color).color2; + triaColor1 = Phaser.ColorUtils.getTriadicHarmony(color).color3; + + // Calc color strings. + colorStr = Phaser.ColorUtils.RGBtoWebstring(color); + var compStr = Phaser.ColorUtils.RGBtoWebstring(compHColor), + analStr = Phaser.ColorUtils.RGBtoWebstring(analoColor), + analStr1 = Phaser.ColorUtils.RGBtoWebstring(analoColor1), + spliStr = Phaser.ColorUtils.RGBtoWebstring(splitColor), + spliStr1 = Phaser.ColorUtils.RGBtoWebstring(splitColor1), + triaStr = Phaser.ColorUtils.RGBtoWebstring(triaColor), + triaStr1 = Phaser.ColorUtils.RGBtoWebstring(triaColor1); + + // Update color of the rectangles. + selected.texture.dynamicTexture.fillRect(rect, colorStr); + compHarmony.texture.dynamicTexture.fillRect(rect, compStr); + analoHarmony.texture.dynamicTexture.fillRect(rect, analStr); + analoHarmony1.texture.dynamicTexture.fillRect(rect, analStr1); + splitHarmony.texture.dynamicTexture.fillRect(rect, spliStr); + splitHarmony1.texture.dynamicTexture.fillRect(rect, spliStr1); + triaHarmony.texture.dynamicTexture.fillRect(rect, triaStr); + triaHarmony1.texture.dynamicTexture.fillRect(rect, triaStr1); + }); + + // Set the background color to white. + game.stage.backgroundColor = '#fff'; + } + function render() { + colorWheel.render(offset.x, offset.y); + + Phaser.DebugUtils.context.fillStyle = '#000'; + Phaser.DebugUtils.context.fillText('Tap or click the color wheel to select a color.', 480, 52); + Phaser.DebugUtils.context.fillText('All the harmony colors are calculated on the fly.', 480, 590); + + // Display more color formated infos here. You can also get a + // string contains everything using getColorInfo(); + Phaser.DebugUtils.context.fillText('Selected Color: ', 600, 312); + Phaser.DebugUtils.context.fillText('Web String: ' + colorStr, 640, 342); + Phaser.DebugUtils.context.fillText('Hex String: ' + Phaser.ColorUtils.RGBtoHexstring(color), 640, 358); + var hsv = Phaser.ColorUtils.RGBtoHSV(color); + Phaser.DebugUtils.context.fillText('HSV: (' + hsv.hue.toFixed() + ', ' + hsv.saturation.toFixed(2) + ', ' + hsv.value.toFixed(2) + ')', 640, 374); + + // Harmony color types info. + Phaser.DebugUtils.context.fillText('Complement Harmony Color: ', 540, 412); + Phaser.DebugUtils.context.fillText(' Analogous Harmony Color: ', 540, 456); + Phaser.DebugUtils.context.fillText('Split Complement Harmony Color: ', 502, 500); + Phaser.DebugUtils.context.fillText(' Triadic Harmony Color: ', 540, 544); + } +})(); diff --git a/Tests/misc/dynamic texture 1.js b/Tests/misc/dynamic texture 1.js new file mode 100644 index 00000000..579b1e3c --- /dev/null +++ b/Tests/misc/dynamic texture 1.js @@ -0,0 +1,23 @@ +(function() { + var game = new Phaser.Game(this, 'game', 800, 600, null, create, null, render); + + // Pattern texture for tiling render to the stage later. + var pattern; + + function create() { + // Create a simple pattern texture. + pattern = game.add.dynamicTexture(96, 96); + pattern.fillRect(new Phaser.Rectangle(0, 0, 48, 48), '#5b35c0'); + pattern.fillRect(new Phaser.Rectangle(48, 48, 48, 48), '#5b35c0'); + pattern.fillRect(new Phaser.Rectangle(48, 0, 48, 48), '#43baf3'); + pattern.fillRect(new Phaser.Rectangle(0, 48, 48, 48), '#43baf3'); + } + function render() { + // Directly render the texture to the stage. + // In screen coordinates. + pattern.render(400 - 48, 300 - 48); + + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('There\'s no sprites here, only a DynamicTexture created on the fly.', 210, 450); + } +})(); diff --git a/Tests/misc/dynamic texture 2.js b/Tests/misc/dynamic texture 2.js new file mode 100644 index 00000000..1e362587 --- /dev/null +++ b/Tests/misc/dynamic texture 2.js @@ -0,0 +1,27 @@ +(function() { + var game = new Phaser.Game(this, 'game', 800, 600, null, create, null, render); + + // Pattern texture for tiling render to the stage later. + var pattern; + + function create() { + // Create a simple pattern texture. + pattern = game.add.dynamicTexture(96, 96); + pattern.fillRect(new Phaser.Rectangle(0, 0, 48, 48), '#5b35c0'); + pattern.fillRect(new Phaser.Rectangle(48, 48, 48, 48), '#5b35c0'); + pattern.fillRect(new Phaser.Rectangle(48, 0, 48, 48), '#43baf3'); + pattern.fillRect(new Phaser.Rectangle(0, 48, 48, 48), '#43baf3'); + + // Create a sprite and load to our newly created DynamicTexture. + // Notice that loadDynamicTexture() will destroy sprite's AnimationManager, + // so all the animations already added will no longer exist. + var sprite = game.add.sprite(game.stage.centerX - 48, game.stage.centerY - 48); + sprite.texture.loadDynamicTexture(pattern); + + console.log('Size of the sprite is now: (' + sprite.width + ', ' + sprite.height + ').'); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('This is a sprite whose appearance defined by a DynamicTexture created on the fly.', 160, 450); + } +})(); diff --git a/Tests/misc/dynamic texture 3.js b/Tests/misc/dynamic texture 3.js new file mode 100644 index 00000000..8758bb15 --- /dev/null +++ b/Tests/misc/dynamic texture 3.js @@ -0,0 +1,32 @@ +(function() { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, null, render); + + // Pattern texture for tiling render to the stage later. + var pattern; + + function init() { + game.load.spritesheet('cat', 'assets/sprites/baddie_cat_1.png', 16, 16); + game.load.start(); + } + function create() { + // Create a simple pattern first. + pattern = game.add.dynamicTexture(64, 16); + for (var i = 0; i < 4; i++) { + pattern.fillRect(new Phaser.Rectangle(i * 16, 0, 8, 8), '#5b35c0'); + pattern.fillRect(new Phaser.Rectangle((i + 1) * 16 - 8, 8, 8, 8), '#5b35c0'); + pattern.fillRect(new Phaser.Rectangle((i + 1) * 16 - 8, 0, 8, 8), '#43baf3'); + pattern.fillRect(new Phaser.Rectangle(i * 16, 8, 8, 8), '#43baf3'); + } + + // Paste cat image to the texture, so the cat is on top of our pattern. + pattern.pasteImage('cat'); + + // Create a sprite with our result texture. + var sprite = game.add.sprite(game.stage.centerX - 32, game.stage.centerY - 8); + sprite.texture.loadDynamicTexture(pattern); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Paste exist spritesheet to a DynamicTexture created on the fly.', 220, 450); + } +})(); diff --git a/Tests/misc/rectangle utils 1.js b/Tests/misc/rectangle utils 1.js new file mode 100644 index 00000000..c3724d29 --- /dev/null +++ b/Tests/misc/rectangle utils 1.js @@ -0,0 +1,10 @@ +(function() { + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + + function init() { + // body... + } + function create() { + + } +})(); diff --git a/Tests/sprites/out of screen.js b/Tests/sprites/out of screen.js new file mode 100644 index 00000000..efba6bc9 --- /dev/null +++ b/Tests/sprites/out of screen.js @@ -0,0 +1,29 @@ +(function() { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + function init() { + game.load.spritesheet('rect', 'assets/buttons/number-buttons-90x90.png', 90, 90); + game.load.start(); + } + function create() { + var rect, factor; + for (var i = 0; i < 16; i++) { + rect = game.add.sprite(10 + Math.random() * 700, 10 + Math.random() * 300, 'rect', Math.round(Math.random() * 5)); + factor = 0.2 + Math.random() * 2; + rect.transform.scale.setTo(factor, factor); + factor = 2 + Math.random() * 6; + rect.speed = factor; + } + console.log(game.world.group.length); + } + function update() { + game.world.group.forEach(function(rect) { + // Apply speed to each rect. + rect.y += rect.speed; + // Move the rect back to screen if it's not. + if (!Phaser.SpriteUtils.onScreen(rect)) { + rect.y = 0; + } + }); + } +})(); diff --git a/Tests/sprites/rotate around.js b/Tests/sprites/rotate around.js new file mode 100644 index 00000000..01efc3fc --- /dev/null +++ b/Tests/sprites/rotate around.js @@ -0,0 +1,40 @@ +(function() { + var game = new Phaser.Game(this, 'game', 800, 600, init, create, update, render); + + var rotationSrv, angle = 0; + + function init() { + game.load.spritesheet('x', 'assets/sprites/x.png', 220, 160); + game.load.start(); + } + function create() { + // Create 6 sprites rotating around the center at the beginning. + for (var i = 0; i < 3; i++) { + game.add.sprite(210 - ((i % 2) ? 140 : 0), 120 * (i + 1), 'x', i); + game.add.sprite(370 + ((i % 2) ? 140 : 0), 120 * (i + 1), 'x', i + 3); + } + + // Set a default rotation server pointer. + rotationSrv = new Phaser.Point(game.stage.centerX, game.stage.centerY); + + // Rotate all the sprites around the touch point. + game.input.onTap.add(function(pointer) { + rotationSrv.x = pointer.position.x; + rotationSrv.y = pointer.position.y; + }); + } + function update() { + angle += 0.1; + + game.world.group.forEach(function(obj) { + var resPointer = new Phaser.Point(obj.x, obj.y); + Phaser.PointUtils.rotateAroundPoint(resPointer, rotationSrv, angle); + obj.x = resPointer.x; + obj.y = resPointer.y; + }); + } + function render() { + Phaser.DebugUtils.context.fillStyle = '#fff'; + Phaser.DebugUtils.context.fillText('Tap or click to set new rotation point.', 280, 100); + } +})(); diff --git a/Tests/tweens/easing example 1.js b/Tests/tweens/easing example 1.js new file mode 100644 index 00000000..bc2a3976 --- /dev/null +++ b/Tests/tweens/easing example 1.js @@ -0,0 +1,22 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + + function init() { + game.load.spritesheet('shadow', 'assets/tests/tween/shadow.png', 80, 15); + game.load.spritesheet('PHASER', 'assets/tests/tween/PHASER.png', 70, 90); + game.load.start(); + } + function create() { + var item; + for (var i = 0; i < 6; i++) { + item = game.add.sprite(190 + 69 * i, -100, 'PHASER', i); + // Add a simple bounce tween to each character's position. + game.add.tween(item) + .to({y: 240}, 2400, Phaser.Easing.Bounce.Out, true, 1000 + 400 * i, false); + } + + // Set background color to white. + game.stage.backgroundColor = '#fff'; + } +})(); diff --git a/Tests/tweens/easing example 2.js b/Tests/tweens/easing example 2.js new file mode 100644 index 00000000..491ebd49 --- /dev/null +++ b/Tests/tweens/easing example 2.js @@ -0,0 +1,27 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + + function init() { + game.load.spritesheet('shadow', 'assets/tests/tween/shadow.png', 80, 15); + game.load.spritesheet('PHASER', 'assets/tests/tween/PHASER.png', 70, 90); + game.load.start(); + } + function create() { + var item; + for (var i = 0; i < 6; i++) { + item = game.add.sprite(190 + 69 * i, -100, 'PHASER', i); + // Add a simple bounce tween to each character's position. + game.add.tween(item) + .to({y: 240}, 2400, Phaser.Easing.Bounce.Out, true, 1000 + 400 * i, false); + // Add another rotation tween to the same character. + // Notice that depends on the default origin setting, characters will + // rotate around the left-top corner which looks a little strange. + game.add.tween(item) + .to({rotation: 360}, 2400, Phaser.Easing.Cubic.In, true, 1000 + 400 * i, false); + } + + // Set background color to white. + game.stage.backgroundColor = '#fff'; + } +})(); diff --git a/Tests/tweens/easing example 3.js b/Tests/tweens/easing example 3.js new file mode 100644 index 00000000..b914e734 --- /dev/null +++ b/Tests/tweens/easing example 3.js @@ -0,0 +1,27 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + + function init() { + game.load.spritesheet('shadow', 'assets/tests/tween/shadow.png', 80, 15); + game.load.spritesheet('PHASER', 'assets/tests/tween/PHASER.png', 70, 90); + game.load.start(); + } + function create() { + var item, tween; + for (var i = 0; i < 6; i++) { + item = game.add.sprite(190 + 69 * i, -100, 'PHASER', i); + // Add a simple bounce tween to each character's position. + tween = game.add.tween(item) + .to({y: 240}, 2400, Phaser.Easing.Bounce.Out, true, 1000 + 400 * i, false); + // Chain another tween to the character after it falls down. + tween.chain( + game.add.tween(item) + .to({y: 640}, 1400, Phaser.Easing.Circular.In, false, 0, false) + ); + } + + // Set background color to white. + game.stage.backgroundColor = '#fff'; + } +})(); diff --git a/Tests/tweens/easing example 4.js b/Tests/tweens/easing example 4.js new file mode 100644 index 00000000..b31b6c09 --- /dev/null +++ b/Tests/tweens/easing example 4.js @@ -0,0 +1,37 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + + function init() { + game.load.spritesheet('shadow', 'assets/tests/tween/shadow.png', 80, 15); + game.load.spritesheet('PHASER', 'assets/tests/tween/PHASER.png', 70, 90); + game.load.start(); + } + function create() { + var item, tween; + for (var i = 0; i < 6; i++) { + item = game.add.sprite(190 + 69 * i, -100, 'PHASER', i); + // Set origin to the center to make the rotation look better. + item.transform.origin.setTo(0.5, 0.5); + // Add a simple bounce tween to each character's position. + tween = game.add.tween(item) + .to({y: 240}, 2400, Phaser.Easing.Bounce.Out, true, 1000 + 400 * i, false); + // A more complex chain, add a falling and a rotating after + // the first tween done. Notice that tween.chain(t1).chain(t2) + // will not chain the t2 to the t1, they're both chained to + // the tween itself so they'll start the same time. + tween + .chain( + game.add.tween(item) + .to({y: 640}, 1400, Phaser.Easing.Circular.In, false, 0, false) + ) + .chain( + game.add.tween(item) + .to({rotation: 720}, 1600, Phaser.Easing.Cubic.Out, false, 200, false) + ); + } + + // Set background color to white. + game.stage.backgroundColor = '#fff'; + } +})(); diff --git a/Tests/tweens/easing example 5.js b/Tests/tweens/easing example 5.js new file mode 100644 index 00000000..aa0f276d --- /dev/null +++ b/Tests/tweens/easing example 5.js @@ -0,0 +1,38 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + + function init() { + game.load.spritesheet('shadow', 'assets/tests/tween/shadow.png', 138, 15); + game.load.spritesheet('PHASER', 'assets/tests/tween/PHASER.png', 70, 90); + game.load.start(); + } + function create() { + var item, shadow, tween; + for (var i = 0; i < 6; i++) { + // Add a shadow to the location which characters will land on. + // And tween their size to make them look like a real shadow. + // Put the following code before items to give shadow a lower + // render order. + shadow = game.add.sprite(190 + 69 * i, 284, 'shadow'); + // Set shadow's size 0 so that it'll be invisible at the beginning. + shadow.transform.scale.setTo(0.0, 0.0); + // Also set the origin to the center since we don't want to + // see the shadow scale to the left top. + shadow.transform.origin.setTo(0.5, 0.5); + game.add.tween(shadow.transform.scale) + .to({x: 1.0, y: 1.0}, 2400, Phaser.Easing.Bounce.Out, true, 1000 + 400 * i, false); + + // Add characters on top of shadows. + item = game.add.sprite(190 + 69 * i, -100, 'PHASER', i); + // Set origin to the center to make the rotation look better. + item.transform.origin.setTo(0.5, 0.5); + // Add a simple bounce tween to each character's position. + tween = game.add.tween(item) + .to({y: 240}, 2400, Phaser.Easing.Bounce.Out, true, 1000 + 400 * i, false); + } + + // Set background color to white. + game.stage.backgroundColor = '#fff'; + } +})(); diff --git a/Tests/tweens/easing example 6.js b/Tests/tweens/easing example 6.js new file mode 100644 index 00000000..023b251b --- /dev/null +++ b/Tests/tweens/easing example 6.js @@ -0,0 +1,53 @@ +/// +(function () { + var game = new Phaser.Game(this, 'game', 800, 600, init, create); + + function init() { + game.load.spritesheet('shadow', 'assets/tests/tween/shadow.png', 80, 15); + game.load.spritesheet('PHASER', 'assets/tests/tween/PHASER.png', 70, 90); + game.load.spritesheet('ribbon', 'assets/tests/tween/ribbon.png', 731, 49); + game.load.start(); + } + function create() { + var ribbon = game.add.sprite(-1000, 256, 'ribbon'); + ribbon.transform.scale.setTo(1.2, 1.0); + // Add ribbon appear animation. + var tween = game.add.tween(ribbon) + .to({x: -218}, 2400, Phaser.Easing.Elastic.Out, true, 0, false); + + // Add characters and give them a delay so they'll appear after the + // ribbon already there. + var item; + var letterGroup = game.add.group(); + for (var i = 0; i < 6; i++) { + item = game.add.sprite(80 + 69 * i, -100, 'PHASER', i); + letterGroup.add(item); + // Set origin to the center to make the rotation look better. + item.transform.origin.setTo(0.5, 0.5); + // Add a simple bounce tween to each character's position. + tween = game.add.tween(item) + .to({y: 240}, 2000, Phaser.Easing.Bounce.Out, true, 1600 + 400 * i, false); + } + + // Move the ribbon out after the last letter landded. + // Instead of using delay, we can use the callback of tweens. + tween.onComplete.add(function() { + tween = game.add.tween(ribbon) + .to({x: -1000}, 1600, Phaser.Easing.Elastic.In, true, 500, false); + // Again add falling animations to the letter after ribbon disappeared. + tween.onComplete.add(function() { + var index = 5; + letterGroup.forEach(function(item) { + game.add.tween(item) + .to({y: 640}, 1000, Phaser.Easing.Circular.In, true, index * 100, false); + game.add.tween(item) + .to({rotation: 720}, 1600, Phaser.Easing.Cubic.Out, true, 200 + index * 300, false); + index--; + }); + }); + }); + + // Set background color to white. + game.stage.backgroundColor = '#fff'; + } +})();