From 2d4653340a5dfa04e7cef1df49a1335f089e80f4 Mon Sep 17 00:00:00 2001 From: Dylan Wilson Date: Fri, 19 Aug 2016 22:49:55 +1000 Subject: [PATCH] roughed out some entity components --- .../Content/Content.mgcb | 40 ++++++ .../Content/logo-square-128.png | Bin 0 -> 3513 bytes .../Content/motw.png | Bin 0 -> 24060 bytes .../Demo.EntityComponentSystem.csproj | 81 ++++++++++++ .../Demos/Demo.EntityComponentSystem/Game1.cs | 122 ++++++++++++++++++ .../Demos/Demo.EntityComponentSystem/Icon.ico | Bin 0 -> 147541 bytes .../OpenTK.dll.config | 27 ++++ .../Demo.EntityComponentSystem/Program.cs | 16 +++ .../Properties/AssemblyInfo.cs | 39 ++++++ .../Demo.EntityComponentSystem/app.config | 7 + Source/Demos/Demo.Particles/Game1.cs | 3 +- .../Demo.Platformer/Demo.Platformer.csproj | 10 -- .../Entities/Components/EntityComponent.cs | 11 -- .../Components/SpriteAnimatorComponent.cs | 17 --- .../Entities/Components/SpriteComponent.cs | 31 ----- .../Systems/SpriteAnimatorComponentSystem.cs | 20 --- .../Systems/SpriteBatchComponentSystem.cs | 36 ------ Source/Demos/Demo.Platformer/Game1.cs | 8 +- Source/MonoGame.Extended.sln | 13 +- .../Animations/SpriteSheets/AnimatedSprite.cs | 45 +++++++ .../SpriteSheets/SpriteSheetAnimator.cs | 1 + .../Entities/Components/EntityComponent.cs | 52 ++++++++ .../Entities/Entity.cs | 23 ++-- .../Entities/EntityComponentSystem.cs | 59 ++++++--- .../Systems/AnimatedSpriteComponentSystem.cs | 17 +++ .../Entities/Systems/ComponentSystem.cs | 2 +- .../Systems/DrawableComponentSystem.cs | 2 +- .../Systems/ParticleEmitterComponentSystem.cs | 20 +++ .../Systems/SpriteBatchComponentSystem.cs | 35 +++++ .../Systems/UpdatableComponentSystem.cs | 2 +- .../MonoGame.Extended.csproj | 11 +- .../Particles/ParticleEffect.cs | 1 - .../Particles/ParticleEmitter.cs | 13 +- .../Particles/SpriteBatchExtensions.cs | 9 +- Source/MonoGame.Extended/Sprites/Sprite.cs | 6 +- .../Sprites/SpriteAnimator.cs | 103 --------------- 36 files changed, 601 insertions(+), 281 deletions(-) create mode 100644 Source/Demos/Demo.EntityComponentSystem/Content/Content.mgcb create mode 100644 Source/Demos/Demo.EntityComponentSystem/Content/logo-square-128.png create mode 100644 Source/Demos/Demo.EntityComponentSystem/Content/motw.png create mode 100644 Source/Demos/Demo.EntityComponentSystem/Demo.EntityComponentSystem.csproj create mode 100644 Source/Demos/Demo.EntityComponentSystem/Game1.cs create mode 100644 Source/Demos/Demo.EntityComponentSystem/Icon.ico create mode 100644 Source/Demos/Demo.EntityComponentSystem/OpenTK.dll.config create mode 100644 Source/Demos/Demo.EntityComponentSystem/Program.cs create mode 100644 Source/Demos/Demo.EntityComponentSystem/Properties/AssemblyInfo.cs create mode 100644 Source/Demos/Demo.EntityComponentSystem/app.config delete mode 100644 Source/Demos/Demo.Platformer/Entities/Components/EntityComponent.cs delete mode 100644 Source/Demos/Demo.Platformer/Entities/Components/SpriteAnimatorComponent.cs delete mode 100644 Source/Demos/Demo.Platformer/Entities/Components/SpriteComponent.cs delete mode 100644 Source/Demos/Demo.Platformer/Entities/Systems/SpriteAnimatorComponentSystem.cs delete mode 100644 Source/Demos/Demo.Platformer/Entities/Systems/SpriteBatchComponentSystem.cs create mode 100644 Source/MonoGame.Extended/Animations/SpriteSheets/AnimatedSprite.cs create mode 100644 Source/MonoGame.Extended/Entities/Components/EntityComponent.cs rename Source/{Demos/Demo.Platformer => MonoGame.Extended}/Entities/Entity.cs (65%) rename Source/{Demos/Demo.Platformer => MonoGame.Extended}/Entities/EntityComponentSystem.cs (63%) create mode 100644 Source/MonoGame.Extended/Entities/Systems/AnimatedSpriteComponentSystem.cs rename Source/{Demos/Demo.Platformer => MonoGame.Extended}/Entities/Systems/ComponentSystem.cs (88%) rename Source/{Demos/Demo.Platformer => MonoGame.Extended}/Entities/Systems/DrawableComponentSystem.cs (79%) create mode 100644 Source/MonoGame.Extended/Entities/Systems/ParticleEmitterComponentSystem.cs create mode 100644 Source/MonoGame.Extended/Entities/Systems/SpriteBatchComponentSystem.cs rename Source/{Demos/Demo.Platformer => MonoGame.Extended}/Entities/Systems/UpdatableComponentSystem.cs (79%) delete mode 100644 Source/MonoGame.Extended/Sprites/SpriteAnimator.cs diff --git a/Source/Demos/Demo.EntityComponentSystem/Content/Content.mgcb b/Source/Demos/Demo.EntityComponentSystem/Content/Content.mgcb new file mode 100644 index 00000000..12686f98 --- /dev/null +++ b/Source/Demos/Demo.EntityComponentSystem/Content/Content.mgcb @@ -0,0 +1,40 @@ + +#----------------------------- Global Properties ----------------------------# + +/outputDir:bin/$(Platform) +/intermediateDir:obj/$(Platform) +/platform:Windows +/config: +/profile:Reach +/compress:False + +#-------------------------------- References --------------------------------# + +/reference:../../../MonoGame.Extended.Content.Pipeline/bin/MonoGame.Extended.Content.Pipeline.dll + +#---------------------------------- Content ---------------------------------# + +#begin logo-square-128.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:logo-square-128.png + +#begin motw.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:motw.png + diff --git a/Source/Demos/Demo.EntityComponentSystem/Content/logo-square-128.png b/Source/Demos/Demo.EntityComponentSystem/Content/logo-square-128.png new file mode 100644 index 0000000000000000000000000000000000000000..1dbe3e85cf58f08270faf30af047db9917cca3c4 GIT binary patch literal 3513 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 literal 0 HcmV?d00001 diff --git a/Source/Demos/Demo.EntityComponentSystem/Content/motw.png b/Source/Demos/Demo.EntityComponentSystem/Content/motw.png new file mode 100644 index 0000000000000000000000000000000000000000..08c0e6a158a52468e0648b64e0053ba1650b111d GIT binary patch literal 24060 zcmeFZ2UHZ%qOM60Xe0}QWSR_021!lM8Ob>aNRl8(Xru|!1eKg6BOp2F)F3EP$w7%W z(2_*SNRy`8bKg5>-o5v|JG0iTS!?F8R%=t;yLRneRh$3+_qXenzOEX{ZMxf7SXd+) z>dFRKSUBFmOCE#^Y>{fMgaH3x`x>YzV%3Z>Yy-dCa#qk$z{09eAiA{2!@|PF($_Xp z0k&h|k>TJ{;1V$7k=z3jGGpB(rnp5;NiBvWc8dfo%tb^5xkDt(PKHHi!Xc|bYLBOY zi)Fz|@q~ul9!n|^g7rd`9%_Z<73hN{+CyTEr0HJHz#=Wg!mSA4xw%cc#r@*k80+Q@ z+4=|U{WHt9k*3AP#G9L4Ouhg6=YRLW|JyzAliHOPxKFU28|WI|{Qvt0%kYeV12`Xq z-s2e-SD7QQ@!oS4v*(6hPo4+Z`#52F+q-%`=l67a&LYY$$S?U+Bt#br z%iLH)S-~jKX0JOgXt8C=|B46tRIJ&7tA1Ld^NX!@>1HVWs_FUoEf%~m7B`WQvphfR zWbVgNxD@xpl}FZY&h*His)J~rYX0+O^mXr4?(5!DR1YVdh!^gC6Zw-ghtYo6L>7A& z^=(fUhCYnY%MWU-8VdJO1)UiZB466ijW#Y?+pb=HM|X(3!*ZJsfBJi^TC^RUdg#sh zVnSH;okJO&(J%6$|bLn2erQS-X+-j^oET2S~!MF z3rel;s0`m+YNdesORt<-{=v?ZxfX@+l0A|Pz7xbC1Tn}1LiGg165TtYzsG_? z9;a?v+wMB1iJ6$$IvX(srK44UGpSAeE%DZy4fl90Qcp%%1X~Ea4Xu9R;HT=-vP~a5 z+`pmT6!qLZFG-5+a3A}7lUFcS+5Ap5WuFcRX(xhI#aFMdwcSm^W{ciD$w`tLZ}k%7 z9Ph`)aSinJGz$vWP}@Mdr}QHvI}>Vm|<@CZzsSfXCG&ID~dPi#>@;C;DQ zc@%tsUvwx4-q{~$_0m=!m2}^Y9Wvadr)0lvJ^^0=dK^x!`;>hNjm`RoWXG;AB-FQY z)t$aNmV)9Mw)&k1jn8&S-v2#OiF#Upe7o)>xhAc2PMkEjAQA7&RwZ!2_ke#sxFJQthCBqvz(DRSg+c(kCj34IEGwKh*fuDhYfeK zb!}!j*AT!##3o6B8IEV)g2Y+JJ=JD5$Cul0oTJ~=zZWjgC!ackK z;hNmkTEuE}*f2F9g3m90@9y>_?EgU#Nf+9DtbQghJ1MExWF+ba!@b;L4wq<$QbR0l^h7_6M1Q;fwkbQ*$Fn<8qsu#8aE&Bla(s z_QuAm>-*GmPYziK&214&4EC=^v`J2?n*H1k_fOl?BL-d{+D}cLh`qL)ASRV4Sf|rS z+B`fIE#(;ZJX;J8_?=wwvoYYe+2|da<_YE*_7ZfHE+|0p?==YAtv20Ka?Xk~$3q*w zA=f*`9yBq@#e1s_uXIH5uxMl3P4Ef1rM86=)E^tlcZc<{CX^1*OU43`s;hnX2U$QjAS42qnP2`Ulj!hnO z!>%unmOJHcQr~4o?fNw>8%0<50?h}m??odCqqidwQhd-%eb<0+_OiT;0Qw1jo$h$k zmN3dh0zw~Xv86Q=r^lL%?wQ4)E;mZu;1iT_wtDs%R8*q_QiZDLv`Q95HK8VFs(HjR zj25}IMzZ}K?f1`Kq@Ew?Wt4L!tessniYz4Ujmsq^Zf>MsyKW}i*syMU^_;^;9BjDY z+2nm5+zgbw5qYC*+dGGWO`;c}7}Zhi;^Uvb@$I)9lbv{KW#Yj>(fw$_GWO+E=WxoeSzeMF zLH+~&BeZm$QL?WJ1i*?K60agyw;}~`zKD9X9QL->W>wfwk6BU-pdS6|$MyMaODVKN z?{)PEkNl){HCQuWuOh3>qbM3tPC8YBDET{@cq$OXb|I zJCznpsb{9um2ak_3$jO_QaewERBX!^U};CvEH=^gakOi~ zMsEy3NMXgcxJZWyT9yp1>iR@lgX4<;)))f5B14`0E`#JI<5x8zTgO8vupwRWWnh*{ zlsk{cxr1CcYq>HU??!$xd0|0T9MzbM-o@T?AxW(JK`AOhOrkVYu%9#h`m#Z`@8MI{ z;_&7lgmf-OEH++f!`0`n-T4`4cjyW9T{dyC41eT@2Cc@_!`YfB?de+(j}n|`#zhp{ zV#(uUzreKwxH1T;+QZ(w+uAmeCi~&%M$6DwveuZ6gOfCT98+B%N;h^)}J-h5el)3Pe;>Qk*k} zNQp4_TnU!6n1;Iqx@1?pnu{A)!$PP)b@Kp(hCjC*-)%ouU)+@EXU6^0_95Ak<9AcWxx4c& z@mt=V_Q<>TW}@s~x|)1U&CrK}duJ1sdUC@>NovGQSaflR?%)n2i<#I}60;?gzZ0Vd8;r1!eM6TO zc2K7xWx%@83YXr|XLC3rGodY-3<*#bBHq5^e#<}|wx7RBh*`Ay-(l|z@4w=&b%_(n z+!2jGLbOXQJ@^CKO_7*J)U&HhPTq-kk)Aqk@^VBO27odOuN!B{Jt>iwa`GOTt)G`t z9I^45G`g|gHFxC{x%}#89i`R}bBVG!+<;a7_GZa@kls{vLM^J~QSN2)tlTT4?xlvh zVV-{%9#w%@cl)XM!l>lJ!!w&CC!)+=nvZ@sAuHml+O`b&PZ|c)-pz>9oQS@$xXz#H z^2+(6M+;uM)m(yz^w#5MK=PKy>DCv}HnkORa9dh?qBgYeTTBo)3(24zGaM8|Tqd(a zbO%IqH1qvnqklgsdFA{X?@Pfay{Ab^5Bn>EiLw;5#+u&Y>F8^fdl?em;n%J9x-Zj1V{4Fu~dXHzB4gD?>P7$6fE3UeP4ep4Q-U~* zyCDQGz3;1LWQiK&Vv*rpKiNGkh>zJ1zIe!*5ONrqVs!c7rJ3wU`|O(!K7a=~L>wrD zMbK}}P>*Rclmm6@f{+g>Jskmav|k=g9P(fwe>U2sYD|6XA&fpnt$swBlY!|4+|trn zInQ-fUyYg2!uB3Uq<;Zi#X>6=6;PDw0^Q7Xl9NANVa@8(gt0v_kk_5}Mgy|dR zwm{KoL{g-3(1YKde}y@D%}gs7rcxKDzR4oB#<-v{_1vT!5469Od>uOjffxeDHt&m` zF}HNiYkZ(r?p4-*tDFqCR7}gyK(_*@`(C*Sry@vPRNj%IJc97!o$kehD%siU+M^tx z*?JvR5-H@i^tL1SDn(d<(#pxDRl&(rB~m(9d&C8cz- z_rEfH2iTiaDWMapISAv-vo8XmzCtUz&Za*y)7zga-ckYd3DL4?hVUAV+3pabnd+YG!qR zhUH;u9pT^jk43Cyf#P6ld_}W#FT~v3Gpg*Am z?&?6eJ95_je!Q%By$Sc`f_uyNJS6v2W@?DxTED!UtvotHVcZ+P-c)IIU%flQ^Fo_7 z$$Lu zD}&$)2M$s(^7!UvZBZpAp3>Ii(c3)H5-{?*SrT?SzrYCH6(4GuDJLFtO|;;!g*x`y zpV9)li*C`!J!ZXxT{!!J?q@+D+xU?HSJ^+cdt^sG@3La#a%z#!h$!MW$jC#_=K*M!o-Xo-A#Nq zD!D^{r9j7SuqqK8PEPIrl6^ft6CG8s7wfuewM)(qe<9oFI>-t2?>zElgx7`L&cT_A zCf?Ylj7K_O@LRz;?(Afb_Ola64NZ&I>=faHvu7s2}Gpp&?MZsnBzXwtRCl!|L?{ZT*5EcoyFd?n- zLj1~<@VSs5O!(_sNK-aN2g%Mg+ZGm?VPCxkUj}-fh-+6U70V{8w?Y24u-t2h#_nSZ z;b8F){nP8|mNcR=E#li>NAUE&|A=bMfcX{2nJS3LGysZ8LP>h`V!&j_u&zkLSmB{h zI(qAHD>0(lDol#l;3h9`-h3p*>WG1}`?$XF0r|6It$I)e8O{mu?`)q;Bc(Q6@KPh? zub;8YpBF!^Fcu>1@730zWvh1ap7EM1Ef_{Cm>wI6=ZWB1d?nUNF!)@Q!K-PI;N`XY z%nyB*m%Qs{^FC|w(Dx3UzQO?(J5FSrd9vi(Mc&xo5C!gu=lOx|HmAC=1=92h(wKzo$W>)#Mi702fMxTKu zuLZ>YT(xL#EpXGi8IM{-f4DL1+yD@Y7SoA7iN<1T z=+i~7%U9aa=jIt`)l^R7IbS(r^@;Q|okdemCdR%mEL`x>3)PtvP(ZBoEp^Gz_rlE? z#Six(zwen%5W7SCtrMVmcwZ#&nOLop65jP5Jy*0jrxsnm7s7I)Gs1VKv+(C* zCZOoQ=+m>vPbvH@=eRZLH|IT@jGj``vd;x)8H^58%@IzL-dVBt)I8l~;oZ7uPtJW1M#}WueThmdC_R}Sl zdAYv4JcAJ-If1i;`O@77E>U7k=lOSQW@Y}b3FrTl#EvERjQTI=Z9&eya22Qjl|uf{ zr8HpZasD%1{V$~kUU@6*r^3BIy#MD*fuehR^B5dG>VaY-@5573Y`f7Et;*T@A(~hn z{M^VX4${e(!MZ=%)69=foi^lxUzEGVD7M*Q?fnuv^iIx})1}@MFyNe<15$YBz_AR0 z>d`wAFpQ3Ns0KL#^|0)s9^r@PJeYHo9Hj+vP=~yJyhrJc?`Wujf=(PY++s`cnw=wExJ!3~((rTtA#9Vr-mahT+IawxyFMVrmAkInGGBb4UQlX6j2-=2 zEQ6e5lTO~jo|~ghQsXKe(xjcBuEB)g4#i$ztI%BSwj}JJ14SiVZCN@_rd{*@mbVY} zgGr;Ojh@<@xB2-2B5hA!g}`SOvA1g(3e@zEV3k0n@QN1TSUlUQ}Rp)Nciip zXoF{CD2?~3#Qf$)`{C;BQ~O`%Tm68O1BBhIa7(_WA*`e$bh9%e4BqbVgZ+Pxh{Xg%=WOtJ^gsNI}me$-`N5?WrL?cvVj1fEKzA-6Uh0rPAq)GPk{cm zci!@-3OX5NzC0Vllh}dLm#5rI;Uc+zHcBhwXT|iZ#IoWs50_+CSh$PzE&Fn>i*8}7 zRwiJcCYGEuW<|M;0vh(-=t-e)x#XCNfThu z0!9f3K)F*;aYR2bTX^QaQn_^2lO!Epb~(46F64a0BqZm%i6*{vkeXfV>iMT6PhCG6o=zdbxJ@cW(w zWw#q32)PMoM!knyns{z|V3(omN*r$;%21Nh0HryAK1Sd^|m$`caxbH#aa^ zSMhzfy)_oj0lj4&Lh%go7_K>I1pi~CWEh~wD9`8#fwS-AavrXgN77XW9QOM|Y999H|Qf6{yU{qpQR=|C}mFC=lh&<({eq@7OvFPtL)7R1E40Zp%t)-ZrD=rvahiDfmVy#aeya9*}6oAoP!eaxd+84`gPY z;p*5}OzjyT`~q7Bu=LdN;3U~vo9(clQ=XZ(KibE0+&#Tmf41`5WnhL^W3n)>brA*$ z^I?|LjBJ6_aO1QWY|LJ$UXEsH7ap_aTMR!v(Ge^N0|mKzkr?}g-?Ol^j^tju`baHU zR;?MLe=81Cb-TQF(wvq2>-PvA#7Zmq7zp{j6jaJ{ID6l%he``%sBS3z(k9U4$s@3C2>Vq}KED^-D899qc@OlKy|>N1`9q&C8IGuTh?*=qlqPxH~FwDTl-9d4XNY z*PHK!p6$Tcln$gWrT6HK`SuCGOG)IUA+NouzV}Ryj;^$hc>kQYSD)3fY{&8|`vC7s z?Jr=1a~fw1(h>ck+D_en@?TtprS>S%r_~cY&dynfK?G{jbVlwx z(L6>Y8jKP+(lrHT0JAyCS0HH>Uxl- zcOtIP7OmIzuB5USGhwL`qyFyV73{Uis>DGp?q@An5tFoer@3^O36}z#Q&RZ2ic3u_ z(D&Edxxkm4QmT&#q!wUG%qs2zNtMKT;ds}*BFE|O%y771cd_^znMnk-jy0sxXa`&$#5n{>+# z%PZ}bJ6WYKF{GD5RB+{+ZatfP z6Bb*^`TMgf%)SygM|%4`*c$q&q(t)nZTXCsyGAL)Op68~UjpJZ6wDy?J+)Pr`P&GW zT{pxkDC`Y>%)iH4iUd5Ra;#dTIN1PA*ROKx!BXHw3zvI4CWVfT0c3atMgd%Yt20YM z9XnNJM32^+)qOyjSJf-p0^CayFk;`0*NTZ);Xk!*cyYhVU2g$EP5w-^M$!lKEYjVN zoiP_6qnT-(Am%4=!d5}=z`YX`L1zN+#)EApmd7W9oVB(`L*qH8#JlxF;VV*hJmWQ9 zY==)%L|Dg5oS5QEoI-qF4fS%j>L`0%Rsx&)BTMi%~4>`w=u?QZ7VgZzjG7~DN zA;$qP)&ST!8!)Th){I+>oSfMDFK9n(7#*?E|$4h!qx=2RR`UjtG++a8wA@^43d+&&K>IYzbnIUhD!>HmW=F zK>L?0pqVeJj?kd~{zXq2iwQtJvmF*Awv%K_WdHsq$e)1FB)pO|Oov+vkeMsP&imA` z8=fad5K}c25SIG2$^C<@`N-K92SmD$PcP4n=IN>7lUVKeF%vuV&t#SP$rfE<%Q1Xzi{+$gi?uOYErE{7(et3vLvE!E>P-XC z_S;hxDA^o)+5#|X^A9G&X37G3eIDI*bYxn)!T>$d#K13EQa_&%HmWk|Hj|e~@ap&1 z7f>2$JU-K`XdNv*tg{-Gme$IkN`^eBkBp99hz?th_sC$c4t<&k>Cg|Xg;>SD&NRGS z^P5&dcg!W5H%F1l-OeR%BkaZ zZZG~Af}SxXxOez(9+gXZ(W{Blek-OHlX+)^-|UQurex6l1bNv%cluAbZyHm~ znBMxZKbDLJt$L13`nQ#p<1vAdA>@4@-uDSrKg(ntE<$xc4BUIpi1#;}HH?#gxV@MS z0x&;$1OEJ|v_~WMduXXFDcINP)R8-*rRMzcazDY^AUd$eU^ z&~~RZr9#$G+gG$3z2KvZ&@tAK?0DLU7wt_r7vB%2iAJ+?@$B-&#FHkI{yz?B^Tx1ws--WmGyS7G_sl8+E?VRNVz#r)oSwViiJx;{c zRne!X-6}ErHThYk+9~{Tw?&0lxZHQPh;`N&_MzaHGgL8VP|^g8K^PB#t~MX7?Rwvu z8XH7Y9W9&RJ^%M(R!sR=mOCu>3W#ZY;kQp7~zCeq>%!lN1Q z_=sWa?SigvG1tZjg$9u%58J=7LMen1c^md|mG%mhK7OJ+@5YkfuZ)S7Fz`NlD@HAf z3x$hf@y)C3`~RZcZLIQEGT;;^TtD@=me%x2fln3BqX6gG&jGMuU~r5*QhzGXYV8)t1% zGqvysvS$o~SIW1mCGYY#=e|2}LTcWXKQa7Uqn1ah%N5)0O#xm28mY&sH;8tbFmMmL z<UD;4NtG*ve7nhJ(um2ZE{Zj%TQ*WtT$z&E=+>9_$rk;D zWd-8D?5G(sZzr4jLUo(7Yw~~8c_NJUtxs5-;NF1Mo%7^opiji%*SkPn)Hq1QpuBN# zajEs~br@S}HR9A-k-`*CSJiOtW}T9*nCoJuVGGjk;xTrnde}Q<5mk@gs)Z>3b$;9dZZRRK%h8JDx29 z`;q7G_>|&2cM`m0@1^^BFJ#hZ!3L8X(5Ae~>eLedggIEn(l0jF{q(#N#MS#(W;YPa z6o+`P+>4g4!M7&DE%0SuB@zkUVD(DDzPV(rk3Zkp6?Nu)K2jKT(pw8SqNZPlD1T<9 zw(ZklbE^1^8q#-t-)NCqo$(U*YMtR=iFxR7Qs7(r@EZ`8}~nUDz#J$!DtN(X5<{**fu_LpV-NBoUb6 zFybgyY+b>9M5EoT@Sc`LukQn}+FNMN5aVqCPm+ius0L=~Hc#?7>#B5{{ck;@ns{>L zM8w@o{pyjk!pr#pMq7b^ZH8_A?5+37Qd)-vt_uzNmshYWc`_L_tm1=|UB0_vCO4Vk zf!7pvJOs<+@enHK_EQT{rk}1?ML*2>$ta*TdH1EpHO4I^`7QE_c9hKmLE;?n6m0%X zpQ$60F*juV+d=+2@3NocV$||o{it1h44`4aKWjcVIggke5(`5snLj@@vOqGVY>>grR>K5lj(ccZqnlg?@{QJul01xa4280I?n$j*b%kUveM+ zjIRMigZ^Jx4g$qC+W)9H?cCRYWjr8)00+YQ@9>U)iJ||W<3RqE3Hf*LQAuzuF1OLr zr=gtV-Cn`Qk8F*a(r#wq-g0+?j^zZbg0{P*!}E1fYIuI@1V+_`!)U4T982!rsF>TTCG9GMkfc@2EW&@bFD~aYnoZ!F%dG$nEYvPQ5OZ3RS4E+rCcl}X z#$@=Dyr$O-(8Ekm`l^{(qCT=Ij1s5eQPEN$p=Tb|5bamVQD#m%?|K1VT-)GqZba$w z=4!RJXUF9FLxEvBAV7h6@w!(4TORWzx&LE|=ZLFQH4Reo%tJYE`PV2-MwE+f$WN&{ z8$gqM-QBe%yIf5|RAGYk*d#<8U?dp(=E=yX6V}=Y_?}g6#?C+iRKmR*vcavnw)ITX z*@LlRZuID|#5v5_+#wR91>s3jj*;Hoew=;hq(2Y=VN?qI{e8Dm=gcQ!>!sKvUkC0W zlA2AJ-Vaa>Hw`t+&2kL^ZAF3EGB$6nYpqK#Zo$47(6K5&55*EEHq_L_JaIW5I`SV_ zkXnbW`)om11Fzd)mH@K<{02qjg>IL4y_V51r#a$oAu#S4z&q}vs|Scj47<$At#o$N z-{%@on-a|s0)Gp(e-$nzx5@Q(5nwEUz8VV&eO8EgR*{XcwyFc{I3|;irvB7WtOeh} z(Z7%pPV=3cr`Say_oGJpXEQW82?XL#m&j7jG|bHb2UQ%$sUqW+``>q_ zQKN$~H+x-3E}~5C41q~$*6nhLEdrobM)4^>3H~~>_~GyxkLr<;O(}<~W!?e-mW==< z^5X2LKwCTXCQrlAgF5p=YKIMQp^p}ss-!c2ob`2oFa z!J6Qz4;?7E$5$Y)VPIYM8Rxb-Q`E|C@OfWhn*VCdpYc$MEn(}HFr1n84nPb&>DJX^ znoB#B_Zo@R3o=3B}q{k1&6l+cXeBIzGr zBJL?uXI2K9U?&M5Xq$w;yCTxyD=|kFVY(lWCy^AkhVk%jnSs_V!lLZa2-#}H)gh7P zsd|E(^aU!zWEC>C8>mB+S!l18YzQr2Cre>otviLfW91@DWUBGPB>=_<w#YU_s$M> zJ!p`&h}6%;m}A49)~{{W=k&sBl`5nEp_!M0NZI=0@^6mvoiU8h zRcs@PT({$jmQ0Z)-v0Cn#o^B9(&rfvI<9guDN68drF(sCnOXwuAu?<4W9$d~MVx!{ z#)`?+I}`}G`jtZ2n|_rmn^b!_wlCP|G`qvrE49(WhWunS0<~}C$FjwPJ&?1N(b1iq z(F6$m=EZ}w(<5M}N&(M9thS$~Y)2AsCJ8g;!$oH0eRE=xJMD9p-*2t1b;S$wZK-2~ zrPkwTFCHUhLsf6#tNir;9Y2FFR^BgqzVGeZKUNgMr}NEYp@y^{Bs}7kfvqtko)Ilp zRjFeEUH!un2I+cNf^f}#DyE^ST20EjrSl?L4OZ!{0~{47ia#J=b2A`-`%RdOi-O3p z9_aLfokz(c`Nn!`ahdKvtpvD zIUQJ|Gq`GRwq*JDq!iHvn7eBFsRL+TyKQ{2wC|}y4 zR~pN9_=tS3bkC2X%*Qw4!B25c(McDutZ#Y6%24=`u{0O72>NXGSvN@vg zK7Ti6IsHPC!s>-SiGftr&iW*sU06+JdCu5NeMSw>BELuCJs}@7(xeiSqNpV{sz9;p zoW02XYQWKw2Ebe*2CGH@E~$uA$IFPu#&Lg;7!|Dq?sc%loA4hWO9r@uyHqKoxN~MK zCvo&H?X6zjeqo>{1>6lJR7YH%F$(|73IkZ{UCYte26kh$n6QWK5RF{hP(G)_ z&CkKl?mTKLR?BNN8r8_Eh}Wv<@1+i8flDhak{};a#BY>CWID5u_NE8M2ie&xU<*@% zp<&eaZZ>Q913q*4$Ywvg){CI;rzWfgIbufo`Rt4?Zp96FMv0y?-}isd*H%kq?YuwS zqU}iAc=V=0KJ-tiQ_K5@MAz7Tvt*eQu7dl)O zRfQis)fkLDy~@8{fBvj9a2+q4?a%H;mb6ncL6Rt!D>VM zZZjVdguE}e*F>pJ2d>1(*nn!H^m^OA`N><8&5y7 zPz^iXI6K9{J4GV>$XETG7j>zR(yc}=hEO}J`_SdN^ zpmfQ8@<)V70(nm~JQfeB=^FoEz(oEtfE#ea{r_{C`>(3MM~UoxC;VT6vHwH0P7Aie z{+}Y;e@lVamD^YXH33A#@W1+EvTi%%S$xPQ$@bLPnMB66=+cW7elZMqZg>CiP*^sz zPrdP**bNE2WpQU~ARqF6G$KII_L-l?bN7pd<>ongA75R~m<5Gm8`~~{x*V$tz8w2( z=i=Pv)7jQ~DR&fjeHz+VUsB85 zLDKTXqc}dQ$CgQ$>f*Fl=tNL~|7N3tbzWU_&I0|`)%c&YfF6aItfrR^p7;%HfY+wEbPW#5E>G3M>ZN{+-G=_DH+R}- z659jdZ9qvTH70pGuyzG~`qUxE#G;gtkT1eXR@ye)(e}Log|`1%S_UZ8lV8(ZAsuhE zXOOt^_nox?zJ8x=($$R}ojEhp1n}*c1%!p(Y^;eY@pflI`oKO|$uelx9PY<$f7hu`qgm{Rm1doMTb3LlOKmG=KGb{R252MxVKn#??@{x<%NHF6Wv{L(`Aj08la%L7?od!22$I z`mj0&P=Wxc3(O`AY-mWwKjpu4&@mqH0mSLNe6h{9=~<21Qd6dP;Y2U@Pi>ppl>hE>tlcn$MEoX`MV2Nutx$I4zvWARee-9&T0LE0PP;g%R-9NOooh~ z1$>Fb%D%hBF|m8qgz4X-FB((r%O#yS92*N@ATUTLD+=4J8V05$)=5sM3eD~%iPlcv zC#&;on)_f$y33D>RR`9La;h+XG=_+~S4{n5A8gKS$U~YYU1tBBweuq>%VlNBUEwaT z19olLiC&AHUy$`7pk$L@7nWwJacrqXk6|l`0`Kw&7Vs1j$7^exy4%z zK2ODlr%TCbz@dR{-A>GbHhLvpy7}+;$)GTFVo3;0THYkVr((JSaL$CtA%mVgt2V1V z8<@Ye?vcCt?_V{w86w9o`T6+;1o%@YGg3x<{ry8%r^VN-#Wg&2NV?*w_9WY~{$k4) z=o2JzcYe_lF)+sQiPpruDsgB31gGM-i!Q@CSN3C&sMcs&*>nv>pD}PwDB|q{pkKdr zqsa;9=P#~017zqDeSt-^pcG!e>Oz1ge+#MEo$@TO{U~yGT3lyn&J29zkoYb*&}EYy zYSrNcOWgcL3i~6Kia2dwYOJ-T9lCgt@cYrA*w(z-3(L17KU%C@%T+Oq?DR^=V=g^ZK;10MbsX999lty6rht@KunJxGld_UT}z)kizuLC`j@7l$!hO9~U z7Mk&V{E~IQOjB!;yha_Q2CxhodAsiU#|sgfbDjadNBiEeWv*}*GHiXtMIh%~5g%5< zPXiSEs35h0{G!bD;;@ZY=bgY~6i3?ESJn2YS>HR_hk_--Dl4l;^@X|3i>{A1SdNnO zNNxGC8W`PqS&`4Dc((fuD(NH{KBh?}yFkYuam{k`0ILpwm2wpEx8#}Ni@#y5t+zRl zq8c_#W;^#1*B=|snwU!Zf7t*>tem)vys9|+ZEi6wz8ch*b-T?wnZRt_z-)r>BMYY- z+cVKJ+FZMPceNPvnlIjia-To`cH)ZS&@e}zl9(sCl!wj?yXWu%wP{%DnHgf+5Jph+ zRa29)lhLtE92O*FJ05=`8mH)%96Gx07Vf31;C`L4!d9ll=u~q)7zUB*`XIvFBJwK8 zS3ZcJtdxaF;<%E-oqO%(USjn0HVnPRj9XgX*3+(F;_8Tf*QnH(4Fg4%ss#jG;tFp$>G38@!u#2422Q)~Yd=5z&Qj8yeL5?qQwj7| z988CWkn779t=7hj2z;lYEHu#U&jc0~2$_m^C8-AFLAduLQ}99ao%ELxN;e-1qzbA| ziJoPyB}RvwR1_fEeOi35Pdu!t50_Sae6-qIItZiRoV{q6`zg*InfD-+uRaP6kL`hWos~rd8zy^@^paxNiludE98ziFbYvWuafsK zwU!YjvcK zJ`wG8CRP3uz&KY4!KE8sd5itslf8wX2OJZ}-u@>zA#D7YB{l(K;W@Lv=mv$+=-Gnr z4*iHmcDkoKFgH(GRsZt8mrA%Czdf%B#7F;8*7{%B*b72F`Jb)q`?rJ_%Yl`_%;^8t zQoVoZJm5b0FD&qL%mLBd($o0ogFycEp&2{ zo)_tTv+p|;%#$tPxLBd0>htwm%hxZMwP$P&xfo8_d7a?gFKKxNc+No{4S?aF_zi)O z>5>%j`Lok{J0~|kXVk|`9(zq=V2KYeSRw`yqfK$@Qn%fXxL#gj$5o@};od5W5?|#d zLTVrXa~e^H6329S)8_i@wj$EouI8X-TXO|~~*RL%r=07$QTZV>=l zJcSA<*jk*DIN?frs z_FMC>fSh*X*KDtgcaZ<7`dARf0Pu*8#US9(A)mM-1|6m{{7Wb>g|y#{sGBDM2zIs* zAVMi|`|4ka3DU9p2X#)Ejm3c2B$Z|TfTxpy2iat5xtzO;H>xuT{2&q8W(#C8fDoj` zO!hL+oFh7b5cN)*tn!?dqo{K?P;P$)SiBdlzSj0EOLH{AnqY1;LTZD3$gG132H+;1 z187XRc_)5!)d$-u6e8^~Z|R#C>&#d&KQ?pQ zZFjz*r5u4y+u2uwFKIDz4rK@cao*pwv|bw&;E0R-I@}fPFYzG1i)oZL>A5nK@Jdfl zTU$ra&Gp%;T!>?4RXwmQuBkRnEm~sY$DXCIZ0HZJcZ)FkN)g~O36csb_~THkk#NkK z|5$Qe$!t(5O-aUY>F`lSU@hi}q(gE|#$e;b=Gxl&;A-f6gBUd}@URyqpGxwjXk#+`?_0~X&+Je0B<5nA86JjU9C_*cNiH5*C$Ut+tVni;>+~y^H z{RJxg0C9qW#wRaiaLNO$9u5Op>}(QmfzxC%0Tpf*Z@ZVVlxI^BK&)fn^O_!A1qsHc zwhpOZ5ub9g@+Ldi!(O>pgB%V8NnCfLO1FS(>i7*d(ynIa7nE;zHw>Q%y+N_TozQxN zX0g+`8w3n1c)*pcEpaVD8jkkI0eAr^v`_LocYlUO)%kHZLM|IW_NU3Z($A))?H?q_o= z;RuzrbZ8hf*&4jF%9n+H)v&TMO}jqIPhhSt40o%_INr0I`I!-oOV8A^y1F6@Sz2jn zOnwK=&09&z-fhfLflRKF9#`bL{X8?`ng84Kb#J}lR<^6l)>c+FK5dPgsQ;srGmnO{ z?c;d15Lt>gjU{6%R32h58C#agk|bs3@jYpG&vE|0s^;Hi~S4gg~E!J7b8ZPQ) zO$KtN@(n2F&D8;@$(l2zF^}5fGWak<&khAT?=12MXJ$=Je9hlB z`*8o~?#>Q8a4;nMQ>^T@)1Pk|@bk?t($quR1*mX$uP-_Wlh(Y{=mxLSu(=W!C#@49 z<9)DC*vdvtb$r}W0C;e3vNF!s>i2!i))%yH8yO+zJD_j!Tf3LAAaOGoh1W0rb;Odq zER;I9`8ROI`@%YVXZ3wB+*MZbGuI|20p5eOI97ZS$BIi33sZVTRL00=cbYP3gHvmm zdk<2H+6-+o846OjOHK~*4_#F!G|z^-oyhP6=O;-G8h&~$KVBC%Mpe4?d%vPw0L6q) z?^WuPb6;-h?lUMJ>=*vr)q@l^K`Ut=ZhsaJ{oE({e%;%%+JnCZxroa7l<^Odjy}3bu3wF(tyT(GR<>NX(4r!?CCk&H>oY zJn+J@CAW^Wxt>a2-cL|P6I#D|3qcp&i;QwVDdR<}K>Y5gKG77#SaUzeEb?^7hjVt` zEIlgxWamBKNLKFWntHA+UE#GDRZvtf{yL@@YHN~r7gfSh$mwYue|1AvO6Fr3PX*iY zk^yvh1CJX*NyD;UfoV3by)Vr(JSo_%WFSq{!;%F}Ky)uI3y@x~;&T+|=jJHaUq9Gw ziShO)K8V_F;WaQbfeyIc~+N#0nV8PXka=HzhN@4CSo!NmR<8d4v zhI8CA0mcf(Kq@X_+#47`cZ!j>grtT$Og-Sa zT0e_N6he!wKEk~(QnT8{QsseD(RwWC(OwMbown2i9b`#FDY1FVf6^qXW|MsMA5eUv zOm^#eT9BPL+Qjf{Y)XeIsOv9e%duX0^zr`9WIym2cc|rVgzfh~RkA^i`HuW6k7UMP z1QB$v%aO;g5y?{X!UYuZl!QvPoRm3WA@YHCzwk)|$5t98f7KFS`@v#H#4VGZE*4w- zV^rx_!4?)@uUwPG8Wyd(vJIOF8&bRc1_*;sME`su!21-!(97W`+F4~ zo{6aMB$;BViJBwQF2M?rYLkOF{wmRb(ENu)pQbrtX_D?}v)FYa#*5i&u4i{m zLcVUr1~_uZC}_5!b~>%$b@aWw`%!oSP0+Lj#D+;6`V9BgoIDY;6zo*>Amihwdis+n z-!-5xd24=()PNhI@26l#5T|znE+DxM8~rX-m{4o|3mDgQ*2Xfm9-GgF-;-kPMn`wI zDC-JpJg>4eHg3z%x5=k#u3DiyOFS+2gOcy_b-*1X(C|HioPY%gjdhNH?8r~A_3lKS z+u^2B?K{-#~?@sE!*5PT3hzup(t)0SHVH~ouY^->bKKZKLbj=9- zs3;qj_Gx71n=8<`y*RF~NDGV@S)n{BJj*GA_#&M?KnQLFsMpf4RR%j&iP4qlc6*n` z=<-|#I%*AgwH<-tq_08-H6Ytfx$d;?swIdrCd=z6|1r!rfFXqx=&k18G?e53k3vhZ zM?abbipIcDR2xxsfH@e@0eY*IUG7{kGB?A&1ABYK9%uuUjzt|niFlTTR~Y+oC&-}; zoVT>fD(PSE#y)$y!lF9}OgkN$^P|hWV)MkK26%G%y7vuJLGAhD^Z~(N3xH#QG>4*} z+~A;y9dKPY^Ca)p#XqkA6Nn`mTnA!`bv&ID-Y!Oifi#P@nJ&k9I<@0=8F&dsh)nCE z&j3G-$HV9L@-FuRc)9MO2uUsFrR|8a1f3-1Q;7nODKfZSOCk!*>Zp=>r&VkrM#7$* zUM(O1J-?UPqSX+B*ySDWdztiBiESR%FYdkV6`BKnL{S!D5f}c1JIT3NduRGmO(Lm0 zpco6y&o>Rn!)k}*!99IB>&5GLJ5t+^UNk8KMsLKVvV_oy;ep#97GAOX zw6(QVF$sqfnuua7vIGoZx+!K1d-$#mcVBs`6I|)EPCfQrlvp|#A1BG_E6ct3oyAM$ zT!@doR5!`&7>eT^;*7T5zL+5}&2I0T$V_P5^wB`WcBeB2VL%xGS)az3MNfjtk5I8vWaWAnyYfw+CH=EM5>8*OUPKA3|8r+*&;FXKB0Ykg6VrNq@E z4-}i73AcJ2i=8rDck0rFxWaz2&Jt^t#q_3LUU!8)Z)K0wNmjgM)wp9#?WXy|2Rqih zw(Tk`e{~}vU!bilqtr==Z8?j&Z`0SR9(#*zU=ae2M)bGx0h{flW>FfUb7wh`Grc)}+sJmficYEr1^bM8sgx=^M= zX-7CxgK}JACe7QPV~vT^>yCCrvfd%US)4GWc3-)G@%l+cZ?1no(zu~Bkk5L=3mTdh zja3Ns_XOd3OY^M~O_=-i(lSvc%~qI6F9kKdg<5eWuow<6llV*^1xrLE*F!)>g4+5E z`qd7&uMnhP9C>+-{ww*fs19l3wrL#}ghuXut$(n~h)#(1C zy)=+yefTu5Y>(+vlSDcBNYOD}-uWrDOL_`Ds2bzmG(l##DBPeb zJ5ILWWNB2cnVNu~6rq5WU4g$DGHuGLN6I#nSWY9(wAF6SQJ1HXE?n)_*41?bilZc? zceGbA_VsGwBv~EO|H%L+1xkWa`sYLn$fx*){%RV|Q z8MR%bg)BB1{at5uA>kDxH_*+^@X)I#H=H68P4d;JCEp5cK=DRu>sId(v}bnpSNB)( zLtPHW)HO|=VbZ%c!g%0bDDmTvqPQK@-njGD8QtNJiUYRilC}ymQfJkLvUa6!F;)f# zaw#hAb`1Jy2@WP~v% zFBIQDJ(V@Hd?F&!e-kr*G@C-3@Sy04xM@4Ag0^}O-Xz?M7=bAlV)4LO;i6} zc0OA`C90iowyHTkSC7{`@e&dyxwz%nC=p)1%C>vH6U=@+-lrU$v-7r9nmj()64(>T z^a@1gB%WA?L(PerMwVfXsxIL^911nEJ;{@2$@gw`8%KqK7X58WiBM$s>;@7hm?C$g zjpV^hD~{Uhs;WN`*Y4>{I%DBRZr$si9(TU^JwIxVH0l#2fAwK0>#r8;SAF^gXP_Uv z?;u^<2J8qMv`IU0AaSdqeJsgzMIb7=LrF0J_ajlmyPydnK zf=4x!>@FONGTkYJgXU_H>xryP3ow!<_Q(j}9KaA+du5l~9)ThEf+4C7_@CcHoZ$3g zYmfWOVix{_mHvK)@{N;AU8uN^Koc2My%oAl0V`kv9&Q`R;7%!_mSN+7Xj6Dr3eYS5 zl0o*LJTr-+YwaI!C`Nh~U)T+H+&^ + + + + Debug + AnyCPU + {A2B9E42A-B2D1-476D-9F4B-E64824DA57EE} + WinExe + Properties + Demo.EntityComponentSystem + Demo.EntityComponentSystem + DesktopGL + v4.5 + + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + false + + + true + bin\Release + prompt + 4 + false + false + + + Icon.ico + + + + + + + + + + + $(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\$(MonoGamePlatform)\MonoGame.Framework.dll + + + + + + + + + + + + + + + + PreserveNewest + + + + + {41724c52-3d50-45bb-81eb-3c8a247eafd1} + MonoGame.Extended + + + + + + \ No newline at end of file diff --git a/Source/Demos/Demo.EntityComponentSystem/Game1.cs b/Source/Demos/Demo.EntityComponentSystem/Game1.cs new file mode 100644 index 00000000..ed2607bf --- /dev/null +++ b/Source/Demos/Demo.EntityComponentSystem/Game1.cs @@ -0,0 +1,122 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using MonoGame.Extended; +using MonoGame.Extended.Animations.SpriteSheets; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; +using MonoGame.Extended.Particles; +using MonoGame.Extended.Particles.Modifiers; +using MonoGame.Extended.Particles.Modifiers.Containers; +using MonoGame.Extended.Particles.Modifiers.Interpolators; +using MonoGame.Extended.Particles.Profiles; +using MonoGame.Extended.Sprites; +using MonoGame.Extended.TextureAtlases; +using MonoGame.Extended.ViewportAdapters; + +namespace Demo.EntityComponentSystem +{ + public class Game1 : Game + { + // ReSharper disable once NotAccessedField.Local + private readonly GraphicsDeviceManager _graphicsDeviceManager; + private Camera2D _camera; + + private MonoGame.Extended.Entities.EntityComponentSystem _entityComponentSystem; + private Entity _entity; + + public Game1() + { + _graphicsDeviceManager = new GraphicsDeviceManager(this); + Content.RootDirectory = "Content"; + IsMouseVisible = true; + Window.AllowUserResizing = true; + } + + protected override void LoadContent() + { + var viewportAdapter = new BoxingViewportAdapter(Window, GraphicsDevice, 800, 480); + _camera = new Camera2D(viewportAdapter); + + _entityComponentSystem = new MonoGame.Extended.Entities.EntityComponentSystem(); + _entityComponentSystem.RegisterSystem(new SpriteBatchComponentSystem(GraphicsDevice, _camera)); + _entityComponentSystem.RegisterSystem(new AnimatedSpriteComponentSystem()); + _entityComponentSystem.RegisterSystem(new ParticleEmitterComponentSystem()); + + var logoTexture = Content.Load("logo-square-128"); + _entity = _entityComponentSystem.CreateEntity("logo", new Vector2(400, 240)); + _entity.AttachComponent(new Sprite(logoTexture)); + + var motwTexture = Content.Load("motw"); + var motwAtlas = TextureAtlas.Create(motwTexture, 52, 72); + var motwAnimationFactory = new SpriteSheetAnimationFactory(motwAtlas); + motwAnimationFactory.Add("idle", new SpriteSheetAnimationData(new[] { 0 })); + motwAnimationFactory.Add("walkSouth", new SpriteSheetAnimationData(new[] { 0, 1, 2, 1 }, isLooping: false)); + motwAnimationFactory.Add("walkWest", new SpriteSheetAnimationData(new[] { 12, 13, 14, 13 }, isLooping: false)); + motwAnimationFactory.Add("walkEast", new SpriteSheetAnimationData(new[] { 24, 25, 26, 25 }, isLooping: false)); + motwAnimationFactory.Add("walkNorth", new SpriteSheetAnimationData(new[] { 36, 37, 38, 37 }, isLooping: false)); + + var animatedEntity = _entityComponentSystem.CreateEntity("animated", new Vector2(50, 50)); + animatedEntity.AttachComponent(new AnimatedSprite(motwAnimationFactory, "walkSouth")); + + var particleEntity = _entityComponentSystem.CreateEntity("particles", new Vector2(500, 50)); + var particleEmitter = new ParticleEmitter(new TextureRegion2D(logoTexture), 500, TimeSpan.FromSeconds(0.5f), + Profile.Point()) + { + Parameters = new ParticleReleaseParameters + { + Speed = new Range(0f, 150f), + Quantity = 30, + Rotation = new Range(-1f, 1f), + Scale = new Range(3.0f, 4.0f) + }, + Modifiers = new IModifier[] + { + new AgeModifier + { + Interpolators = new IInterpolator[] + { + new ColorInterpolator + { + InitialColor = new HslColor(0.8f, 0.8f, 0.8f), + FinalColor = new HslColor(0.5f, 0.9f, 1.0f) + } + } + }, + new RotationModifier {RotationRate = -2.1f}, + new RectangleContainerModifier {Width = 800, Height = 480}, + new LinearGravityModifier {Direction = -Vector2.UnitY, Strength = 130f} + } + }; + particleEntity.AttachComponent(particleEmitter); + } + + protected override void UnloadContent() + { + } + + protected override void Update(GameTime gameTime) + { + var deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + var keyboardState = Keyboard.GetState(); + + if (keyboardState.IsKeyDown(Keys.Escape)) + Exit(); + + _entity.Rotation += deltaTime; + _entityComponentSystem.Update(gameTime); + + base.Update(gameTime); + } + + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.Black); + + _entityComponentSystem.Draw(gameTime); + + base.Draw(gameTime); + } + } +} \ No newline at end of file diff --git a/Source/Demos/Demo.EntityComponentSystem/Icon.ico b/Source/Demos/Demo.EntityComponentSystem/Icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..7d9dec18704053ee43cd7c956022ddbdb34d8de1 GIT binary patch literal 147541 zcmeGl2|QHY_o31*DkNL0ilkjLBkemP*sNDHl0|CFz!@@Z9>Xho|^ zX)(&oghZPy%>SM@9z%l}GjCAu{C;oVGIu%KJ@?!l!{o4r7=Rq6i}`C}*jDuH?#_Sj z(ohc5(!wx%d;WXyUJM)FNe&w{sQCXO7?yEW4l^<;{=XB3wJty@=@!4Yz_1(bYu7&fPuJk|nzhy3Q(L-FbInCE!&koEwT+Nz3QDC=VaTw4ZBvK3)IcJncsYp*{AE`PBW!L95G))yFul z?-lXE>GGkuvm7^!8Eg5kO`8KcYn3~kT{rcB*41tf3mQ(_$ow+s`gZsB5p?cbUK`a+ z`Ct9!apHIbdPgqFJ8)o*OST*5@OS#-<p*PFK#mSvsSY!GY0>*?L8*+c77CPyq^ zCT{lK<=XN4?8ECWe>}f_dZ(0MI*T2O)JJlZ9kk`vX68qPZtJh5q_r!r!}n<35|8WW z%rg97OhCw^urtQU36TO}q9-UB7zw675d(-VV88jUEVAImQ2I{}I6|S;V zJHsBkVXEpiwT|;uZ*Tm(mNRzzlf^{?ls(OLJLz-kHG28KIh{m&V!{$F%wlxxhYJP$3YNw# zw?1dLXX_+A`(X=P4D6V6ug$k_t?nhoyqWD;kYI4uYh=0|Jg9y+PMd&rLm z=8D|W#{>0x8+Nzxx#D70=u4Y3bQ^Eq(fo@G*K2F+yOVU$sd4jkC%be!tx{UY>Ks}1(Cz5IL~uSVWfSUzH)msw)peeJ{a zV-I?cV%x1VpIqP*8*6egz0u%^@MhY6sS#_f8u%Q_=)UFtu2~NcjyP{($!=%M>=gi=|`wP@s4m%;wbQ-d5<*7be&59;Y*FI-w5p;ht_gqhpHc{Ue&zRMqn~Gf4x7E*; zbhiE*aI0yoORGtK`gZajHb;!VsK40JJ(0cQ^2tU+- zEsq`%H*nU4@DB#_R$?m_eKqagPe z4O32>v7@hT$llD9^k?mJJs)y+?7YXjADhp&nBCesZB4H2&?dbSw*)tEU!|G0 z%wws?!fT-^szKKoN;!8wT)F=IfA#Iw<}BHBwYS;YgQq={X6>n8>(O(S`&7&HH?H#CVQ>bw9RM0=&;}inb_uM+8 z;bz+jJ2AlZromy;-SwS%?2Mc-yP$XDbECpp-m^Az^}ibww&Ly9G=|6HZefPkJEcd> z3wo1nAH;JRuE3=0TzD}cZttlnR%?bh9pTRMzHF9%q{&y88JSKd&DS0rd?mqn|8cwJ z&91FnA>TXBln$AkIZg6 zhHgvx(I-STwabo=p>bvvZPpSqD)0b>k#fl~mPdrrgpo>Rzep@Sz%UN!t9>?)ar!F`X z60~Pk_{*5?dofmwh1KL^TL!&WU@pmCdvbi2DI1P|d%b{hc=DGogQhARJs+*KdeeIJ z?R!q6`;FI58?dUWUw5ov==!27Id9)svagoIk+AU43@Vw z&<@v|z&4&5oPuRpWInw3p=UtyNUH%wZ9F_19JWkzjP9g3C{#H~?s10RGiRsv9_ReN z$#tsl?lviqQ83|`jqd50YI~Qpp2@2YAN)saet0nUN#okD`mSsCXV+`_bg|z;?M?slYP0NmFm}K1hqm9GZ)97k zSe{!v$|39G#+$B8Iabnzd+E2mt~)CF-Y7Wav)|ZTfthx~8tqHQhKY6_SC$%CO;_>{)ajB*f2(kp-drVd zc!Em8aC6o7cbpr~yWYKbgSICkBOZKxl1dBqPZ*lQ{ngILBjxLO*Cgd{#zP_&cfUJ) z!HP@Hjd+htGgBWf+IhvIXy$2`r~5wS@9d~#5fgv4r-$B%Ia#~A+Rhx{T!eL1X>sbo zrhcPUZ~wPCW`%2O^Q9}Z)*hJp-J!nQ@mF$24s#Fo-D%t_^8rKtkzXgC)u~OZ?!D|B zZ%RLKYj{M_y30N6-+8JhTKXJjyqg&Dsqy@MJy?obJqsLob3?i%Y#ZbLMK5sev3j@E z<{UGzUfceE<8DSLq|gg)8ZaYw)nC2n>cCZVTHbxm{_2?bw#WV01{tX#?w8XOebw^} z`mN+8FP3}acem5Cb=RC&fo)BS0xUnySou|pQ$t{?W|TENhgY7e^i z$y}m-)}1e2!GtibeM>(o!KY0&$0;dcKOHmCG#oLA)pW~gFUTLtXyadULUt6jPJ zzv8^j*QLAHe>Lr2(=?q4cJZELzc=WgrTTXL_a%1P-<=DCjlX=(?DKNjw4QPv=^w6W zycv1zbV8B#kmTb7eD8F9=N3K@3o&c=`iuRfN!dGX4Pxl~RaRu(UY5%p){$mX;Ir9GmE-$;Cq#W%)nu8YZ3nYQJkI$AZ}Ot2j`sf?snY#Q*Emkm zpu7$}3DRKJHiwdoQ`*LC6h0x?W%sv(ZI@*}q2G; z*Wy=Z&zePCYJr_~WPDIxH!LEUX&ds{dFlL47Mab)9@F1-SN?#Go?nsUWY@(j8t81F z74J4>OZ-+X$A5>f4jGpaovAU+$aSrn?v~b;0sD*Yns{kA`X1@po0F5ca_^pypYuBP zUTqcOz3ksjUwcg%<>eYO_2uT7Yg4{%b?G}ePhsfw3(6m(uAjE>=+irJ&$f>j)4S~1 z5_W!4Yvn92?9xp{Iu8Aw_eMr{WGd6j#@fGU`KV669YqqMP zZxFY~_O%Uc_x+RYfswueTW^M+{5t0zD*}Sg^7B0#7kyW!W6w?B487azxzi+Z<>ukn z3zSnJ#D_f6c_>S45r3g-KE zmF12unJ4zWe0}lR7%zv6JG)%_jP2}l&_!$b@(Yi`PhNQ1^A$1!*xdUs*{T`sqf}GZ z_Q_sqacx2Sv*G&enI~Pe?kqF8p1Mlzxa;Ce+q@i-51zFf@#@4Dm($@-0-l6+XyFmx z@_UDAYn3~mI29BA{*>Lw7EhbGXDEyw7;HD}6*!umCttC2`k}sVki71}i)!s+&W7J_ z;Le>nAuQ;c;r`UoZyp%G&0Y1tQ}^+$+?4n&z9&ylv(cE>rsa|3hu6FoVxwN18l%SQ zn$auD&ne0{<-)iK??JPSjh^mcC(hYyHVr#9stId!25pl)X6-F!Z`#1UK?C))O;OOC3D;!J4L6Y)`DqIO--I3of2q>dv?xY^V71*3h?0&-=Ty z8Ek}YAG3Gt$5!f$e^C)@iXB(!iS;qU?yEG#nl;73>M0D`2xY2%WJ0J%aQB`6?YPB2 zrDFR+Y-*!zWJ zCmj3TC7&28{*90T8^*t-R-k?1$ZHB2}4^=Qdrvzo@gm}LZUOh)4d(7PWw9V&v z1)3cue2{yTHo|eZLi9zauGd_Yrp6zPvb}f90U7)I5yo@JsrHzkF!-X=q{bufX%!1irU1xMV~V&VrRUaXg#|4!ZG!fej$AeZh|Ya9D7Xlvk) z8KFP=+zBzCy(wha*G@v9jTM~^bp0xjk)^>@*- zq9;z+zgV+ie1tcuvd1|r9n=mx(c}B}*;&dN2ge-P-&}2*_Ib?a;@D$pmuJa0NEl$P z!QOc?J$Y5L?)z;UVyUrjJ6eRkG(6o=`{sf9w^k<38UHgjC@5)(^I7B6a^E^P&TN5?&6Ss{2Iqk*vp|hA{zlBea@Y}uGcx1o*%bUoZPph|M zd$TAS%AGUoDd*TIt#4f}Ir`U6}J3Amcf0fS+j>gx2 z7@8;TtpBxTJ=)sTFh11dw1rcLFV5~`k=l54@@(21_rTnG002&+M!H$l?-fO5(-wKQ0C>4V{;D zG(^YSr8^sZLI;Jsw!FLuejne)X5JoGTsF=*c)xk0jZNCfTm2KdkEa&KNpMV<(7b4k zW#+8g8>TMIo{_nt`EtW8r#gN-J$F~LRlls|;$LeW)h(DC$#^@dyG@b2+C$IJycyTS zmt%cCczw$<$cqJJl!J?pnC&e7C46 z{eM2XbNsqTSB8aq{siMknX}CMYNox}=k_zC5AWWn?~#k{J$A8q8q_)~oH6dXVZV+= z^@mvjMBiz5#RfGxmwNV`-;q>9wZwk)jZ&ix6`q;{Ri|L?<03%oJlO=5#=u`Awlai7ekXV0P(Uwu~N3Y^O zGWQ5vHr_WeY(e{MpS8KG993s@(;qw`BB1f=h)^w0-^a5i=ICU@oaJRZqz#u z?gEQe%FSNA_H3%1nrWsmu;rK`te&p9=d-PpEhCF`^?7X+Tt6}uba&=l)t(;gr|hx) zv~T+HiPzFIE#{tIt((~+&33+H{kOVG*Yg_q-dMc%Ebphn`sJ2#b2Q|X>&xp&cKh5)v#?t=^J~Ykn z?0h_fVSn<+uXCt7M!r7u9Zpt?+O$Bk|IRMUYz;JSG;0|*WJRlAXEq-CdS-&L)dtsN zAMJZ&r0SiX6zX-^A>HlmegnS-d4;?4zg~CPKWeIue}3~}59r@I)?2*KBJZEksHADZ&OV4|n9`WIkO2?-quUXx`&Am2-N79o5!!%=TpuMo7y?&s} zm29=4RzDfnznN?Pt8nPTh37uq-drfKZF%>qtAVq-<+Y^dmOqzm>}%e%rOHF=>E4g^ z(;qMvb=Axqu-bNreQ?a>p;mVs*hvnyhXdk1U_r|*}Z@EyJ%;5}&v|oDuhNpxp5fdFwa0?ti|kQKq5Yu^CSjE+U((t);7B?6xFw zY0s;N=>=;h_>NsuICS%;+l&CcL47do>4Rg^0R(WzYu@ZfI)Hg-d4^#CN~?F#wZw&IdjaD^t`b_w9r7)u-_n`NbQ6ewdJjs3>@;}ex&2JA3x{aY&<4c^3B_&ECPb^V^h54ibHpY6OQBzN+A+k`|cE05bOWa(F( z>Dn_qJPI$Sx6?3E(>H6Hq|RpD+s6o;BUe$i-G zC8trI zFVNW7h2|%074=-Ty;m?a?+o>_V$IwauFh-!?!LdK+T)b;U5n=5rDcS5J2qGTs9uq7 zClC74{qu~>Z*I>S6S+9VpyB9`_M5M38`^m)hYmh6`@E0KSt~|D^dXfWS}H%%=Zw8M zn3K82G3N4vg7tROc|)gdi@kjJ!ifnUOJ05AVcs_yb+me8G!P9qVxxzf4+|Y)zo`p) zc83pWG!lj@aX>?&wE|31v@jFSM2ybeh%q?97@hq9J%7X)+-!95{_rasrxj?%X-7N& zUI0)2R51R~2+7zI(R&!lHu(>iuO#}5c!PKZyaJxpb)d0L5G{cijs1g?xtMm1&$FY5 zcP4d94S4cM*4D_zJ)&eTrpzm<`}n-H#xTU&+6;8g1SI#Dl-#8x_wxDxyagWDHlU^G zAv=GAk~>Lq|4k1NuLrQf#jjyN_K411jnTNdlj2n%s@zM`uPfuYxQ&)hU4Z*~RDEBz zeANMa13sFhJ|W)5qx}3jCwsylfHqpS+lHubhic!;*lv?xS3ri<=_7)^B|?v=d)?Lp zyq{2vMgjEaQ+>L1Tjqjg7Gw!B6&0wloIgkQgdTuQMFD)C4hi)Tfd_T3Io$%;Rtord z9yNadr|KxoAE?Y1gn2uED(w_qgxx{&h$;XY_aP$g<5x=WfO(@f2#1 z+qE-m;0f?XR(3$JEy!P&Ba1p{QSD@YEy9YyT_hVFK*?iGt521ipvhW9pb-1L;ANjVFuP3_fiIBiEvfBkEYp_XdhtjzR36iM0 zm>dA!ky$p0_4nlF@%Ogx#T55%!3S^+NR>aa_X271NBw#fNX7vg=P7AAP`d91S#7@^ zk`YhEMzTl!;w072r0=90Ai|4&d9-8w1Ymd&= zMEN)V&=&1=ZA4un@_4$-6wYl>Ezc zj|{7I|RsQO9XdeS|BCIDsQ*y*UsO)={88Gn2J+8;Bk>Ht8aV%v z!HpwN{wQr(1KH<4^3MPztIm+^`LErcH$bu{QJ+!TkcTXR?DJpY3}CV9Kyl`a%J}?e zI(HCxv=q}#;|`Xk_%R0JAzAXlWzPvFEq%b7&XwKy?{v-~Qfa~IL3zjufOllc9#0p^ zp3dD!Y94g%L7A}2l-&x^@sm_q__D~xATL<}@QzIRgX~Q>6G_d3!Oq79u)C1XE;?s7 zxpWBBdyp5|06YWUktu(Wy-A7|sd)hYG%gdH#8V)RWejeAjK(e?oen}4{Ji>;Mi1}` zct+$$)*WOIz~Cm6o)?|FnG}98IIS@{JBf7s%gX@I6Xi_?0I$mDC;j*264V)-!!pPZ z+L((<@|4B{BUu@xNoIS$s&+BT8{r^L03JzS)C_TPso!;a-V~)uQJ28LfI2O zA>e{=!VqrN0pNu!>U)9?kTu9$5a{ec+42+lwlwYmk^2WmB`PBPtkLyYws;aU7U>SS zSz~~!C;;ty-~riwJ|TDF4zex}bT*^r_=@*&?Ld89wix}BF-A}Af$!gF!XAlmT8zF2 zBR*x;9DX9nzO;_TamD-97GppI>_-VS0d4&Le4v%Qemz3Y72QGB!hptoSZ8=#5pC4> zQau#L3y^U|z_+iJ#}}3+^{p=P%(^1+VGM^j8>Xr1s9%^%=|COT0gxTYP!fPXD;hV4(t$dr10XYyoiu>Ku|j>+ zg_I7|6&(OsA(=@NOg=eK@~s52kSyg-x=YQy1uDxSMKM|i+W4(FxMJ5TtLLAwwClcS*0I$XE z&lj0^2?D~L(%LeA0M=;GIRU7iZ(D7OATFdK%e5ty*&X1m;Jn>x6Gmo47&kz3AZuza z8Q$-O)@T~1c9a^GkQS^ht*LeopOeCqH124hbbK>AA zPFQ@c5#+&*A)OxJ8St*6xtikOUDILl_7$u#!Pgl{Ypq!}M&n%P*V8GTWlkak^7XJmI@qcGu!&pwFX z^HIB#F7tgjDq{z}?+C&P#|_~KxB|`$?q?x(A{(cb*n5FkgH5c(tSlcA{^Rj@xkR!$ z=mmj0@h*qI77?!)<^~_KO5c^>omKj-2=DHt?~s5%bUcBA(!VjxR3LZwu2Uv?3_}^P z1jC~Yn1b&LWwOICl%e3?sKP9hJwl*N_6ULU?#NPxjW$<2xt0+I}9RyblGT=uU5tqK8Cxn9x-jTdPtN8?@2kKoiey}hMY;g%c z%e=ecMiu>ETK<{1l_`EV#f>boI>q)v2RE|Fw1O>k$L$MxKx%>B!Tu=m6LKT$kpe%W zDVS>bUyfg#m7r#jL*Fnr_`wu#dxt;5D<2eC#1sFnSk-$OOM!4HZ?DV0m$&!j--~%b zVBuE2J`t?mfVAK0qcR91CYM1FDLEe@;0pr8T0R1bEO-S|%|}3qAI*(dT*2w!(V#x% z;UV4dU?5{W1N4VGijLO|@DKU}g1N!}@Q*2;4;~#bz#rTpcOGoaVvjB+y5ulj^owM? z7r&AG!;`}Xa1D?zCfeP1><5sGab=h6YW{pQ-Q%* zK+R!Avcc!^B3_WW50jwH8^GyXV|~D4+lvZxmyC3vFBf=28i0-GtU&Vq_1D=NQRM}^ z0Uk-ao*vF^g6vHg#dlH56XF%{Od5dC<&r_ayr?=>cfz5u3<>u!!^cIab>r18_xPB3 zHD!R?97^x2&HK`F8Y8|fLUk==@1@u_NA-a?bu!f9rSg*^9-`J?e_%M=FA||b#{GNB z$CSGMfp1z>`v7m(*66;Me|lMqtF)aAeF~J_Az23ykA(sBBT;LTN#;GO*MP^u`s|=D zkJ5ee`42n>UY7yr+aaqD8Lb_oac?8p?!fak;o4)h`Qq#04nEE#tw{u43;LrBjwuPc zkLEmawqvw(jWVLHOD}*s&>+2ea02BE@tgo@?^8}=-$y#$j!3@F-+>mONvif4jiccJ zZCz=O8KSnHsQcvBCBfkP6ic%Y81Woz5R5BJORk_Je~9;gOWKS)#kZ?+)zFBw*bFR7NEV_{3GV)NSGG*n046C5m#?;zepOs zDLWFCB{a{d+VbPe4gCAR4ft&u3H287UOMyAWP2WJZICscyHjGll@9NPw5MwWgGk1q zHucv)f5P7eK(nNFTUzlc{!3a9NEV+g{?j?SrtFR2dI<@l8TQ~F<*^;c5dDgCGPUs4^a%ke4wr}V!r>#wA^ zQ~FQozoa@;m*Z3V|A*>7*9^@MaQ>q&X_Py%^#5-dQ>OS|vr?w`Pw~HIIZ(5?Q~FQw zzh*g5v$@x1{fF}w=v;S+E=Yq6prsf|gcm_qZRWo;=3hY?WB~Zw(%_vm(jd$Kr}!^g zyPD#^Xnc}}t_w?p;y=ZIVR`}IDEnXi+K;mTqLnMk{)on>ipr>@-zol6{I5udDEm*@ z|B7@&THh)AL)o8-bcwP*)we$k&IQT)SWp^d0F?QPWG?IPzwKuxC4w2;C@IhwB_(Xi zCL^u&*V0)7PtN`W3@%Fw{AZPAoRr>RKRZeFyyTppTDbp)Nm?6;=_B|9X-ONTwf_bK z-vdR$`kRFPXQWlWK?c&ckJ8OW4S^!6W4DzTBkhT9L;8Gj*Up4t;f%g3ULL%?^GJrfFFL8j>{a11R zo034cX!{S-KN;7|Stn>ORmi(Ckk$UfV1s0{|2CY7Iuq>^x)O~G9zu5SEeUcbY>kL_ zgahCLI00^ae?+$XZ-Wj<&kqujZfW?ubu8s{MhAk=fMij6t{ZW_Rk?G1*!jg{jcASunxDx(%f=crO;slgtCDmf5B|Dt zbbby#zchi53&M$zP0748b|m`dkMMKCX(EB=JYE(bH6)zYg3?`Q=6jZuk%A82*eaxgwN2B_6JO3UE^d zodjJ)HwDmDcf=120pbNb6ClSVo=`Z!XIANVMZssmGKKOdpiH^L+0OsRv{X-#Jc!V! zEaT<@#{`upCi(-<9hE1@K#_%hP#J;@@RW7R#Z(;eB@%f&ttniD~SFH(7$*?8VK4hR>hJIVAFVXiNovjyeD zt^ry_^W6Y9z)_m>l6$ioBbw29+uWSmOLsZl!*NA81MZRl?b856voz-FizvTxbX2bY zqNK^ffQIUT$tQHNrcTv-OZ1#l9V4rnt$J5HQpEd`a$1nE8u<6B9?!k8QRV?_Ir`#5B@_tQji60XxDQeb>1S}Bh-_!Xk_lO~3QJc4`BU^$ z@~^deElk&ieWUch+UB1s|5W*>%DAx85UrPTe{jVkmDEq&Q#Bqk|kAKlPi6Y|#VXF(`kAI0X z23WoEPg7n!vE~=S{2Yi=9T0c?Qx@ajCfp$+%bxH@A&$6Eo$+s&13=^{%Dp=CA873V z#L5HkfH>kpb>=^iJ^zKqogy~vgd8BQs8HScFE9s)$WPR}sPms_pUhF(;@Fq+ZP9Er zU)8)y7DzJxNs{?*49;4i^I_<0Z8WdyAex_7BsOnmTXdTbN0TR!Mg74BsTB_4oMIU;juT$6x=tO)7dylZkEH8g2_C>*qV>=0=Sa4TMA}mZ_ML&S3_MQx_COWyB&>fHwkp843PE4-Z9k4QPKL{$6=rNbm0;oh7eMgS7d1puAwuK1ue)1H3uY5x%d` zRfT;a?f+Le4&u@Q=cn-bP*Zr9%@=S1oJ0XScM!5^nKj7svbYnn2b=)6%7Bl1Zmq+; zl!n|2X~56isfBzea3}5{hu?GwFRNf%gv+kBeTVWOSf=@Qrf%R)@Dgyw0r6fO8;Sd% zuvaAP11I9VpQ^&)`?{et#cMOZ!exNBwM5bz+?{~r{s9g8yoaIu*Pn5(U&)@MaizmO1t=yjhovevH zGa=8a%R}Y35OuM4hnzC zb2nF6mZXWlDE=FS5fz~9RfS(w|BF+8Dg4VyhT^~U{Rdg=KeXXQ1!?QQG}@2Qh87j* zZ09QN1%we5L~FlS-UlI0{|SS8x=Q>Zj3^*#|A|QBET~VfDu6z1k@jswdprKt|1BhO z=&P*SwnLw}JJ~v0{p!3&6>PH2CItGI{6@fVYhZ6PQLf`eLVQ5U`r5L#L+XHwU z6j!hxzdHT55TC(C=c0(nJG@U1m1#Qr1{(M0h#aq?^dSvM3(9KM{e^;Up@b6J>-6{q zC}ABRKLQf!^!ObRfS@jqpYkanXpqwQHD@atb3&JhwxP0cqKsb?G=MINRIgQl7tB?o zb0!eU;m?xHUjtl3sq;!Qga^D#i#dOT{SEPZyU;TS;jBUYKL}F+-M@dY-u#X7bnxpq zVyvvxU*gvVaK;$gKjza^k&}eSpjg z(gU>r2K$+4zGp>xk9<-*4U`t7Sry>tc5?qGMmZAnJF0%BL)sOb8)}@|5tZXNq~%>= z15h52mmu(Mhz#;3se-YN3S6@(6Vm(7#{@mo!GX=}$Rb0jd^DTK^BvxLP1;%kGNw<{O6_sz` zn&H9l%wsupWc|gh6HXFJG61=pb5CB@E~s&kFO0 z|AaxM{s(Fs2rYxqc0lKf6MhJ+O%rAB4G2T5V}rPmM#cT-KKOboq4^ivMZVtx{jj3U zTP64iVbOWgRrsHrrRHYLv`9;H10#hyNAN{M_9cE--NWkAb$YhgDA3~ zu?tW-yYTtD{J#BNNY?0EMR^js1nn$=b{9X_-+zgAiJ*VZ?~g%aDI7PUXVSyj^7wyf z45g&+2Feh$;VW)`qkb737V1%8qTU5})Kvf%27p$3!8yTjq19hZ1r$)|g?dR~iJn5P z4hmEDlFL$ZhYK4dk0M<$;dg2^W$~^0`=6LTgVPQ1r_^T`@3}0` zgz-mY1ridlynKYEZ~Q^!w{iyG$^+D;5MS^TC4FJ~1K-L6q+33{^6$d%uifdFFT=mv z2L^YX5W2^eXAcVVyM5r>pi&(wZ{NUIWw3Alo<90U_`r}+h4xLzcp%>n0xpZu75jVI zCH@Nh2Vp9<&t%sxIBncXmEc&)yYjkL`TL|Y@?oGnDyt{?ejM=3rBa`cpGMiViHwN) zlBjneO};GrF-A&fA{hS6;QHhL@$;?FKVe~t7!y;#+>6~aNJ9ZF&R682f83EXRsKR- z6DV#(|CPHGP$~pKT9777T@eF642Fkv(M9-SgX*CdVSwu@@JEC_O8H@2N^}^H%ef}L zoKYMiUqN}(xM=M%>iZCO!GD5bahVF>4Exx@{u~tn{3p2AoglrCc4cviG$G9Ic%b=@ z<@#$xY1<0YBK`QQh4QdGUkMz_=TFdE)xDzlu-{TiUg%j67~JHN|0<5}ULtGYr654M zL_FeNUVdfgyLpvFFE2kq9U$}v_bb?+O7nnc5Xl^+`W2eMf| zO7SSM@5pu*mmeUEC`SY>d|P%J8_4O3UoaPvu#x4;ue)4llmP!yWOYWP&7Cn#^iEtl RJoIeLznU7AhJ`o~_y6Yy51#-4 literal 0 HcmV?d00001 diff --git a/Source/Demos/Demo.EntityComponentSystem/OpenTK.dll.config b/Source/Demos/Demo.EntityComponentSystem/OpenTK.dll.config new file mode 100644 index 00000000..9342d688 --- /dev/null +++ b/Source/Demos/Demo.EntityComponentSystem/OpenTK.dll.config @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/Demos/Demo.EntityComponentSystem/Program.cs b/Source/Demos/Demo.EntityComponentSystem/Program.cs new file mode 100644 index 00000000..9c8da56e --- /dev/null +++ b/Source/Demos/Demo.EntityComponentSystem/Program.cs @@ -0,0 +1,16 @@ +using System; + +namespace Demo.EntityComponentSystem +{ + internal static class Program + { + [STAThread] + private static void Main(string[] args) + { + using (var game = new Game1()) + { + game.Run(); + } + } + } +} \ No newline at end of file diff --git a/Source/Demos/Demo.EntityComponentSystem/Properties/AssemblyInfo.cs b/Source/Demos/Demo.EntityComponentSystem/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..e79fb489 --- /dev/null +++ b/Source/Demos/Demo.EntityComponentSystem/Properties/AssemblyInfo.cs @@ -0,0 +1,39 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("Demo.EntityComponentSystem")] +[assembly: AssemblyProduct("Demo.EntityComponentSystem")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("9b7203c6-a9a6-40e9-a798-893df7f10bf1")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] + +[assembly: AssemblyVersion("3.4.0.456")] +[assembly: AssemblyFileVersion("3.4.0.456")] \ No newline at end of file diff --git a/Source/Demos/Demo.EntityComponentSystem/app.config b/Source/Demos/Demo.EntityComponentSystem/app.config new file mode 100644 index 00000000..5c73fc53 --- /dev/null +++ b/Source/Demos/Demo.EntityComponentSystem/app.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Source/Demos/Demo.Particles/Game1.cs b/Source/Demos/Demo.Particles/Game1.cs index 05f20ab4..d098e9de 100644 --- a/Source/Demos/Demo.Particles/Game1.cs +++ b/Source/Demos/Demo.Particles/Game1.cs @@ -95,9 +95,8 @@ namespace Demo.Particles { Emitters = new[] { - new ParticleEmitter(500, TimeSpan.FromSeconds(2.5), Profile.Ring(150f, Profile.CircleRadiation.In)) + new ParticleEmitter(textureRegion, 500, TimeSpan.FromSeconds(2.5), Profile.Ring(150f, Profile.CircleRadiation.In)) { - TextureRegion = textureRegion, Parameters = new ParticleReleaseParameters { Speed = new Range(0f, 50f), diff --git a/Source/Demos/Demo.Platformer/Demo.Platformer.csproj b/Source/Demos/Demo.Platformer/Demo.Platformer.csproj index 66eb7999..dbe985bc 100644 --- a/Source/Demos/Demo.Platformer/Demo.Platformer.csproj +++ b/Source/Demos/Demo.Platformer/Demo.Platformer.csproj @@ -36,16 +36,6 @@ Icon.ico - - - - - - - - - - diff --git a/Source/Demos/Demo.Platformer/Entities/Components/EntityComponent.cs b/Source/Demos/Demo.Platformer/Entities/Components/EntityComponent.cs deleted file mode 100644 index ad8fed61..00000000 --- a/Source/Demos/Demo.Platformer/Entities/Components/EntityComponent.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Demo.Platformer.Entities.Components -{ - public abstract class EntityComponent - { - protected EntityComponent() - { - } - - public Entity Entity { get; internal set; } - } -} \ No newline at end of file diff --git a/Source/Demos/Demo.Platformer/Entities/Components/SpriteAnimatorComponent.cs b/Source/Demos/Demo.Platformer/Entities/Components/SpriteAnimatorComponent.cs deleted file mode 100644 index f34d0973..00000000 --- a/Source/Demos/Demo.Platformer/Entities/Components/SpriteAnimatorComponent.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MonoGame.Extended.Animations.SpriteSheets; - -namespace Demo.Platformer.Entities.Components -{ - public class SpriteAnimatorComponent : EntityComponent - { - public SpriteAnimatorComponent(SpriteSheetAnimationFactory animationFactory, string playAnimation = null) - { - Animator = new SpriteSheetAnimator(animationFactory); - - if (playAnimation != null) - Animator.Play(playAnimation); - } - - public SpriteSheetAnimator Animator { get; } - } -} \ No newline at end of file diff --git a/Source/Demos/Demo.Platformer/Entities/Components/SpriteComponent.cs b/Source/Demos/Demo.Platformer/Entities/Components/SpriteComponent.cs deleted file mode 100644 index c315aec4..00000000 --- a/Source/Demos/Demo.Platformer/Entities/Components/SpriteComponent.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Extended.TextureAtlases; - -namespace Demo.Platformer.Entities.Components -{ - public class SpriteComponent : EntityComponent - { - public SpriteComponent(TextureRegion2D textureRegion) - { - IsVisible = true; - TextureRegion = textureRegion; - Color = Color.White; - Origin = new Vector2(textureRegion.Size.Width, textureRegion.Size.Height)*0.5f; - Effect = SpriteEffects.None; - Alpha = 1.0f; - Depth = 0.0f; - } - - public bool IsVisible { get; set; } - public TextureRegion2D TextureRegion { get; set; } - public Color Color { get; set; } - public Vector2 Origin { get; set; } - public SpriteEffects Effect { get; set; } - public Vector2 Position => Entity.Position; - public float Rotation => Entity.Rotation; - public Vector2 Scale => Entity.Scale; - public float Alpha { get; set; } - public float Depth { get; set; } - } -} diff --git a/Source/Demos/Demo.Platformer/Entities/Systems/SpriteAnimatorComponentSystem.cs b/Source/Demos/Demo.Platformer/Entities/Systems/SpriteAnimatorComponentSystem.cs deleted file mode 100644 index 80409451..00000000 --- a/Source/Demos/Demo.Platformer/Entities/Systems/SpriteAnimatorComponentSystem.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Demo.Platformer.Entities.Components; -using Microsoft.Xna.Framework; - -namespace Demo.Platformer.Entities.Systems -{ - public class SpriteAnimatorComponentSystem : UpdatableComponentSystem - { - public SpriteAnimatorComponentSystem() - { - } - - public override void Update(GameTime gameTime) - { - var components = GetComponents(); - - foreach (var component in components) - component.Animator.Update(gameTime); - } - } -} \ No newline at end of file diff --git a/Source/Demos/Demo.Platformer/Entities/Systems/SpriteBatchComponentSystem.cs b/Source/Demos/Demo.Platformer/Entities/Systems/SpriteBatchComponentSystem.cs deleted file mode 100644 index bf1807d6..00000000 --- a/Source/Demos/Demo.Platformer/Entities/Systems/SpriteBatchComponentSystem.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Demo.Platformer.Entities.Components; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; - -namespace Demo.Platformer.Entities.Systems -{ - public class SpriteBatchComponentSystem : DrawableComponentSystem - { - public SpriteBatchComponentSystem(GraphicsDevice graphicsDevice) - { - _spriteBatch = new SpriteBatch(graphicsDevice); - } - - private readonly SpriteBatch _spriteBatch; - - public override void Draw(GameTime gameTime) - { - var spriteComponents = GetComponents(); - - _spriteBatch.Begin(); - - foreach (var sprite in spriteComponents) - { - if (sprite.IsVisible) - { - var texture = sprite.TextureRegion.Texture; - var sourceRectangle = sprite.TextureRegion.Bounds; - - _spriteBatch.Draw(texture, sprite.Position, sourceRectangle, sprite.Color * sprite.Alpha, sprite.Rotation, sprite.Origin, - sprite.Scale, sprite.Effect, sprite.Depth); - } - } - _spriteBatch.End(); - } - } -} \ No newline at end of file diff --git a/Source/Demos/Demo.Platformer/Game1.cs b/Source/Demos/Demo.Platformer/Game1.cs index b6da1d2e..dd09cc27 100644 --- a/Source/Demos/Demo.Platformer/Game1.cs +++ b/Source/Demos/Demo.Platformer/Game1.cs @@ -1,11 +1,11 @@ -using Demo.Platformer.Entities; -using Demo.Platformer.Entities.Components; -using Demo.Platformer.Entities.Systems; -using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using MonoGame.Extended; using MonoGame.Extended.Animations.SpriteSheets; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Components; +using MonoGame.Extended.Entities.Systems; using MonoGame.Extended.Maps.Tiled; using MonoGame.Extended.TextureAtlases; using MonoGame.Extended.ViewportAdapters; diff --git a/Source/MonoGame.Extended.sln b/Source/MonoGame.Extended.sln index d4ee4ccc..357139c6 100644 --- a/Source/MonoGame.Extended.sln +++ b/Source/MonoGame.Extended.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGame.Extended", "MonoGame.Extended\MonoGame.Extended.csproj", "{41724C52-3D50-45BB-81EB-3C8A247EAFD1}" EndProject @@ -93,6 +93,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo.Screens", "Demos\Demo. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo.Platformer", "Demos\Demo.Platformer\Demo.Platformer.csproj", "{A7A5E924-A49D-4052-ACA2-894161007B00}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo.EntityComponentSystem", "Demos\Demo.EntityComponentSystem\Demo.EntityComponentSystem.csproj", "{A2B9E42A-B2D1-476D-9F4B-E64824DA57EE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -253,6 +255,14 @@ Global {A7A5E924-A49D-4052-ACA2-894161007B00}.Release|Any CPU.Build.0 = Release|Any CPU {A7A5E924-A49D-4052-ACA2-894161007B00}.Release|x86.ActiveCfg = Release|Any CPU {A7A5E924-A49D-4052-ACA2-894161007B00}.Release|x86.Build.0 = Release|Any CPU + {A2B9E42A-B2D1-476D-9F4B-E64824DA57EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2B9E42A-B2D1-476D-9F4B-E64824DA57EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2B9E42A-B2D1-476D-9F4B-E64824DA57EE}.Debug|x86.ActiveCfg = Debug|Any CPU + {A2B9E42A-B2D1-476D-9F4B-E64824DA57EE}.Debug|x86.Build.0 = Debug|Any CPU + {A2B9E42A-B2D1-476D-9F4B-E64824DA57EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2B9E42A-B2D1-476D-9F4B-E64824DA57EE}.Release|Any CPU.Build.0 = Release|Any CPU + {A2B9E42A-B2D1-476D-9F4B-E64824DA57EE}.Release|x86.ActiveCfg = Release|Any CPU + {A2B9E42A-B2D1-476D-9F4B-E64824DA57EE}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -275,5 +285,6 @@ Global {62E83B48-D581-4E85-B7E7-9A87A811A99C} = {932F8931-4A8D-4205-BFCF-98E794207786} {50C281D9-1D55-4E5C-836B-94110EC09605} = {932F8931-4A8D-4205-BFCF-98E794207786} {A7A5E924-A49D-4052-ACA2-894161007B00} = {932F8931-4A8D-4205-BFCF-98E794207786} + {A2B9E42A-B2D1-476D-9F4B-E64824DA57EE} = {932F8931-4A8D-4205-BFCF-98E794207786} EndGlobalSection EndGlobal diff --git a/Source/MonoGame.Extended/Animations/SpriteSheets/AnimatedSprite.cs b/Source/MonoGame.Extended/Animations/SpriteSheets/AnimatedSprite.cs new file mode 100644 index 00000000..8cf51d9d --- /dev/null +++ b/Source/MonoGame.Extended/Animations/SpriteSheets/AnimatedSprite.cs @@ -0,0 +1,45 @@ +using System; +using Microsoft.Xna.Framework; +using MonoGame.Extended.Sprites; + +namespace MonoGame.Extended.Animations.SpriteSheets +{ + public class AnimatedSprite : Sprite + { + public AnimatedSprite(SpriteSheetAnimationFactory animationFactory, string playAnimation) + : base(animationFactory.Frames[0]) + { + _animationFactory = animationFactory; + + Play(playAnimation).IsLooping = true; + } + + private readonly SpriteSheetAnimationFactory _animationFactory; + private SpriteSheetAnimation _currentAnimation; + + public SpriteSheetAnimation Play(string name, Action onCompleted = null) + { + if (_currentAnimation == null || _currentAnimation.IsComplete || _currentAnimation.Name != name) + { + _currentAnimation = _animationFactory.Create(name); + _currentAnimation.OnCompleted = onCompleted; + } + + return _currentAnimation; + } + + public void Update(float deltaTime) + { + if (_currentAnimation != null && !_currentAnimation.IsComplete) + { + _currentAnimation.Update(deltaTime); + TextureRegion = _currentAnimation.CurrentFrame; + } + } + + public void Update(GameTime gameTime) + { + Update(gameTime.GetElapsedSeconds()); + } + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended/Animations/SpriteSheets/SpriteSheetAnimator.cs b/Source/MonoGame.Extended/Animations/SpriteSheets/SpriteSheetAnimator.cs index 16796bf0..c7b4a0ba 100644 --- a/Source/MonoGame.Extended/Animations/SpriteSheets/SpriteSheetAnimator.cs +++ b/Source/MonoGame.Extended/Animations/SpriteSheets/SpriteSheetAnimator.cs @@ -5,6 +5,7 @@ using MonoGame.Extended.Sprites; namespace MonoGame.Extended.Animations.SpriteSheets { + [Obsolete("Please use AnimatedSprite instead")] public class SpriteSheetAnimator : IUpdate { public SpriteSheetAnimator(SpriteSheetAnimationFactory animationFactory) diff --git a/Source/MonoGame.Extended/Entities/Components/EntityComponent.cs b/Source/MonoGame.Extended/Entities/Components/EntityComponent.cs new file mode 100644 index 00000000..8d9194ec --- /dev/null +++ b/Source/MonoGame.Extended/Entities/Components/EntityComponent.cs @@ -0,0 +1,52 @@ +using Microsoft.Xna.Framework; + +namespace MonoGame.Extended.Entities.Components +{ + public abstract class EntityComponent : IMovable, IRotatable, IScalable + { + protected EntityComponent() + { + } + + public Entity Entity { get; internal set; } + + private Vector2 _position; + public Vector2 Position + { + get { return Entity?.Position ?? _position; } + set + { + _position = value; + + if (Entity != null) + Entity.Position = _position; + } + } + + private float _rotation; + public float Rotation + { + get { return Entity?.Rotation ?? _rotation; } + set + { + _rotation = value; + + if (Entity != null) + Entity.Rotation = value; + } + } + + private Vector2 _scale; + public Vector2 Scale + { + get { return Entity?.Scale ?? _scale; } + set + { + _scale = value; + + if (Entity != null) + _scale = value; + } + } + } +} \ No newline at end of file diff --git a/Source/Demos/Demo.Platformer/Entities/Entity.cs b/Source/MonoGame.Extended/Entities/Entity.cs similarity index 65% rename from Source/Demos/Demo.Platformer/Entities/Entity.cs rename to Source/MonoGame.Extended/Entities/Entity.cs index 7766015d..b35a0457 100644 --- a/Source/Demos/Demo.Platformer/Entities/Entity.cs +++ b/Source/MonoGame.Extended/Entities/Entity.cs @@ -1,9 +1,9 @@ using System; -using Demo.Platformer.Entities.Components; +using System.Linq; using Microsoft.Xna.Framework; -using MonoGame.Extended; +using MonoGame.Extended.Entities.Components; -namespace Demo.Platformer.Entities +namespace MonoGame.Extended.Entities { public class Entity : IMovable, IRotatable, IScalable { @@ -33,25 +33,22 @@ namespace Demo.Platformer.Entities public void AttachComponent(EntityComponent component) { - if (component.Entity != null) - throw new InvalidOperationException("Component already attached to another entity"); - - component.Entity = this; - _entityComponentSystem.AttachComponent(component); + _entityComponentSystem.AttachComponent(this, component); } public void DetachComponent(EntityComponent component) { - if (component.Entity != this) - throw new InvalidOperationException("Component not attached to entity"); - - component.Entity = null; - _entityComponentSystem.DetachComponent(component); + _entityComponentSystem.DetachComponent(this, component); } public void Destroy() { _entityComponentSystem.DestroyEntity(this); } + + public T GetComponent() where T : EntityComponent + { + return _entityComponentSystem.GetComponent(this); + } } } diff --git a/Source/Demos/Demo.Platformer/Entities/EntityComponentSystem.cs b/Source/MonoGame.Extended/Entities/EntityComponentSystem.cs similarity index 63% rename from Source/Demos/Demo.Platformer/Entities/EntityComponentSystem.cs rename to Source/MonoGame.Extended/Entities/EntityComponentSystem.cs index d831f729..25897ef4 100644 --- a/Source/Demos/Demo.Platformer/Entities/EntityComponentSystem.cs +++ b/Source/MonoGame.Extended/Entities/EntityComponentSystem.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using Demo.Platformer.Entities.Components; -using Demo.Platformer.Entities.Systems; using Microsoft.Xna.Framework; +using MonoGame.Extended.Entities.Components; +using MonoGame.Extended.Entities.Systems; -namespace Demo.Platformer.Entities +namespace MonoGame.Extended.Entities { public class EntityComponentSystem { @@ -31,6 +31,14 @@ namespace Demo.Platformer.Entities _systems.Add(system); } + public Entity CreateEntity(string name, Vector2 position, float rotation = 0) + { + var entity = CreateEntity(name); + entity.Position = position; + entity.Rotation = rotation; + return entity; + } + public Entity CreateEntity(string name) { var entity = new Entity(this, _nextEntityId, name); @@ -39,7 +47,7 @@ namespace Demo.Platformer.Entities return entity; } - public Entity FindEntity(string name) + public Entity GetEntity(string name) { return _entities.FirstOrDefault(e => e.Name == name); } @@ -49,21 +57,6 @@ namespace Demo.Platformer.Entities _entities.Remove(entity); } - public void AttachComponent(EntityComponent component) - { - _components.Add(component); - } - - public void DetachComponent(EntityComponent component) - { - _components.Remove(component); - } - - internal IEnumerable GetComponents() - { - return _components.OfType(); - } - public void Update(GameTime gameTime) { foreach (var componentSystem in _systems.OfType()) @@ -75,5 +68,33 @@ namespace Demo.Platformer.Entities foreach (var componentSystem in _systems.OfType()) componentSystem.Draw(gameTime); } + + internal T GetComponent(Entity entity) where T : EntityComponent + { + return _components.OfType().FirstOrDefault(i => i.Entity == entity); + } + + internal void AttachComponent(Entity entity, EntityComponent component) + { + if (component.Entity != null) + throw new InvalidOperationException("Component already attached to another entity"); + + component.Entity = entity; + _components.Add(component); + } + + internal void DetachComponent(Entity entity, EntityComponent component) + { + if (component.Entity != entity) + throw new InvalidOperationException("Component not attached to entity"); + + component.Entity = null; + _components.Remove(component); + } + + internal IEnumerable GetComponents() + { + return _components.OfType(); + } } } \ No newline at end of file diff --git a/Source/MonoGame.Extended/Entities/Systems/AnimatedSpriteComponentSystem.cs b/Source/MonoGame.Extended/Entities/Systems/AnimatedSpriteComponentSystem.cs new file mode 100644 index 00000000..bf7471b8 --- /dev/null +++ b/Source/MonoGame.Extended/Entities/Systems/AnimatedSpriteComponentSystem.cs @@ -0,0 +1,17 @@ +using Microsoft.Xna.Framework; +using MonoGame.Extended.Animations.SpriteSheets; + +namespace MonoGame.Extended.Entities.Systems +{ + public class AnimatedSpriteComponentSystem : UpdatableComponentSystem + { + public override void Update(GameTime gameTime) + { + var deltaTime = gameTime.GetElapsedSeconds(); + var sprites = GetComponents(); + + foreach (var animatedSprite in sprites) + animatedSprite.Update(deltaTime); + } + } +} \ No newline at end of file diff --git a/Source/Demos/Demo.Platformer/Entities/Systems/ComponentSystem.cs b/Source/MonoGame.Extended/Entities/Systems/ComponentSystem.cs similarity index 88% rename from Source/Demos/Demo.Platformer/Entities/Systems/ComponentSystem.cs rename to Source/MonoGame.Extended/Entities/Systems/ComponentSystem.cs index 50b4516a..b55684ea 100644 --- a/Source/Demos/Demo.Platformer/Entities/Systems/ComponentSystem.cs +++ b/Source/MonoGame.Extended/Entities/Systems/ComponentSystem.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Demo.Platformer.Entities.Systems +namespace MonoGame.Extended.Entities.Systems { public abstract class ComponentSystem { diff --git a/Source/Demos/Demo.Platformer/Entities/Systems/DrawableComponentSystem.cs b/Source/MonoGame.Extended/Entities/Systems/DrawableComponentSystem.cs similarity index 79% rename from Source/Demos/Demo.Platformer/Entities/Systems/DrawableComponentSystem.cs rename to Source/MonoGame.Extended/Entities/Systems/DrawableComponentSystem.cs index d300e75d..a6c9a141 100644 --- a/Source/Demos/Demo.Platformer/Entities/Systems/DrawableComponentSystem.cs +++ b/Source/MonoGame.Extended/Entities/Systems/DrawableComponentSystem.cs @@ -1,6 +1,6 @@ using Microsoft.Xna.Framework; -namespace Demo.Platformer.Entities.Systems +namespace MonoGame.Extended.Entities.Systems { public abstract class DrawableComponentSystem : ComponentSystem { diff --git a/Source/MonoGame.Extended/Entities/Systems/ParticleEmitterComponentSystem.cs b/Source/MonoGame.Extended/Entities/Systems/ParticleEmitterComponentSystem.cs new file mode 100644 index 00000000..ea6bd109 --- /dev/null +++ b/Source/MonoGame.Extended/Entities/Systems/ParticleEmitterComponentSystem.cs @@ -0,0 +1,20 @@ +using Microsoft.Xna.Framework; +using MonoGame.Extended.Particles; + +namespace MonoGame.Extended.Entities.Systems +{ + public class ParticleEmitterComponentSystem : UpdatableComponentSystem + { + public override void Update(GameTime gameTime) + { + var deltaTime = gameTime.GetElapsedSeconds(); + var emitters = GetComponents(); + + foreach (var particleEmitter in emitters) + { + particleEmitter.Update(deltaTime); + particleEmitter.Trigger(); + } + } + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended/Entities/Systems/SpriteBatchComponentSystem.cs b/Source/MonoGame.Extended/Entities/Systems/SpriteBatchComponentSystem.cs new file mode 100644 index 00000000..74681561 --- /dev/null +++ b/Source/MonoGame.Extended/Entities/Systems/SpriteBatchComponentSystem.cs @@ -0,0 +1,35 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended.Particles; +using MonoGame.Extended.Sprites; + +namespace MonoGame.Extended.Entities.Systems +{ + public class SpriteBatchComponentSystem : DrawableComponentSystem + { + public SpriteBatchComponentSystem(GraphicsDevice graphicsDevice, Camera2D camera) + { + _camera = camera; + _spriteBatch = new SpriteBatch(graphicsDevice); + } + + private readonly Camera2D _camera; + private readonly SpriteBatch _spriteBatch; + + public override void Draw(GameTime gameTime) + { + var sprites = GetComponents(); + var emitters = GetComponents(); + + _spriteBatch.Begin(transformMatrix: _camera.GetViewMatrix()); + + foreach (var sprite in sprites) + _spriteBatch.Draw(sprite); + + foreach (var particleEmitter in emitters) + _spriteBatch.Draw(particleEmitter); + + _spriteBatch.End(); + } + } +} \ No newline at end of file diff --git a/Source/Demos/Demo.Platformer/Entities/Systems/UpdatableComponentSystem.cs b/Source/MonoGame.Extended/Entities/Systems/UpdatableComponentSystem.cs similarity index 79% rename from Source/Demos/Demo.Platformer/Entities/Systems/UpdatableComponentSystem.cs rename to Source/MonoGame.Extended/Entities/Systems/UpdatableComponentSystem.cs index d463e258..d0960315 100644 --- a/Source/Demos/Demo.Platformer/Entities/Systems/UpdatableComponentSystem.cs +++ b/Source/MonoGame.Extended/Entities/Systems/UpdatableComponentSystem.cs @@ -1,6 +1,6 @@ using Microsoft.Xna.Framework; -namespace Demo.Platformer.Entities.Systems +namespace MonoGame.Extended.Entities.Systems { public abstract class UpdatableComponentSystem : ComponentSystem { diff --git a/Source/MonoGame.Extended/MonoGame.Extended.csproj b/Source/MonoGame.Extended/MonoGame.Extended.csproj index 133914e4..b3b81555 100644 --- a/Source/MonoGame.Extended/MonoGame.Extended.csproj +++ b/Source/MonoGame.Extended/MonoGame.Extended.csproj @@ -38,6 +38,7 @@ + @@ -59,6 +60,15 @@ + + + + + + + + + @@ -225,7 +235,6 @@ - diff --git a/Source/MonoGame.Extended/Particles/ParticleEffect.cs b/Source/MonoGame.Extended/Particles/ParticleEffect.cs index 20522a3b..29427775 100644 --- a/Source/MonoGame.Extended/Particles/ParticleEffect.cs +++ b/Source/MonoGame.Extended/Particles/ParticleEffect.cs @@ -1,6 +1,5 @@ using System.Linq; using Microsoft.Xna.Framework; -using MonoGame.Extended.Particles.Profiles; namespace MonoGame.Extended.Particles { diff --git a/Source/MonoGame.Extended/Particles/ParticleEmitter.cs b/Source/MonoGame.Extended/Particles/ParticleEmitter.cs index 9e1f9a87..126a1bfe 100644 --- a/Source/MonoGame.Extended/Particles/ParticleEmitter.cs +++ b/Source/MonoGame.Extended/Particles/ParticleEmitter.cs @@ -1,22 +1,24 @@ using System; using Microsoft.Xna.Framework; +using MonoGame.Extended.Entities.Components; using MonoGame.Extended.Particles.Modifiers; using MonoGame.Extended.Particles.Profiles; using MonoGame.Extended.TextureAtlases; namespace MonoGame.Extended.Particles { - public unsafe class ParticleEmitter : IDisposable + public unsafe class ParticleEmitter : EntityComponent, IDisposable { - public ParticleEmitter(int capacity, TimeSpan term, Profile profile) + public ParticleEmitter(TextureRegion2D textureRegion, int capacity, TimeSpan term, Profile profile) { if (profile == null) throw new ArgumentNullException(nameof(profile)); _term = (float)term.TotalSeconds; + TextureRegion = textureRegion; Buffer = new ParticleBuffer(capacity); - Offset = new Vector2(); + Offset = Vector2.Zero; Profile = profile; Modifiers = new IModifier[0]; ModifierExecutionStrategy = ParticleModifierExecutionStrategy.Serial; @@ -79,6 +81,11 @@ namespace MonoGame.Extended.Particles ModifierExecutionStrategy.ExecuteModifiers(Modifiers, elapsedSeconds, iterator); } + public void Trigger() + { + Trigger(Position); + } + public void Trigger(Vector2 position) { var numToRelease = _random.Next(Parameters.Quantity); diff --git a/Source/MonoGame.Extended/Particles/SpriteBatchExtensions.cs b/Source/MonoGame.Extended/Particles/SpriteBatchExtensions.cs index 0cdf285f..21136a6d 100644 --- a/Source/MonoGame.Extended/Particles/SpriteBatchExtensions.cs +++ b/Source/MonoGame.Extended/Particles/SpriteBatchExtensions.cs @@ -9,10 +9,15 @@ namespace MonoGame.Extended.Particles public static void Draw(this SpriteBatch spriteBatch, ParticleEffect effect) { foreach (var emitter in effect.Emitters) - Draw(spriteBatch, emitter); + UnsafeDraw(spriteBatch, emitter); } - private static unsafe void Draw(SpriteBatch spriteBatch, ParticleEmitter emitter) + public static void Draw(this SpriteBatch spriteBatch, ParticleEmitter emitter) + { + UnsafeDraw(spriteBatch, emitter); + } + + private static unsafe void UnsafeDraw(SpriteBatch spriteBatch, ParticleEmitter emitter) { var textureRegion = emitter.TextureRegion; var origin = new Vector2(textureRegion.Width / 2f, textureRegion.Height / 2f); diff --git a/Source/MonoGame.Extended/Sprites/Sprite.cs b/Source/MonoGame.Extended/Sprites/Sprite.cs index ae1f2c78..3fc298e8 100644 --- a/Source/MonoGame.Extended/Sprites/Sprite.cs +++ b/Source/MonoGame.Extended/Sprites/Sprite.cs @@ -2,13 +2,14 @@ using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended.Entities.Components; using MonoGame.Extended.SceneGraphs; using MonoGame.Extended.Shapes; using MonoGame.Extended.TextureAtlases; namespace MonoGame.Extended.Sprites { - public class Sprite : IMovable, IRotatable, IScalable, IColorable, ISceneEntity, ISpriteBatchDrawable + public class Sprite : EntityComponent, IColorable, ISceneEntity, ISpriteBatchDrawable { public Sprite(TextureRegion2D textureRegion) { @@ -33,9 +34,6 @@ namespace MonoGame.Extended.Sprites public float Alpha { get; set; } public Color Color { get; set; } public bool IsVisible { get; set; } - public Vector2 Position { get; set; } - public Vector2 Scale { get; set; } - public float Rotation { get; set; } public Vector2 Origin { get; set; } public SpriteEffects Effect { get; set; } public float Depth { get; set; } diff --git a/Source/MonoGame.Extended/Sprites/SpriteAnimator.cs b/Source/MonoGame.Extended/Sprites/SpriteAnimator.cs deleted file mode 100644 index 1212d847..00000000 --- a/Source/MonoGame.Extended/Sprites/SpriteAnimator.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using Microsoft.Xna.Framework; -using MonoGame.Extended.TextureAtlases; - -namespace MonoGame.Extended.Sprites -{ - [Obsolete("Please use the SpriteSheetAnimator instead")] - public class SpriteAnimator : IUpdate - { - public SpriteAnimator(Sprite sprite, TextureAtlas textureAtlas, int framesPerSecond = 60) - { - IsLooping = true; - IsPlaying = true; - FramesPerSecond = framesPerSecond; - - _sprite = sprite; - _textureAtlas = textureAtlas; - _frameIndex = 0; - _nextFrameDelay = 0; - _sprite.TextureRegion = _textureAtlas[_frameIndex]; - } - - private readonly Sprite _sprite; - private readonly TextureAtlas _textureAtlas; - private float _nextFrameDelay; - - public bool IsLooping { get; set; } - - private int _frameIndex; - public int FrameIndex - { - get { return _frameIndex; } - set - { - if (value < 0) - throw new ArgumentOutOfRangeException(nameof(value), "FrameIndex has to be equal or higher than 0."); - - if (value >= _textureAtlas.RegionCount) - throw new ArgumentOutOfRangeException(nameof(value), "FrameIndex cannot be higher than the ammount of frames that the sprite contains."); - - _frameIndex = value; - _sprite.TextureRegion = _textureAtlas[_frameIndex]; - } - } - - private float _framesPerSecond; - public float FramesPerSecond - { - get { return _framesPerSecond; } - set - { - if (_framesPerSecond < 0) - throw new ArgumentOutOfRangeException(nameof(value), "FramesPerSecond has to be equal or higher than 0."); - - _framesPerSecond = value; - } - } - - public bool IsPlaying { get; set; } - - public void Update(GameTime gameTime) - { - if (IsPlaying && FramesPerSecond > 0) - { - var deltaSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds; - - if(_nextFrameDelay <= 0) - { - _nextFrameDelay = 1.0f / FramesPerSecond; - _frameIndex++; - - if (_frameIndex >= _textureAtlas.RegionCount) - { - if (IsLooping) - _frameIndex = 0; - else - IsPlaying = false; - } - - _sprite.TextureRegion = _textureAtlas[_frameIndex]; - } - - _nextFrameDelay -= deltaSeconds; - } - } - - public void Play() - { - IsPlaying = true; - } - - public void Pause() - { - IsPlaying = false; - } - - public void Stop() - { - IsPlaying = false; - _frameIndex = 0; - } - } -}