first project upload
BIN
images/ball.png
Normal file
After Width: | Height: | Size: 188 KiB |
BIN
images/cerbero.jpg
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
images/cerdo.png
Normal file
After Width: | Height: | Size: 9.0 KiB |
BIN
images/dream_forest_background.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
images/dream_forest_background2.png
Normal file
After Width: | Height: | Size: 680 KiB |
BIN
images/enemy1_anim.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
images/fairy_anim.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
images/fairy_anim2.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
images/game_over_screen.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
images/help.jpg
Normal file
After Width: | Height: | Size: 373 KiB |
BIN
images/interfaz.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
images/pearl_anim.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
images/punch.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
images/rayman_anim.png
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
images/rayman_anim_w_cols.png
Normal file
After Width: | Height: | Size: 134 KiB |
BIN
images/room.jpg
Normal file
After Width: | Height: | Size: 203 KiB |
BIN
images/shield_anim.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
images/test_sprite.png
Normal file
After Width: | Height: | Size: 206 KiB |
BIN
images/vaca.jpg
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
images/water_particle.png
Normal file
After Width: | Height: | Size: 583 B |
BIN
images/win_screen.png
Normal file
After Width: | Height: | Size: 129 KiB |
BIN
maps/dream_forest_background.png
Normal file
After Width: | Height: | Size: 69 KiB |
2010
maps/level1.json
Normal file
BIN
maps/level1.png
Normal file
After Width: | Height: | Size: 762 KiB |
154
maps/level1.tmx
Normal file
@ -0,0 +1,154 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.0" orientation="orthogonal" renderorder="right-down" width="256" height="64" tilewidth="16" tileheight="16" backgroundcolor="#bbfaff" nextobjectid="160">
|
||||
<tileset firstgid="1" name="RA_DreamForestTileset" tilewidth="16" tileheight="16" spacing="1" margin="1">
|
||||
<image source="../images/tilesets/RA_DreamForestTileset.png" trans="f800f8" width="1006" height="583"/>
|
||||
</tileset>
|
||||
<tileset firstgid="2007" name="RA_DreamForestTileset_3" tilewidth="16" tileheight="16">
|
||||
<image source="../images/tilesets/RA_DreamForestTileset_3.png" trans="709ad1" width="943" height="1023"/>
|
||||
</tileset>
|
||||
<layer name="Fondo" width="256" height="64">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJzt3Qe0VNWhBuChXHoTG1WjeYn0jh3pvUm3Ji8WkKp5SV5Uegepdo1YkK4xiUrvRaomdo0aC5ZoXpQq3ZJvHrjW9XoRZpgCl/2v9S3Gw71nzpyZfzjnzJ5tJBISEhISkq40KBCJNKQRjWlCU5rRnBa0LJDurQwJCUlGbg/dDgkJCQkJCQkJCTlpUqFgurcgJCQkXbku9D/kBE12161DYssU/X/40HvAo/58jKk8zjSmMyO8R4SE5MhEr//3ZwADGcRghjCUYQwP76shITkyc3V7HvNZwEIWsZglLGVZ6H9ISI7MFt3eyja2s4OdfMkudrMn9D8khyWMeTuY6PX/ilSiMlWoSjWqU4Oa4fw/5ARLL6/Z3j/yug3nvAcTvf5/PTdwI93pwU30LHjk/RgSkq5kvW79XY7munU45z2Y767/P1IwXP8POXkSznkPJlz/DzkZE855DyZc/w85GXOs57zxXj98t0gk8h7v8wGb+ZCP+JhP+Cef8hn/KpL4x5454fp/yMmYYz3njfeY+cyikUgpSlOGspSjfNHEP8ajSazX/3d7P9rDXvaxnwNJfo8KCTneEu8xcwc970gnOtOFrnRLU/9jvf5fw3bWpBa1qUPdNG17SEi6Eu8x8zhdGc8EJjKJyWnsT6zX/3vZ1t70oS/9uDn0P+QkS7zXD9fqyjrWs4GNbOJ5XsimRy8nuVuxzv8z3fbMYCazmM2c0P+QkyzxXj/8NtqVYpFILnKTh7xkkI/8FKAghShcLLmPY26M/X/P9r/PB2zmQz4K/Q85yRLv9cOL9PliLuFS6nEZ9WlAQxrRmCY0TXL/t8TY/1K2pzRlKEs5yid5G0NCckp+oyu/5Xf8L7/nVm7jdvozgIEMYnCSuxXr/D8dbU8nOtOFrnQL/Q8JOao8pSt/4s/8had5hmeZyzzms4CFLEpyt2Kd/2e87ZnARCYxmTtD/0NCjiqf6spn/Iv/4998zhdsYSvb2M4Odia5W1Oy9D+M/w9JdY63MXHJzDnFI5Fz+Sn/xc/4OedRgYpUojJVqFo8+/Ukap+F8f8h6c7xNiYumblan6/hWn7BL/lvfsV1XM8N3Eh3ehym/4naZ2H8f0i6c7yNiUtm7tXn+7ifB3iQP/AQU3iYR3iUx5h6mP4nap+F8f8h6c7xNiYumXlRn1/iZV7hVV7jdd7gTf7OW7zNO4fpf6L2WZj/JyTdScSYuFaFIpHWtKEt7WjP5XSgI50KJf+xHCkFS0QihShMEYpSjOKU4BRKciqncXqJ7NeTqHGEYf6fkHQnEWPiRuj2SEYxmjGM5Q7GMZ4Jx0H/G+tzE5rSjOa0oCWtaE0b2tKO9ofpf6LGEYb5f0LSnUSMiVuu2ytYySpWs4bnWMs61h8H/R+oz4MYzBCGMozhjGAkoxjNGMYepv+JGkcYrv+HpDuJGBO3V7f3sZ8DfMXXfMO30d4X9m9l4ZQ/tB9kgT4vZBGLWcJSlrGcFaxkFatZc5j+J2ocYbzX/1sfB++lITkjiRgTV0u3a1OHupzPBVzIRVzMJZn6f6LPY5GocYTh+n9IupOIMXF9dLsv/biZW/g1/8Nv+C2/y9T/E30ei0SNIwzX/0PSnUSMiZup27OYzRye4En+yFP8iT9n6n+s81i86tjgNV7nDd7k77zF27yT4mOHRI0jDNf/Q9KdRI2Ji+Zoj+tjnceiqL8rRnFKcAolOZXTOD3Fxw6J2mfh+n9IupOoMXHRHO1xfazzWDT3dy1oSSta04a2tKN9ivufyH0WEpLOJGpMXDRHe1wf6zwWQ61jGMMZwUhGMZoxjE1x/xO5z0JC0plEjYmL5miP62Odx2KJdSxlGctZwUpWsZo1Ke5/IvdZSEg6E8+YuMOd2x/tcX2s81jsso7d7GEv+9jPAb7i6xT3P1HjCKNpUCD8/5BD0pd4xsQd7tw+WfPTVbeOGtSkFrWpQ13O54IE3EcsSdQ4wmjCGMCQdCaeMXGHO7dP1vx0Pa2jF73pQ1/6cTO38OsU9z9R4wijCXMAhJwIOZpz+2TNTzfNOqYzg5nMYjZzeIInU9z/RCaeMYBH+q5lSEiik86559/V7/d4nw/YzId8xMd8cgL3P54xgEf6rmVISKKTzrnnzyzu/ilNGcpSjvKcxdkn8Odr8YwBPNJ3LUNCEp10zj3fQb870onOdKEr3biCK4ufuN8pimcM4JG+axkSkuikc+75cfo9nglMZBKTuZO7uLt47N8pOiO34wpKUZoyuVPzWBKRI33XMiQkJ2Wtfq9jPRvYyCae5wX+Wjz27xR10PeOdKIzXdLc/1jGABzpu5YhJ2fuyRuJ3Mt93M8DPJj34N89lDe925bsxPqdovH6PoGJTGJymvsfxgCEHEv+pt8v8hIv8wqv8hqv8wZv5uD3gFg+n1in6+vZwEY28TwvpPE9IIwBCIkn+TMikQIUpBCFKUJRilGcEpxCyYx0b23yEsvnE7nyRCK5yUNeMshHfgrkSe12f5cwD1BILGmgyw1pRGOa0JRmNKcFLWlFa9rQNgf3P9bPJ+rp+WXUpwEND/W+cZr6H+YBCokl/XV5AAMZxGCGMJRhDGcEIxnFaMbkgP5Xpko2y2P9fOJWPb+N2+nPAAYyiMEMYSjDUvR+EOYBCok3i/R6MUtYyjKWs4KVOaDzmdOdHtxEzzh+/2l9foZnmcs85rOAhSxiMUtYyrIU9T/MAxRyLNml57vZw172sZ8DOaz/U3mcaXH+/uf6/AVb2Mo2trODnXzJLnazh71pOh8ICYkntfJFIrWpQ9186d6axOQt3uYd/sG7x7Cu8/JGIhWoSCUqU4WqVKM6NahJLWrn4M9MQnJe+up8P27mliP0P/pxV/Sft+hLPHqYEP3x/EQvNUcPN78bThodRpviKTb+PyVzRSKnchqncwZnUorSlMn1/Z8/y3+fzU84h3Nz/XCd13mw13MDN9KdHtxET3rRmz70pd+h/qd6Xx3vz83JnuPt+ZlpA2Yxmzk8wZP8kaeyeR+4lHpcRn0a0JBGNKYJTWlGc1okYBsb6mOjbDqZNa39TBva0o72XE4HOtKJznShK90OrfNKf17F1VzDtT9yX4964h5jKo8zjenMYCazmM2cvKnfV6m4v794TTzNMzzLXOYxnwU55LgxWUlHd46UzZ6zD/mIj/mEf/Ipn2XzfP6eW7mN2+nPAAYyiMEMYSjDGM4IRjKK0YxhLHcwjvFMYGKW25MO3ecAfRzIIAYzhKEMy9TTkW6PYjRjGMsdjGM8E5jIJCZzJ3dxN/dwL/dxPw/wIH/gIaZkup+39fod/sG7vMf7fMDmLMf88eyrzPsm8+3s9tWkLMuT/dxE7+/fXhOf8wVb2Mo2trMj9P9Hk4rnJ5bfKevAoxzlOYuz+QnncC4/zf/D+3iGZ5nLPOazgIUsYjFLWMoylrOClaxiNWt4jrWsYz0b2Jjl9qbo+nVvAQtZxGKWsJRlLGcFK1nFatbwHGtZx3o2sJFNPM8L/JW/8SIv8TKv8Cqv8Tpv8GaW44EzHLidSSlKU4aylKM8Z3F2Rnz7KvO+yXw7u321KcvyZD830fv7udfEeVSgIpWoTBWqUo3q1KBmWPa9Zal4fmL5na62qRtXcCVXcTXXcC2/yP/D+/iCLWxlG9vZwU6+ZBe72cNe9rGfA3zF13zDt9Ei6VUucpOHvFluZ7CdHezkS3axmz3sZR/7OcBXfM03fBvtrJOtXOQmD3nJIB/5KUBBClGYIhSlGMUpwSmU5FTa6/TldKAjnehMF7rSjSu4kqsy4ttXmfdN5tvZ7auMLMuT/dxE7+9XXhPXcT03cCPd6cFN9KQXvekTln1vWSqen3h+J5blFahIJSpThapUozo1qEktalOHupzPBVzIRVzMJVxKPS6jfpbbDaLr17uqVKM6NahJLWpTh7qczwVcyEVczCVcSj0uoz4NaEgjGtOEpjSjOS1oSSta04a2tOMOnR7HeCYwkUlM5k7u4m7u4d6M+PZV5n2T+XZ2+6pBluXJfm6i9zfF6/hhHuFRHmMqjzON6cxgJrPCsu8tS8XzE8/vxLL8P6LQ/Y0=
|
||||
</data>
|
||||
</layer>
|
||||
<layer name="Fondo2" width="256" height="64">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJzt3GlQlHUAx/FHwQsFQVROu7VX5YFyqfXKm0NOtUOtNyoCguDxMk9ATu1Oa6YEjxSvepWmAoKg2Uxp2qFy2OXxLm+uvrxohgyqZXefZeH3nfnMOI31f5z4LbuyzxqGUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllLJHs90MYw4iEIkoRGMuYhDr5hxnKKUsbyPb24TNyEI2crAFucizwTbNOEMpZXnH2d4JnEQZylGBU6hElQ22acYZSinLu8/2HuAhGtGEZrSgtW2Xgzv+9+4OMYx7uI8HeIjGIbY9Qyll3yawvSBMxCQEIwShCEN4J9sc524Y4zEBQZiISe62PUMpZd+S2V4KUrECaUjHSmQgs5NtJrH15UhGClKxopP9d/UMpVT3rJitl2AXdmMP9nayf6VUz+oqW69FHerRgGvav1K9Il8Pw/CDPwIQiFEe5l7DlSE8DqEWdahHQyd/B6mUsl2xbD0O8UhAIuaZvH8fnm/4wg/+CECgnoMoZffy2Ho+ClCIImw1ef8xbD0WcYhHAhK1f+UEebkaxjB4uzrm/PM8T76A73ARl/A9fsCP+MkJnkfnsvU85KMAhSiy0f693Pj/A28MxwiMhA989X4lZWUR7D4SUYjGXMSY+Fjgzk48MBSe8MIweGM4RjjB99FKrrEKp1GNGpyx0XXrfgVlz7LYejZysAW5yEO+SY8BM9jJTMzCbMxBBCIRhWgn2H9r2zXymqMP+sIFrjZ6DaL7FZS9KmPj5ajAKVSiCqdRbdL+17Gd9diAjdiEzchCNnKcYP9t9RnI9uEC14G2++/qfoWe2Q32ddNBr7nbauTsJjSjBa1t19KPr2P0hQtc+9n/Oo6y72P4EsdxAidRhnJUOMn+J7P5KZiKF2y4f92v0PN6hl2NxhgT9tVZwZwdglCEIRyTMQVT8QJeNOH67rDvu7iH+3iAh2hEE5qdZP+r2PxqrMFaG+5f9yv0rBayqUVYjNfwugMeA9I4Mx0rkYFMrMJqrMFaE69pLK+Tx2E8JiAIEzEJwQgx+Wd5Xe0gmz+Ewzhiw/3rfoWe1fts6wNsxw58iI8c8BiwnzNLcQAHcQiHcQSfmXg9y9h3EpYjGSlIxQqkId1J9n+dzd/ATdyy4f5Vz+k8u7qA73ARl/A9fnDg64DrnH0DN3HLAdexk30XowS7sBt7sBefYp+T7P/pQbyuw2iMGeToq1HdIbf+hjEYQ+AODwyFJ7wwDN4YjhH9HXONz3DuaIzBsw64hivs+ypqUYd6NOAafsYvTrL/V9n8QizCYu2/w5a4GMZSLEOSi6Ovxv5NY0/TMQMzMQuzMQcRiEQUotvtLpZfxyEeCSbu8TUrz+roHpj/k89Qw/CFH/wRgECMwmN4fKh112VW77L59/A+PtD+/9HH7P0T7EQxSnrB/v9qPdvagI3YhM3IQjZysKXd9vL5dQEKUWTS/rdzzg58aMV5Xb0HJoZ9xyIO8UhAIuZhPhY8sv8/BhjGbdzBXdzDfTzAQzSiCc1oQSsMC16PW/J5Yu37hs1/i/O4oP3/o8vs/QquohZ1qEdDL3gc+JJdHccJnEQZylGBU6hEFU6jGjUmPw+/yHmXrDyzq/fA5LLvPOSjAIUowlZsw5uP7P85tvw8xmIcxmMCgjARkxCMEIQiDOEW7N+SzxNr32A3XufBHR42fF/Ofv78pZ08B/qMf/65kzw/8nHl+wP84I8ABGKUA98D44ga2VkTmtGC1rbd8T2qD/rCBa4DzL0mL84bBm8rzu3qPTCVfP1W4TSqUYMzOIuvcO6Rr+8lbHkpliEJy5GMFKRiBdKQjpXIQKYF+7fk88TaN43NT8cMzLTh/n/lz/+bk2z834pl53GIRwISMQ/ze9n+g9lYCEIRhnBMxhRMNXn3fxXBuZGIsuL8ju6B+T+1tn1te/L4h75wgSv6oT8GeP7993/Mlj/BThSjBLuwG3uwF59iH/ajFAcs2L81nyf2Brtfh/U23P8Tnv/9ezqqrB/PMVHhwJ8tPVoBWy9EEbZiWy/bfhr7SsdKZCATq7Aaaxy0/bayODsbOVZcQ0f3wNijn9jyZVzBVdSiDvVowDX8jF/wK37D7xbs35rPE/uC3R/FsW7wvvwmdt+Mlm60/xr2fgZn8RXO4ete9Biwj33tRykO4CAO4TCOOGj/ZZxbjgqcQmUXryOMvYdjMqZgqp32P2KQYYyED3zhB38EIBCj8BgexxN4Ek9Z8Pdx1nye2G12fwd3u8H+Q3hdGYowB/1cWfWuMthIJlZhNdbYaf/RbHkuYhCLOMQjAYmYh/lYgJfwMl6xYP/WfJ7Y84MNYyzG6X25qpdVykYO4CAO4bCd9p/DlrcgF3nIRwEKUYSt2IY38RbexjsW7N+azxNbyu6XIakH7f9POCvieg==
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup color="#000000" name="Platforms">
|
||||
<object id="3" x="2" y="987" width="443" height="13"/>
|
||||
<object id="4" x="483" y="979" width="42" height="16"/>
|
||||
<object id="5" x="529" y="985" width="75" height="13"/>
|
||||
<object id="7" x="606" y="978" width="33" height="14"/>
|
||||
<object id="8" x="630" y="970" width="39" height="12"/>
|
||||
<object id="9" x="647" y="960" width="37" height="13"/>
|
||||
<object id="10" x="662" y="950" width="43" height="12"/>
|
||||
<object id="11" x="683" y="941" width="83" height="14"/>
|
||||
<object id="12" x="757" y="949" width="27" height="18"/>
|
||||
<object id="13" x="775" y="956" width="32" height="17"/>
|
||||
<object id="14" x="801" y="965" width="24" height="20"/>
|
||||
<object id="15" x="813" y="977" width="40" height="15"/>
|
||||
<object id="16" x="848" y="983" width="125" height="14"/>
|
||||
<object id="17" x="881" y="944" width="35" height="13"/>
|
||||
<object id="18" x="997" y="915" width="195" height="13"/>
|
||||
<object id="19" x="1014" y="903" width="165" height="12"/>
|
||||
<object id="20" x="1030" y="893" width="119" height="13"/>
|
||||
<object id="21" x="843" y="836" width="71" height="12"/>
|
||||
<object id="22" x="704" y="753" width="61" height="13"/>
|
||||
<object id="23" x="702" y="674" width="121" height="12"/>
|
||||
<object id="24" x="715" y="617" width="80" height="14"/>
|
||||
<object id="25" x="199" y="737" width="80" height="13"/>
|
||||
<object id="26" x="342" y="675" width="82" height="9"/>
|
||||
<object id="27" x="505" y="623" width="77" height="17"/>
|
||||
<object id="28" x="323" y="528" width="116" height="14"/>
|
||||
<object id="30" x="191.333" y="611.333" width="43.3333" height="12.6667"/>
|
||||
<object id="31" x="165.333" y="615.333" width="28" height="10"/>
|
||||
<object id="32" x="48.6667" y="606" width="60" height="14"/>
|
||||
<object id="33" x="96" y="598" width="36" height="13.3333"/>
|
||||
<object id="34" x="124" y="605.333" width="32.6667" height="10.6667"/>
|
||||
<object id="35" x="147.333" y="610" width="21.3333" height="12.6667"/>
|
||||
<object id="36" x="82" y="601.333" width="22.6667" height="11.3333"/>
|
||||
<object id="37" x="48.6667" y="460" width="65.3333" height="12.6667"/>
|
||||
<object id="39" x="496.667" y="228" width="121.333" height="13.3333"/>
|
||||
<object id="40" x="753" y="307" width="121" height="15"/>
|
||||
<object id="41" x="992" y="295" width="68" height="14"/>
|
||||
<object id="42" x="992" y="443" width="50" height="16"/>
|
||||
<object id="43" x="1138" y="446" width="39" height="13"/>
|
||||
<object id="44" x="1109" y="454" width="34" height="12"/>
|
||||
<object id="45" x="1033" y="436" width="46" height="14"/>
|
||||
<object id="46" x="1074" y="444" width="27" height="10"/>
|
||||
<object id="47" x="1095" y="450" width="21" height="14"/>
|
||||
<object id="48" x="1281" y="459" width="64" height="12"/>
|
||||
<object id="49" x="1280" y="606" width="52" height="13"/>
|
||||
<object id="50" x="1313" y="595" width="32" height="17"/>
|
||||
<object id="51" x="1340" y="597" width="33" height="15"/>
|
||||
<object id="52" x="1365" y="604" width="37" height="15"/>
|
||||
<object id="53" x="1397" y="614" width="35" height="15"/>
|
||||
<object id="54" x="1424" y="604" width="42" height="16"/>
|
||||
<object id="56" x="1570" y="262" width="122" height="10"/>
|
||||
<object id="60" x="1569" y="450" width="124" height="14"/>
|
||||
<object id="62" x="1567" y="550" width="124" height="12"/>
|
||||
<object id="64" x="1585" y="707" width="122" height="17"/>
|
||||
<object id="65" x="1777" y="746" width="121" height="14"/>
|
||||
<object id="66" x="1601" y="836" width="121" height="12"/>
|
||||
<object id="67" x="1265" y="881" width="47" height="11"/>
|
||||
<object id="68" x="1486" y="895" width="46" height="15"/>
|
||||
<object id="70" x="1349" y="873" width="90" height="13"/>
|
||||
<object id="71" x="1199" y="991" width="847" height="17"/>
|
||||
<object id="88" x="1573" y="163" width="113" height="15"/>
|
||||
<object id="92" x="486" y="985" width="190" height="9"/>
|
||||
<object id="93" x="784" y="978" width="62" height="20"/>
|
||||
<object id="94" x="663" y="970" width="148" height="18"/>
|
||||
<object id="109" x="3314.67" y="995.333" width="776.667" height="16"/>
|
||||
<object id="122" x="2224" y="922" width="67" height="14"/>
|
||||
<object id="123" x="2448" y="896" width="64" height="16"/>
|
||||
<object id="124" x="2445" y="813" width="120" height="16"/>
|
||||
<object id="125" x="2458" y="760" width="83" height="16"/>
|
||||
<object id="126" x="2481" y="590" width="119" height="17"/>
|
||||
<object id="127" x="2695" y="674" width="81" height="21"/>
|
||||
<object id="128" x="2704" y="967" width="78" height="16"/>
|
||||
<object id="129" x="2727" y="960" width="57" height="13"/>
|
||||
<object id="130" x="2743" y="952" width="43" height="13"/>
|
||||
<object id="131" x="2635" y="1003" width="42" height="17"/>
|
||||
<object id="132" x="2051" y="994" width="83" height="17"/>
|
||||
<object id="134" x="2050" y="981" width="69" height="15"/>
|
||||
<object id="135" x="2062" y="974" width="42" height="10"/>
|
||||
<object id="136" x="3015" y="979" width="79" height="14"/>
|
||||
<object id="138" x="3231" y="714" width="67" height="15"/>
|
||||
<object id="139" x="2881" y="588" width="122" height="16"/>
|
||||
<object id="140" x="3586" y="780" width="121" height="20"/>
|
||||
<object id="141" x="3858" y="843" width="52" height="19"/>
|
||||
<object id="142" x="3899" y="824" width="49" height="19"/>
|
||||
<object id="143" x="3940" y="811" width="110" height="21"/>
|
||||
<object id="157" x="1751" y="353" width="80" height="12"/>
|
||||
</objectgroup>
|
||||
<objectgroup color="#37ff00" name="Player">
|
||||
<object id="72" x="178" y="867" width="74" height="72"/>
|
||||
</objectgroup>
|
||||
<objectgroup color="#002eff" name="PickableObjects">
|
||||
<object id="75" name="PEARL" x="843" y="751" width="74" height="72"/>
|
||||
<object id="77" name="ETERNAL_FLY" x="1592" y="185" width="74" height="72"/>
|
||||
<object id="78" name="SHIELD" x="1283" y="355" width="74" height="72"/>
|
||||
<object id="79" name="PUNCH_SPEED" x="779" y="208" width="74" height="72"/>
|
||||
<object id="95" name="PEARL" x="341" y="435" width="74" height="72"/>
|
||||
<object id="96" name="PEARL" x="46" y="361" width="74" height="72"/>
|
||||
<object id="97" name="PEARL" x="524" y="890" width="74" height="72"/>
|
||||
<object id="98" name="PEARL" x="1060" y="800" width="74" height="72"/>
|
||||
<object id="99" name="PEARL" x="1610" y="624" width="74" height="72"/>
|
||||
<object id="100" name="PEARL" x="1358" y="779" width="74" height="72"/>
|
||||
<object id="102" name="PEARL" x="1608" y="371" width="74" height="72"/>
|
||||
<object id="103" name="PEARL" x="1075" y="351" width="74" height="72"/>
|
||||
<object id="104" name="PEARL" x="53" y="899" width="74" height="72"/>
|
||||
<object id="111" name="PEARL" x="2219" y="833.333" width="74" height="72"/>
|
||||
<object id="112" name="PEARL" x="2460.33" y="674.667" width="74" height="72"/>
|
||||
<object id="113" name="PEARL" x="2504.33" y="500" width="74" height="72"/>
|
||||
<object id="114" name="PEARL" x="2709.67" y="861.333" width="74" height="72"/>
|
||||
<object id="115" name="PEARL" x="3020.33" y="889.333" width="74" height="72"/>
|
||||
<object id="116" name="PEARL" x="3224.33" y="624" width="74" height="72"/>
|
||||
<object id="117" name="PEARL" x="2908.33" y="502.667" width="74" height="72"/>
|
||||
<object id="118" name="PEARL" x="3929.67" y="713.333" width="74" height="72"/>
|
||||
<object id="119" name="PEARL" x="4007" y="908" width="74" height="72"/>
|
||||
<object id="120" name="PEARL" x="3549.67" y="912" width="74" height="72"/>
|
||||
<object id="121" name="PEARL" x="3611" y="689.333" width="74" height="72"/>
|
||||
<object id="155" name="SHIELD" x="2699" y="576" width="74" height="72"/>
|
||||
<object id="156" name="SHIELD" x="3813.67" y="756" width="74" height="72"/>
|
||||
</objectgroup>
|
||||
<objectgroup color="#ff4000" name="Enemys">
|
||||
<object id="82" x="1603" y="898" width="74" height="72"/>
|
||||
<object id="83" x="1383" y="485" width="74" height="72"/>
|
||||
<object id="84" x="520" y="142" width="74" height="72"/>
|
||||
<object id="86" x="688" y="847" width="74" height="72"/>
|
||||
<object id="87" x="720" y="521" width="74" height="72"/>
|
||||
<object id="147" x="2698" y="568" width="74" height="72"/>
|
||||
<object id="148" x="2451" y="809" width="74" height="72"/>
|
||||
<object id="149" x="3369" y="905" width="74" height="72"/>
|
||||
<object id="150" x="3942" y="903" width="74" height="72"/>
|
||||
<object id="151" x="3634" y="663" width="74" height="72"/>
|
||||
<object id="152" x="3732.33" y="913" width="74" height="72"/>
|
||||
<object id="153" x="3957" y="721" width="74" height="72"/>
|
||||
</objectgroup>
|
||||
<objectgroup color="#ffff00" name="Win">
|
||||
<object id="159" x="3813.67" y="941.667" width="37.6667" height="51.3333"/>
|
||||
</objectgroup>
|
||||
</map>
|
BIN
sounds/Rayman/enemy_hitted.wav
Normal file
BIN
sounds/Rayman/flying.wav
Normal file
BIN
sounds/Rayman/game_over.mp3
Normal file
BIN
sounds/Rayman/ground_hit.wav
Normal file
BIN
sounds/Rayman/idle.wav
Normal file
BIN
sounds/Rayman/pearl_picked.wav
Normal file
BIN
sounds/Rayman/power_picked.wav
Normal file
BIN
sounds/Rayman/punch_thrown.wav
Normal file
BIN
sounds/Rayman/rayman_hitted.wav
Normal file
BIN
sounds/Rayman/shield_picked.wav
Normal file
BIN
sounds/Rayman/song.mp3
Normal file
BIN
sounds/Rayman/win_level.wav
Normal file
BIN
sounds/test_song.mp3
Normal file
BIN
sounds/test_sound1.wav
Normal file
BIN
sounds/test_sound2.WAV
Normal file
BIN
sounds/test_sound3.WAV
Normal file
50
src/HTML/Demo_Balls.html
Normal file
@ -0,0 +1,50 @@
|
||||
<!doctype html>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<title>Ball physics simulation</title>
|
||||
|
||||
<!-- The canvas -->
|
||||
<canvas width="800" height="600" style="border:3px solid #000; margin:5px auto;">
|
||||
No canvas supported
|
||||
</canvas>
|
||||
|
||||
<form style="position:absolute; top:16px; left:832px;">
|
||||
<input type="button" id="generate" value="Generate ball">
|
||||
<br>
|
||||
<input type="checkbox" name="gravity" id="gravity" value="ON">Gravedad
|
||||
<br>
|
||||
<input type="radio" name="gravityDir" id="gravityDir" value="0" checked disabled>Down
|
||||
<br>
|
||||
<input type="radio" name="gravityDir" id="gravityDir" value="1" disabled>Up
|
||||
<br>
|
||||
<input type="radio" name="gravityDir" id="gravityDir" value="2" disabled>Left
|
||||
<br>
|
||||
<input type="radio" name="gravityDir" id="gravityDir" value="3" disabled>Right
|
||||
<br>
|
||||
<input type="button" id="reset" value="Remove all balls">
|
||||
</form>
|
||||
|
||||
<!-- The game code -->
|
||||
<script src="../JS/XgameJS/requestAnimationFramePolyfill.js"></script>
|
||||
<script src="../JS/XgameJS/Sprite.js"></script>
|
||||
<script src="../JS/XgameJS/AnimatedSprite.js"></script>
|
||||
<script src="../JS/XgameJS/Ball.js"></script>
|
||||
<script src="../JS/XgameJS/Circle.js"></script>
|
||||
<script src="../JS/XgameJS/GameStates.js"></script>
|
||||
<script src="../JS/XgameJS/GravityDirections.js"></script>
|
||||
<script src="../JS/Demo_Balls.js"></script>
|
||||
<!-- XNA -->
|
||||
<script src="../JS/XNA_Classes/ContentManager.js"></script>
|
||||
<script src="../JS/XNA_Classes/GraphicsDevice.js"></script>
|
||||
<script src="../JS/XNA_Classes/Keyboard.js"></script>
|
||||
<script src="../JS/XNA_Classes/Keys.js"></script>
|
||||
<script src="../JS/XNA_Classes/Mouse.js"></script>
|
||||
<script src="../JS/XNA_Classes/Point.js"></script>
|
||||
<script src="../JS/XNA_Classes/Program.js"></script>
|
||||
<script src="../JS/XNA_Classes/Rectangle.js"></script>
|
||||
<script src="../JS/XNA_Classes/Song.js"></script>
|
||||
<script src="../JS/XNA_Classes/SoundEffect.js"></script>
|
||||
<script src="../JS/XNA_Classes/SpriteBatch.js"></script>
|
||||
<script src="../JS/XNA_Classes/SpriteEffects.js"></script>
|
||||
<script src="../JS/XNA_Classes/Texture2D.js"></script>
|
||||
<script src="../JS/XNA_Classes/Vector2.js"></script>
|
44
src/HTML/Rayman.html
Normal file
@ -0,0 +1,44 @@
|
||||
<!doctype html>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<title>Rayman Demo XgameJS</title>
|
||||
|
||||
<!-- The canvas -->
|
||||
<canvas width="800" height="600" style="border:3px solid #000; margin:4px auto;">
|
||||
No canvas supported on this browser :(
|
||||
</canvas>
|
||||
|
||||
<!-- The game code -->
|
||||
<script src="../JS/XgameJS/requestAnimationFramePolyfill.js"></script>
|
||||
<script src="../JS/XgameJS/Sprite.js"></script>
|
||||
<script src="../JS/XgameJS/AnimationTypes.js"></script>
|
||||
<script src="../JS/Rayman_Classes/Ball.js"></script>
|
||||
<script src="../JS/XgameJS/Camera.js"></script>
|
||||
<script src="../JS/XgameJS/Circle.js"></script>
|
||||
<script src="../JS/Rayman_Classes/Enemy.js"></script>
|
||||
<script src="../JS/Rayman_Classes/Enums.js"></script>
|
||||
<script src="../JS/XgameJS/GameStates.js"></script>
|
||||
<script src="../JS/XgameJS/GravityDirections.js"></script>
|
||||
<script src="../JS/Rayman_Classes/Level.js"></script>
|
||||
<script src="../JS/XgameJS/PickableObject.js"></script>
|
||||
<script src="../JS/Rayman_Classes/Player.js"></script>
|
||||
<script src="../JS/XgameJS/Polygon.js"></script>
|
||||
<script src="../JS/Rayman_Classes/Projectile.js"></script>
|
||||
<script src="../JS/XgameJS/Segment.js"></script>
|
||||
<script src="../JS/XgameJS/AnimatedSprite.js"></script>
|
||||
<script src="../JS/Rayman.js"></script>
|
||||
<!-- XNA -->
|
||||
<script src="../JS/XNA_Classes/ContentManager.js"></script>
|
||||
<script src="../JS/XNA_Classes/GraphicsDevice.js"></script>
|
||||
<script src="../JS/XNA_Classes/Keyboard.js"></script>
|
||||
<script src="../JS/XNA_Classes/Keys.js"></script>
|
||||
<script src="../JS/XNA_Classes/Mouse.js"></script>
|
||||
<script src="../JS/XNA_Classes/Point.js"></script>
|
||||
<script src="../JS/XNA_Classes/Program.js"></script>
|
||||
<script src="../JS/XNA_Classes/Rectangle.js"></script>
|
||||
<script src="../JS/XNA_Classes/Song.js"></script>
|
||||
<script src="../JS/XNA_Classes/SoundEffect.js"></script>
|
||||
<script src="../JS/XNA_Classes/SpriteBatch.js"></script>
|
||||
<script src="../JS/XNA_Classes/SpriteEffects.js"></script>
|
||||
<script src="../JS/XNA_Classes/Texture2D.js"></script>
|
||||
<script src="../JS/XNA_Classes/Vector2.js"></script>
|
32
src/HTML/Test_GraphicsDevice_AnimatedSprite.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!doctype html>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<title>Test for GraphicsDevice and AnimatedSprite</title>
|
||||
|
||||
<!-- The canvas -->
|
||||
<canvas width="800" height="600" style="border:3px solid #000; margin:5px auto;">
|
||||
No canvas supported
|
||||
</canvas>
|
||||
|
||||
<!-- XgameJS -->
|
||||
<script src="../JS/XgameJS/GameStates.js"></script>
|
||||
<script src="../JS/XgameJS/Segment.js"></script>
|
||||
<script src="../JS/XgameJS/Sprite.js"></script>
|
||||
<script src="../JS/XgameJS/AnimatedSprite.js"></script>
|
||||
<script src="../JS/XgameJS/AnimationTypes.js"></script>
|
||||
<!-- XNA_Classes -->
|
||||
<script src="../JS/XgameJS/requestAnimationFramePolyfill.js"></script>
|
||||
<script src="../JS/XNA_Classes/GraphicsDevice.js"></script>
|
||||
<script src="../JS/XNA_Classes/ContentManager.js"></script>
|
||||
<script src="../JS/XNA_Classes/SpriteBatch.js"></script>
|
||||
<script src="../JS/XNA_Classes/SpriteEffects.js"></script>
|
||||
<script src="../JS/XNA_Classes/Mouse.js"></script>
|
||||
<script src="../JS/XNA_Classes/Keyboard.js"></script>
|
||||
<script src="../JS/XNA_Classes/Keys.js"></script>
|
||||
<script src="../JS/XNA_Classes/Point.js"></script>
|
||||
<script src="../JS/XNA_Classes/Vector2.js"></script>
|
||||
<script src="../JS/XNA_Classes/Rectangle.js"></script>
|
||||
<script src="../JS/XNA_Classes/Texture2D.js"></script>
|
||||
<script src="../JS/XNA_Classes/SpriteEffects.js"></script>
|
||||
<script src="../JS/Unit_Testing/Test_GraphicsDevice_AnimatedSprite.js"></script>
|
||||
<script src="../JS/XNA_Classes/Program.js"></script>
|
23
src/HTML/Test_Mouse_Keyboard.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!doctype html>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<title>Test Mouse and Keyboard</title>
|
||||
|
||||
<!-- The canvas -->
|
||||
<canvas width="800" height="600" style="border:3px solid #000; margin:5px auto;">
|
||||
No canvas supported
|
||||
</canvas>
|
||||
|
||||
<!-- XNA_Classes -->
|
||||
<script src="../JS/XgameJS/requestAnimationFramePolyfill.js"></script>
|
||||
<script src="../JS/XNA_Classes/GraphicsDevice.js"></script>
|
||||
<script src="../JS/XNA_Classes/ContentManager.js"></script>
|
||||
<script src="../JS/XgameJS/GameStates.js"></script>
|
||||
<script src="../JS/XNA_Classes/SpriteBatch.js"></script>
|
||||
<script src="../JS/XNA_Classes/Mouse.js"></script>
|
||||
<script src="../JS/XNA_Classes/Keyboard.js"></script>
|
||||
<script src="../JS/XNA_Classes/Keys.js"></script>
|
||||
<script src="../JS/XNA_Classes/Point.js"></script>
|
||||
<script src="../JS/XNA_Classes/Vector2.js"></script>
|
||||
<script src="../JS/Unit_Testing/Test_Mouse_Keyboard.js"></script>
|
||||
<script src="../JS/XNA_Classes/Program.js"></script>
|
25
src/HTML/Test_Point_Vector2_Rectangle.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!doctype html>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<title>Test for Point, Vector2 and Rectangle classes</title>
|
||||
|
||||
<!-- The canvas -->
|
||||
<canvas width="800" height="600" style="border:3px solid #000; margin:5px auto;">
|
||||
No canvas supported
|
||||
</canvas>
|
||||
|
||||
<!-- XNA_Classes -->
|
||||
<script src="../JS/XgameJS/requestAnimationFramePolyfill.js"></script>
|
||||
<script src="../JS/XNA_Classes/GraphicsDevice.js"></script>
|
||||
<script src="../JS/XNA_Classes/ContentManager.js"></script>
|
||||
<script src="../JS/XgameJS/GameStates.js"></script>
|
||||
<script src="../JS/XgameJS/Segment.js"></script>
|
||||
<script src="../JS/XNA_Classes/SpriteBatch.js"></script>
|
||||
<script src="../JS/XNA_Classes/Mouse.js"></script>
|
||||
<script src="../JS/XNA_Classes/Keyboard.js"></script>
|
||||
<script src="../JS/XNA_Classes/Keys.js"></script>
|
||||
<script src="../JS/XNA_Classes/Point.js"></script>
|
||||
<script src="../JS/XNA_Classes/Vector2.js"></script>
|
||||
<script src="../JS/XNA_Classes/Rectangle.js"></script>
|
||||
<script src="../JS/Unit_Testing/Test_Point_Vector2_Rectangle.js"></script>
|
||||
<script src="../JS/XNA_Classes/Program.js"></script>
|
30
src/HTML/Test_Song_SoundEffect.html
Normal file
@ -0,0 +1,30 @@
|
||||
<!doctype html>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<title>Test for Song and SoundEffect</title>
|
||||
|
||||
<!-- The canvas -->
|
||||
<canvas width="800" height="600" style="border:3px solid #000; margin:5px auto;">
|
||||
No canvas supported
|
||||
</canvas>
|
||||
|
||||
<!-- XNA_Classes -->
|
||||
<script src="../JS/XgameJS/requestAnimationFramePolyfill.js"></script>
|
||||
<script src="../JS/XNA_Classes/GraphicsDevice.js"></script>
|
||||
<script src="../JS/XNA_Classes/ContentManager.js"></script>
|
||||
<script src="../JS/XgameJS/GameStates.js"></script>
|
||||
<script src="../JS/XNA_Classes/SpriteBatch.js"></script>
|
||||
<script src="../JS/XNA_Classes/Mouse.js"></script>
|
||||
<script src="../JS/XNA_Classes/Keyboard.js"></script>
|
||||
<script src="../JS/XNA_Classes/Keys.js"></script>
|
||||
<script src="../JS/XNA_Classes/Point.js"></script>
|
||||
<script src="../JS/XNA_Classes/Vector2.js"></script>
|
||||
<script src="../JS/XNA_Classes/Rectangle.js"></script>
|
||||
<script src="../JS/XNA_Classes/Song.js"></script>
|
||||
<script src="../JS/XNA_Classes/SoundEffect.js"></script>
|
||||
<script src="../JS/XNA_Classes/Texture2D.js"></script>
|
||||
<script src="../JS/XNA_Classes/SpriteEffects.js"></script>
|
||||
<script src="../JS/XgameJS/Segment.js"></script>
|
||||
<script src="../JS/XgameJS/Sprite.js"></script>
|
||||
<script src="../JS/Unit_Testing/Test_Song_SoundEffect.js"></script>
|
||||
<script src="../JS/XNA_Classes/Program.js"></script>
|
248
src/JS/Demo_Balls.js
Normal file
@ -0,0 +1,248 @@
|
||||
/**
|
||||
* Provides basic graphics device initialization, game logic, and rendering code.
|
||||
*/
|
||||
function Game() {
|
||||
"use strict";
|
||||
/*globals ContentManager, GraphicsDevice, document, SpriteBatch, GameStates, GravityDirections*/
|
||||
this.Content = new ContentManager();
|
||||
this.GraphicsDevice = new GraphicsDevice(document);
|
||||
this.spriteBatch = null;
|
||||
this.gameState = GameStates.Initializing;
|
||||
|
||||
//The HTML elements
|
||||
this.generateButton = document.querySelector("#generate");
|
||||
this.gravityCheckBox = document.querySelector("#gravity");
|
||||
this.gravityDirRadioButtons = document.querySelectorAll("#gravityDir");
|
||||
this.removeAllBallsButton = document.querySelector("#reset");
|
||||
|
||||
//The ball image
|
||||
this.ballTexture = null;
|
||||
|
||||
//The room image
|
||||
this.roomImage = null;
|
||||
|
||||
//The balls array
|
||||
this.balls = [];
|
||||
|
||||
//The room Sprite
|
||||
this.roomSprite = null;
|
||||
|
||||
//Gravity properties
|
||||
this.gravityActivated = false;
|
||||
this.gravityDir = GravityDirections.G_DOWN;
|
||||
this.gravityForce = 0.4;
|
||||
|
||||
//Other
|
||||
this.preloading = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the game to perform any initialization it needs to before starting to run.
|
||||
* This is where it can query for any required services and load any non-graphic
|
||||
* related content.
|
||||
* @name Initialize
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Initialize = function () {
|
||||
"use strict";
|
||||
/*globals GenerateBall*/
|
||||
var self = this,
|
||||
len,
|
||||
i;
|
||||
|
||||
//Add the event listener to the generate ball button
|
||||
self.generateButton.addEventListener("mousedown", self.GenerateBall.bind(self), false);
|
||||
|
||||
//Remove all the balls in the room if this button is pressed
|
||||
self.removeAllBallsButton.addEventListener("mousedown", function (event) {
|
||||
self.balls.splice(0, self.balls.length);
|
||||
}, false);
|
||||
|
||||
//Enable or disable the radiobuttons depending on the gravity checkbox
|
||||
self.gravityCheckBox.addEventListener("mousedown", function (event) {
|
||||
|
||||
if (self.gravityCheckBox.checked) {
|
||||
self.gravityActivated = false;
|
||||
for (i = 0, len = self.gravityDirRadioButtons.length; i < len; i += 1) {
|
||||
self.gravityDirRadioButtons[i].disabled = true;
|
||||
}
|
||||
} else {
|
||||
self.gravityActivated = true;
|
||||
for (i = 0, len = self.gravityDirRadioButtons.length; i < len; i += 1) {
|
||||
self.gravityDirRadioButtons[i].disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
}, false);
|
||||
|
||||
//Depending on which radiobutton is checked the gravity direction changes
|
||||
for (i = 0, len = self.gravityDirRadioButtons.length; i < len; i += 1) {
|
||||
|
||||
self.gravityDirRadioButtons[i].addEventListener("mousedown", function (event) {
|
||||
self.gravityDir = parseInt(this.value, 10);
|
||||
}, false);
|
||||
}
|
||||
|
||||
self.gameState = GameStates.Loading;
|
||||
};
|
||||
|
||||
/**
|
||||
* LoadContent will be called once per game and is the place to load
|
||||
* all of your content.
|
||||
* @name LoadContent
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.LoadContent = function () {
|
||||
"use strict";
|
||||
/*globals Sprite, Rectangle, Point, Vector2*/
|
||||
var self = this;
|
||||
|
||||
if (self.preloading) {
|
||||
// Create a new SpriteBatch, which can be used to draw textures.
|
||||
self.spriteBatch = new SpriteBatch(self.GraphicsDevice);
|
||||
|
||||
// TODO: use this.Content.Load... to load your game content here
|
||||
self.ballTexture = self.Content.LoadTexture2D("../../images/ball.png");
|
||||
self.roomImage = self.Content.LoadTexture2D("../../images/room.jpg");
|
||||
self.preloading = false;
|
||||
}
|
||||
|
||||
if (self.Content.AllContentLoaded()) {
|
||||
//Create the room sprite and add it to the sprites list
|
||||
self.roomSprite = new Sprite(self.roomImage, Vector2.One(),
|
||||
new Rectangle(0, 0, self.roomImage.Width(), self.roomImage.Height()),
|
||||
Point.Zero(), true
|
||||
);
|
||||
|
||||
self.gameState = GameStates.Playing;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Allows the game to run logic such as updating the world,
|
||||
* checking for collisions, gathering input, and playing audio.
|
||||
* @name Update
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Update = function () {
|
||||
"use strict";
|
||||
var self = this,
|
||||
len = self.balls.length,
|
||||
i;
|
||||
|
||||
// TODO: Add your update logic here
|
||||
if (len > 0) {
|
||||
for (i = 0; i < len; i += 1) {
|
||||
self.balls[i].Update(
|
||||
self.GraphicsDevice.PreferredBackBufferWidth(),
|
||||
self.GraphicsDevice.PreferredBackBufferHeight(),
|
||||
self.balls,
|
||||
self.gravityActivated,
|
||||
self.gravityDir,
|
||||
self.gravityForce
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is called when the game should draw itself.
|
||||
* @name Draw
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Draw = function () {
|
||||
"use strict";
|
||||
/*globals Vector2, SpriteEffects*/
|
||||
var self = this,
|
||||
len = self.balls.length,
|
||||
i,
|
||||
auxSprite = null;
|
||||
|
||||
self.GraphicsDevice.Clear();
|
||||
|
||||
//Draw the room
|
||||
self.spriteBatch.Draw(self.roomSprite.Texture,
|
||||
Vector2.Zero(),
|
||||
new Rectangle(0, 0, self.roomSprite.Width(), self.roomSprite.Height()), 0, self.roomSprite.Scale, SpriteEffects.None);
|
||||
|
||||
//Draw the balls
|
||||
if (len > 0) {
|
||||
for (i = 0; i < len; i += 1) {
|
||||
auxSprite = self.balls[i].Sprite;
|
||||
//console.log(self.balls[i].Sprite.Scale);console.log(auxSprite.Position.Y);
|
||||
if (auxSprite.IsVisible) {
|
||||
self.spriteBatch.Draw(
|
||||
auxSprite.Texture,
|
||||
auxSprite.Position,
|
||||
new Rectangle(0, 0, auxSprite.Texture.Width(), auxSprite.Texture.Height()),
|
||||
auxSprite.Rotation,
|
||||
auxSprite.Scale,
|
||||
SpriteEffects.None
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Game.prototype.GenerateBall = function () {
|
||||
"use strict";
|
||||
/*globals Sprite, Ball, Rectangle, Point*/
|
||||
|
||||
//Create a ball with random scale
|
||||
var self = this,
|
||||
scale = (Math.floor(Math.random() * 20) + 10) / 100,
|
||||
canvasWidth = self.GraphicsDevice.PreferredBackBufferWidth(),
|
||||
canvasHeight = self.GraphicsDevice.PreferredBackBufferHeight(),
|
||||
sprite = new Sprite(
|
||||
self.ballTexture,
|
||||
new Vector2(scale, scale),
|
||||
new Rectangle(0, 0, self.ballTexture.Width(), self.ballTexture.Height()),
|
||||
Point.Zero(),
|
||||
true
|
||||
),
|
||||
position = new Point((canvasWidth / 2 - sprite.HalfWidth()), (canvasHeight / 2 - sprite.HalfHeight())),
|
||||
ball = new Ball(
|
||||
sprite,
|
||||
sprite.HalfWidth(),
|
||||
position,
|
||||
self.balls.length,
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
self.balls.push(ball);
|
||||
};
|
||||
|
||||
/**
|
||||
* Call this method to initialize the game, begin running the game loop, and
|
||||
* start processing events for the game.
|
||||
* @name Run
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Run = function () {
|
||||
"use strict";
|
||||
/*globals requestAnimationFrame*/
|
||||
var self = this;
|
||||
|
||||
//Call the game loop
|
||||
requestAnimationFrame(self.Run.bind(self), self.GraphicsDevice.canvas);
|
||||
|
||||
//Choose the method to run according to the game state
|
||||
switch (self.gameState) {
|
||||
case GameStates.Initializing:
|
||||
self.Initialize();
|
||||
break;
|
||||
case GameStates.Loading:
|
||||
self.LoadContent();
|
||||
break;
|
||||
case GameStates.Playing:
|
||||
self.Update();
|
||||
self.Draw();
|
||||
break;
|
||||
}
|
||||
};
|
784
src/JS/Rayman.js
Normal file
@ -0,0 +1,784 @@
|
||||
/**
|
||||
* Provides basic graphics device initialization, game logic, and rendering code.
|
||||
*/
|
||||
function Game() {
|
||||
"use strict";
|
||||
/*globals ContentManager, GraphicsDevice, document, SpriteBatch, GameStates, setInterval, clearInterval, Mouse, SpriteEffects*/
|
||||
this.Content = new ContentManager();
|
||||
this.GraphicsDevice = new GraphicsDevice(document);
|
||||
this.spriteBatch = null;
|
||||
this.gameState = GameStates.Initializing;
|
||||
this.preloading = true;
|
||||
|
||||
this.level = null;
|
||||
this.sprites = [];
|
||||
|
||||
this.gravityForce = 0.3;
|
||||
|
||||
this.pearlsToCollect = 0;
|
||||
|
||||
//The images
|
||||
this.levelTexture = null;
|
||||
this.distantBackgroundTexture = null;
|
||||
this.raymanTexture = null;
|
||||
this.enemyTexture = null;
|
||||
this.punchTexture = null;
|
||||
this.flyPowerTexture = null;
|
||||
this.punchSpeedTexture = null;
|
||||
this.pearlTexture = null;
|
||||
this.shieldTexture = null;
|
||||
this.helpTexture = null;
|
||||
this.gameOverTexture = null;
|
||||
this.winTexture = null;
|
||||
this.hudTexture = null;
|
||||
|
||||
//The song
|
||||
this.song = null;
|
||||
|
||||
//Sound effects
|
||||
this.soundEffects = [];
|
||||
|
||||
//Create the platforms, pickable objects and enemys arrays
|
||||
this.platforms = [];
|
||||
this.pickableObjects = [];
|
||||
this.enemys = [];
|
||||
|
||||
//Create the player
|
||||
this.player = null;
|
||||
|
||||
//Create the game camera
|
||||
this.camera = null;
|
||||
|
||||
//The win zone rectangle
|
||||
this.winRect = null;
|
||||
|
||||
//The help screen sprite
|
||||
this.helpSprite = null;
|
||||
|
||||
//The game over screen sprite
|
||||
this.gameOverSprite = null;
|
||||
|
||||
//The win screen sprite
|
||||
this.winSprite = null;
|
||||
|
||||
//The win screen sprite
|
||||
this.hudSprite = null;
|
||||
|
||||
//Flags
|
||||
this.moveRight = false;
|
||||
this.moveLeft = false;
|
||||
this.jump = false;
|
||||
this.punch = false;
|
||||
this.showCollisions = false;
|
||||
|
||||
this.interval = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the game to perform any initialization it needs to before starting to run.
|
||||
* This is where it can query for any required services and load any non-graphic
|
||||
* related content.
|
||||
* @name Initialize
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Initialize = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
self.gameState = GameStates.Loading;
|
||||
};
|
||||
|
||||
/**
|
||||
* LoadContent will be called once per game and is the place to load
|
||||
* all of your content.
|
||||
* @name LoadContent
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.LoadContent = function () {
|
||||
"use strict";
|
||||
/*globals Level, Sprite, Point, Rectangle, Vector2, PickableObject, AnimationTypes, PickableObjectTypes, AnimatedSprite, Enemy, Player, Projectile, Camera*/
|
||||
var self = this,
|
||||
distantBackgroundRepeats = 0,
|
||||
i = 0,
|
||||
len = 0,
|
||||
currentPlatform = null,
|
||||
currentObject = null,
|
||||
currentEnemy = null,
|
||||
objSprite = null,
|
||||
type = null,
|
||||
aux = 0;
|
||||
|
||||
if (self.preloading) {
|
||||
// Create a new SpriteBatch, which can be used to draw textures.
|
||||
self.spriteBatch = new SpriteBatch(self.GraphicsDevice);
|
||||
|
||||
//Textures
|
||||
self.levelTexture = self.Content.LoadTexture2D("../../maps/level1.png");
|
||||
self.distantBackgroundTexture = self.Content.LoadTexture2D("../../images/dream_forest_background.png");
|
||||
self.raymanTexture = self.Content.LoadTexture2D("../../images/rayman_anim.png");
|
||||
self.enemyTexture = self.Content.LoadTexture2D("../../images/enemy1_anim.png");
|
||||
self.punchTexture = self.Content.LoadTexture2D("../../images/punch.png");
|
||||
self.flyPowerTexture = self.Content.LoadTexture2D("../../images/fairy_anim.png");
|
||||
self.punchSpeedTexture = self.Content.LoadTexture2D("../../images/fairy_anim2.png");
|
||||
self.pearlTexture = self.Content.LoadTexture2D("../../images/pearl_anim.png");
|
||||
self.shieldTexture = self.Content.LoadTexture2D("../../images/shield_anim.png");
|
||||
self.helpTexture = self.Content.LoadTexture2D("../../images/help.jpg");
|
||||
self.gameOverTexture = self.Content.LoadTexture2D("../../images/game_over_screen.png");
|
||||
self.winTexture = self.Content.LoadTexture2D("../../images/win_screen.png");
|
||||
self.hudTexture = self.Content.LoadTexture2D("../../images/interfaz.png");
|
||||
|
||||
//The song
|
||||
self.song = self.Content.LoadSong("../../sounds/Rayman/song.mp3");
|
||||
|
||||
//Sound Effects
|
||||
self.soundEffects.push(["enemy_hitted", self.Content.LoadSoundEffect("../../sounds/Rayman/enemy_hitted.wav")]);
|
||||
self.soundEffects.push(["flying", self.Content.LoadSoundEffect("../../sounds/Rayman/flying.wav")]);
|
||||
self.soundEffects.push(["game_over", self.Content.LoadSoundEffect("../../sounds/Rayman/game_over.mp3")]);
|
||||
self.soundEffects.push(["pearl_picked", self.Content.LoadSoundEffect("../../sounds/Rayman/pearl_picked.wav")]);
|
||||
self.soundEffects.push(["power_picked", self.Content.LoadSoundEffect("../../sounds/Rayman/power_picked.wav")]);
|
||||
self.soundEffects.push(["punch_thrown", self.Content.LoadSoundEffect("../../sounds/Rayman/punch_thrown.wav")]);
|
||||
self.soundEffects.push(["rayman_hitted", self.Content.LoadSoundEffect("../../sounds/Rayman/rayman_hitted.wav")]);
|
||||
self.soundEffects.push(["shield_picked", self.Content.LoadSoundEffect("../../sounds/Rayman/shield_picked.wav")]);
|
||||
self.soundEffects.push(["win_level", self.Content.LoadSoundEffect("../../sounds/Rayman/win_level.wav")]);
|
||||
self.soundEffects.push(["idle", self.Content.LoadSoundEffect("../../sounds/Rayman/idle.wav")]);
|
||||
self.soundEffects.push(["ground_hit", self.Content.LoadSoundEffect("../../sounds/Rayman/ground_hit.wav")]);
|
||||
|
||||
self.preloading = false;
|
||||
}
|
||||
|
||||
if (self.Content.AllContentLoaded()) {
|
||||
|
||||
//Create the level
|
||||
self.level = new Level(
|
||||
new Sprite(
|
||||
self.levelTexture,
|
||||
Vector2.One(),
|
||||
new Rectangle(0, 0, self.levelTexture.Width(), self.levelTexture.Height()),
|
||||
Point.Zero(),
|
||||
true
|
||||
)
|
||||
);
|
||||
distantBackgroundRepeats = Math.ceil(self.levelTexture.Width() / self.distantBackgroundTexture.Width());
|
||||
|
||||
for (i = 0; i < distantBackgroundRepeats; i += 1) {
|
||||
self.level.DistantBackgroundsSprites.push(
|
||||
new Sprite(
|
||||
self.distantBackgroundTexture,
|
||||
Vector2.One(),
|
||||
new Rectangle(0, 0, self.distantBackgroundTexture.Width(), self.distantBackgroundTexture.Height()),
|
||||
new Point(self.distantBackgroundTexture.Width() * i, 0),
|
||||
true
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
/// Build the level ///
|
||||
///////////////////////
|
||||
for (i = 0, len = self.level.DistantBackgroundsSprites.length; i < len; i += 1) {
|
||||
self.sprites.push(self.level.DistantBackgroundsSprites[i]);
|
||||
}
|
||||
self.sprites.push(self.level.Sprite);
|
||||
|
||||
//Create all the platforms and add them to the platforms array
|
||||
for (i = 0, len = self.level.Platforms.length; i < len; i += 1) {
|
||||
|
||||
currentPlatform = self.level.Platforms[i];
|
||||
self.platforms.push(
|
||||
new Rectangle(
|
||||
currentPlatform.x,
|
||||
currentPlatform.y,
|
||||
currentPlatform.width,
|
||||
currentPlatform.height
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//Create all the pickable objects and add them to the pickable objects array
|
||||
for (i = 0, len = self.level.PickableObjects.length; i < len; i += 1) {
|
||||
|
||||
currentObject = self.level.PickableObjects[i];
|
||||
|
||||
switch (currentObject.name) {
|
||||
case "PEARL":
|
||||
objSprite = new AnimatedSprite(
|
||||
self.pearlTexture,
|
||||
new Vector2(1.35, 1.35),
|
||||
new Rectangle(0, 0, 24, 24),
|
||||
new Point(currentObject.x, currentObject.y),
|
||||
true,
|
||||
AnimationTypes.PingPongLoop,
|
||||
8,
|
||||
90
|
||||
);
|
||||
type = PickableObjectTypes.PEARL;
|
||||
self.pearlsToCollect += 1;
|
||||
break;
|
||||
|
||||
case "LIFE":
|
||||
objSprite = new AnimatedSprite(
|
||||
self.flyPowerTexture,
|
||||
Vector2.One(),
|
||||
new Rectangle(0, 0, 64, 64),
|
||||
new Point(currentObject.x, currentObject.y),
|
||||
true,
|
||||
AnimationTypes.PingPongLoop,
|
||||
10,
|
||||
25
|
||||
);
|
||||
type = PickableObjectTypes.LIFE;
|
||||
break;
|
||||
|
||||
case "MINI_SHIELD":
|
||||
objSprite = new AnimatedSprite(
|
||||
self.flyPowerTexture,
|
||||
Vector2.One(),
|
||||
new Rectangle(0, 0, 64, 64),
|
||||
new Point(currentObject.x, currentObject.y),
|
||||
true,
|
||||
AnimationTypes.PingPongLoop,
|
||||
10,
|
||||
25
|
||||
);
|
||||
type = PickableObjectTypes.MINI_SHIELD;
|
||||
break;
|
||||
|
||||
case "SHIELD":
|
||||
objSprite = new AnimatedSprite(
|
||||
self.shieldTexture,
|
||||
new Vector2(2.1, 1.7),
|
||||
new Rectangle(0, 0, 24, 19),
|
||||
new Point(currentObject.x, currentObject.y),
|
||||
true,
|
||||
AnimationTypes.PingPongLoop,
|
||||
4,
|
||||
120
|
||||
);
|
||||
type = PickableObjectTypes.SHIELD;
|
||||
break;
|
||||
|
||||
case "PUNCH_SPEED":
|
||||
objSprite = new AnimatedSprite(
|
||||
self.punchSpeedTexture,
|
||||
new Vector2(1.2, 1.2),
|
||||
new Rectangle(0, 0, 64, 64),
|
||||
new Point(currentObject.x, currentObject.y),
|
||||
true,
|
||||
AnimationTypes.PingPongLoop,
|
||||
10,
|
||||
35
|
||||
);
|
||||
type = PickableObjectTypes.PUNCH_SPEED;
|
||||
break;
|
||||
|
||||
case "PUNCH_POWER":
|
||||
objSprite = new AnimatedSprite(
|
||||
self.flyPowerTexture,
|
||||
Vector2.One(),
|
||||
new Rectangle(0, 0, 64, 64),
|
||||
new Point(currentObject.x, currentObject.y),
|
||||
true,
|
||||
AnimationTypes.PingPongLoop,
|
||||
10,
|
||||
25
|
||||
);
|
||||
type = PickableObjectTypes.PUNCH_POWER;
|
||||
break;
|
||||
|
||||
case "ETERNAL_FLY":
|
||||
objSprite = new AnimatedSprite(
|
||||
self.flyPowerTexture,
|
||||
new Vector2(1.2, 1.2),
|
||||
new Rectangle(0, 0, 64, 64),
|
||||
new Point(currentObject.x, currentObject.y),
|
||||
true,
|
||||
AnimationTypes.PingPongLoop,
|
||||
10,
|
||||
30
|
||||
);
|
||||
type = PickableObjectTypes.ETERNAL_FLY;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (objSprite !== null && type !== null) {
|
||||
self.sprites.push(objSprite);
|
||||
self.pickableObjects.push(new PickableObject(objSprite, type));
|
||||
}
|
||||
}
|
||||
|
||||
//Create all the enemys and add them to the enemys array
|
||||
for (i = 0, len = self.level.Enemys.length; i < len; i += 1) {
|
||||
|
||||
currentEnemy = self.level.Enemys[i];
|
||||
|
||||
self.enemys.push(
|
||||
new Enemy(
|
||||
new AnimatedSprite(
|
||||
self.enemyTexture,
|
||||
new Vector2(0.3, 0.3),
|
||||
new Rectangle(0, 0, 80, 80),
|
||||
new Point(currentEnemy.x, currentEnemy.y),
|
||||
true,
|
||||
AnimationTypes.Loop,
|
||||
20,
|
||||
35
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
self.sprites.push(self.enemys[i].Sprite);
|
||||
}
|
||||
|
||||
//Create the player (Rayman) and his punch
|
||||
self.player = new Player(
|
||||
new AnimatedSprite(
|
||||
self.raymanTexture,
|
||||
new Vector2(0.1, 0.1),
|
||||
new Rectangle(0, 0, 80, 80),
|
||||
new Point(self.level.Player.x, self.level.Player.y),
|
||||
true,
|
||||
AnimationTypes.Loop,
|
||||
11,
|
||||
45
|
||||
)
|
||||
);
|
||||
|
||||
self.player.Punch = new Projectile(
|
||||
new Sprite(
|
||||
self.punchTexture,
|
||||
new Vector2(1.2, 1.2),
|
||||
new Rectangle(0, 0, self.punchTexture.HalfWidth(), self.punchTexture.Height()),
|
||||
Point.Zero(),
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
self.sprites.push(self.player.Sprite);
|
||||
self.sprites.push(self.player.Punch.Sprite);
|
||||
|
||||
//Instanciate the game camera
|
||||
self.camera = new Camera(
|
||||
self.GraphicsDevice.DefaultBackBufferWidth(),
|
||||
self.GraphicsDevice.DefaultBackBufferHeight(),
|
||||
self.levelTexture.Width(),
|
||||
self.levelTexture.Height(),
|
||||
1.2
|
||||
);
|
||||
|
||||
//Initialize the win zone rectangle
|
||||
self.winRect = new Rectangle(self.level.WinRect.x, self.level.WinRect.y, self.level.WinRect.width, self.level.WinRect.height);
|
||||
|
||||
//Initialize the help screen sprite
|
||||
self.helpSprite = new Sprite(
|
||||
self.helpTexture,
|
||||
Vector2.One(),
|
||||
new Rectangle(0, 0, self.helpTexture.Width(), self.helpTexture.Height()),
|
||||
Point.Zero(),
|
||||
true
|
||||
);
|
||||
|
||||
//Initialize the game over screen sprite
|
||||
self.gameOverSprite = new Sprite(
|
||||
self.gameOverTexture,
|
||||
Vector2.One(),
|
||||
new Rectangle(0, 0, self.gameOverTexture.Width(), self.gameOverTexture.Height()),
|
||||
Point.Zero(),
|
||||
true
|
||||
);
|
||||
|
||||
//Initialize the win screen sprite
|
||||
self.winSprite = new Sprite(
|
||||
self.winTexture,
|
||||
Vector2.One(),
|
||||
new Rectangle(0, 0, self.winTexture.Width(), self.winTexture.Height()),
|
||||
Point.Zero(),
|
||||
true
|
||||
);
|
||||
|
||||
//Initialize the hud sprite
|
||||
self.hudSprite = new Sprite(
|
||||
self.hudTexture,
|
||||
Vector2.One(),
|
||||
new Rectangle(0, 0, self.hudTexture.Width(), self.hudTexture.Height()),
|
||||
Point.Zero(),
|
||||
true
|
||||
);
|
||||
|
||||
/////////////////////////
|
||||
|
||||
//If mouse left button clicked enter full screen mode
|
||||
self.GraphicsDevice.canvas.addEventListener("click", self.GraphicsDevice.ToggleFullScreen.bind(self.GraphicsDevice));
|
||||
|
||||
//Play the game song
|
||||
self.song.Play();
|
||||
|
||||
self.interval = setInterval(function () {
|
||||
if (self.gameState === GameStates.Playing && self.player.CurrentState === self.player.IDLE) {
|
||||
self.soundEffects[9][1].Play();
|
||||
}
|
||||
}, 3500);
|
||||
|
||||
//Change game state to "playing"
|
||||
self.gameState = GameStates.Paused;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Allows the game to run logic such as updating the world,
|
||||
* checking for collisions, gathering input, and playing audio.
|
||||
* @name Update
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Update = function () {
|
||||
"use strict";
|
||||
/*globals Keyboard, Keys*/
|
||||
var self = this,
|
||||
i = 0,
|
||||
len = 0,
|
||||
playerPunch = null,
|
||||
levelWidth = self.level.Sprite.Width();
|
||||
|
||||
//Show help screen if 'h' key pressed
|
||||
if (Keyboard.IsKeyPressed(Keys.h)) {
|
||||
self.gameState = GameStates.Paused;
|
||||
}
|
||||
|
||||
//Toggle full page mode if mouse right button pressed
|
||||
if (Mouse.IsButtonClicked(Mouse.RightButton)) {
|
||||
self.GraphicsDevice.ToggleFullPage();
|
||||
}
|
||||
|
||||
//Catch the Mouse and Keyboard buttons
|
||||
self.moveLeft = Keyboard.IsKeyDown(Keys.a) || Keyboard.IsKeyDown(Keys.left_arrow);
|
||||
self.moveRight = Keyboard.IsKeyDown(Keys.d) || Keyboard.IsKeyDown(Keys.right_arrow);
|
||||
self.jump = Keyboard.IsKeyDown(Keys.w) || Keyboard.IsKeyDown(Keys.up_arrow);
|
||||
if ((!self.showCollisions && Keyboard.IsKeyPressed(Keys.c)) ||
|
||||
(self.showCollisions && !Keyboard.IsKeyPressed(Keys.c))) {
|
||||
self.showCollisions = true;
|
||||
} else {
|
||||
self.showCollisions = false;
|
||||
}
|
||||
if (!self.punch && Keyboard.IsKeyUp(Keys.space)) {
|
||||
self.punch = true;
|
||||
self.soundEffects[5][1].Play();
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.add)) {
|
||||
self.camera.IncreaseZoom();
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.subtract)) {
|
||||
self.camera.DecreaseZoom();
|
||||
}
|
||||
|
||||
//Update the player
|
||||
self.player.Update(self.moveLeft, self.moveRight, self.jump, self.punch, self.platforms, levelWidth, self.pickableObjects, self.sprites, self.gravityForce, self.soundEffects, self.enemys);
|
||||
|
||||
//Check if the player have all pearls and is in the win zone
|
||||
if (self.player.Pearls === self.pearlsToCollect && self.player.Bounds().Intersects(self.winRect) !== false) {
|
||||
self.song.Stop();
|
||||
self.soundEffects[8][1].Play();
|
||||
self.gameState = GameStates.GameWin;
|
||||
return;
|
||||
}
|
||||
|
||||
//If player dies go to game over game state
|
||||
if (self.player.Shield <= 0 || self.player.Sprite.Position.Y > self.level.Sprite.Height()) {
|
||||
self.song.Stop();
|
||||
self.soundEffects[2][1].Play();
|
||||
self.gameState = GameStates.GameOver;
|
||||
return;
|
||||
}
|
||||
|
||||
//Control the punch collision with Rayman
|
||||
playerPunch = self.player.Punch;
|
||||
if (self.punch &&
|
||||
playerPunch.IsReturning &&
|
||||
(self.player.Bounds().Intersects(playerPunch.Sprite.Bounds()) !== false)) {
|
||||
playerPunch.Sprite.IsVisible = false;
|
||||
playerPunch.IsReturning = false;
|
||||
self.punch = false;
|
||||
}
|
||||
|
||||
//Update the camera
|
||||
self.camera.Update(self.player);
|
||||
|
||||
//Update the enemys
|
||||
for (i = 0, len = self.enemys.length; i < len; i += 1) {
|
||||
self.enemys[i].Update(levelWidth, self.platforms, self.gravityForce);
|
||||
}
|
||||
|
||||
//Move the distantBackground at half the speed of the camera
|
||||
for (i = 0, len = self.level.DistantBackgroundsSprites.length; i < len; i += 1) {
|
||||
self.level.DistantBackgroundsSprites[i].Position.X += self.camera.SpeedV.X / 2;
|
||||
}
|
||||
|
||||
//Capture the camera's current x position so we can use it as the
|
||||
//previousX value in the next frame
|
||||
self.camera.PreviousSpeedX = self.camera.Position.X;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is called when the game should draw itself.
|
||||
* @name Draw
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Draw = function () {
|
||||
"use strict";
|
||||
var self = this,
|
||||
len = self.sprites.length,
|
||||
i = 0,
|
||||
auxSprite = null,
|
||||
hudSprite = self.hudSprite;
|
||||
|
||||
self.GraphicsDevice.Clear();
|
||||
|
||||
self.spriteBatch.ctx.save();
|
||||
|
||||
self.spriteBatch.ctx.scale(self.camera.Zoom, self.camera.Zoom);
|
||||
self.spriteBatch.ctx.translate(-self.camera.Position.X, -self.camera.Position.Y);
|
||||
|
||||
//Draw the sprites if visibles
|
||||
if (len > 0) {
|
||||
for (i = 0; i < len; i += 1) {
|
||||
auxSprite = self.sprites[i];
|
||||
if (auxSprite.IsVisible) {
|
||||
self.spriteBatch.Draw(
|
||||
auxSprite.Texture,
|
||||
auxSprite.Position,
|
||||
new Rectangle(auxSprite.SourceRect.X, auxSprite.SourceRect.Y, auxSprite.SourceRect.Width, auxSprite.SourceRect.Height),
|
||||
auxSprite.Rotation,
|
||||
auxSprite.Scale,
|
||||
auxSprite.SpriteEffects
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Display the collision rectangles if requested
|
||||
if (self.showCollisions) {
|
||||
for (i = 0, len = self.platforms.length; i < len; i += 1) {
|
||||
self.spriteBatch.DrawRectangle(self.platforms[i], "2", null);
|
||||
}
|
||||
|
||||
//Draw the player bounds
|
||||
self.spriteBatch.DrawRectangle(self.player.Bounds(), "2", "#00FF00");
|
||||
|
||||
//Draw the Rayman's punch
|
||||
if (self.player.Punch.Sprite.IsVisible) {
|
||||
self.spriteBatch.DrawRectangle(self.player.Punch.Sprite.Bounds(), "2", "#0000FF");
|
||||
}
|
||||
|
||||
//Draw the enemy bounds
|
||||
for (i = 0, len = self.enemys.length; i < len; i += 1) {
|
||||
self.spriteBatch.DrawRectangle(self.enemys[i].Bounds(), "2", "#FF0000");
|
||||
}
|
||||
|
||||
//Draw the pickable objects bounds
|
||||
for (i = 0, len = self.pickableObjects.length; i < len; i += 1) {
|
||||
self.spriteBatch.DrawRectangle(self.pickableObjects[i].Bounds(), "2", "#FF00FF");
|
||||
}
|
||||
|
||||
//Draw the win zone bounds
|
||||
self.spriteBatch.DrawRectangle(self.winRect, "2", "#ffee00");
|
||||
}
|
||||
|
||||
self.spriteBatch.ctx.restore();
|
||||
|
||||
//Draw the hud
|
||||
self.spriteBatch.Draw(
|
||||
hudSprite.Texture,
|
||||
hudSprite.Position,
|
||||
new Rectangle(hudSprite.SourceRect.X, hudSprite.SourceRect.Y, hudSprite.SourceRect.Width, hudSprite.SourceRect.Height),
|
||||
hudSprite.Rotation,
|
||||
hudSprite.Scale,
|
||||
hudSprite.SpriteEffects
|
||||
);
|
||||
|
||||
self.spriteBatch.DrawString(
|
||||
"normal bold 24px Helvetica",
|
||||
self.player.Shield + " / 5",
|
||||
new Point(77, 25),
|
||||
"#000000",
|
||||
Vector2.One()
|
||||
);
|
||||
|
||||
self.spriteBatch.DrawString(
|
||||
"normal bold 20px Helvetica",
|
||||
self.player.Pearls + " / " + self.pearlsToCollect,
|
||||
new Point(735, 28),
|
||||
"#000000",
|
||||
Vector2.One()
|
||||
);
|
||||
|
||||
if (self.player.CanFly) {
|
||||
self.spriteBatch.Draw(
|
||||
self.flyPowerTexture,
|
||||
new Point(348, -2),
|
||||
new Rectangle(0, 0, 64, 64),
|
||||
0,
|
||||
new Vector2(1.3, 1.21),
|
||||
SpriteEffects.None
|
||||
);
|
||||
}
|
||||
|
||||
if (self.player.PunchImproved) {
|
||||
self.spriteBatch.Draw(
|
||||
self.punchSpeedTexture,
|
||||
new Point(404, -2),
|
||||
new Rectangle(0, 0, 64, 64),
|
||||
0,
|
||||
new Vector2(1.3, 1.21),
|
||||
SpriteEffects.None
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Call this method to initialize the game, begin running the game loop, and
|
||||
* start processing events for the game.
|
||||
* @name Run
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Run = function () {
|
||||
"use strict";
|
||||
/*globals requestAnimationFrame*/
|
||||
var self = this,
|
||||
helpSprite = self.helpSprite,
|
||||
gameOverSprite = self.gameOverSprite,
|
||||
winSprite = self.winSprite;
|
||||
|
||||
//Call the game loop
|
||||
requestAnimationFrame(self.Run.bind(self), self.GraphicsDevice.canvas);
|
||||
|
||||
//Choose the method to run according to the game state
|
||||
switch (self.gameState) {
|
||||
|
||||
case GameStates.Initializing:
|
||||
self.Initialize();
|
||||
break;
|
||||
|
||||
case GameStates.Loading:
|
||||
self.LoadContent();
|
||||
break;
|
||||
|
||||
case GameStates.Playing:
|
||||
self.Update();
|
||||
self.Draw();
|
||||
break;
|
||||
|
||||
case GameStates.Paused:
|
||||
self.spriteBatch.Draw(
|
||||
helpSprite.Texture,
|
||||
helpSprite.Position,
|
||||
new Rectangle(helpSprite.SourceRect.X, helpSprite.SourceRect.Y, helpSprite.SourceRect.Width, helpSprite.SourceRect.Height),
|
||||
helpSprite.Rotation,
|
||||
helpSprite.Scale,
|
||||
helpSprite.SpriteEffects
|
||||
);
|
||||
|
||||
//Go back to game if 'h' key pressed
|
||||
if (Keyboard.IsKeyPressed(Keys.h)) {
|
||||
self.gameState = GameStates.Playing;
|
||||
}
|
||||
|
||||
//Toggle full page mode if mouse right button pressed
|
||||
if (Mouse.IsButtonClicked(Mouse.RightButton)) {
|
||||
self.GraphicsDevice.ToggleFullPage();
|
||||
}
|
||||
break;
|
||||
|
||||
case GameStates.GameOver:
|
||||
self.spriteBatch.Draw(
|
||||
gameOverSprite.Texture,
|
||||
gameOverSprite.Position,
|
||||
new Rectangle(gameOverSprite.SourceRect.X, gameOverSprite.SourceRect.Y, gameOverSprite.SourceRect.Width, gameOverSprite.SourceRect.Height),
|
||||
gameOverSprite.Rotation,
|
||||
gameOverSprite.Scale,
|
||||
gameOverSprite.SpriteEffects
|
||||
);
|
||||
|
||||
//Go reset the game if 'r' key pressed
|
||||
if (Keyboard.IsKeyPressed(Keys.r)) {
|
||||
self.Reset();
|
||||
self.gameState = GameStates.Loading;
|
||||
}
|
||||
break;
|
||||
|
||||
case GameStates.GameWin:
|
||||
self.spriteBatch.Draw(
|
||||
winSprite.Texture,
|
||||
winSprite.Position,
|
||||
new Rectangle(winSprite.SourceRect.X, winSprite.SourceRect.Y, winSprite.SourceRect.Width, winSprite.SourceRect.Height),
|
||||
winSprite.Rotation,
|
||||
winSprite.Scale,
|
||||
winSprite.SpriteEffects
|
||||
);
|
||||
|
||||
//Go reset the game if 'r' key pressed
|
||||
if (Keyboard.IsKeyPressed(Keys.r)) {
|
||||
self.Reset();
|
||||
self.gameState = GameStates.Loading;
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset the game
|
||||
*/
|
||||
Game.prototype.Reset = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
self.Content = new ContentManager();
|
||||
self.GraphicsDevice = new GraphicsDevice(document);
|
||||
self.spriteBatch = null;
|
||||
self.gameState = GameStates.Initializing;
|
||||
self.preloading = true;
|
||||
|
||||
self.level = null;
|
||||
self.sprites = [];
|
||||
|
||||
self.pearlsToCollect = 0;
|
||||
|
||||
//Create the platforms, pickable objects and enemys arrays
|
||||
self.platforms = [];
|
||||
self.pickableObjects = [];
|
||||
self.enemys = [];
|
||||
|
||||
//Create the player
|
||||
self.player = null;
|
||||
|
||||
//Create the game camera
|
||||
self.camera = null;
|
||||
|
||||
//The win zone rectangle
|
||||
self.winRect = null;
|
||||
|
||||
//The help screen sprite
|
||||
self.helpSprite = null;
|
||||
|
||||
//The game over screen sprite
|
||||
self.gameOverSprite = null;
|
||||
|
||||
//The win screen sprite
|
||||
self.winSprite = null;
|
||||
|
||||
//Flags
|
||||
self.moveRight = false;
|
||||
self.moveLeft = false;
|
||||
self.jump = false;
|
||||
self.punch = false;
|
||||
self.showCollisions = false;
|
||||
|
||||
clearInterval(self.interval);
|
||||
|
||||
/*if (self.GraphicsDevice.IsFullScreen()) {
|
||||
self.GraphicsDevice.ToggleFullScreen();
|
||||
}*/
|
||||
};
|
348
src/JS/Rayman_Classes/Ball.js
Normal file
@ -0,0 +1,348 @@
|
||||
/**
|
||||
* Defines a Ball.
|
||||
* @constructor
|
||||
* @param {Sprite} sprite - The sprite that represents the ball.
|
||||
* @param {Number} radius - The radius of the circle of the ball.
|
||||
* @param {Point} position - The position of the ball.
|
||||
* @param {Number} position - The position of the ball.
|
||||
* @param {Boolean} bounce - Determines if the ball can bounce or not.
|
||||
*/
|
||||
function Ball(sprite, radius, position, index, bounce, rotate) {
|
||||
"use strict";
|
||||
/*global Vector2, Circle*/
|
||||
this.Sprite = sprite;
|
||||
this.Circle = new Circle(radius, position.X, position.Y);
|
||||
|
||||
//Physics properties
|
||||
this.SpeedV = Vector2.Zero();
|
||||
this.GroundFriction = 0.975; //balls 0.975 fluid 0.99
|
||||
this.BallBounceFriction = 0.85; //balls 0.85 fluid 0.0
|
||||
this.WallBounceFriction = 0.7; //balls 0.7 fluid 0.4
|
||||
this.MaxRotationSpeedTransmision = 25;
|
||||
this.CurrentRotationSpeed = 0;
|
||||
|
||||
//Platform game properties
|
||||
this.IsOnGround = false;
|
||||
|
||||
//Drag & Drop properties
|
||||
this.IsDraggable = true;
|
||||
this.IsBeenDragged = false;
|
||||
|
||||
//Other properties
|
||||
this.RandomDir = [-0.1, 0.1];
|
||||
this.Index = index;
|
||||
this.IsBounceOn = bounce;
|
||||
this.IsRotationOn = rotate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ball.
|
||||
* @name Update
|
||||
* @function
|
||||
* @param {Number} worldWidth - The width of the game world.
|
||||
* @param {Number} worldHeight - The height of the game world.
|
||||
* @param {Array} balls - Array of existing balls.
|
||||
* @param {Boolean} isGravityOn - Determines if the gravity is activated or not.
|
||||
* @param {GravityDirections} gravityDir - The gravity direction of the game world.
|
||||
* @param {Number} gravityForce - The gravity force value.
|
||||
* @memberOf Ball
|
||||
*/
|
||||
Ball.prototype.Update = function (worldWidth, worldHeight, balls, isGravityOn, gravityDir, gravityForce) {
|
||||
"use strict";
|
||||
/*global GravityDirections, Mouse, Point, hitTestPoint*/
|
||||
var self = this,
|
||||
randomDirImpulse = 0,
|
||||
len = 0,
|
||||
i = 0,
|
||||
j = 0;
|
||||
|
||||
//Check if the mouse clicked a ball to drag it
|
||||
if (self.Circle.Contains(new Point(Mouse.X, Mouse.Y)) && self.IsDraggable && Mouse.LeftButtonPressed && !Mouse.IsDraggingSomething) { //Si quitamos IsDraggingSom... ocurren cosas divertidas
|
||||
//Assign the sprite to the dragSprite variable
|
||||
self.IsBeenDragged = true;
|
||||
Mouse.IsDraggingSomething = true;
|
||||
self.CurrentRotationSpeed = 0;
|
||||
self.SpeedV.X = 0;
|
||||
self.SpeedV.Y = 0;
|
||||
i = self.Index;
|
||||
len = balls.length;
|
||||
|
||||
//push the dragSprite to the end of the sprites
|
||||
//array so that it's displayed last
|
||||
self.Index = balls.length - 1;
|
||||
balls.push(self);
|
||||
|
||||
//Splice the dragSprite from its previous
|
||||
//position in the sprites array
|
||||
balls.splice(i, 1);
|
||||
|
||||
for (j = i; j < len - 1; j += 1) {
|
||||
balls[j].Index -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Update the Circle position with the mouse position
|
||||
if (Mouse.IsMoving && self.IsBeenDragged) {
|
||||
self.Circle.X = Mouse.X - self.Circle.Radius;
|
||||
self.Circle.Y = Mouse.Y - self.Circle.Radius;
|
||||
}
|
||||
|
||||
//If the mouse left button was released drop the ball
|
||||
if (self.IsBeenDragged && !Mouse.LeftButtonPressed) {
|
||||
self.IsBeenDragged = false;
|
||||
Mouse.IsDraggingSomething = false;
|
||||
}
|
||||
|
||||
//Apply gravity depending on the gravity direction
|
||||
if (isGravityOn && !self.IsBeenDragged) {
|
||||
|
||||
//Random impulse when the balls are generated
|
||||
if (!self.IsOnGround && self.SpeedV.X === 0 && self.SpeedV.Y === 0) {
|
||||
randomDirImpulse = self.RandomDir[Math.floor(Math.random() * 2)];
|
||||
}
|
||||
|
||||
switch (gravityDir) {
|
||||
|
||||
//Gravity down
|
||||
case GravityDirections.G_DOWN:
|
||||
self.SpeedV.Y += gravityForce;
|
||||
self.SpeedV.X += randomDirImpulse;
|
||||
if (self.Circle.Bottom() >= worldHeight) {
|
||||
self.SpeedV.X *= self.GroundFriction;
|
||||
self.IsOnGround = true;
|
||||
}
|
||||
break;
|
||||
|
||||
//Gravity up
|
||||
case GravityDirections.G_UP:
|
||||
self.SpeedV.Y -= gravityForce;
|
||||
self.SpeedV.X += randomDirImpulse;
|
||||
if (self.Circle.Top() <= 0) {
|
||||
self.SpeedV.X *= self.GroundFriction;
|
||||
self.IsOnGround = true;
|
||||
}
|
||||
break;
|
||||
|
||||
//Gravity left
|
||||
case GravityDirections.G_LEFT:
|
||||
self.SpeedV.X -= gravityForce;
|
||||
self.SpeedV.Y += randomDirImpulse;
|
||||
if (self.Circle.Left() <= 0) {
|
||||
self.SpeedV.Y *= self.GroundFriction;
|
||||
self.IsOnGround = true;
|
||||
}
|
||||
break;
|
||||
|
||||
//Gravity right
|
||||
case GravityDirections.G_RIGHT:
|
||||
self.SpeedV.X += gravityForce;
|
||||
self.SpeedV.Y += randomDirImpulse;
|
||||
if (self.Circle.Right() >= worldWidth) {
|
||||
self.SpeedV.Y *= self.GroundFriction;
|
||||
self.IsOnGround = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Move the ball if it isn't dragged
|
||||
if (!self.IsBeenDragged) {
|
||||
self.Circle.X += self.SpeedV.X;
|
||||
self.Circle.Y += self.SpeedV.Y;
|
||||
}
|
||||
|
||||
//Collision with balls
|
||||
len = balls.length;
|
||||
if (len > 1 && !self.IsBeenDragged) {
|
||||
for (i = 0; i < len; i += 1) {
|
||||
if (self.Index !== i) {
|
||||
self.CollisionWithBall(balls[i], self.IsBounceOn, self.IsRotationOn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Screen boundaries
|
||||
//Left
|
||||
if (self.Circle.Left() < 0) {
|
||||
if (self.IsBounceOn) {
|
||||
self.SpeedV.X *= -self.WallBounceFriction;
|
||||
}
|
||||
self.Circle.X = 0;
|
||||
}
|
||||
//Up
|
||||
if (self.Circle.Top() < 0) {
|
||||
if (self.IsBounceOn) {
|
||||
self.SpeedV.Y *= -self.WallBounceFriction;
|
||||
}
|
||||
self.Circle.Y = 0;
|
||||
}
|
||||
//Right
|
||||
if (self.Circle.Right() > worldWidth) {
|
||||
if (self.IsBounceOn) {
|
||||
self.SpeedV.X *= -self.WallBounceFriction;
|
||||
}
|
||||
self.Circle.X = worldWidth - self.Circle.Diameter();
|
||||
}
|
||||
//Down
|
||||
if (self.Circle.Bottom() > worldHeight) {
|
||||
if (self.IsBounceOn) {
|
||||
self.SpeedV.Y *= -self.WallBounceFriction;
|
||||
}
|
||||
self.Circle.Y = worldHeight - self.Circle.Diameter();
|
||||
}
|
||||
|
||||
//Update the sprite
|
||||
self.Sprite.Position.X = self.Circle.X;
|
||||
self.Sprite.Position.Y = self.Circle.Y;
|
||||
|
||||
//Update the sprite rotation
|
||||
self.Sprite.Rotation += self.CurrentRotationSpeed;
|
||||
self.CurrentRotationSpeed *= self.GroundFriction;
|
||||
//console.log(self.CurrentRotationSpeed);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a ball collide with other ball. Besides, bounce and rotate the balls if needed.
|
||||
* @name CollisionWithBall
|
||||
* @function
|
||||
* @param {Ball} ball - The ball which will be checked to find a collision.
|
||||
* @memberOf Ball
|
||||
*/
|
||||
Ball.prototype.CollisionWithBall = function (ball) {
|
||||
"use strict";
|
||||
var self = this,
|
||||
overlapV = self.Circle.IsInsideCircle(ball.Circle),
|
||||
vector = null,
|
||||
d = null,
|
||||
angle = 0,
|
||||
b1Magnitude = 0,
|
||||
b2Magnitude = 0,
|
||||
s = null;
|
||||
|
||||
//If the other ball is inside the other
|
||||
if (overlapV !== false) {
|
||||
self.Circle.X += overlapV.X;
|
||||
self.Circle.Y += overlapV.Y;
|
||||
return true;
|
||||
}
|
||||
|
||||
//Check if this ball is inside the other
|
||||
overlapV = self.Circle.Intersects(ball.Circle);
|
||||
|
||||
//If there is a collision with the other ball move it away of the other
|
||||
if (overlapV !== false) {
|
||||
|
||||
vector = overlapV.Y; //the vector between the balls centers
|
||||
d = vector.Normalize();
|
||||
angle = Math.atan2(d.X, d.X) * 180 / Math.PI;
|
||||
b1Magnitude = self.SpeedV.Length();
|
||||
b2Magnitude = ball.SpeedV.Length();
|
||||
|
||||
//If rotation is activated then rotate the ball
|
||||
if (self.IsRotationOn) {
|
||||
if (
|
||||
(angle >= 0 && angle <= 90 && self.SpeedV.X > 0) ||
|
||||
(angle > 90 && angle <= 180 && self.SpeedV.X >= 0) ||
|
||||
(angle < 0 && angle >= -90 && self.SpeedV.X <= 0) ||
|
||||
(angle < -90 && angle >= -180 && self.SpeedV.X < 0)
|
||||
) {
|
||||
self.CurrentRotationSpeed = Math.min(Math.abs(b1Magnitude), self.MaxRotationSpeedTransmision);
|
||||
ball.CurrentRotationSpeed = -Math.min(Math.abs(b2Magnitude), ball.MaxRotationSpeedTransmision);
|
||||
} else {
|
||||
self.CurrentRotationSpeed = -Math.min(Math.abs(b1Magnitude), self.MaxRotationSpeedTransmision);
|
||||
ball.CurrentRotationSpeed = Math.min(Math.abs(b2Magnitude), ball.MaxRotationSpeedTransmision);
|
||||
}
|
||||
|
||||
//Limit the rotation speeds
|
||||
if (Math.abs(self.CurrentRotationSpeed) < 1) {
|
||||
self.CurrentRotationSpeed = 0;
|
||||
}
|
||||
if (Math.abs(ball.CurrentRotationSpeed) < 1) {
|
||||
ball.CurrentRotationSpeed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Move circle 1 out of the collision by multiplying
|
||||
//the overlap with the normalized vector and add it to
|
||||
//ball 1's position
|
||||
self.Circle.X += overlapV.X * d.X;
|
||||
self.Circle.Y += overlapV.X * d.Y;
|
||||
//Ocurren cosas diver al poner esto
|
||||
//ball.Circle.X += overlapV.X * overlapV.Y[0];
|
||||
//ball.Circle.Y += overlapV.X * overlapV.Y[1];
|
||||
|
||||
if (self.IsBounceOn) {
|
||||
//Create a collision vector object to represent the bounce surface
|
||||
//Find the bounce surface's X and Y properties
|
||||
//(This represents the normal of the distance vector between the circles)
|
||||
s = new Vector2(vector.Y, -vector.X);
|
||||
//var s = {};
|
||||
//s.X = vector.Y;
|
||||
//s.Y = -vector.X;
|
||||
|
||||
//Bounce b1 off the surface
|
||||
self.BounceOffSurface(ball, s);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Bounces the current ball with other ball given the virtual surface between them.
|
||||
* @name BounceOffSurface
|
||||
* @function
|
||||
* @param {Ball} ball - The ball which will bounced.
|
||||
* @param {Vector2} s - The surface to bounce off.
|
||||
* @memberOf Ball
|
||||
*/
|
||||
Ball.prototype.BounceOffSurface = function (ball, s) {
|
||||
"use strict";
|
||||
//1. Calculate the collision surface's properties
|
||||
|
||||
|
||||
var self = this,
|
||||
//Find the surface vector's left normal
|
||||
leftNormalV = new Vector2(s.Y, -s.X),
|
||||
//s.lx = s.Y;
|
||||
//s.ly = -s.X;
|
||||
|
||||
//Find its magnitude
|
||||
sLength = s.Length(),
|
||||
|
||||
//Find its normalized/unit vector values
|
||||
dV = s.Normalize(),
|
||||
|
||||
//2. Bounce the ball off the surface (s)
|
||||
|
||||
//Find the dot product between the object and the surface
|
||||
dp1 = self.SpeedV.X * dV.X + self.SpeedV.Y * dV.Y,
|
||||
|
||||
//Project the object's velocity onto the collision surface
|
||||
p1V = new Vector2(dp1 * dV.X, dp1 * dV.Y),
|
||||
|
||||
//Find the dot product of the object and the surface's left normal (s.lx and s.ly)
|
||||
dp2 = self.SpeedV.X * (leftNormalV.X / sLength) + self.SpeedV.Y * (leftNormalV.Y / sLength),
|
||||
|
||||
//Project the object's velocity onto the surface's left normal
|
||||
p2V = new Vector2(dp2 * (leftNormalV.X / sLength), dp2 * (leftNormalV.Y / sLength)),
|
||||
bounceV = null;
|
||||
|
||||
//Reverse the projection on the surface's left normal
|
||||
p2V.X *= -1;
|
||||
p2V.Y *= -1;
|
||||
|
||||
//Add up the projections to create a new bounce vector
|
||||
bounceV = new Vector2(p1V.X + p2V.X, p1V.Y + p2V.Y);
|
||||
|
||||
//Assign the bounce vector to the object's velocity
|
||||
self.SpeedV.X = bounceV.X * self.BallBounceFriction;
|
||||
self.SpeedV.Y = bounceV.Y * self.BallBounceFriction;
|
||||
if (!ball.IsBeenDragged) {
|
||||
ball.SpeedV.X = -bounceV.X * ball.BallBounceFriction;
|
||||
ball.SpeedV.Y = -bounceV.Y * ball.BallBounceFriction;
|
||||
}
|
||||
};
|
186
src/JS/Rayman_Classes/Enemy.js
Normal file
@ -0,0 +1,186 @@
|
||||
/**
|
||||
* Represents one enemy.
|
||||
* @constructor
|
||||
* @param {AnimatedSprite|Sprite} sprite - The enemys's sprite.
|
||||
*/
|
||||
function Enemy(sprite) {
|
||||
"use strict";
|
||||
/*globals Vector2, setInterval, AnimatedSprite, SpriteEffects*/
|
||||
|
||||
this.Sprite = sprite;
|
||||
|
||||
//Physics properties
|
||||
this.SpeedV = Vector2.Zero();
|
||||
this.Speed = 0;
|
||||
|
||||
//Platform game properties
|
||||
this.IsOnGround = undefined;
|
||||
|
||||
//Enemy States
|
||||
this.IDLE = 0;
|
||||
this.MOVING = 1;
|
||||
this.HITTED = 2;
|
||||
//this.TURNING = 3;
|
||||
//[...]
|
||||
this.CurrentState = 0;
|
||||
|
||||
//Enemy attributtes
|
||||
//this.life = 2;
|
||||
|
||||
//If the sprite is animated starts the sprite animation
|
||||
if (this.Sprite instanceof AnimatedSprite) {
|
||||
this.Sprite.StartAnimation();
|
||||
}
|
||||
|
||||
//Change the enemy state every 1,8 seconds
|
||||
this.interval = setInterval(this.ChangeEnemyState.bind(this), 1800);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates de enemy.
|
||||
* @name Update
|
||||
* @function
|
||||
* @param {Number} levelWidth - The width of the level.
|
||||
* @param {Array} platforms - The platforms array.
|
||||
* @param {Number} gravityForce - The gravity force.
|
||||
* @memberOf Enemy
|
||||
*/
|
||||
Enemy.prototype.Update = function (levelWidth, platforms, gravityForce) {
|
||||
"use strict";
|
||||
var self = this,
|
||||
enemySprite = self.Sprite,
|
||||
bounds = null,
|
||||
i = 0,
|
||||
overlapV = null,
|
||||
currentPlatform = null,
|
||||
len = 0;
|
||||
|
||||
//If the enemy was hitted stop it
|
||||
if (self.CurrentState !== self.HITTED) {
|
||||
|
||||
switch (self.CurrentState) {
|
||||
case self.IDLE:
|
||||
//enemySprite.currentFrame = 0;
|
||||
enemySprite.NumberOfFrames = 20;
|
||||
self.Speed = 0;
|
||||
break;
|
||||
case self.MOVING:
|
||||
//enemySprite.currentFrame = 0;
|
||||
enemySprite.NumberOfFrames = 14;
|
||||
self.Speed = 1.5;
|
||||
break;
|
||||
}
|
||||
|
||||
//Apply the acceleration
|
||||
self.SpeedV.X = self.Speed;
|
||||
if (enemySprite.SpriteEffects === SpriteEffects.FlipHorizontally) {
|
||||
self.SpeedV.X *= -1;
|
||||
}
|
||||
|
||||
//Apply gravityForce
|
||||
self.SpeedV.Y += gravityForce;
|
||||
|
||||
//Check for a collision between the enemy and the platforms
|
||||
bounds = self.Bounds();
|
||||
|
||||
for (i = 0, len = platforms.length; i < len; i += 1) {
|
||||
|
||||
currentPlatform = platforms[i];
|
||||
overlapV = bounds.Intersects(currentPlatform);
|
||||
|
||||
if (overlapV !== false && self.SpeedV.Y >= 0) {
|
||||
|
||||
if (bounds.Bottom() >= currentPlatform.Top() &&
|
||||
bounds.Bottom() <= currentPlatform.Bottom()) {
|
||||
|
||||
//Move the rectangle out of the collision
|
||||
enemySprite.Position.Y -= overlapV.Y;
|
||||
|
||||
//Tell the game that the player is on the ground if
|
||||
//it's standing on top of a platform
|
||||
self.IsOnGround = true;
|
||||
|
||||
//Neutralize gravity by applying its
|
||||
//exact opposite force to the character's vy
|
||||
self.SpeedV.Y = -gravityForce;
|
||||
}
|
||||
|
||||
} else if (overlapV === false && self.SpeedV.Y > 0) {
|
||||
self.IsOnGround = false;
|
||||
}
|
||||
}
|
||||
|
||||
//Screen boundaries
|
||||
//Left
|
||||
if (bounds.X < 0) {
|
||||
self.SpeedV.X = 0;
|
||||
enemySprite.Position.X = enemySprite.Position.X - bounds.Position.X;
|
||||
}
|
||||
//Up
|
||||
if (bounds.Y < 0) {
|
||||
self.SpeedV.Y = 0;
|
||||
enemySprite.Position.Y = enemySprite.Position.Y - bounds.Position.Y;
|
||||
}
|
||||
//Right
|
||||
if (bounds.X + bounds.Width > levelWidth) {
|
||||
self.SpeedV.X = 0;
|
||||
enemySprite.Position.X = levelWidth - (enemySprite.Right() - bounds.Right()) - bounds.Width;
|
||||
}
|
||||
}
|
||||
|
||||
//Move the enemy
|
||||
enemySprite.Position.X += self.SpeedV.X;
|
||||
enemySprite.Position.Y += self.SpeedV.Y;
|
||||
|
||||
//If the sprite is animated change its vertical offset depending on the player's state
|
||||
if (self.Sprite instanceof AnimatedSprite) {
|
||||
self.Sprite.VerticalOffset = self.CurrentState;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the enemy state randomly
|
||||
* @name ChangeEnemysState
|
||||
* @function
|
||||
* @memberOf Enemy
|
||||
*/
|
||||
Enemy.prototype.ChangeEnemyState = function () {
|
||||
"use strict";
|
||||
/*globals SpriteEffects*/
|
||||
var self = this,
|
||||
enemySprite = self.Sprite;
|
||||
|
||||
self.CurrentState = Math.floor((Math.random() * 2));
|
||||
if (self.CurrentState === self.MOVING) {
|
||||
if (enemySprite.SpriteEffects === SpriteEffects.FlipHorizontally) {
|
||||
enemySprite.SpriteEffects = SpriteEffects.None;
|
||||
} else {
|
||||
enemySprite.SpriteEffects = SpriteEffects.FlipHorizontally;
|
||||
}
|
||||
}
|
||||
|
||||
//Reset the current frame if is an animated sprite
|
||||
if (enemySprite instanceof AnimatedSprite) {
|
||||
enemySprite.CurrentFrame = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The enemys's collision rectangle.
|
||||
* @name Bounds
|
||||
* @function
|
||||
* @memberOf Enemy
|
||||
*/
|
||||
Enemy.prototype.Bounds = function () {
|
||||
"use strict";
|
||||
/*globals Rectangle*/
|
||||
var self = this,
|
||||
spriteBounds = self.Sprite.Bounds();
|
||||
|
||||
return new Rectangle(
|
||||
spriteBounds.X + spriteBounds.HalfWidth() / 2,
|
||||
spriteBounds.Y + 20,
|
||||
spriteBounds.HalfWidth(),
|
||||
spriteBounds.Height - 20
|
||||
);
|
||||
};
|
27
src/JS/Rayman_Classes/Enums.js
Normal file
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Defines the types of the pickable objects.
|
||||
* @readonly
|
||||
* @enum {number}
|
||||
*/
|
||||
var PickableObjectTypes = Object.freeze({
|
||||
"PEARL": 0,
|
||||
"LIFE": 1,
|
||||
"MINI_SHIELD": 2,
|
||||
"SHIELD": 3,
|
||||
"PUNCH_SPEED": 4,
|
||||
"PUNCH_POWER": 5,
|
||||
"ETERNAL_FLY": 6
|
||||
});
|
||||
|
||||
/**
|
||||
* Defines the powers.
|
||||
* @readonly
|
||||
* @enum {number}
|
||||
*/
|
||||
var Powers = Object.freeze({
|
||||
"PUNCH": 0,
|
||||
"HOLD": 1,
|
||||
"FLY": 2,
|
||||
"ENGAGE": 3,
|
||||
"RUN": 4
|
||||
});
|
1886
src/JS/Rayman_Classes/Level.js
Normal file
342
src/JS/Rayman_Classes/Player.js
Normal file
@ -0,0 +1,342 @@
|
||||
/**
|
||||
* Represents the player, in this case, Rayman.
|
||||
* @constructor
|
||||
* @param {AnimatedSprite|Sprite} sprite - The player's sprite.
|
||||
*/
|
||||
function Player(sprite) {
|
||||
"use strict";
|
||||
/*globals Vector2, AnimatedSprite*/
|
||||
this.Sprite = sprite; //The player sprite
|
||||
|
||||
//Physics properties
|
||||
this.SpeedV = Vector2.Zero();
|
||||
this.AccelerationV = Vector2.Zero();
|
||||
this.SpeedLimit = 3;
|
||||
this.GroundFriction = 1; //0.96
|
||||
//this.bounce = -0.7;
|
||||
|
||||
//Platform game properties
|
||||
this.IsOnGround = undefined;
|
||||
this.JumpForce = -8;
|
||||
|
||||
//Player States
|
||||
this.IDLE = 0;
|
||||
this.MOVING = 3;
|
||||
this.JUMPING = 4;
|
||||
this.FLYING = 10;
|
||||
this.HITTED = 5;
|
||||
//this.CROUCHED = 4;
|
||||
//[...]
|
||||
this.CurrentState = 0;
|
||||
|
||||
//Player attributtes (Rayman)
|
||||
this.Pearls = 0;
|
||||
//this.Life = 3;
|
||||
this.Shield = 5;
|
||||
this.CanFly = false;
|
||||
this.PunchImproved = false;
|
||||
|
||||
//The punch (Rayman)
|
||||
this.Punch = null;
|
||||
|
||||
//If the sprite is animated starts the sprite animation
|
||||
if (this.Sprite instanceof AnimatedSprite) {
|
||||
this.Sprite.StartAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates de player.
|
||||
* @name Update
|
||||
* @function
|
||||
* @param {Boolean} moveLeft - Tells if the player moved left or not.
|
||||
* @param {Boolean} moveRight - Tells if the player moved right or not.
|
||||
* @param {Boolean} jump - Tells if the player jumped or not.
|
||||
* @param {Boolean} punchPressed - Tells if the player shoot the punch or not.
|
||||
* @param {Array} platforms - The platforms array.
|
||||
* @param {Number} levelWidth - The width of the level.
|
||||
* @param {Array} pickableObjects - The pickable objects array.
|
||||
* @param {Array} sprites - The sprites array.
|
||||
* @param {Number} gravityForce - The gravity force.
|
||||
* @memberOf Player
|
||||
*/
|
||||
Player.prototype.Update = function (moveLeft, moveRight, jump, punchPressed, platforms, levelWidth, pickableObjects, sprites, gravityForce, soundEffects, enemys) {
|
||||
"use strict";
|
||||
/*globals SpriteEffects, Keyboard, Keys*/
|
||||
var self = this,
|
||||
playerSprite = self.Sprite,
|
||||
bounds = null,
|
||||
i = 0,
|
||||
len = 0,
|
||||
overlapV = null,
|
||||
currentPlatform = null,
|
||||
currentPickableObject = null,
|
||||
currentEnemy = null,
|
||||
index = 0;
|
||||
|
||||
//If rayman was hitted remove any control
|
||||
if (self.CurrentState !== self.HITTED) {
|
||||
//Left
|
||||
if (moveLeft && !moveRight) {
|
||||
self.AccelerationV.X = -2.8; //0.2
|
||||
self.GroundFriction = 1;
|
||||
self.CurrentState = self.MOVING;
|
||||
playerSprite.SpriteEffects = SpriteEffects.FlipHorizontally;
|
||||
}
|
||||
//Right
|
||||
if (moveRight && !moveLeft) {
|
||||
self.AccelerationV.X = 2.8; //0.2
|
||||
self.GroundFriction = 1;
|
||||
self.CurrentState = self.MOVING;
|
||||
playerSprite.SpriteEffects = SpriteEffects.None;
|
||||
}
|
||||
//Space
|
||||
if (jump && self.IsOnGround) {
|
||||
self.SpeedV.Y += self.JumpForce;
|
||||
self.IsOnGround = false;
|
||||
self.GroundFriction = 1;
|
||||
}
|
||||
|
||||
//Set the player's acceleration, friction and gravity
|
||||
//to zero if none of the arrow keys are being pressed
|
||||
if (!moveLeft && !moveRight) {
|
||||
self.AccelerationV.X = 0;
|
||||
self.GroundFriction = 0.1; //0.96
|
||||
gravityForce = 0.3;
|
||||
self.CurrentState = self.IDLE;
|
||||
}
|
||||
|
||||
//If player is in the air set the state to "jumping"
|
||||
if (!self.IsOnGround) {
|
||||
self.CurrentState = self.JUMPING;
|
||||
self.hitGroundCounter = 0;
|
||||
}
|
||||
|
||||
//Apply the acceleration
|
||||
self.SpeedV.X += self.AccelerationV.X;
|
||||
self.SpeedV.Y += self.AccelerationV.Y;
|
||||
|
||||
//Apply friction
|
||||
if (self.IsOnGround) {
|
||||
self.SpeedV.X *= self.GroundFriction;
|
||||
}
|
||||
|
||||
//If space pressed and is not on ground then fly
|
||||
//If not apply gravity
|
||||
if (self.CanFly && (Keyboard.IsKeyDown(Keys.w) || Keyboard.IsKeyDown(Keys.up_arrow)) && !self.IsOnGround && self.SpeedV.Y > 0) {
|
||||
self.CurrentState = self.FLYING;
|
||||
self.SpeedV.X /= 2;
|
||||
self.SpeedV.Y = self.SpeedLimit / 3.2;
|
||||
soundEffects[1][1].Play();
|
||||
} else {
|
||||
self.SpeedV.Y += gravityForce;
|
||||
}
|
||||
|
||||
//Limit the speed
|
||||
//Don't limit the upward speed because it will choke the jump effect
|
||||
if (self.SpeedV.X > self.SpeedLimit) {
|
||||
self.SpeedV.X = self.SpeedLimit;
|
||||
}
|
||||
if (self.SpeedV.X < -self.SpeedLimit) {
|
||||
self.SpeedV.X = -self.SpeedLimit;
|
||||
}
|
||||
if (self.SpeedV.Y > self.SpeedLimit * 2) {
|
||||
self.SpeedV.Y = self.SpeedLimit * 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Move the player
|
||||
playerSprite.Position.X += self.SpeedV.X;
|
||||
playerSprite.Position.Y += self.SpeedV.Y;
|
||||
|
||||
//Update the punch
|
||||
if (punchPressed) {
|
||||
self.Punch.Update(playerSprite, levelWidth, sprites, enemys, soundEffects[0][1]);
|
||||
}
|
||||
|
||||
bounds = self.Bounds();
|
||||
|
||||
//Check for a collision between the player and the platforms
|
||||
for (i = 0, len = platforms.length; i < len; i += 1) {
|
||||
|
||||
currentPlatform = platforms[i];
|
||||
overlapV = bounds.Intersects(currentPlatform);
|
||||
|
||||
if (overlapV !== false && self.SpeedV.Y >= 0) {
|
||||
|
||||
if (bounds.Bottom() >= currentPlatform.Top() &&
|
||||
bounds.Bottom() <= currentPlatform.Bottom()) {
|
||||
|
||||
//Move the rectangle out of the collision
|
||||
playerSprite.Position.Y -= overlapV.Y;
|
||||
|
||||
//Tell the game that the player is on the ground if
|
||||
//it's standing on top of a platform
|
||||
self.IsOnGround = true;
|
||||
|
||||
//Neutralize gravity by applying its
|
||||
//exact opposite force to the character's vy
|
||||
self.SpeedV.Y = -gravityForce;
|
||||
|
||||
//Play the hit the ground sound effect if rayman is not moving in the Y axis
|
||||
if (self.hitGroundCounter === 0) {
|
||||
soundEffects[10][1].Play();
|
||||
self.hitGroundCounter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (overlapV === false && self.SpeedV.Y > 0) {
|
||||
self.IsOnGround = false;
|
||||
}
|
||||
}
|
||||
|
||||
//Check for a collision between the player and the pickable objects
|
||||
for (i = 0, len = pickableObjects.length; i < len; i += 1) {
|
||||
|
||||
currentPickableObject = pickableObjects[i];
|
||||
|
||||
overlapV = bounds.Intersects(currentPickableObject.Bounds());
|
||||
|
||||
//If the collision occurs pick the object and delete the object from the level
|
||||
if (overlapV !== false) {
|
||||
|
||||
self.PickObject(currentPickableObject, soundEffects);
|
||||
index = sprites.indexOf(currentPickableObject.Sprite);
|
||||
if (index !== -1) {
|
||||
sprites.splice(index, 1);
|
||||
}
|
||||
index = pickableObjects.indexOf(currentPickableObject);
|
||||
if (index !== -1) {
|
||||
pickableObjects.splice(index, 1);
|
||||
len -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Check for a collision between the player and the enemys if the player wasn't hitted
|
||||
//in one second
|
||||
if (self.CurrentState !== self.HITTED) {
|
||||
for (i = 0, len = enemys.length; i < len; i += 1) {
|
||||
|
||||
currentEnemy = enemys[i];
|
||||
|
||||
overlapV = bounds.Intersects(currentEnemy.Bounds());
|
||||
|
||||
//If the collision occurs throw rayman away
|
||||
if (currentEnemy.CurrentState !== currentEnemy.HITTED && overlapV !== false) {
|
||||
|
||||
self.SpeedV.Y += self.JumpForce / 3;
|
||||
if (playerSprite.SpriteEffects === SpriteEffects.FlipHorizontally) {
|
||||
self.SpeedV.X += self.SpeedLimit * 2;
|
||||
} else {
|
||||
self.SpeedV.X -= self.SpeedLimit * 2;
|
||||
}
|
||||
self.IsOnGround = false;
|
||||
self.GroundFriction = 1;
|
||||
self.CurrentState = self.HITTED;
|
||||
//Set timeout to avoid many hits in a row
|
||||
setTimeout(function () {
|
||||
self.CurrentState = self.IDLE;
|
||||
}, 600);
|
||||
//Play the hitted sound
|
||||
soundEffects[6][1].Play();
|
||||
//Decrement the shield by 1 point
|
||||
self.Shield -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Screen boundaries
|
||||
bounds = self.Bounds();
|
||||
//Left
|
||||
if (bounds.X < 0) {
|
||||
self.SpeedV.X = 0;
|
||||
playerSprite.Position.X = playerSprite.Position.X - bounds.X;
|
||||
}
|
||||
//Up
|
||||
if (bounds.Y < 0) {
|
||||
self.SpeedV.Y = 0;
|
||||
playerSprite.Position.Y = playerSprite.Position.Y - bounds.Y;
|
||||
}
|
||||
//Right
|
||||
if (bounds.X + bounds.Width > levelWidth) {
|
||||
self.SpeedV.X = 0;
|
||||
playerSprite.Position.X = levelWidth - (playerSprite.Right() - bounds.Right()) - bounds.Width;
|
||||
}
|
||||
|
||||
//If the sprite is animated change its vertical offset depending on the player's state
|
||||
if (self.Sprite instanceof AnimatedSprite) {
|
||||
self.Sprite.VerticalOffset = self.CurrentState;
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.PickObject = function (object, soundEffects) {
|
||||
"use strict";
|
||||
/*globals PickableObjectTypes*/
|
||||
var self = this;
|
||||
|
||||
switch (object.Type) {
|
||||
case PickableObjectTypes.PEARL:
|
||||
self.Pearls += 1;
|
||||
if (self.Pearls >= 100) {
|
||||
self.Pearls = 0;
|
||||
self.Life += 1;
|
||||
}
|
||||
soundEffects[3][1].Play();
|
||||
break;
|
||||
|
||||
case PickableObjectTypes.LIFE:
|
||||
self.Life += 1;
|
||||
break;
|
||||
|
||||
case PickableObjectTypes.MINI_SHIELD:
|
||||
self.Shield += 1;
|
||||
if (self.Shield > 5) {
|
||||
self.Shield = 5;
|
||||
}
|
||||
break;
|
||||
|
||||
case PickableObjectTypes.SHIELD:
|
||||
self.Shield = 5;
|
||||
soundEffects[7][1].Play();
|
||||
break;
|
||||
|
||||
case PickableObjectTypes.PUNCH_SPEED:
|
||||
self.Punch.Speed = 8;
|
||||
self.Punch.MaxScope = 290;
|
||||
self.Punch.Sprite.SourceRect.X += 20;
|
||||
self.PunchImproved = true;
|
||||
soundEffects[4][1].Play();
|
||||
break;
|
||||
|
||||
case PickableObjectTypes.PUNCH_POWER:
|
||||
self.Punch.Power = 1.5;
|
||||
break;
|
||||
|
||||
case PickableObjectTypes.ETERNAL_FLY:
|
||||
self.CanFly = true;
|
||||
soundEffects[4][1].Play();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The player's collision rectangle.
|
||||
* @name Bounds
|
||||
* @function
|
||||
* @memberOf Player
|
||||
*/
|
||||
Player.prototype.Bounds = function () {
|
||||
"use strict";
|
||||
/*globals Rectangle*/
|
||||
var self = this,
|
||||
spriteBounds = self.Sprite.Bounds();
|
||||
|
||||
return new Rectangle(
|
||||
spriteBounds.X + spriteBounds.HalfWidth() / 2,
|
||||
spriteBounds.Y + 20,
|
||||
spriteBounds.HalfWidth(),
|
||||
spriteBounds.Height - 20
|
||||
);
|
||||
};
|
133
src/JS/Rayman_Classes/Projectile.js
Normal file
@ -0,0 +1,133 @@
|
||||
/**
|
||||
* Represents the Rayman's punch.
|
||||
* @constructor
|
||||
* @param {Sprite} sprite - The sprite of the punch.
|
||||
*/
|
||||
function Projectile(sprite) {
|
||||
"use strict";
|
||||
/*globals Vector2*/
|
||||
this.Sprite = sprite;
|
||||
this.Speed = 6;
|
||||
this.MaxScope = 200;
|
||||
this.ScopeCounter = 0;
|
||||
this.IsReturning = false;
|
||||
this.Power = 1;
|
||||
this.SpeedV = Vector2.Zero();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates de player's (Rayman) punch.
|
||||
* @name Update
|
||||
* @function
|
||||
* @param {Sprite} playerSprite - The player's sprite.
|
||||
* @param {Number} levelWidth - The width of the level.
|
||||
* @memberOf Projectile
|
||||
*/
|
||||
Projectile.prototype.Update = function (playerSprite, levelWidth, sprites, enemys, enemyHittedSound) {
|
||||
"use strict";
|
||||
/*globals SpriteEffects*/
|
||||
var self = this,
|
||||
moveDistance = 0,
|
||||
moveVector = null,
|
||||
d = null,
|
||||
punchSprite = self.Sprite,
|
||||
bounds = punchSprite.Bounds(),
|
||||
currentEnemy = null,
|
||||
i = 0,
|
||||
len = 0,
|
||||
overlapV = null,
|
||||
aux = 0,
|
||||
aux2 = null;
|
||||
|
||||
//If the punch isn't visible update its position with the player position
|
||||
if (!punchSprite.IsVisible) {
|
||||
|
||||
punchSprite.IsVisible = true;
|
||||
punchSprite.Position.X = playerSprite.Position.X + playerSprite.HalfWidth() - punchSprite.HalfWidth();
|
||||
punchSprite.Position.Y = playerSprite.Position.Y + playerSprite.HalfHeight() - punchSprite.HalfHeight();
|
||||
punchSprite.SpriteEffects = playerSprite.SpriteEffects;
|
||||
|
||||
} else {
|
||||
|
||||
//Control the scope
|
||||
if (self.ScopeCounter >= self.MaxScope ||
|
||||
bounds.X < 0 ||
|
||||
bounds.Y < 0 ||
|
||||
bounds.X + bounds.Width > levelWidth) {
|
||||
|
||||
self.ScopeCounter = 0;
|
||||
self.IsReturning = true;
|
||||
if (punchSprite.SpriteEffects === SpriteEffects.FlipHorizontally) {
|
||||
punchSprite.SpriteEffects = SpriteEffects.None;
|
||||
} else {
|
||||
punchSprite.SpriteEffects = SpriteEffects.FlipHorizontally;
|
||||
}
|
||||
}
|
||||
|
||||
//If the punch is returning to the player update the movement
|
||||
if (self.IsReturning) {
|
||||
|
||||
moveVector = new Vector2(playerSprite.Center().X - punchSprite.Center().X, playerSprite.Center().Y - punchSprite.Center().Y);
|
||||
d = moveVector.Normalize();
|
||||
|
||||
//Increase the punch's velocity
|
||||
self.SpeedV.X += d.X;
|
||||
self.SpeedV.Y += d.Y;
|
||||
|
||||
d = self.SpeedV.Normalize();
|
||||
|
||||
//Apply easing
|
||||
self.SpeedV.X = self.Speed * d.X;
|
||||
self.SpeedV.Y = self.Speed * d.Y;
|
||||
punchSprite.Position.X += self.SpeedV.X;
|
||||
punchSprite.Position.Y += self.SpeedV.Y;
|
||||
|
||||
//If not update the position with the speed
|
||||
} else {
|
||||
|
||||
if (punchSprite.SpriteEffects === SpriteEffects.FlipHorizontally) {
|
||||
punchSprite.Position.X += self.Speed * -1;
|
||||
} else {
|
||||
punchSprite.Position.X += self.Speed;
|
||||
}
|
||||
self.ScopeCounter += self.Speed;
|
||||
}
|
||||
|
||||
//Check for a collision between the punch and the enemys
|
||||
for (i = 0, len = enemys.length; i < len; i += 1) {
|
||||
|
||||
currentEnemy = enemys[i];
|
||||
|
||||
overlapV = self.Sprite.Bounds().Intersects(currentEnemy.Bounds());
|
||||
|
||||
//If the collision occurs throw rayman away
|
||||
if (currentEnemy.CurrentState !== currentEnemy.HITTED && overlapV !== false) {
|
||||
|
||||
//Set the punch returning
|
||||
self.ScopeCounter = 0;
|
||||
self.IsReturning = true;
|
||||
if (punchSprite.SpriteEffects === SpriteEffects.FlipHorizontally) {
|
||||
punchSprite.SpriteEffects = SpriteEffects.None;
|
||||
} else {
|
||||
punchSprite.SpriteEffects = SpriteEffects.FlipHorizontally;
|
||||
}
|
||||
|
||||
currentEnemy.CurrentState = currentEnemy.HITTED;
|
||||
currentEnemy.SpeedV.Y = -4;
|
||||
clearInterval(currentEnemy.interval);
|
||||
|
||||
//Set timeout to avoid many hits in a row
|
||||
aux = i;
|
||||
aux2 = currentEnemy;
|
||||
setTimeout(function () {
|
||||
aux2.Sprite.IsVisible = false;
|
||||
enemys.splice(aux, 1);
|
||||
}, 600);
|
||||
|
||||
//Play the hitted sound
|
||||
enemyHittedSound.Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
338
src/JS/Unit_Testing/Test_GraphicsDevice_AnimatedSprite.js
Normal file
@ -0,0 +1,338 @@
|
||||
/**
|
||||
* Provides basic graphics device initialization, game logic, and rendering code.
|
||||
*/
|
||||
function Game() {
|
||||
"use strict";
|
||||
/*globals ContentManager, GraphicsDevice, document, SpriteBatch, GameStates, Vector2, Point, Sprite, AnimatedSprite, Rectangle, AnimationTypes, Segment, SpriteEffects, Mouse, Keys, Keyboard*/
|
||||
this.Content = new ContentManager();
|
||||
this.GraphicsDevice = new GraphicsDevice(document);
|
||||
this.spriteBatch = null;
|
||||
this.gameState = GameStates.Initializing;
|
||||
this.preloading = true;
|
||||
|
||||
//Constants
|
||||
this.FONT_LITTLE = "normal bold 15px Helvetica";
|
||||
this.FONT_BIG = "normal bold 18px Helvetica";
|
||||
this.BLACK = "#000000";
|
||||
this.GREEN = "#00FF00";
|
||||
this.RED = "#FF0000";
|
||||
this.BLUE = "#0000FF";
|
||||
this.SPEED = 3;
|
||||
|
||||
//The animated sprite
|
||||
this.image = null;
|
||||
this.sprite = null;
|
||||
|
||||
//Flags
|
||||
this.showBounds = false;
|
||||
this.animStarted = false;
|
||||
|
||||
//Other variables
|
||||
this.animTypeIndex = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the game to perform any initialization it needs to before starting to run.
|
||||
* This is where it can query for any required services and load any non-graphic
|
||||
* related content.
|
||||
* @name Initialize
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Initialize = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
// TODO: Add your initialization logic here
|
||||
|
||||
self.gameState = GameStates.Loading;
|
||||
};
|
||||
|
||||
/**
|
||||
* LoadContent will be called once per game and is the place to load
|
||||
* all of your content.
|
||||
* @name LoadContent
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.LoadContent = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
if (self.preloading) {
|
||||
// Create a new SpriteBatch, which can be used to draw textures.
|
||||
self.spriteBatch = new SpriteBatch(self.GraphicsDevice);
|
||||
|
||||
self.image = self.Content.LoadTexture2D("../../images/test_sprite.png");
|
||||
|
||||
self.preloading = false;
|
||||
}
|
||||
|
||||
if (self.Content.AllContentLoaded()) {
|
||||
//texture, scale, sourceRect, position, isVisible, animationType, numberOfFrames, millisecondsPerFrame
|
||||
self.sprite = new AnimatedSprite(
|
||||
self.image,
|
||||
new Vector2(0.5, 0.5),
|
||||
new Rectangle(0, 0, 128, 128),
|
||||
new Point(500, 200),
|
||||
true,
|
||||
AnimationTypes.Loop,
|
||||
14,
|
||||
100
|
||||
);
|
||||
|
||||
self.GraphicsDevice.canvas.addEventListener("click", self.GraphicsDevice.ToggleFullScreen.bind(self.GraphicsDevice));
|
||||
self.gameState = GameStates.Playing;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Allows the game to run logic such as updating the world,
|
||||
* checking for collisions, gathering input, and playing audio.
|
||||
* @name Update
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Update = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
//GraphicsDevice
|
||||
if (Mouse.IsButtonClicked(Mouse.RightButton)) {
|
||||
self.GraphicsDevice.ToggleFullPage();
|
||||
}
|
||||
|
||||
//AnimatedSprite
|
||||
if (Keyboard.IsKeyDown(Keys.left_arrow)) {
|
||||
self.sprite.Position.X -= self.SPEED;
|
||||
}
|
||||
if (Keyboard.IsKeyDown(Keys.right_arrow)) {
|
||||
self.sprite.Position.X += self.SPEED;
|
||||
|
||||
}
|
||||
if (Keyboard.IsKeyDown(Keys.up_arrow)) {
|
||||
self.sprite.Position.Y -= self.SPEED;
|
||||
|
||||
}
|
||||
if (Keyboard.IsKeyDown(Keys.down_arrow)) {
|
||||
self.sprite.Position.Y += self.SPEED;
|
||||
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.a)) {
|
||||
self.animTypeIndex += 1;
|
||||
if (self.animTypeIndex > 2) {
|
||||
self.animTypeIndex = 0;
|
||||
}
|
||||
self.sprite.AnimationType = self.animTypeIndex;
|
||||
self.sprite.CurrentFrame = 0;
|
||||
self.sprite.Forward = true;
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.b)) {
|
||||
if (self.showBounds) {
|
||||
self.showBounds = false;
|
||||
} else {
|
||||
self.showBounds = true;
|
||||
}
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.h)) {
|
||||
if (self.sprite.SpriteEffects === SpriteEffects.FlipHorizontally) {
|
||||
self.sprite.SpriteEffects = SpriteEffects.None;
|
||||
} else {
|
||||
self.sprite.SpriteEffects = SpriteEffects.FlipHorizontally;
|
||||
}
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.v)) {
|
||||
if (self.sprite.SpriteEffects === SpriteEffects.FlipVertically) {
|
||||
self.sprite.SpriteEffects = SpriteEffects.None;
|
||||
} else {
|
||||
self.sprite.SpriteEffects = SpriteEffects.FlipVertically;
|
||||
}
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.s)) {
|
||||
if (self.animStarted) {
|
||||
self.sprite.StopAnimation();
|
||||
self.animStarted = false;
|
||||
} else {
|
||||
self.sprite.RunAnimation = true;
|
||||
if (self.sprite.AnimationType === AnimationTypes.PlayOneTime) {
|
||||
self.sprite.CurrentFrame = 0;
|
||||
self.sprite.Forward = true;
|
||||
}
|
||||
self.sprite.StartAnimation();
|
||||
self.animStarted = true;
|
||||
}
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.m)) {
|
||||
self.sprite.MillisecondsPerFrame += 20;
|
||||
//It's compulsory to restart animation
|
||||
self.sprite.StopAnimation();
|
||||
if (self.animStarted) {
|
||||
self.sprite.StartAnimation();
|
||||
}
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.l)) {
|
||||
self.sprite.MillisecondsPerFrame -= 20;
|
||||
if (self.sprite.MillisecondsPerFrame < 0) {
|
||||
self.sprite.MillisecondsPerFrame = 0;
|
||||
}
|
||||
//It's compulsory to restart animation
|
||||
self.sprite.StopAnimation();
|
||||
if (self.animStarted) {
|
||||
self.sprite.StartAnimation();
|
||||
}
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.add)) {
|
||||
self.sprite.Scale.X += 0.1;
|
||||
self.sprite.Scale.Y += 0.1;
|
||||
if (self.sprite.Scale.X > 1.1 || self.sprite.Scale.Y > 1.1) {
|
||||
self.sprite.Scale.X = 1.1;
|
||||
self.sprite.Scale.Y = 1.1;
|
||||
}
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.subtract)) {
|
||||
self.sprite.Scale.X -= 0.1;
|
||||
self.sprite.Scale.Y -= 0.1;
|
||||
if (self.sprite.Scale.X < 0.1 || self.sprite.Scale.Y < 0.1) {
|
||||
self.sprite.Scale.X = 0.1;
|
||||
self.sprite.Scale.Y = 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
//Map bounds
|
||||
if (self.sprite.Position.X < 335) {
|
||||
self.sprite.Position.X = 335;
|
||||
}
|
||||
if (self.sprite.Position.X + self.sprite.Width() > 800) {
|
||||
self.sprite.Position.X = 800 - self.sprite.Width();
|
||||
}
|
||||
if (self.sprite.Position.Y < 0) {
|
||||
self.sprite.Position.Y = 0;
|
||||
}
|
||||
if (self.sprite.Position.Y + self.sprite.Height() > 420) {
|
||||
self.sprite.Position.Y = 420 - self.sprite.Height();
|
||||
}
|
||||
|
||||
self.sprite.Rotation = Mouse.ScrollWheelValue * 10;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is called when the game should draw itself.
|
||||
* @name Draw
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Draw = function () {
|
||||
"use strict";
|
||||
var self = this,
|
||||
position = self.sprite.Position,
|
||||
scale = self.sprite.Scale,
|
||||
center = self.sprite.Center();
|
||||
|
||||
self.GraphicsDevice.Clear();
|
||||
|
||||
//GraphicsDevice
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "------ GraphicsDevice ------", new Point(30, 20), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "PreferredBackBufferWidth: " + self.GraphicsDevice.PreferredBackBufferWidth() + " pixels", new Point(30, 45), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "PreferredBackBufferHeight: " + self.GraphicsDevice.PreferredBackBufferHeight() + " pixels", new Point(30, 70), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Is canvas in full page mode? " + self.GraphicsDevice.IsFullPage(), new Point(30, 95), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Is canvas in full screen mode: " + self.GraphicsDevice.IsFullScreen(), new Point(30, 120), self.BLACK, Vector2.One());
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "------ AnimatedSprite ------", new Point(30, 160), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "X: " + position.X.toFixed(2) + " Y: " + position.Y.toFixed(2), new Point(30, 185), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Scale (width): " + scale.X.toFixed(2) + " Scale (height): " + scale.Y.toFixed(2), new Point(30, 210), self.BLACK, Vector2.One());
|
||||
switch (self.sprite.SpriteEffects) {
|
||||
case SpriteEffects.None:
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Sprite effects: None", new Point(30, 235), self.BLACK, Vector2.One());
|
||||
break;
|
||||
case SpriteEffects.FlipHorizontally:
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Sprite effects: FlipHorizontally", new Point(30, 235), self.BLACK, Vector2.One());
|
||||
break;
|
||||
case SpriteEffects.FlipVertically:
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Sprite effects: FlipVertically", new Point(30, 235), self.BLACK, Vector2.One());
|
||||
break;
|
||||
}
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Rotation: " + self.sprite.Rotation, new Point(30, 260), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Top: " + self.sprite.Top().toFixed(2), new Point(30, 285), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Bottom: " + self.sprite.Bottom().toFixed(2), new Point(30, 310), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Left: " + self.sprite.Left().toFixed(2), new Point(30, 335), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Right: " + self.sprite.Right().toFixed(2), new Point(30, 360), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Half width: " + self.sprite.HalfWidth().toFixed(2), new Point(30, 385), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Half height: " + self.sprite.HalfHeight().toFixed(2), new Point(30, 410), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Center X: " + center.X.toFixed(2) + " Center Y: " + center.Y.toFixed(2), new Point(30, 435), self.BLACK, Vector2.One());
|
||||
switch (self.sprite.AnimationType) {
|
||||
case AnimationTypes.Loop:
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Animation type: Loop", new Point(30, 460), self.BLACK, Vector2.One());
|
||||
break;
|
||||
case AnimationTypes.PingPongLoop:
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Animation type: PingPongLoop", new Point(30, 460), self.BLACK, Vector2.One());
|
||||
break;
|
||||
case AnimationTypes.PlayOneTime:
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Animation type: PlayOneTime", new Point(30, 460), self.BLACK, Vector2.One());
|
||||
break;
|
||||
}
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Milliseconds per frame: " + self.sprite.MillisecondsPerFrame, new Point(30, 485), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Current frame / Number of frames: " + self.sprite.CurrentFrame + "/" + self.sprite.NumberOfFrames, new Point(30, 510), self.BLACK, Vector2.One());
|
||||
|
||||
//Draw the separating lines
|
||||
self.spriteBatch.DrawSegment(new Segment(new Point(335, 0), new Point(335, 600)), "3", self.BLACK);
|
||||
self.spriteBatch.DrawSegment(new Segment(new Point(335, 420), new Point(800, 420)), "3", self.BLACK);
|
||||
|
||||
//Instructions
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Left click to enter full screen", new Point(347, 440), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Press B to show bounds", new Point(347, 465), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Press arrow keys to move it", new Point(347, 490), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Press M to increase milliseconds", new Point(347, 515), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Press L to decrease milliseconds", new Point(347, 540), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Press S to start/stop anim.", new Point(347, 565), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Right click to enter full page", new Point(592, 440), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Press A to change anim. type", new Point(592, 465), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Press H to flip horizontally", new Point(592, 490), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Press V to flip vertically", new Point(592, 515), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "+/- to incr./decr. scale", new Point(592, 540), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Mouse wheel to rotate sprite", new Point(592, 565), self.BLUE, Vector2.One());
|
||||
|
||||
//The sprite
|
||||
self.spriteBatch.Draw(
|
||||
self.sprite.Texture,
|
||||
self.sprite.Position,
|
||||
self.sprite.SourceRect,
|
||||
self.sprite.Rotation,
|
||||
self.sprite.Scale,
|
||||
self.sprite.SpriteEffects
|
||||
);
|
||||
|
||||
//Bounds
|
||||
if (self.showBounds) {
|
||||
self.spriteBatch.DrawRectangle(self.sprite.Bounds(), "3", self.GREEN);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Call this method to initialize the game, begin running the game loop, and
|
||||
* start processing events for the game.
|
||||
* @name Run
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Run = function () {
|
||||
"use strict";
|
||||
/*globals requestAnimationFrame*/
|
||||
var self = this;
|
||||
|
||||
//Call the game loop
|
||||
requestAnimationFrame(self.Run.bind(self), self.GraphicsDevice.canvas);
|
||||
|
||||
//Choose the method to run according to the game state
|
||||
switch (self.gameState) {
|
||||
case GameStates.Initializing:
|
||||
self.Initialize();
|
||||
break;
|
||||
case GameStates.Loading:
|
||||
self.LoadContent();
|
||||
break;
|
||||
case GameStates.Playing:
|
||||
self.Update();
|
||||
self.Draw();
|
||||
break;
|
||||
}
|
||||
};
|
183
src/JS/Unit_Testing/Test_Mouse_Keyboard.js
Normal file
@ -0,0 +1,183 @@
|
||||
/**
|
||||
* Provides basic graphics device initialization, game logic, and rendering code.
|
||||
*/
|
||||
function Game() {
|
||||
"use strict";
|
||||
/*globals ContentManager, GraphicsDevice, document, SpriteBatch, GameStates*/
|
||||
this.Content = new ContentManager();
|
||||
this.GraphicsDevice = new GraphicsDevice(document);
|
||||
this.spriteBatch = null;
|
||||
this.gameState = GameStates.Initializing;
|
||||
this.preloading = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the game to perform any initialization it needs to before starting to run.
|
||||
* This is where it can query for any required services and load any non-graphic
|
||||
* related content.
|
||||
* @name Initialize
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Initialize = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
// TODO: Add your initialization logic here
|
||||
|
||||
self.gameState = GameStates.Loading;
|
||||
};
|
||||
|
||||
/**
|
||||
* LoadContent will be called once per game and is the place to load
|
||||
* all of your content.
|
||||
* @name LoadContent
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.LoadContent = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
if (self.preloading) {
|
||||
// Create a new SpriteBatch, which can be used to draw textures.
|
||||
self.spriteBatch = new SpriteBatch(self.GraphicsDevice);
|
||||
|
||||
// TODO: use this.Content.Load... to load your game content here
|
||||
|
||||
self.preloading = false;
|
||||
}
|
||||
|
||||
if (self.Content.AllContentLoaded) {
|
||||
// TODO: create the objects that will use the content previously loaded
|
||||
|
||||
self.gameState = GameStates.Playing;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Allows the game to run logic such as updating the world,
|
||||
* checking for collisions, gathering input, and playing audio.
|
||||
* @name Update
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Update = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
// TODO: Add your update logic here
|
||||
};
|
||||
|
||||
/**
|
||||
* This is called when the game should draw itself.
|
||||
* @name Draw
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Draw = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
self.GraphicsDevice.Clear();
|
||||
|
||||
// TODO: Add your drawing code here
|
||||
self.GraphicsDevice.Clear();
|
||||
|
||||
self.spriteBatch.DrawString(
|
||||
"normal bold 18px Helvetica",
|
||||
"------ MOUSE ------",
|
||||
new Point(30, 20),
|
||||
"#000000",
|
||||
Vector2.One()
|
||||
);
|
||||
self.spriteBatch.DrawString(
|
||||
"normal bold 16px Helvetica",
|
||||
"X: "+Mouse.X+" Y: "+Mouse.Y,
|
||||
new Point(30, 50),
|
||||
"#000000",
|
||||
Vector2.One()
|
||||
);
|
||||
self.spriteBatch.DrawString(
|
||||
"normal bold 16px Helvetica",
|
||||
"Wheel: "+Mouse.ScrollWheelValue,
|
||||
new Point(30, 80),
|
||||
"#000000",
|
||||
Vector2.One()
|
||||
);
|
||||
self.spriteBatch.DrawString(
|
||||
"normal bold 16px Helvetica",
|
||||
"LeftButtonPressed: "+Mouse.LeftButtonPressed,
|
||||
new Point(30, 110),
|
||||
"#000000",
|
||||
Vector2.One()
|
||||
);
|
||||
self.spriteBatch.DrawString(
|
||||
"normal bold 16px Helvetica",
|
||||
"RightButtonPressed: "+Mouse.RightButtonPressed,
|
||||
new Point(30, 140),
|
||||
"#000000",
|
||||
Vector2.One()
|
||||
);
|
||||
self.spriteBatch.DrawString(
|
||||
"normal bold 16px Helvetica",
|
||||
"MiddleButtonPressed: "+Mouse.MiddleButtonPressed,
|
||||
new Point(30, 170),
|
||||
"#000000",
|
||||
Vector2.One()
|
||||
);
|
||||
|
||||
self.spriteBatch.DrawString(
|
||||
"normal bold 18px Helvetica",
|
||||
"------ KEYBOARD ------",
|
||||
new Point(30, 230),
|
||||
"#000000",
|
||||
Vector2.One()
|
||||
);
|
||||
|
||||
self.spriteBatch.DrawString(
|
||||
"normal bold 16px Helvetica",
|
||||
"Teclas que están siendo pulsadas: "+Keyboard.keyDownList,
|
||||
new Point(30, 260),
|
||||
"#000000",
|
||||
Vector2.One()
|
||||
);
|
||||
|
||||
self.spriteBatch.DrawString(
|
||||
"normal bold 16px Helvetica",
|
||||
"Teclas pulsadas: "+Keyboard.keyUpList,
|
||||
new Point(30, 290),
|
||||
"#000000",
|
||||
Vector2.One()
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Call this method to initialize the game, begin running the game loop, and
|
||||
* start processing events for the game.
|
||||
* @name Run
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Run = function () {
|
||||
"use strict";
|
||||
/*globals requestAnimationFrame*/
|
||||
var self = this;
|
||||
|
||||
//Call the game loop
|
||||
requestAnimationFrame(self.Run.bind(self), self.GraphicsDevice.canvas);
|
||||
|
||||
//Choose the method to run according to the game state
|
||||
switch (self.gameState) {
|
||||
case GameStates.Initializing:
|
||||
self.Initialize();
|
||||
break;
|
||||
case GameStates.Loading:
|
||||
self.LoadContent();
|
||||
break;
|
||||
case GameStates.Playing:
|
||||
self.Update();
|
||||
self.Draw();
|
||||
break;
|
||||
}
|
||||
};
|
377
src/JS/Unit_Testing/Test_Point_Vector2_Rectangle.js
Normal file
@ -0,0 +1,377 @@
|
||||
/**
|
||||
* Provides basic graphics device initialization, game logic, and rendering code.
|
||||
*/
|
||||
function Game() {
|
||||
"use strict";
|
||||
/*globals ContentManager, GraphicsDevice, document, SpriteBatch, GameStates, Point, Vector2, Rectangle, Keyboard, Keys, Mouse, Segment*/
|
||||
this.Content = new ContentManager();
|
||||
this.GraphicsDevice = new GraphicsDevice(document);
|
||||
this.spriteBatch = null;
|
||||
this.gameState = GameStates.Initializing;
|
||||
this.preloading = true;
|
||||
|
||||
//Constants
|
||||
this.FONT_LITTLE = "normal bold 15px Helvetica";
|
||||
this.FONT_BIG = "normal bold 18px Helvetica";
|
||||
this.BLACK = "#000000";
|
||||
this.GREEN = "#00FF00";
|
||||
this.RED = "#FF0000";
|
||||
this.BLUE = "#0000FF";
|
||||
this.RECT_VEL = 3;
|
||||
this.RECT_INFLATE_VALUE = 2;
|
||||
|
||||
/***** TEST VARIABLES *****/
|
||||
this.testingRectangle = false;
|
||||
//Point
|
||||
this.pointZero_OK = false;
|
||||
this.pointOne_OK = false;
|
||||
this.pointsAreEqual = false;
|
||||
this.pointsAreDifferent = false;
|
||||
//Vector2
|
||||
this.vectorZero_OK = false;
|
||||
this.vectorOne_OK = false;
|
||||
this.vectorAdd_OK = false;
|
||||
this.vectorSubstract_OK = false;
|
||||
this.vectorDivide_OK = false;
|
||||
this.vectorMultiply_OK = false;
|
||||
this.vectorDistance_OK = false;
|
||||
this.vectorLength_OK = false;
|
||||
this.vectorsAreEqual = false;
|
||||
this.vectorsAreDifferent = false;
|
||||
//Rectangle
|
||||
this.r1 = null;
|
||||
this.r2 = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the game to perform any initialization it needs to before starting to run.
|
||||
* This is where it can query for any required services and load any non-graphic
|
||||
* related content.
|
||||
* @name Initialize
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Initialize = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
self.r1 = new Rectangle(430, 315, 20, 40);
|
||||
self.r2 = new Rectangle(690, 30, 80, 50);
|
||||
|
||||
self.gameState = GameStates.Loading;
|
||||
};
|
||||
|
||||
/**
|
||||
* LoadContent will be called once per game and is the place to load
|
||||
* all of your content.
|
||||
* @name LoadContent
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.LoadContent = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
if (self.preloading) {
|
||||
// Create a new SpriteBatch, which can be used to draw textures.
|
||||
self.spriteBatch = new SpriteBatch(self.GraphicsDevice);
|
||||
|
||||
// TODO: use this.Content.Load... to load your game content here
|
||||
|
||||
self.preloading = false;
|
||||
}
|
||||
|
||||
if (self.Content.AllContentLoaded) {
|
||||
// TODO: create the objects that will use the content previously loaded
|
||||
|
||||
self.gameState = GameStates.Playing;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Allows the game to run logic such as updating the world,
|
||||
* checking for collisions, gathering input, and playing audio.
|
||||
* @name Update
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Update = function () {
|
||||
"use strict";
|
||||
var self = this,
|
||||
p1 = null,
|
||||
p2 = null,
|
||||
v1 = null,
|
||||
v2 = null;
|
||||
|
||||
if (!self.testingRectangle && Keyboard.IsKeyPressed(Keys.r)) {
|
||||
self.testingRectangle = true;
|
||||
}
|
||||
|
||||
if (self.testingRectangle) {
|
||||
//Rectangle
|
||||
if (Keyboard.IsKeyDown(Keys.a) || Keyboard.IsKeyDown(Keys.left_arrow)) {
|
||||
self.r1.X -= self.RECT_VEL;
|
||||
}
|
||||
if (Keyboard.IsKeyDown(Keys.d) || Keyboard.IsKeyDown(Keys.right_arrow)) {
|
||||
self.r1.X += self.RECT_VEL;
|
||||
|
||||
}
|
||||
if (Keyboard.IsKeyDown(Keys.w) || Keyboard.IsKeyDown(Keys.up_arrow)) {
|
||||
self.r1.Y -= self.RECT_VEL;
|
||||
|
||||
}
|
||||
if (Keyboard.IsKeyDown(Keys.s) || Keyboard.IsKeyDown(Keys.down_arrow)) {
|
||||
self.r1.Y += self.RECT_VEL;
|
||||
|
||||
}
|
||||
if (Keyboard.IsKeyDown(Keys.add)) {
|
||||
self.r1.Inflate(self.RECT_INFLATE_VALUE, self.RECT_INFLATE_VALUE);
|
||||
if (self.r1.Width > 400) {
|
||||
self.r1.Width = 400;
|
||||
}
|
||||
if (self.r1.Height > 600) {
|
||||
self.r1.Height = 600;
|
||||
}
|
||||
}
|
||||
if (Keyboard.IsKeyDown(Keys.subtract)) {
|
||||
self.r1.Inflate(-self.RECT_INFLATE_VALUE, -self.RECT_INFLATE_VALUE);
|
||||
}
|
||||
|
||||
//Map bounds
|
||||
if (self.r1.X < 400) {
|
||||
self.r1.X = 400;
|
||||
}
|
||||
if (self.r1.X + self.r1.Width > 800) {
|
||||
self.r1.X = 800 - self.r1.Width;
|
||||
}
|
||||
if (self.r1.Y < 0) {
|
||||
self.r1.Y = 0;
|
||||
}
|
||||
if (self.r1.Y + self.r1.Height > 600) {
|
||||
self.r1.Y = 600 - self.r1.Height;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
//Point
|
||||
p1 = Point.Zero();
|
||||
p2 = Point.One();
|
||||
if (p1.X === 0 && p1.Y === 0) {
|
||||
self.pointZero_OK = true;
|
||||
}
|
||||
if (p2.X === 1 && p2.Y === 1) {
|
||||
self.pointOne_OK = true;
|
||||
}
|
||||
p2 = new Point(25, 150);
|
||||
self.pointsAreDifferent = !Point.Equals(p1, p2);
|
||||
p2 = new Point(0, 0);
|
||||
self.pointsAreEqual = Point.Equals(p1, p2);
|
||||
|
||||
//Vector2
|
||||
v1 = Vector2.Zero();
|
||||
v2 = Vector2.One();
|
||||
if (v1.X === 0 && v1.Y === 0) {
|
||||
self.vectorZero_OK = true;
|
||||
}
|
||||
if (v2.X === 1 && v2.Y === 1) {
|
||||
self.vectorOne_OK = true;
|
||||
}
|
||||
v1 = new Vector2(100, 150);
|
||||
self.vectorsAreDifferent = !Vector2.Equals(v1, v2);
|
||||
v2 = new Vector2(100, 150);
|
||||
self.vectorsAreEqual = Vector2.Equals(v1, v2);
|
||||
v2 = new Vector2(20, 25);
|
||||
self.vectorAdd_OK = Vector2.Equals(Vector2.Add(v1, v2), new Vector2(120, 175));
|
||||
self.vectorSubstract_OK = Vector2.Equals(Vector2.Substract(v1, v2), new Vector2(80, 125));
|
||||
self.vectorDivide_OK = Vector2.Equals(Vector2.Divide(v1, v2), new Vector2(5, 6));
|
||||
self.vectorMultiply_OK = Vector2.Equals(Vector2.Multiply(v1, v2), new Vector2(2000, 3750));
|
||||
self.vectorDistance_OK = Math.floor(Vector2.Distance(v1, v2)) === 148;
|
||||
self.vectorLength_OK = Math.floor(v2.Length()) === 32;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is called when the game should draw itself.
|
||||
* @name Draw
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Draw = function () {
|
||||
"use strict";
|
||||
var self = this,
|
||||
location = self.r1.Location(),
|
||||
center = self.r1.Center(),
|
||||
collision = (self.r2.Intersects(self.r1) !== false);
|
||||
|
||||
self.GraphicsDevice.Clear();
|
||||
|
||||
if (self.testingRectangle) {
|
||||
|
||||
//Rectangle data
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "------ RECTANGLE ------", new Point(30, 20), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "X: " + location.X + " Y: " + location.Y, new Point(30, 50), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Top: " + self.r1.Top(), new Point(30, 80), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Bottom: " + self.r1.Bottom(), new Point(30, 110), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Left: " + self.r1.Left(), new Point(30, 140), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Right: " + self.r1.Right(), new Point(30, 170), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Half width: " + self.r1.HalfWidth(), new Point(30, 200), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Half height: " + self.r1.HalfHeight(), new Point(30, 230), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Center X: " + center.X + " Center Y: " + center.Y, new Point(30, 260), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Is empty? (width and height = 0): " + self.r1.IsEmpty(), new Point(30, 290), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Red rectangle contains the upper-left vertex", new Point(30, 320), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "of the green one?: " + self.r2.Contains(self.r1.Location()), new Point(30, 340), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Is there a collision between the rectangles?: " + collision, new Point(30, 370), self.BLACK, Vector2.One());
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "Use A, W, S, D or arrow keys to move", new Point(30, 450), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "the green rectangle", new Point(30, 470), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "Use + key to inflate the rectangle", new Point(30, 510), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "Use - key to deflate the rectangle", new Point(30, 540), self.BLUE, Vector2.One());
|
||||
|
||||
//Draw the separating line
|
||||
self.spriteBatch.DrawSegment(new Segment(new Point(400, 0), new Point(400, 600)), "3", self.BLACK);
|
||||
|
||||
//Rectangle
|
||||
self.spriteBatch.DrawRectangle(self.r1, "3", self.GREEN);
|
||||
self.spriteBatch.DrawRectangle(self.r2, "3", self.RED);
|
||||
|
||||
} else {
|
||||
|
||||
//Point
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "------ POINT ------", new Point(30, 20), self.BLACK, Vector2.One());
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Point.Zero()...", new Point(30, 50), self.BLACK, Vector2.One());
|
||||
if (self.pointZero_OK) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "OK", new Point(300, 50), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "ERROR", new Point(300, 50), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Point.One()...", new Point(30, 80), self.BLACK, Vector2.One());
|
||||
if (self.pointOne_OK) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "OK", new Point(300, 80), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "ERROR", new Point(300, 80), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Point.Equals(). Are p1(0,0) and p2(25,150) different?", new Point(30, 110), self.BLACK, Vector2.One());
|
||||
if (self.pointsAreDifferent) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "YES", new Point(570, 110), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "NO", new Point(570, 110), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Point.Equals(). Are p1(0,0) and p2(0,0) equals?", new Point(30, 140), self.BLACK, Vector2.One());
|
||||
if (self.pointsAreEqual) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "YES", new Point(570, 140), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "NO", new Point(570, 140), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
//Vector2
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "----- VECTOR2 -----", new Point(30, 200), self.BLACK, Vector2.One());
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Vector2.Zero()...", new Point(30, 230), self.BLACK, Vector2.One());
|
||||
if (self.vectorZero_OK) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "OK", new Point(320, 230), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "ERROR", new Point(320, 230), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Vector2.One()...", new Point(30, 260), self.BLACK, Vector2.One());
|
||||
if (self.vectorOne_OK) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "OK", new Point(320, 260), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "ERROR", new Point(320, 260), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Vector2.Equals(). Are v1(100,150) and v2(1,1) different?", new Point(30, 290), self.BLACK, Vector2.One());
|
||||
if (self.vectorsAreDifferent) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "YES", new Point(600, 290), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "NO", new Point(600, 290), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Vector2.Equals(). Are v1(100,150) and v2(100,150) equals?", new Point(30, 320), self.BLACK, Vector2.One());
|
||||
if (self.vectorsAreEqual) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "YES", new Point(600, 320), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "NO", new Point(600, 320), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Vector2.Add(). v1(100,150) + v2(20,25) = v(120,175)?", new Point(30, 350), self.BLACK, Vector2.One());
|
||||
if (self.vectorAdd_OK) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "YES", new Point(600, 350), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "NO", new Point(600, 350), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Vector2.Substract(). v1(100,150) - v2(20,25) = v(80,125)?", new Point(30, 380), self.BLACK, Vector2.One());
|
||||
if (self.vectorSubstract_OK) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "YES", new Point(600, 380), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "NO", new Point(600, 380), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Vector2.Divide(). v1(100,150) / v2(20,25) = v(5,6)?", new Point(30, 410), self.BLACK, Vector2.One());
|
||||
if (self.vectorDivide_OK) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "YES", new Point(600, 410), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "NO", new Point(600, 410), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Vector2.Multiply(). v1(100,150) * v2(20,25) = v(2000,3750)?", new Point(30, 440), self.BLACK, Vector2.One());
|
||||
if (self.vectorMultiply_OK) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "YES", new Point(600, 440), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "NO", new Point(600, 440), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Vector2.Distance() between v1(100,150) and v2(20,25)...", new Point(30, 470), self.BLACK, Vector2.One());
|
||||
if (self.vectorMultiply_OK) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "148", new Point(600, 470), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "NOT 148", new Point(600, 470), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Testing static method Vector2.Length() of v2(20,25)...", new Point(30, 500), self.BLACK, Vector2.One());
|
||||
if (self.vectorMultiply_OK) {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "32", new Point(600, 500), self.GREEN, Vector2.One());
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "NOT 32", new Point(600, 500), self.RED, Vector2.One());
|
||||
}
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "Press R to test Rectangle methods...", new Point(30, 550), self.BLUE, Vector2.One());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Call this method to initialize the game, begin running the game loop, and
|
||||
* start processing events for the game.
|
||||
* @name Run
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Run = function () {
|
||||
"use strict";
|
||||
/*globals requestAnimationFrame*/
|
||||
var self = this;
|
||||
|
||||
//Call the game loop
|
||||
requestAnimationFrame(self.Run.bind(self), self.GraphicsDevice.canvas);
|
||||
|
||||
//Choose the method to run according to the game state
|
||||
switch (self.gameState) {
|
||||
case GameStates.Initializing:
|
||||
self.Initialize();
|
||||
break;
|
||||
case GameStates.Loading:
|
||||
self.LoadContent();
|
||||
break;
|
||||
case GameStates.Playing:
|
||||
self.Update();
|
||||
self.Draw();
|
||||
break;
|
||||
}
|
||||
};
|
281
src/JS/Unit_Testing/Test_Song_SoundEffect.js
Normal file
@ -0,0 +1,281 @@
|
||||
/**
|
||||
* Provides basic graphics device initialization, game logic, and rendering code.
|
||||
*/
|
||||
function Game() {
|
||||
"use strict";
|
||||
/*globals ContentManager, GraphicsDevice, document, SpriteBatch, GameStates, Point, Vector2, Rectangle, Keyboard, Keys, Mouse, Segment, SpriteEffects, Sprite, Texture2D, setTimeout*/
|
||||
this.Content = new ContentManager();
|
||||
this.GraphicsDevice = new GraphicsDevice(document);
|
||||
this.spriteBatch = null;
|
||||
this.gameState = GameStates.Initializing;
|
||||
this.preloading = true;
|
||||
|
||||
//Constants
|
||||
this.FONT_LITTLE = "normal bold 15px Helvetica";
|
||||
this.FONT_BIG = "normal bold 18px Helvetica";
|
||||
this.BLACK = "#000000";
|
||||
this.GREEN = "#00FF00";
|
||||
this.RED = "#FF0000";
|
||||
this.BLUE = "#0000FF";
|
||||
|
||||
/***** TEST VARIABLES *****/
|
||||
//Song
|
||||
this.song = null;
|
||||
|
||||
//SoundEffects
|
||||
this.vacaSound = null;
|
||||
this.cerdoSound = null;
|
||||
this.cerberoSound = null;
|
||||
|
||||
//Images
|
||||
this.vaca = null;
|
||||
this.cerdo = null;
|
||||
this.cerbero = null;
|
||||
|
||||
//Sprites
|
||||
this.vacaSprite = null;
|
||||
this.cerdoSprite = null;
|
||||
this.cerberoSprite = null;
|
||||
|
||||
//Flags
|
||||
this.playing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the game to perform any initialization it needs to before starting to run.
|
||||
* This is where it can query for any required services and load any non-graphic
|
||||
* related content.
|
||||
* @name Initialize
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Initialize = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
// TODO: Add your initialization logic here
|
||||
|
||||
self.gameState = GameStates.Loading;
|
||||
};
|
||||
|
||||
/**
|
||||
* LoadContent will be called once per game and is the place to load
|
||||
* all of your content.
|
||||
* @name LoadContent
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.LoadContent = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
if (self.preloading) {
|
||||
// Create a new SpriteBatch, which can be used to draw textures.
|
||||
self.spriteBatch = new SpriteBatch(self.GraphicsDevice);
|
||||
|
||||
self.song = self.Content.LoadSong("../../sounds/test_song.mp3");
|
||||
self.vacaSound = self.Content.LoadSoundEffect("../../sounds/test_sound2.wav");
|
||||
self.cerdoSound = self.Content.LoadSoundEffect("../../sounds/test_sound3.wav");
|
||||
self.cerberoSound = self.Content.LoadSoundEffect("../../sounds/test_sound1.wav");
|
||||
self.vaca = self.Content.LoadTexture2D("../../images/vaca.jpg");
|
||||
self.cerdo = self.Content.LoadTexture2D("../../images/cerdo.png");
|
||||
self.cerbero = self.Content.LoadTexture2D("../../images/cerbero.jpg");
|
||||
|
||||
self.preloading = false;
|
||||
}
|
||||
|
||||
if (self.Content.AllContentLoaded()) {
|
||||
|
||||
self.vacaSprite = new Sprite(
|
||||
self.vaca,
|
||||
new Vector2(0.75, 0.75),
|
||||
new Rectangle(0, 0, self.vaca.Width(), self.vaca.Height()),
|
||||
new Point(500, 30),
|
||||
false
|
||||
);
|
||||
|
||||
self.cerdoSprite = new Sprite(
|
||||
self.cerdo,
|
||||
new Vector2(0.70, 0.70),
|
||||
new Rectangle(0, 0, self.cerdo.Width(), self.cerdo.Height()),
|
||||
new Point(540, 210),
|
||||
false
|
||||
);
|
||||
|
||||
self.cerberoSprite = new Sprite(
|
||||
self.cerbero,
|
||||
new Vector2(0.75, 0.75),
|
||||
new Rectangle(0, 0, self.cerbero.Width(), self.cerbero.Height()),
|
||||
new Point(500, 380),
|
||||
false
|
||||
);
|
||||
|
||||
self.gameState = GameStates.Playing;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Allows the game to run logic such as updating the world,
|
||||
* checking for collisions, gathering input, and playing audio.
|
||||
* @name Update
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Update = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
//Song
|
||||
if (Keyboard.IsKeyPressed(Keys.p)) {
|
||||
if (self.playing) {
|
||||
self.song.Pause();
|
||||
self.playing = false;
|
||||
} else {
|
||||
self.song.Play();
|
||||
self.playing = true;
|
||||
}
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.s)) {
|
||||
self.song.Stop();
|
||||
self.playing = false;
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.m)) {
|
||||
if (self.song.IsMuted()) {
|
||||
self.song.IsMuted(false);
|
||||
} else {
|
||||
self.song.IsMuted(true);
|
||||
}
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.l)) {
|
||||
if (self.song.IsRepeating()) {
|
||||
self.song.IsRepeating(false);
|
||||
} else {
|
||||
self.song.IsRepeating(true);
|
||||
}
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.add)) {
|
||||
self.song.Volume(self.song.Volume() + 0.05);
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.subtract)) {
|
||||
self.song.Volume(self.song.Volume() - 0.05);
|
||||
}
|
||||
|
||||
//Sounds
|
||||
if (Keyboard.IsKeyPressed(Keys.num1) || Keyboard.IsKeyPressed(Keys.numpad_1)) {
|
||||
self.vacaSound.Play();
|
||||
self.vacaSprite.IsVisible = true;
|
||||
setTimeout(function () { self.vacaSprite.IsVisible = false; }, self.vacaSound.Duration() * 1000);
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.num2) || Keyboard.IsKeyPressed(Keys.numpad_2)) {
|
||||
self.cerdoSound.Play();
|
||||
self.cerdoSprite.IsVisible = true;
|
||||
setTimeout(function () { self.cerdoSprite.IsVisible = false; }, self.cerdoSound.Duration() * 1000);
|
||||
}
|
||||
if (Keyboard.IsKeyPressed(Keys.num3) || Keyboard.IsKeyPressed(Keys.numpad_3)) {
|
||||
self.cerberoSound.Play();
|
||||
self.cerberoSprite.IsVisible = true;
|
||||
setTimeout(function () { self.cerberoSprite.IsVisible = false; }, self.cerberoSound.Duration() * 1000);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is called when the game should draw itself.
|
||||
* @name Draw
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Draw = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
self.GraphicsDevice.Clear();
|
||||
|
||||
//Song attributes
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "------ SONG ------", new Point(30, 20), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Duration (in seconds): " + self.song.Duration(), new Point(30, 50), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Is muted? " + self.song.IsMuted(), new Point(30, 80), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Play in loop? " + self.song.IsRepeating(), new Point(30, 110), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Current time (in seconds): " + self.song.PlayPosition(), new Point(30, 140), self.BLACK, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_LITTLE, "Volume: " + (Math.round(self.song.Volume() * 100) / 100), new Point(30, 170), self.BLACK, Vector2.One());
|
||||
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "Press M to mute the song", new Point(30, 350), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "Press L to activate loop", new Point(30, 390), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "Press + to increase volume", new Point(30, 430), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "Press - to decrease volume", new Point(30, 470), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "Press P to play/pause the song", new Point(30, 510), self.BLUE, Vector2.One());
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "Press S to stop the song", new Point(30, 550), self.BLUE, Vector2.One());
|
||||
|
||||
//Draw the separating line
|
||||
self.spriteBatch.DrawSegment(new Segment(new Point(400, 0), new Point(400, 600)), "3", self.BLACK);
|
||||
|
||||
//Draw the images
|
||||
if (self.vacaSprite.IsVisible) {
|
||||
self.spriteBatch.Draw(
|
||||
self.vacaSprite.Texture,
|
||||
self.vacaSprite.Position,
|
||||
self.vacaSprite.SourceRect,
|
||||
self.vacaSprite.Rotation,
|
||||
self.vacaSprite.Scale,
|
||||
SpriteEffects.None
|
||||
);
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "Press 1 to play sound effect 1", new Point(470, 60), self.BLUE, Vector2.One());
|
||||
}
|
||||
|
||||
if (self.cerdoSprite.IsVisible) {
|
||||
self.spriteBatch.Draw(
|
||||
self.cerdoSprite.Texture,
|
||||
self.cerdoSprite.Position,
|
||||
self.cerdoSprite.SourceRect,
|
||||
self.cerdoSprite.Rotation,
|
||||
self.cerdoSprite.Scale,
|
||||
SpriteEffects.None
|
||||
);
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "Press 2 to play sound effect 2", new Point(470, 260), self.BLUE, Vector2.One());
|
||||
}
|
||||
|
||||
if (self.cerberoSprite.IsVisible) {
|
||||
self.spriteBatch.Draw(
|
||||
self.cerberoSprite.Texture,
|
||||
self.cerberoSprite.Position,
|
||||
self.cerberoSprite.SourceRect,
|
||||
self.cerberoSprite.Rotation,
|
||||
self.cerberoSprite.Scale,
|
||||
SpriteEffects.None
|
||||
);
|
||||
} else {
|
||||
self.spriteBatch.DrawString(self.FONT_BIG, "Press 3 to play sound effect 3", new Point(470, 460), self.BLUE, Vector2.One());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Call this method to initialize the game, begin running the game loop, and
|
||||
* start processing events for the game.
|
||||
* @name Run
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Run = function () {
|
||||
"use strict";
|
||||
/*globals requestAnimationFrame*/
|
||||
var self = this;
|
||||
|
||||
//Call the game loop
|
||||
requestAnimationFrame(self.Run.bind(self), self.GraphicsDevice.canvas);
|
||||
|
||||
//Choose the method to run according to the game state
|
||||
switch (self.gameState) {
|
||||
case GameStates.Initializing:
|
||||
self.Initialize();
|
||||
break;
|
||||
case GameStates.Loading:
|
||||
self.LoadContent();
|
||||
break;
|
||||
case GameStates.Playing:
|
||||
self.Update();
|
||||
self.Draw();
|
||||
break;
|
||||
}
|
||||
};
|
108
src/JS/XNA_Classes/ContentManager.js
Normal file
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* The ContentManager loads sound and images of the game into memory.
|
||||
* @constructor
|
||||
*/
|
||||
function ContentManager() {
|
||||
"use strict";
|
||||
this.assetsToLoad = [];
|
||||
this.assetsLoaded = 0;
|
||||
this.allLoaded = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called when a content was loaded in memory.
|
||||
* @name loadHandler
|
||||
* @function
|
||||
* @private
|
||||
* @memberOf ContentManager
|
||||
*/
|
||||
ContentManager.prototype.loadHandler = function () {
|
||||
"use strict";
|
||||
var self = this,
|
||||
len = self.assetsToLoad.length,
|
||||
i;
|
||||
|
||||
self.assetsLoaded += 1;
|
||||
|
||||
//If all contents were loaded then remove listeners and reset variables
|
||||
if (self.assetsLoaded === len) {
|
||||
|
||||
//Remove the load handlers
|
||||
for (i = 0; i < len; i += 1) {
|
||||
self.assetsToLoad[i].removeEventListener("load", self.loadHandler.bind(self), false);
|
||||
}
|
||||
|
||||
self.allLoaded = true;
|
||||
//self.assetsToLoad.splice(0, len);
|
||||
//self.assetsLoaded = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads an image and return a Texture2D instance.
|
||||
* @name LoadTexture2D
|
||||
* @function
|
||||
* @param {String} src - The path to the image.
|
||||
* @memberOf ContentManager
|
||||
*/
|
||||
ContentManager.prototype.LoadTexture2D = function (src) {
|
||||
"use strict";
|
||||
/*global Texture2D*/
|
||||
var self = this,
|
||||
texture = new Texture2D(src);
|
||||
|
||||
//Add load handler
|
||||
texture.Image.addEventListener("load", self.loadHandler.bind(self), false);
|
||||
self.assetsToLoad.push(texture.Image);
|
||||
return texture;
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads a song and return a Song instance.
|
||||
* @name LoadSong
|
||||
* @function
|
||||
* @param {String} src - The path to the song.
|
||||
* @memberOf ContentManager
|
||||
*/
|
||||
ContentManager.prototype.LoadSong = function (src) {
|
||||
"use strict";
|
||||
/*global Song*/
|
||||
var self = this,
|
||||
song = new Song(src);
|
||||
|
||||
//Add load handler
|
||||
song.Audio.addEventListener("loadedmetadata", self.loadHandler.bind(self), false);
|
||||
self.assetsToLoad.push(song.Audio);
|
||||
return song;
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads a sound effect and return a SoundEffect instance.
|
||||
* @name LoadSoundEffect
|
||||
* @function
|
||||
* @param {String} src - The path to the sound effect.
|
||||
* @memberOf ContentManager
|
||||
*/
|
||||
ContentManager.prototype.LoadSoundEffect = function (src) {
|
||||
"use strict";
|
||||
/*global SoundEffect*/
|
||||
var self = this,
|
||||
soundEffect = new SoundEffect(src);
|
||||
|
||||
//Add load handler
|
||||
soundEffect.Audio.addEventListener("loadedmetadata", self.loadHandler.bind(self), false);
|
||||
self.assetsToLoad.push(soundEffect.Audio);
|
||||
return soundEffect;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if all contents were loaded or not.
|
||||
* @name AllContentLoaded
|
||||
* @function
|
||||
* @memberOf ContentManager
|
||||
*/
|
||||
ContentManager.prototype.AllContentLoaded = function () {
|
||||
"use strict";
|
||||
return this.allLoaded;
|
||||
};
|
115
src/JS/XNA_Classes/Game.js
Normal file
@ -0,0 +1,115 @@
|
||||
/**
|
||||
* Provides basic graphics device initialization, game logic, and rendering code.
|
||||
*/
|
||||
function Game() {
|
||||
"use strict";
|
||||
/*global ContentManager, GraphicsDevice, document, SpriteBatch, GameStates*/
|
||||
this.Content = new ContentManager();
|
||||
this.GraphicsDevice = new GraphicsDevice(document);
|
||||
this.spriteBatch = null;
|
||||
this.gameState = GameStates.Initializing;
|
||||
this.preloading = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the game to perform any initialization it needs to before starting to run.
|
||||
* This is where it can query for any required services and load any non-graphic
|
||||
* related content.
|
||||
* @name Initialize
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Initialize = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
// TODO: Add your initialization logic here
|
||||
|
||||
self.gameState = GameStates.Loading;
|
||||
};
|
||||
|
||||
/**
|
||||
* LoadContent will be called once per game and is the place to load
|
||||
* all of your content.
|
||||
* @name LoadContent
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.LoadContent = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
if (self.preloading) {
|
||||
// Create a new SpriteBatch, which can be used to draw textures.
|
||||
self.spriteBatch = new SpriteBatch(self.GraphicsDevice);
|
||||
|
||||
// TODO: use self.Content.Load... to load your game content here
|
||||
|
||||
self.preloading = false;
|
||||
}
|
||||
|
||||
if (self.Content.AllContentLoaded()) {
|
||||
// TODO: create the objects that will use the content previously loaded, like sprites or sounds
|
||||
|
||||
self.gameState = GameStates.Playing;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Allows the game to run logic such as updating the world,
|
||||
* checking for collisions, gathering input, and playing audio.
|
||||
* @name Update
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Update = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
// TODO: Add your update logic here
|
||||
};
|
||||
|
||||
/**
|
||||
* This is called when the game should draw itself.
|
||||
* @name Draw
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Draw = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
self.GraphicsDevice.Clear();
|
||||
|
||||
// TODO: Add your drawing code here
|
||||
};
|
||||
|
||||
/**
|
||||
* Call this method to initialize the game, begin running the game loop, and
|
||||
* start processing events for the game.
|
||||
* @name Run
|
||||
* @function
|
||||
* @memberOf Game
|
||||
*/
|
||||
Game.prototype.Run = function () {
|
||||
"use strict";
|
||||
/*globals requestAnimationFrame*/
|
||||
var self = this;
|
||||
|
||||
//Call the game loop
|
||||
requestAnimationFrame(self.Run.bind(self), self.GraphicsDevice.canvas);
|
||||
|
||||
//Choose the method to run according to the game state
|
||||
switch (self.gameState) {
|
||||
case GameStates.Initializing:
|
||||
self.Initialize();
|
||||
break;
|
||||
case GameStates.Loading:
|
||||
self.LoadContent();
|
||||
break;
|
||||
case GameStates.Playing:
|
||||
self.Update();
|
||||
self.Draw();
|
||||
break;
|
||||
}
|
||||
};
|
172
src/JS/XNA_Classes/GraphicsDevice.js
Normal file
@ -0,0 +1,172 @@
|
||||
/**
|
||||
* Creates an instance of the canvas. Also handles the configuration of the canvas.
|
||||
* @constructor
|
||||
* @param {HTML} document - The descriptor of the HTML.
|
||||
*/
|
||||
function GraphicsDevice(document) {
|
||||
"use strict";
|
||||
/*global Element*/
|
||||
this.canvas = document.querySelector("canvas");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the preferred back-buffer height.
|
||||
* @name PreferredBackBufferHeight
|
||||
* @function
|
||||
* @memberOf GraphicsDevice
|
||||
*/
|
||||
GraphicsDevice.prototype.PreferredBackBufferHeight = function () {
|
||||
"use strict";
|
||||
return this.canvas.height;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the preferred back-buffer width.
|
||||
* @name PreferredBackBufferWidth
|
||||
* @function
|
||||
* @memberOf GraphicsDevice
|
||||
*/
|
||||
GraphicsDevice.prototype.PreferredBackBufferWidth = function () {
|
||||
"use strict";
|
||||
return this.canvas.width;
|
||||
};
|
||||
|
||||
/**
|
||||
* Specifies the default minimum back-buffer height (600).
|
||||
* @name DefaultBackBufferHeight
|
||||
* @function
|
||||
* @memberOf GraphicsDevice
|
||||
* @static
|
||||
*/
|
||||
GraphicsDevice.prototype.DefaultBackBufferHeight = function () {
|
||||
"use strict";
|
||||
return 600;
|
||||
};
|
||||
|
||||
/**
|
||||
* Specifies the default minimum back-buffer width (800).
|
||||
* @name DefaultBackBufferWidth
|
||||
* @function
|
||||
* @memberOf GraphicsDevice
|
||||
* @static
|
||||
*/
|
||||
GraphicsDevice.prototype.DefaultBackBufferWidth = function () {
|
||||
"use strict";
|
||||
return 800;
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggles between full page and windowed mode.
|
||||
* @name ToggleFullPage
|
||||
* @function
|
||||
* @memberOf GraphicsDevice
|
||||
*/
|
||||
GraphicsDevice.prototype.ToggleFullPage = function () {
|
||||
"use strict";
|
||||
var self = this,
|
||||
canvas = self.canvas,
|
||||
scaleX = 0,
|
||||
scaleY = 0;
|
||||
|
||||
//Don't go to full page if full screen is activated
|
||||
if (!self.IsFullScreen()) {
|
||||
if (self.IsFullPage()) {
|
||||
canvas.width = self.DefaultBackBufferWidth();
|
||||
canvas.height = self.DefaultBackBufferHeight();
|
||||
} else {
|
||||
scaleX = window.innerWidth / canvas.width;
|
||||
scaleY = window.innerHeight / canvas.height;
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
canvas.getContext("2d").scale(scaleX, scaleY);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggles between full screen and windowed mode.
|
||||
* @name ToggleFullScreen
|
||||
* @function
|
||||
* @memberOf GraphicsDevice
|
||||
*/
|
||||
GraphicsDevice.prototype.ToggleFullScreen = function () {
|
||||
"use strict";
|
||||
/*global setTimeout*/
|
||||
var self = this,
|
||||
canvas = self.canvas,
|
||||
scaleX = 0,
|
||||
scaleY = 0;
|
||||
|
||||
if (!self.IsFullScreen()) {
|
||||
|
||||
//If canvas is full page turn it normal
|
||||
if (self.IsFullPage()) {
|
||||
self.ToggleFullPage();
|
||||
}
|
||||
|
||||
if (canvas.requestFullScreen) {
|
||||
canvas.requestFullScreen();
|
||||
} else if (canvas.mozRequestFullScreen) {
|
||||
canvas.mozRequestFullScreen();
|
||||
} else if (canvas.webkitRequestFullScreen) {
|
||||
canvas.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
|
||||
}
|
||||
|
||||
scaleX = window.innerWidth / canvas.width;
|
||||
canvas.width = window.innerWidth;
|
||||
//For some reason (that I dunno), setTimeout is compulsory for the correct resizing
|
||||
setTimeout(function () {
|
||||
scaleY = window.innerHeight / canvas.height;
|
||||
canvas.height = window.innerHeight;
|
||||
canvas.getContext("2d").scale(scaleX, scaleY);
|
||||
}, 150);
|
||||
|
||||
} else {
|
||||
if (document.cancelFullScreen) {
|
||||
document.cancelFullScreen();
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
} else if (document.webkitCancelFullScreen) {
|
||||
document.webkitCancelFullScreen();
|
||||
}
|
||||
canvas.width = self.DefaultBackBufferWidth();
|
||||
canvas.height = self.DefaultBackBufferHeight();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a value that indicates whether the device should start in full-page mode.
|
||||
* @name IsFullPage
|
||||
* @function
|
||||
* @memberOf GraphicsDevice
|
||||
*/
|
||||
GraphicsDevice.prototype.IsFullPage = function () {
|
||||
"use strict";
|
||||
/*global window */
|
||||
return (this.canvas.width === window.innerWidth && this.canvas.height === window.innerHeight);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a value that indicates whether the device should start in full-screen mode.
|
||||
* @name IsFullScreen
|
||||
* @function
|
||||
* @memberOf GraphicsDevice
|
||||
*/
|
||||
GraphicsDevice.prototype.IsFullScreen = function () {
|
||||
"use strict";
|
||||
/*global document */
|
||||
return !((document.fullScreenElement && document.fullScreenElement !== null) || (!document.mozFullScreen && !document.webkitIsFullScreen));
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the canvas rectangle.
|
||||
* @name Clear
|
||||
* @function
|
||||
* @memberOf GraphicsDevice
|
||||
*/
|
||||
GraphicsDevice.prototype.Clear = function () {
|
||||
"use strict";
|
||||
var canvas = this.canvas;
|
||||
|
||||
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
|
||||
};
|
153
src/JS/XNA_Classes/Keyboard.js
Normal file
@ -0,0 +1,153 @@
|
||||
/**
|
||||
* Allows retrieval of keystrokes from a keyboard input device.
|
||||
* @global
|
||||
*/
|
||||
var Keyboard = {
|
||||
|
||||
keyDownList: [],
|
||||
keyUpList: [],
|
||||
keyPressList: [],
|
||||
|
||||
/**
|
||||
* Add a key to the list of pressed down keys.
|
||||
* @name addKeyDown
|
||||
* @function
|
||||
* @param {Event} event - This parameter represents a keyboard event.
|
||||
* @memberOf Keyboard
|
||||
* @static
|
||||
*/
|
||||
addKeyDown: function (event) {
|
||||
"use strict";
|
||||
var keyCode = event.keyCode,
|
||||
indexOfKey = Keyboard.keyDownList.indexOf(keyCode);
|
||||
|
||||
if (indexOfKey === -1) {
|
||||
Keyboard.removeKeyUp(keyCode);
|
||||
Keyboard.keyDownList.push(keyCode);
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a key to the list of released keys.
|
||||
* @name addKeyUp
|
||||
* @function
|
||||
* @param {Event} event - This parameter represents a keyboard event.
|
||||
* @memberOf Keyboard
|
||||
* @static
|
||||
*/
|
||||
addKeyUp: function (event) {
|
||||
"use strict";
|
||||
var keyCode = event.keyCode,
|
||||
indexOfKey = Keyboard.keyUpList.indexOf(keyCode);
|
||||
|
||||
if (indexOfKey === -1) {
|
||||
Keyboard.removeKeyDown(keyCode);
|
||||
Keyboard.keyUpList.push(keyCode);
|
||||
}
|
||||
|
||||
indexOfKey = Keyboard.keyPressList.indexOf(keyCode);
|
||||
|
||||
if (indexOfKey !== -1) {
|
||||
Keyboard.keyPressList.splice(indexOfKey, 1);
|
||||
} else {
|
||||
Keyboard.keyPressList.push(keyCode);
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a key of the list of pressed down keys.
|
||||
* @name removeKeyDown
|
||||
* @function
|
||||
* @param {Number} key - The key code.
|
||||
* @memberOf Keyboard
|
||||
* @static
|
||||
*/
|
||||
removeKeyDown: function (key) {
|
||||
"use strict";
|
||||
var indexOfKey = Keyboard.keyDownList.indexOf(key);
|
||||
|
||||
if (indexOfKey !== -1) {
|
||||
Keyboard.keyDownList.splice(indexOfKey, 1);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a key of the list of released keys.
|
||||
* @name removeKeyUp
|
||||
* @function
|
||||
* @param {Number} key - The key code.
|
||||
* @memberOf Keyboard
|
||||
* @static
|
||||
*/
|
||||
removeKeyUp: function (key) {
|
||||
"use strict";
|
||||
var indexOfKey = Keyboard.keyUpList.indexOf(key);
|
||||
|
||||
if (indexOfKey !== -1) {
|
||||
Keyboard.keyUpList.splice(indexOfKey, 1);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether a specified key is currently being pressed.
|
||||
* @name IsKeyDown
|
||||
* @function
|
||||
* @param {Keys} key - Enumerated value that specifies the key to query.
|
||||
* @memberOf Keyboard
|
||||
* @static
|
||||
*/
|
||||
IsKeyDown: function (key) {
|
||||
"use strict";
|
||||
var indexOfKey = Keyboard.keyDownList.indexOf(key);
|
||||
|
||||
if (indexOfKey !== -1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether a specified key is currently not pressed.
|
||||
* @name IsKeyUp
|
||||
* @function
|
||||
* @param {Keys} key - Enumerated value that specifies the key to query.
|
||||
* @memberOf Keyboard
|
||||
* @static
|
||||
*/
|
||||
IsKeyUp: function (key) {
|
||||
"use strict";
|
||||
var indexOfKey = Keyboard.keyUpList.indexOf(key);
|
||||
|
||||
if (indexOfKey !== -1) {
|
||||
Keyboard.removeKeyUp(key);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether a specified key was pressed and released.
|
||||
* @name IsKeyPressed
|
||||
* @function
|
||||
* @param {Keys} key - Enumerated value that specifies the key to query.
|
||||
* @memberOf Keyboard
|
||||
* @static
|
||||
*/
|
||||
IsKeyPressed: function (key) {
|
||||
"use strict";
|
||||
var indexOfKey = Keyboard.keyPressList.indexOf(key);
|
||||
|
||||
if (indexOfKey !== -1) {
|
||||
Keyboard.keyPressList.splice(indexOfKey, 1);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
106
src/JS/XNA_Classes/Keys.js
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Identifies a particular key on a keyboard.
|
||||
* @readonly
|
||||
* @enum {number}
|
||||
*/
|
||||
var Keys = Object.freeze({
|
||||
backspace: 8,
|
||||
tab: 9,
|
||||
enter: 13,
|
||||
shift: 16,
|
||||
ctrl: 17,
|
||||
alt: 18,
|
||||
pause_break: 19,
|
||||
caps_lock: 20,
|
||||
escape: 27,
|
||||
space: 32,
|
||||
page_up: 33,
|
||||
page_down: 34,
|
||||
end: 35,
|
||||
home: 36,
|
||||
left_arrow: 37,
|
||||
up_arrow: 38,
|
||||
right_arrow: 39,
|
||||
down_arrow: 40,
|
||||
insert: 45,
|
||||
supr: 46,
|
||||
num0: 48,
|
||||
num1: 49,
|
||||
num2: 50,
|
||||
num3: 51,
|
||||
num4: 52,
|
||||
num5: 53,
|
||||
num6: 54,
|
||||
num7: 55,
|
||||
num8: 56,
|
||||
num9: 57,
|
||||
a: 65,
|
||||
b: 66,
|
||||
c: 67,
|
||||
d: 68,
|
||||
e: 69,
|
||||
f: 70,
|
||||
g: 71,
|
||||
h: 72,
|
||||
i: 73,
|
||||
j: 74,
|
||||
k: 75,
|
||||
l: 76,
|
||||
m: 77,
|
||||
n: 78,
|
||||
o: 79,
|
||||
p: 80,
|
||||
q: 81,
|
||||
r: 82,
|
||||
s: 83,
|
||||
t: 84,
|
||||
u: 85,
|
||||
v: 86,
|
||||
w: 87,
|
||||
x: 88,
|
||||
y: 89,
|
||||
z: 90,
|
||||
left_window_key: 91,
|
||||
right_window_key: 92,
|
||||
select_key: 93,
|
||||
numpad_0: 96,
|
||||
numpad_1: 97,
|
||||
numpad_2: 98,
|
||||
numpad_3: 99,
|
||||
numpad_4: 100,
|
||||
numpad_5: 101,
|
||||
numpad_6: 102,
|
||||
numpad_7: 103,
|
||||
numpad_8: 104,
|
||||
numpad_9: 105,
|
||||
multiply: 106,
|
||||
add: 107,
|
||||
subtract: 109,
|
||||
decimal_point: 110,
|
||||
divide: 111,
|
||||
f1: 112,
|
||||
f2: 113,
|
||||
f3: 114,
|
||||
f4: 115,
|
||||
f5: 116,
|
||||
f6: 117,
|
||||
f7: 118,
|
||||
f8: 119,
|
||||
f9: 120,
|
||||
f10: 121,
|
||||
f11: 122,
|
||||
f12: 123,
|
||||
num_lock: 144,
|
||||
scroll_lock: 145,
|
||||
semi_colon: 186,
|
||||
equal_sign: 187,
|
||||
comma: 188,
|
||||
dash: 189,
|
||||
period: 190,
|
||||
forward_slash: 191,
|
||||
grave_accent: 192,
|
||||
open_bracket: 219,
|
||||
back_slash: 220,
|
||||
close_braket: 221,
|
||||
single_quote: 222
|
||||
});
|
124
src/JS/XNA_Classes/Mouse.js
Normal file
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Allows retrieval of position and button clicks from a mouse input device.
|
||||
* @global
|
||||
*/
|
||||
var Mouse = {
|
||||
|
||||
X: 0,
|
||||
Y: 0,
|
||||
PreviousX: 0,
|
||||
PreviousY: 0,
|
||||
LeftButtonPressed: false,
|
||||
MiddleButtonPressed: false,
|
||||
RightButtonPressed: false,
|
||||
LeftButtonClicked: false,
|
||||
MiddleButtonClicked: false,
|
||||
RightButtonClicked: false,
|
||||
LeftButton: 0,
|
||||
MiddleButton: 1,
|
||||
RightButton: 2,
|
||||
ScrollWheelValue: 0,
|
||||
IsMoving: false,
|
||||
IsDraggingSomething: false,
|
||||
|
||||
/**
|
||||
* Determine which mouse button was pressed.
|
||||
* @name mouseDownHandler
|
||||
* @function
|
||||
* @param {Event} event - This parameter represents a mouse event.
|
||||
* @memberOf Mouse
|
||||
* @static
|
||||
*/
|
||||
mouseDownHandler: function (event) {
|
||||
"use strict";
|
||||
switch (event.button) {
|
||||
case 0:
|
||||
this.LeftButtonPressed = true;
|
||||
break;
|
||||
case 1:
|
||||
this.MiddleButtonPressed = true;
|
||||
break;
|
||||
case 2:
|
||||
this.RightButtonPressed = true;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Determine which mouse button was released.
|
||||
* @name mouseUpHandler
|
||||
* @function
|
||||
* @param {Event} event - This parameter represents a mouse event.
|
||||
* @memberOf Mouse
|
||||
* @static
|
||||
*/
|
||||
mouseUpHandler: function (event) {
|
||||
"use strict";
|
||||
switch (event.button) {
|
||||
case 0:
|
||||
this.LeftButtonPressed = false;
|
||||
this.LeftButtonClicked = true;
|
||||
break;
|
||||
case 1:
|
||||
this.MiddleButtonPressed = false;
|
||||
this.MiddleButtonClicked = true;
|
||||
break;
|
||||
case 2:
|
||||
this.RightButtonPressed = false;
|
||||
this.RightButtonClicked = true;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether a specified mouse button was clicked (down and up).
|
||||
* @name IsButtonClicked
|
||||
* @function
|
||||
* @param {Number} buttonCode - Enumerated value that specifies the button to query.
|
||||
* @memberOf Mouse
|
||||
* @static
|
||||
*/
|
||||
IsButtonClicked: function (buttonCode) {
|
||||
"use strict";
|
||||
switch (buttonCode) {
|
||||
case 0:
|
||||
if (this.LeftButtonClicked) {
|
||||
this.LeftButtonClicked = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (this.MiddleButtonClicked) {
|
||||
this.MiddleButtonClicked = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (this.RightButtonClicked) {
|
||||
this.RightButtonClicked = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Increments or decrements the ScrollWheelValue property according to the mouse wheel event.
|
||||
* @name mouseWheelHandler
|
||||
* @function
|
||||
* @param {Event} event - This parameter represents a mouse event.
|
||||
* @memberOf Mouse
|
||||
* @static
|
||||
*/
|
||||
mouseWheelHandler: function (event) {
|
||||
"use strict";
|
||||
/*global window*/
|
||||
|
||||
// cross-browser wheel delta
|
||||
var e = window.event || event; // old IE support
|
||||
|
||||
this.ScrollWheelValue += Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
|
||||
}
|
||||
};
|
49
src/JS/XNA_Classes/Point.js
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Defines a point in 2D space.
|
||||
* @constructor
|
||||
* @param {Number} x - The x-coordinate of the point.
|
||||
* @param {Number} y - The y-coordinate of the point.
|
||||
*/
|
||||
function Point(x, y) {
|
||||
"use strict";
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the point (0,0).
|
||||
* @name Zero
|
||||
* @function
|
||||
* @memberOf Point
|
||||
* @static
|
||||
*/
|
||||
Point.Zero = function () {
|
||||
"use strict";
|
||||
return new Point(0, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the point (1,1).
|
||||
* @name One
|
||||
* @function
|
||||
* @memberOf Point
|
||||
* @static
|
||||
*/
|
||||
Point.One = function () {
|
||||
"use strict";
|
||||
return new Point(1, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the points are equal.
|
||||
* @name Equals
|
||||
* @function
|
||||
* @param {Point} p1 - point 1.
|
||||
* @param {Point} p2 - point 2.
|
||||
* @memberOf Point
|
||||
* @static
|
||||
*/
|
||||
Point.Equals = function (p1, p2) {
|
||||
"use strict";
|
||||
return (p1.X === p2.X && p1.Y === p2.Y);
|
||||
};
|
51
src/JS/XNA_Classes/Program.js
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* The main entry point for the application.
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
/*global Game, Keyboard, Mouse, window*/
|
||||
|
||||
//Create the game object and start running it
|
||||
var game = new Game(),
|
||||
canvas = game.GraphicsDevice.canvas;
|
||||
game.Run();
|
||||
|
||||
/***************************************************/
|
||||
/*** Keyboard and Mouse listeners initialization ***/
|
||||
/***************************************************/
|
||||
//Add keyboard event listeners
|
||||
window.addEventListener("keydown", Keyboard.addKeyDown, false);
|
||||
window.addEventListener("keyup", Keyboard.addKeyUp, false);
|
||||
|
||||
//Add mouse event listeners
|
||||
canvas.addEventListener("mousedown", Mouse.mouseDownHandler.bind(Mouse), false);
|
||||
window.addEventListener("mouseup", Mouse.mouseUpHandler.bind(Mouse), false);
|
||||
canvas.addEventListener("mousemove", function (event) {
|
||||
|
||||
//Find the new mouse's x and y position on the canvas
|
||||
Mouse.X = event.pageX - canvas.offsetLeft;
|
||||
Mouse.Y = event.pageY - canvas.offsetTop;
|
||||
|
||||
//If the mouse position changed then set the previous mouse's x and
|
||||
//y position on the canvas
|
||||
if (Mouse.PreviousX !== Mouse.X || Mouse.PreviousY !== Mouse.Y) {
|
||||
Mouse.IsMoving = true;
|
||||
Mouse.PreviousX = Mouse.X;
|
||||
Mouse.PreviousY = Mouse.Y;
|
||||
} else if (Mouse.IsMoving) {
|
||||
Mouse.IsMoving = false;
|
||||
}
|
||||
|
||||
}, false);
|
||||
|
||||
//The mouse wheel listener
|
||||
canvas.addEventListener("wheel", Mouse.mouseWheelHandler.bind(Mouse), false);
|
||||
|
||||
//Disable the context menu when pressing right button of the mouse
|
||||
canvas.addEventListener("contextmenu", function (e) {
|
||||
if (e.button === 2) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}, false);
|
||||
}());
|
197
src/JS/XNA_Classes/Rectangle.js
Normal file
@ -0,0 +1,197 @@
|
||||
/**
|
||||
* Defines a rectangle.
|
||||
* @constructor
|
||||
* @param {Number} x - The x-coordinate of the rectangle.
|
||||
* @param {Number} y - The y-coordinate of the rectangle.
|
||||
* @param {Number} width - Width of the rectangle.
|
||||
* @param {Number} height - Height of the rectangle.
|
||||
*/
|
||||
function Rectangle(x, y, width, height) {
|
||||
"use strict";
|
||||
this.Height = height;
|
||||
this.Width = width;
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the upper-left value of the Rectangle.
|
||||
* @name Location
|
||||
* @function
|
||||
* @memberOf Rectangle
|
||||
*/
|
||||
Rectangle.prototype.Location = function () {
|
||||
"use strict";
|
||||
/*global Point */
|
||||
return new Point(this.X, this.Y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the y-coordinate of the top of the rectangle.
|
||||
* @name Top
|
||||
* @function
|
||||
* @memberOf Rectangle
|
||||
*/
|
||||
Rectangle.prototype.Top = function () {
|
||||
"use strict";
|
||||
return this.Y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the y-coordinate of the bottom of the rectangle.
|
||||
* @name Bottom
|
||||
* @function
|
||||
* @memberOf Rectangle
|
||||
*/
|
||||
Rectangle.prototype.Bottom = function () {
|
||||
"use strict";
|
||||
return this.Y + this.Height;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the x-coordinate of the left side of the rectangle.
|
||||
* @name Left
|
||||
* @function
|
||||
* @memberOf Rectangle
|
||||
*/
|
||||
Rectangle.prototype.Left = function () {
|
||||
"use strict";
|
||||
return this.X;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the x-coordinate of the right of the rectangle.
|
||||
* @name Right
|
||||
* @function
|
||||
* @memberOf Rectangle
|
||||
*/
|
||||
Rectangle.prototype.Right = function () {
|
||||
"use strict";
|
||||
return this.X + this.Width;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the Point that specifies the center of the rectangle.
|
||||
* @name Center
|
||||
* @function
|
||||
* @memberOf Rectangle
|
||||
*/
|
||||
Rectangle.prototype.Center = function () {
|
||||
"use strict";
|
||||
/*global Point */
|
||||
var self = this;
|
||||
return new Point(self.X + (self.Width / 2), self.Y + (self.Height / 2));
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets half of the width of the rectangle.
|
||||
* @name HalfWidth
|
||||
* @function
|
||||
* @memberOf Rectangle
|
||||
*/
|
||||
Rectangle.prototype.HalfWidth = function () {
|
||||
"use strict";
|
||||
return this.Width / 2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets half of the height of the rectangle.
|
||||
* @name HalfHeight
|
||||
* @function
|
||||
* @memberOf Rectangle
|
||||
*/
|
||||
Rectangle.prototype.HalfHeight = function () {
|
||||
"use strict";
|
||||
return this.Height / 2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a Rectangle with all of its values set to zero.
|
||||
* @name Empty
|
||||
* @function
|
||||
* @memberOf Rectangle
|
||||
* @static
|
||||
*/
|
||||
Rectangle.Empty = function () {
|
||||
"use strict";
|
||||
return new Rectangle(0, 0, 0, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a value that indicates whether the Rectangle is empty.
|
||||
* @name IsEmpty
|
||||
* @function
|
||||
* @memberOf Rectangle
|
||||
*/
|
||||
Rectangle.prototype.IsEmpty = function () {
|
||||
"use strict";
|
||||
return (this.Width <= 0 && this.Height <= 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether this Rectangle contains a specified Point.
|
||||
* @name Contains
|
||||
* @function
|
||||
* @param {Point} point - The Point to evaluate.
|
||||
* @memberOf Rectangle
|
||||
*/
|
||||
Rectangle.prototype.Contains = function (value) {
|
||||
"use strict";
|
||||
var self = this;
|
||||
return (value.X >= self.X && value.X <= self.Right()) && (value.Y >= self.Y && value.Y <= self.Bottom());
|
||||
};
|
||||
|
||||
/**
|
||||
* Pushes the edges of the Rectangle out by the horizontal and vertical values specified.
|
||||
* @name Inflate
|
||||
* @function
|
||||
* @param {Number} horizontalAmount - Value to push the sides out by.
|
||||
* @param {Number} verticalAmount - Value to push the top and bottom out by.
|
||||
* @memberOf Rectangle
|
||||
*/
|
||||
Rectangle.prototype.Inflate = function (horizontalAmount, verticalAmount) {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
self.Width += horizontalAmount;
|
||||
if (self.Width < 0) {
|
||||
self.Width = 0;
|
||||
}
|
||||
self.Height += verticalAmount;
|
||||
if (self.Height < 0) {
|
||||
self.Height = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether a specified Rectangle intersects with this Rectangle, and by how much.
|
||||
* @name Intersects
|
||||
* @function
|
||||
* @param {Rectangle} value - The Rectangle to evaluate.
|
||||
* @memberOf Rectangle
|
||||
*/
|
||||
Rectangle.prototype.Intersects = function (value) {
|
||||
"use strict";
|
||||
/*global Vector2*/
|
||||
var self = this,
|
||||
//Calculate the distance vector and the combined half widths and heights
|
||||
distance = new Vector2(
|
||||
self.Center().X - value.Center().X,
|
||||
self.Center().Y - value.Center().Y
|
||||
),
|
||||
combinedHalfWidths = self.HalfWidth() + value.HalfWidth(),
|
||||
combinedHalfHeights = self.HalfHeight() + value.HalfHeight();
|
||||
|
||||
//Check whether distance.X is less than the combined half widths
|
||||
if (Math.abs(distance.X) < combinedHalfWidths) {
|
||||
//An intersection might be occurring!
|
||||
//Check whether distance.y is less than the combined half heights
|
||||
if (Math.abs(distance.Y) < combinedHalfHeights) {
|
||||
//An intersection has occurred! return the overlap vector
|
||||
return new Vector2(combinedHalfWidths - Math.abs(distance.X),
|
||||
combinedHalfHeights - Math.abs(distance.Y));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
138
src/JS/XNA_Classes/Song.js
Normal file
@ -0,0 +1,138 @@
|
||||
/**
|
||||
* A song.
|
||||
* @constructor
|
||||
* @param {String} name - the path to the resource.
|
||||
*/
|
||||
function Song(name) {
|
||||
"use strict";
|
||||
/*global Audio*/
|
||||
this.Name = name;
|
||||
this.Audio = new Audio();
|
||||
this.Audio.src = name;
|
||||
this.Audio.loop = true;
|
||||
this.Audio.muted = false;
|
||||
this.Audio.volume = 0.8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the duration of the song.
|
||||
* @name Duration
|
||||
* @function
|
||||
* @memberOf Song
|
||||
*/
|
||||
Song.prototype.Duration = function () {
|
||||
"use strict";
|
||||
return this.Audio.duration;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets or set the muted setting for the song.
|
||||
* @name IsMuted
|
||||
* @function
|
||||
* @param {Boolean|Undefined} mute - The mute property (true, false or undefined)
|
||||
* @memberOf Song
|
||||
*/
|
||||
Song.prototype.IsMuted = function (mute) {
|
||||
"use strict";
|
||||
if (typeof mute === "undefined") {
|
||||
return this.Audio.muted;
|
||||
}
|
||||
|
||||
this.Audio.muted = mute;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets or set the loop setting for the song.
|
||||
* @name IsRepeating
|
||||
* @function
|
||||
* @param {Boolean|Undefined} loop - The loop property (true, false or undefined)
|
||||
* @memberOf Song
|
||||
*/
|
||||
Song.prototype.IsRepeating = function (loop) {
|
||||
"use strict";
|
||||
if (typeof loop === "undefined") {
|
||||
return this.Audio.loop;
|
||||
}
|
||||
|
||||
this.Audio.loop = loop;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the play position within the currently playing song.
|
||||
* @name PlayPosition
|
||||
* @function
|
||||
* @memberOf Song
|
||||
*/
|
||||
Song.prototype.PlayPosition = function () {
|
||||
"use strict";
|
||||
return this.Audio.currentTime;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets or sets the media player volume.
|
||||
* @name Volume
|
||||
* @function
|
||||
* @param {Number} volume - The loop volume.
|
||||
* @memberOf Song
|
||||
*/
|
||||
Song.prototype.Volume = function (volume) {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
if (typeof volume === "undefined") {
|
||||
return self.Audio.volume;
|
||||
}
|
||||
|
||||
if (volume < 0) {
|
||||
self.Audio.volume = 0;
|
||||
} else if (volume > 1) {
|
||||
self.Audio.volume = 1;
|
||||
} else {
|
||||
self.Audio.volume = volume;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Plays the Song.
|
||||
* @name Play
|
||||
* @function
|
||||
* @memberOf Song
|
||||
*/
|
||||
Song.prototype.Play = function () {
|
||||
"use strict";
|
||||
this.Audio.play();
|
||||
};
|
||||
|
||||
/**
|
||||
* Pauses the Song.
|
||||
* @name Pause
|
||||
* @function
|
||||
* @memberOf Song
|
||||
*/
|
||||
Song.prototype.Pause = function () {
|
||||
"use strict";
|
||||
this.Audio.pause();
|
||||
};
|
||||
|
||||
/**
|
||||
* Resumes the Song.
|
||||
* @name Resume
|
||||
* @function
|
||||
* @memberOf Song
|
||||
*/
|
||||
Song.prototype.Resume = function () {
|
||||
"use strict";
|
||||
this.Audio.play();
|
||||
};
|
||||
|
||||
/**
|
||||
* Stops the Song.
|
||||
* @name Stop
|
||||
* @function
|
||||
* @memberOf Song
|
||||
*/
|
||||
Song.prototype.Stop = function () {
|
||||
"use strict";
|
||||
this.Audio.pause();
|
||||
this.Audio.currentTime = 0.0;
|
||||
};
|
40
src/JS/XNA_Classes/SoundEffect.js
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* A sound effect.
|
||||
* @constructor
|
||||
* @param {String} name - the path to the resource.
|
||||
*/
|
||||
function SoundEffect(name) {
|
||||
"use strict";
|
||||
/*global Audio*/
|
||||
this.Name = name;
|
||||
this.Audio = new Audio();
|
||||
this.Audio.src = name;
|
||||
this.Audio.loop = false;
|
||||
this.Audio.muted = false;
|
||||
this.Audio.volume = 0.85;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays the Sound Effect.
|
||||
* @name Play
|
||||
* @function
|
||||
* @memberOf SoundEffect
|
||||
*/
|
||||
SoundEffect.prototype.Play = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
self.Audio.currentTime = 0.0;
|
||||
self.Audio.play();
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the duration of the sound effect.
|
||||
* @name Duration
|
||||
* @function
|
||||
* @memberOf SoundEffect
|
||||
*/
|
||||
SoundEffect.prototype.Duration = function () {
|
||||
"use strict";
|
||||
return this.Audio.duration;
|
||||
};
|
186
src/JS/XNA_Classes/SpriteBatch.js
Normal file
@ -0,0 +1,186 @@
|
||||
/**
|
||||
* Enables a group of sprites to be drawn using the same settings.
|
||||
* @constructor
|
||||
* @param {GraphicsDevice} graphicsDevice - The graphics device where sprites will be drawn.
|
||||
*/
|
||||
function SpriteBatch(graphicsDevice) {
|
||||
"use strict";
|
||||
this.ctx = graphicsDevice.canvas.getContext("2d");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a sprite to a batch of sprites for rendering using the specified texture, position, and source rectangle.
|
||||
* @name Draw
|
||||
* @function
|
||||
* @param {Texture2D} texture - A texture.
|
||||
* @param {Vector2} position - The location (in screen coordinates) to draw the sprite.
|
||||
* @param {Rectangle} sourceRectangle - A rectangle that specifies (in texels) the source texels from a texture.
|
||||
* @param {Number} rotation - Specifies the angle (in radians) to rotate the sprite about its center.
|
||||
* @param {Vector2} scale - Scale factor.
|
||||
* @param {SpriteEffects} effects - Effects to apply.
|
||||
* @memberOf SpriteBatch
|
||||
*/
|
||||
SpriteBatch.prototype.Draw = function (texture, position, sourceRectangle, rotation, scale, effects) {
|
||||
"use strict";
|
||||
/*global SpriteEffects*/
|
||||
var self = this,
|
||||
flipHorizontally = 1,
|
||||
flipVertically = 1,
|
||||
aspectRatio = texture.Width() / texture.Height(),
|
||||
sourceAspectRatio = sourceRectangle.Width / sourceRectangle.Height,
|
||||
textureWidth = texture.Width(),
|
||||
posX = 0,
|
||||
posY = 0;
|
||||
|
||||
//Save the context to restore later
|
||||
self.ctx.save();
|
||||
|
||||
//Rotate the image if required
|
||||
if (rotation !== 0) {
|
||||
self.ctx.translate(Math.floor(position.X + texture.HalfWidth() * scale.X), Math.floor(position.Y + texture.HalfHeight() * scale.Y));
|
||||
self.ctx.rotate(rotation * Math.PI / 180);
|
||||
posX = -texture.HalfWidth() * scale.X;
|
||||
posY = -texture.HalfHeight() * scale.Y;
|
||||
} else {
|
||||
posX = position.X;
|
||||
posY = position.Y;
|
||||
}
|
||||
|
||||
//Apply sprite effects if needed
|
||||
if (effects === SpriteEffects.FlipHorizontally) {
|
||||
flipHorizontally = -1;
|
||||
} else if (effects === SpriteEffects.FlipVertically) {
|
||||
flipVertically = -1;
|
||||
}
|
||||
|
||||
//Scale the image
|
||||
self.ctx.scale(scale.X * flipHorizontally, scale.Y * flipVertically);
|
||||
|
||||
if (aspectRatio !== sourceAspectRatio) {
|
||||
textureWidth /= aspectRatio;
|
||||
}
|
||||
|
||||
//Draw the image
|
||||
self.ctx.drawImage(texture.Image,
|
||||
sourceRectangle.X, sourceRectangle.Y,
|
||||
sourceRectangle.Width, sourceRectangle.Height,
|
||||
Math.floor(posX) * flipHorizontally / scale.X, Math.floor(posY) * flipVertically / scale.Y,
|
||||
textureWidth * flipHorizontally, texture.Height() * flipVertically
|
||||
);
|
||||
|
||||
//Restore the canvas context
|
||||
self.ctx.restore();
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a string to a batch of sprites for rendering using the specified font, text, position, color and scale.
|
||||
* @name DrawString
|
||||
* @function
|
||||
* @param {String} font - A string representing the font for displaying text (example: "normal bold 20px Helvetica").
|
||||
* @param {String} text - A text string.
|
||||
* @param {Vector2} position - The location (in screen coordinates) to draw the sprite.
|
||||
* @param {String} color - A string representing the color (example: "#FF00F0").
|
||||
* @param {Vector2} scale - Scale factor.
|
||||
* @memberOf SpriteBatch
|
||||
*/
|
||||
SpriteBatch.prototype.DrawString = function (font, text, position, color, scale) {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
//Save the context to restore later
|
||||
self.ctx.save();
|
||||
|
||||
//Scale the image
|
||||
self.ctx.scale(scale.X, scale.Y);
|
||||
|
||||
//Determine the font, color and baseline, and then draw the given text
|
||||
self.ctx.font = font;
|
||||
self.ctx.fillStyle = color;
|
||||
self.ctx.textBaseline = "top";
|
||||
self.ctx.fillText(text, position.X, position.Y);
|
||||
|
||||
//Restore the canvas context
|
||||
self.ctx.restore();
|
||||
};
|
||||
|
||||
/**
|
||||
* Draw a given rectangle.
|
||||
* @name DrawRectangle
|
||||
* @function
|
||||
* @param {Rectangle} rectangle - The rectangle to draw.
|
||||
* @param {String} lineWidth - the width of the line to be drawn.
|
||||
* @param {String} color - A string representing the color (example: "#FF00F0").
|
||||
* @memberOf SpriteBatch
|
||||
*/
|
||||
SpriteBatch.prototype.DrawRectangle = function (rectangle, lineWidth, color) {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
//If the line width is null or undefined set a default value
|
||||
if (lineWidth === null || typeof lineWidth === "undefined") {
|
||||
lineWidth = "1";
|
||||
}
|
||||
|
||||
//If the color is null or undefined set a default color (black)
|
||||
if (color === null || typeof color === "undefined") {
|
||||
color = "#000000";
|
||||
}
|
||||
|
||||
//Save the context to restore later
|
||||
self.ctx.save();
|
||||
|
||||
//Set the line width and the line color
|
||||
self.ctx.lineWidth = lineWidth;
|
||||
self.ctx.strokeStyle = color;
|
||||
|
||||
//Draw the rectangle
|
||||
self.ctx.strokeRect(
|
||||
rectangle.X,
|
||||
rectangle.Y,
|
||||
rectangle.Width,
|
||||
rectangle.Height
|
||||
);
|
||||
|
||||
//Restore the canvas context
|
||||
self.ctx.restore();
|
||||
};
|
||||
|
||||
/**
|
||||
* Draw a given segment.
|
||||
* @name DrawSegment
|
||||
* @function
|
||||
* @param {Segment} segment - The segment to draw.
|
||||
* @param {String} lineWidth - the width of the line to be drawn.
|
||||
* @param {String} color - A string representing the color (example: "#FF00F0").
|
||||
* @memberOf SpriteBatch
|
||||
*/
|
||||
SpriteBatch.prototype.DrawSegment = function (segment, lineWidth, color) {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
//If the line width is null or undefined set a default value
|
||||
if (lineWidth === null || typeof lineWidth === "undefined") {
|
||||
lineWidth = "1";
|
||||
}
|
||||
|
||||
//If the color is null or undefined set a default color (black)
|
||||
if (color === null || typeof color === "undefined") {
|
||||
color = "#000000";
|
||||
}
|
||||
|
||||
//Save the context to restore later
|
||||
self.ctx.save();
|
||||
|
||||
//Set the line width and the line color
|
||||
self.ctx.lineWidth = lineWidth;
|
||||
self.ctx.strokeStyle = color;
|
||||
|
||||
//Draw the segment
|
||||
self.ctx.beginPath();
|
||||
self.ctx.moveTo(segment.pointA.X, segment.pointA.Y);
|
||||
self.ctx.lineTo(segment.pointB.X, segment.pointB.Y);
|
||||
self.ctx.stroke();
|
||||
|
||||
//Restore the canvas context
|
||||
self.ctx.restore();
|
||||
};
|
10
src/JS/XNA_Classes/SpriteEffects.js
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Defines sprite mirroring options.
|
||||
* @readonly
|
||||
* @enum {number}
|
||||
*/
|
||||
var SpriteEffects = Object.freeze({
|
||||
None: 0,
|
||||
FlipHorizontally: 1,
|
||||
FlipVertically: 2
|
||||
});
|
67
src/JS/XNA_Classes/Texture2D.js
Normal file
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Represents a 2D grid of texels.
|
||||
* @constructor
|
||||
* @param {String} name - The path to the resource.
|
||||
*/
|
||||
function Texture2D(name) {
|
||||
"use strict";
|
||||
/*global Rectangle, Image*/
|
||||
this.Name = name;
|
||||
this.Image = new Image();
|
||||
this.Image.src = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the width of the texture.
|
||||
* @name Height
|
||||
* @function
|
||||
* @memberOf Texture2D
|
||||
*/
|
||||
Texture2D.prototype.Height = function () {
|
||||
"use strict";
|
||||
return this.Image.height;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the height of the texture.
|
||||
* @name Width
|
||||
* @function
|
||||
* @memberOf Texture2D
|
||||
*/
|
||||
Texture2D.prototype.Width = function () {
|
||||
"use strict";
|
||||
return this.Image.width;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the bounds of the texture.
|
||||
* @name Bounds
|
||||
* @function
|
||||
* @memberOf Texture2D
|
||||
*/
|
||||
Texture2D.prototype.Bounds = function () {
|
||||
"use strict";
|
||||
return new Rectangle(0, 0, this.Width(), this.Height());
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets half of the width of the texture.
|
||||
* @name HalfWidth
|
||||
* @function
|
||||
* @memberOf Texture2D
|
||||
*/
|
||||
Texture2D.prototype.HalfWidth = function () {
|
||||
"use strict";
|
||||
return this.Width() / 2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets half of the height of the texture.
|
||||
* @name HalfHeight
|
||||
* @function
|
||||
* @memberOf Texture2D
|
||||
*/
|
||||
Texture2D.prototype.HalfHeight = function () {
|
||||
"use strict";
|
||||
return this.Height() / 2;
|
||||
};
|
153
src/JS/XNA_Classes/Vector2.js
Normal file
@ -0,0 +1,153 @@
|
||||
/**
|
||||
* Defines a vector with two components.
|
||||
* @constructor
|
||||
* @param {Number} x - Initial value for the x-component of the vector.
|
||||
* @param {Number} y - Initial value for the y-component of the vector.
|
||||
*/
|
||||
function Vector2(x, y) {
|
||||
"use strict";
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Vector2 with both of its components set to zero.
|
||||
* @name Zero
|
||||
* @function
|
||||
* @memberOf Vector2
|
||||
* @static
|
||||
*/
|
||||
Vector2.Zero = function () {
|
||||
"use strict";
|
||||
return new Vector2(0, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a Vector2 with both of its components set to one.
|
||||
* @name One
|
||||
* @function
|
||||
* @memberOf Vector2
|
||||
* @static
|
||||
*/
|
||||
Vector2.One = function () {
|
||||
"use strict";
|
||||
return new Vector2(1, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds two vectors.
|
||||
* @name Add
|
||||
* @function
|
||||
* @param {Vector2} value1 - Source vector 1
|
||||
* @param {Vector2} value2 - Source vector 2
|
||||
* @memberOf Vector2
|
||||
* @static
|
||||
*/
|
||||
Vector2.Add = function (value1, value2) {
|
||||
"use strict";
|
||||
return new Vector2(value1.X + value2.X, value1.Y + value2.Y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Substract two vectors.
|
||||
* @name Substract
|
||||
* @function
|
||||
* @param {Vector2} value1 - Source vector 1
|
||||
* @param {Vector2} value2 - Source vector 2
|
||||
* @memberOf Vector2
|
||||
* @static
|
||||
*/
|
||||
Vector2.Substract = function (value1, value2) {
|
||||
"use strict";
|
||||
return new Vector2(value1.X - value2.X, value1.Y - value2.Y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Divides the components of a vector by a scalar value or the components of another vector.
|
||||
* @name Divide
|
||||
* @function
|
||||
* @param {Vector2} value1 - Source vector 1
|
||||
* @param {Vector2} value2 - A scalar value or a source vector 2
|
||||
* @memberOf Vector2
|
||||
* @static
|
||||
*/
|
||||
Vector2.Divide = function (value1, value2) {
|
||||
"use strict";
|
||||
if (typeof (value2) === "number") {
|
||||
return new Vector2(value1.X / value2, value1.Y / value2);
|
||||
} else {
|
||||
return new Vector2(value1.X / value2.X, value1.Y / value2.Y);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Multiplies the components of a vector by a scalar value or the components of another vector.
|
||||
* @name Multiply
|
||||
* @function
|
||||
* @param {Vector2} value1 - Source vector 1
|
||||
* @param {Vector2} value2 - A scalar value or a source vector 2
|
||||
* @memberOf Vector2
|
||||
* @static
|
||||
*/
|
||||
Vector2.Multiply = function (value1, value2) {
|
||||
"use strict";
|
||||
if (typeof (value2) === "number") {
|
||||
return new Vector2(value1.X * value2, value1.Y * value2);
|
||||
} else {
|
||||
return new Vector2(value1.X * value2.X, value1.Y * value2.Y);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the distance between two vectors.
|
||||
* @name Distance
|
||||
* @function
|
||||
* @param {Vector2|Point} value1 - Source vector 1
|
||||
* @param {Vector2|Point} value2 - Source vector 2
|
||||
* @memberOf Vector2
|
||||
* @static
|
||||
*/
|
||||
Vector2.Distance = function (value1, value2) {
|
||||
"use strict";
|
||||
return (Math.sqrt(Math.pow(value2.X - value1.X, 2) + Math.pow(value2.Y - value1.Y, 2)));
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the length of the vector.
|
||||
* @name Length
|
||||
* @function
|
||||
* @memberOf Vector2
|
||||
*/
|
||||
Vector2.prototype.Length = function () {
|
||||
"use strict";
|
||||
return (Math.sqrt(Math.pow(this.X, 2) + Math.pow(this.Y, 2)));
|
||||
};
|
||||
|
||||
/**
|
||||
* Turns the current vector into a unit vector. The result is a vector one unit
|
||||
* in length pointing in the same direction as the original vector.
|
||||
* @name Normalize
|
||||
* @function
|
||||
* @memberOf Vector2
|
||||
*/
|
||||
Vector2.prototype.Normalize = function () {
|
||||
"use strict";
|
||||
var self = this,
|
||||
length = self.Length();
|
||||
|
||||
return (new Vector2(self.X / length, self.Y / length));
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the vectors are equal.
|
||||
* @name Equals
|
||||
* @function
|
||||
* @param {Vector2} v1 - vector 1.
|
||||
* @param {Vector2} v2 - vector 2.
|
||||
* @memberOf Vector2
|
||||
* @static
|
||||
*/
|
||||
Vector2.Equals = function (v1, v2) {
|
||||
"use strict";
|
||||
return (v1.X === v2.X && v1.Y === v2.Y);
|
||||
};
|
119
src/JS/XgameJS/AnimatedSprite.js
Normal file
@ -0,0 +1,119 @@
|
||||
/**
|
||||
* Represents an animated sprite, which is composed of various frames.
|
||||
* @constructor
|
||||
* @param {Texture2D} texture - The texture image.
|
||||
* @param {Vector2} scale - The scale of the image.
|
||||
* @param {Rectangle} sourceRect - The image source rectangle.
|
||||
* @param {Point} position - The sprite position in the canvas.
|
||||
* @param {Boolean} isVisible - Determines if the sprite is visible or not.
|
||||
* @param {Boolean} loop - Determines if the animation has to animate in loop or not (one time).
|
||||
* @param {Boolean} pingPongLoop - Determines if the animation should run in reverse when reachs the last
|
||||
* frame or not (reset to initial frame).
|
||||
* @param {Number} millisecondsPerFrame - A number representing the milliseconds between each frame.
|
||||
* @param {Number} numberOfFrames - The number of frames in the sprite sheet.
|
||||
*/
|
||||
function AnimatedSprite(texture, scale, sourceRect, position, isVisible, animationType, numberOfFrames, millisecondsPerFrame) {
|
||||
"use strict";
|
||||
/*global Sprite, AnimationTypes, setInterval, clearInterval*/
|
||||
|
||||
//Call the father constructor (super)
|
||||
Sprite.call(this, texture, scale, sourceRect, position, isVisible);
|
||||
|
||||
this.AnimationType = animationType;
|
||||
this.NumberOfFrames = numberOfFrames;
|
||||
this.MillisecondsPerFrame = millisecondsPerFrame;
|
||||
this.CurrentFrame = 0;
|
||||
this.Forward = true; //to control the direction of the loop
|
||||
this.Columns = Math.floor(texture.Width() / sourceRect.Width);
|
||||
this.RunAnimation = true;
|
||||
this.VerticalOffset = 0; //(optional) used when the animation sheet has different
|
||||
//animations representing different states of the object
|
||||
//which owns the sprite
|
||||
this.interval = null;
|
||||
}
|
||||
|
||||
//Create the AnimatedSprite.prototype object, which inherits from Sprite.prototype.
|
||||
//Then stablish the "constructor" property to reference to AnimatedSprite
|
||||
AnimatedSprite.prototype = Object.create(Sprite.prototype);
|
||||
AnimatedSprite.prototype.constructor = AnimatedSprite;
|
||||
|
||||
/**
|
||||
* Starts the update animation timer.
|
||||
* @name StartAnimation
|
||||
* @function
|
||||
* @memberof AnimatedSprite
|
||||
*/
|
||||
AnimatedSprite.prototype.StartAnimation = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
self.interval = setInterval(self.UpdateAnimation.bind(self), self.MillisecondsPerFrame);
|
||||
};
|
||||
|
||||
/**
|
||||
* Stops the update animation timer.
|
||||
* @name StopAnimation
|
||||
* @function
|
||||
* @memberof AnimatedSprite
|
||||
*/
|
||||
AnimatedSprite.prototype.StopAnimation = function () {
|
||||
"use strict";
|
||||
clearInterval(this.interval);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the animation depending on the number of frames
|
||||
* @name UpdateAnimation
|
||||
* @function
|
||||
* @memberof AnimatedSprite
|
||||
*/
|
||||
AnimatedSprite.prototype.UpdateAnimation = function () {
|
||||
"use strict";
|
||||
var self = this,
|
||||
sourceRect = self.SourceRect;
|
||||
|
||||
sourceRect.X = Math.floor(self.CurrentFrame % self.Columns) * sourceRect.Width;
|
||||
sourceRect.Y = Math.floor(self.CurrentFrame / self.Columns) * sourceRect.Height;
|
||||
|
||||
if (self.RunAnimation) {
|
||||
|
||||
//Do different actions depending on the animation type
|
||||
switch (self.AnimationType) {
|
||||
|
||||
case AnimationTypes.PlayOneTime:
|
||||
//It the last frame has been reached, stop the run
|
||||
if (self.CurrentFrame === self.NumberOfFrames - 1) {
|
||||
self.RunAnimation = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case AnimationTypes.Loop:
|
||||
//If the last frame has been reached, reset to the initial frame
|
||||
if (self.CurrentFrame === self.NumberOfFrames - 1) {
|
||||
self.CurrentFrame = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case AnimationTypes.PingPongLoop:
|
||||
//If the last frame has been reached, reverse the animation
|
||||
if (self.CurrentFrame === self.NumberOfFrames - 1) {
|
||||
self.Forward = false;
|
||||
}
|
||||
//If the first frame has been reached, set forward to true
|
||||
if (self.CurrentFrame === 0) {
|
||||
self.Forward = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//Add 1 to currentFrame if forward is true, subtract 1 if it's false
|
||||
if (self.Forward) {
|
||||
self.CurrentFrame += 1;
|
||||
} else {
|
||||
self.CurrentFrame -= 1;
|
||||
}
|
||||
|
||||
//Apply vertical offset
|
||||
sourceRect.Y += sourceRect.Height * self.VerticalOffset;
|
||||
}
|
||||
};
|
10
src/JS/XgameJS/AnimationTypes.js
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Defines the animation types.
|
||||
* @readonly
|
||||
* @enum {number}
|
||||
*/
|
||||
var AnimationTypes = Object.freeze({
|
||||
PlayOneTime: 0,
|
||||
Loop: 1, //when the animation reaches the last frame then reset to the initial frame
|
||||
PingPongLoop: 2 //when the animation reaches the last frame then reverse the animation
|
||||
});
|
344
src/JS/XgameJS/Ball.js
Normal file
@ -0,0 +1,344 @@
|
||||
/**
|
||||
* Defines a Ball.
|
||||
* @constructor
|
||||
* @param {Sprite} sprite - The sprite that represents the ball.
|
||||
* @param {Number} radius - The radius of the circle of the ball.
|
||||
* @param {Point} position - The position of the ball.
|
||||
* @param {Number} position - The position of the ball.
|
||||
* @param {Boolean} bounce - Determines if the ball can bounce or not.
|
||||
*/
|
||||
function Ball(sprite, radius, position, index, bounce, rotate) {
|
||||
"use strict";
|
||||
/*global Vector2, Circle*/
|
||||
this.Sprite = sprite;
|
||||
this.Circle = new Circle(radius, position.X, position.Y);
|
||||
|
||||
//Physics properties
|
||||
this.SpeedV = Vector2.Zero();
|
||||
this.GroundFriction = 0.975;
|
||||
this.BallBounceFriction = 0.85;
|
||||
this.WallBounceFriction = 0.7;
|
||||
this.MaxRotationSpeedTransmision = 25;
|
||||
this.CurrentRotationSpeed = 0;
|
||||
|
||||
//Platform game properties
|
||||
this.IsOnGround = false;
|
||||
|
||||
//Drag & Drop properties
|
||||
this.IsDraggable = true;
|
||||
this.IsBeenDragged = false;
|
||||
|
||||
//Other properties
|
||||
this.RandomDir = [-0.1, 0.1];
|
||||
this.Index = index;
|
||||
this.IsBounceOn = bounce;
|
||||
this.IsRotationOn = rotate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ball.
|
||||
* @name Update
|
||||
* @function
|
||||
* @param {Number} worldWidth - The width of the game world.
|
||||
* @param {Number} worldHeight - The height of the game world.
|
||||
* @param {Array} balls - Array of existing balls.
|
||||
* @param {Boolean} isGravityOn - Determines if the gravity is activated or not.
|
||||
* @param {GravityDirections} gravityDir - The gravity direction of the game world.
|
||||
* @param {Number} gravityForce - The gravity force value.
|
||||
* @memberOf Ball
|
||||
*/
|
||||
Ball.prototype.Update = function (worldWidth, worldHeight, balls, isGravityOn, gravityDir, gravityForce) {
|
||||
"use strict";
|
||||
/*global GravityDirections, Mouse, Point, hitTestPoint*/
|
||||
var self = this,
|
||||
randomDirImpulse = 0,
|
||||
len = 0,
|
||||
i = 0,
|
||||
j = 0;
|
||||
|
||||
//Check if the mouse clicked a ball to drag it
|
||||
if (self.Circle.Contains(new Point(Mouse.X, Mouse.Y)) && self.IsDraggable && Mouse.LeftButtonPressed && !Mouse.IsDraggingSomething) { //Si quitamos IsDraggingSom... ocurren cosas divertidas
|
||||
//Assign the sprite to the dragSprite variable
|
||||
self.IsBeenDragged = true;
|
||||
Mouse.IsDraggingSomething = true;
|
||||
self.CurrentRotationSpeed = 0;
|
||||
self.SpeedV.X = 0;
|
||||
self.SpeedV.Y = 0;
|
||||
i = self.Index;
|
||||
len = balls.length;
|
||||
|
||||
//push the dragSprite to the end of the sprites
|
||||
//array so that it's displayed last
|
||||
self.Index = balls.length - 1;
|
||||
balls.push(self);
|
||||
|
||||
//Splice the dragSprite from its previous
|
||||
//position in the sprites array
|
||||
balls.splice(i, 1);
|
||||
|
||||
for (j = i; j < len - 1; j += 1) {
|
||||
balls[j].Index -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Update the Circle position with the mouse position
|
||||
if (Mouse.IsMoving && self.IsBeenDragged) {
|
||||
self.Circle.X = Mouse.X - self.Circle.Radius;
|
||||
self.Circle.Y = Mouse.Y - self.Circle.Radius;
|
||||
}
|
||||
|
||||
//If the mouse left button was released drop the ball
|
||||
if (self.IsBeenDragged && !Mouse.LeftButtonPressed) {
|
||||
self.IsBeenDragged = false;
|
||||
Mouse.IsDraggingSomething = false;
|
||||
}
|
||||
|
||||
//Apply gravity depending on the gravity direction
|
||||
if (isGravityOn && !self.IsBeenDragged) {
|
||||
|
||||
//Random impulse when the balls are generated
|
||||
if (!self.IsOnGround && self.SpeedV.X === 0 && self.SpeedV.Y === 0) {
|
||||
randomDirImpulse = self.RandomDir[Math.floor(Math.random() * 2)];
|
||||
}
|
||||
|
||||
switch (gravityDir) {
|
||||
|
||||
//Gravity down
|
||||
case GravityDirections.G_DOWN:
|
||||
self.SpeedV.Y += gravityForce;
|
||||
self.SpeedV.X += randomDirImpulse;
|
||||
if (self.Circle.Bottom() >= worldHeight) {
|
||||
self.SpeedV.X *= self.GroundFriction;
|
||||
self.IsOnGround = true;
|
||||
}
|
||||
break;
|
||||
|
||||
//Gravity up
|
||||
case GravityDirections.G_UP:
|
||||
self.SpeedV.Y -= gravityForce;
|
||||
self.SpeedV.X += randomDirImpulse;
|
||||
if (self.Circle.Top() <= 0) {
|
||||
self.SpeedV.X *= self.GroundFriction;
|
||||
self.IsOnGround = true;
|
||||
}
|
||||
break;
|
||||
|
||||
//Gravity left
|
||||
case GravityDirections.G_LEFT:
|
||||
self.SpeedV.X -= gravityForce;
|
||||
self.SpeedV.Y += randomDirImpulse;
|
||||
if (self.Circle.Left() <= 0) {
|
||||
self.SpeedV.Y *= self.GroundFriction;
|
||||
self.IsOnGround = true;
|
||||
}
|
||||
break;
|
||||
|
||||
//Gravity right
|
||||
case GravityDirections.G_RIGHT:
|
||||
self.SpeedV.X += gravityForce;
|
||||
self.SpeedV.Y += randomDirImpulse;
|
||||
if (self.Circle.Right() >= worldWidth) {
|
||||
self.SpeedV.Y *= self.GroundFriction;
|
||||
self.IsOnGround = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Move the ball if it isn't dragged
|
||||
if (!self.IsBeenDragged) {
|
||||
self.Circle.X += self.SpeedV.X;
|
||||
self.Circle.Y += self.SpeedV.Y;
|
||||
}
|
||||
|
||||
//Collision with balls
|
||||
len = balls.length;
|
||||
if (len > 1 && !self.IsBeenDragged) {
|
||||
for (i = 0; i < len; i += 1) {
|
||||
if (self.Index !== i) {
|
||||
self.CollisionWithBall(balls[i], self.IsBounceOn, self.IsRotationOn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Screen boundaries
|
||||
//Left
|
||||
if (self.Circle.Left() < 0) {
|
||||
if (self.IsBounceOn) {
|
||||
self.SpeedV.X *= -self.WallBounceFriction;
|
||||
}
|
||||
self.Circle.X = 0;
|
||||
}
|
||||
//Up
|
||||
if (self.Circle.Top() < 0) {
|
||||
if (self.IsBounceOn) {
|
||||
self.SpeedV.Y *= -self.WallBounceFriction;
|
||||
}
|
||||
self.Circle.Y = 0;
|
||||
}
|
||||
//Right
|
||||
if (self.Circle.Right() > worldWidth) {
|
||||
if (self.IsBounceOn) {
|
||||
self.SpeedV.X *= -self.WallBounceFriction;
|
||||
}
|
||||
self.Circle.X = worldWidth - self.Circle.Diameter();
|
||||
}
|
||||
//Down
|
||||
if (self.Circle.Bottom() > worldHeight) {
|
||||
if (self.IsBounceOn) {
|
||||
self.SpeedV.Y *= -self.WallBounceFriction;
|
||||
}
|
||||
self.Circle.Y = worldHeight - self.Circle.Diameter();
|
||||
}
|
||||
|
||||
//Update the sprite
|
||||
self.Sprite.Position.X = self.Circle.X;
|
||||
self.Sprite.Position.Y = self.Circle.Y;
|
||||
|
||||
//Update the sprite rotation
|
||||
self.Sprite.Rotation += self.CurrentRotationSpeed;
|
||||
self.CurrentRotationSpeed *= self.GroundFriction;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a ball collide with other ball. Besides, bounce and rotate the balls if needed.
|
||||
* @name CollisionWithBall
|
||||
* @function
|
||||
* @param {Ball} ball - The ball which will be checked to find a collision.
|
||||
* @memberOf Ball
|
||||
*/
|
||||
Ball.prototype.CollisionWithBall = function (ball) {
|
||||
"use strict";
|
||||
var self = this,
|
||||
overlapV = self.Circle.IsInsideCircle(ball.Circle),
|
||||
vector = null,
|
||||
d = null,
|
||||
angle = 0,
|
||||
b1Magnitude = 0,
|
||||
b2Magnitude = 0,
|
||||
s = null;
|
||||
|
||||
//If the other ball is inside the other
|
||||
if (overlapV !== false) {
|
||||
self.Circle.X += overlapV.X;
|
||||
self.Circle.Y += overlapV.Y;
|
||||
return true;
|
||||
}
|
||||
|
||||
//Check if this ball is inside the other
|
||||
overlapV = self.Circle.Intersects(ball.Circle);
|
||||
|
||||
//If there is a collision with the other ball move it away of the other
|
||||
if (overlapV !== false) {
|
||||
|
||||
vector = overlapV.Y; //the vector between the balls centers
|
||||
d = vector.Normalize();
|
||||
angle = Math.atan2(d.X, d.X) * 180 / Math.PI;
|
||||
b1Magnitude = self.SpeedV.Length();
|
||||
b2Magnitude = ball.SpeedV.Length();
|
||||
|
||||
//If rotation is activated then rotate the ball
|
||||
if (self.IsRotationOn) {
|
||||
if (
|
||||
(angle >= 0 && angle <= 90 && self.SpeedV.X > 0) ||
|
||||
(angle > 90 && angle <= 180 && self.SpeedV.X >= 0) ||
|
||||
(angle < 0 && angle >= -90 && self.SpeedV.X <= 0) ||
|
||||
(angle < -90 && angle >= -180 && self.SpeedV.X < 0)
|
||||
) {
|
||||
self.CurrentRotationSpeed = Math.min(Math.abs(b1Magnitude), self.MaxRotationSpeedTransmision);
|
||||
ball.CurrentRotationSpeed = -Math.min(Math.abs(b2Magnitude), ball.MaxRotationSpeedTransmision);
|
||||
} else {
|
||||
self.CurrentRotationSpeed = -Math.min(Math.abs(b1Magnitude), self.MaxRotationSpeedTransmision);
|
||||
ball.CurrentRotationSpeed = Math.min(Math.abs(b2Magnitude), ball.MaxRotationSpeedTransmision);
|
||||
}
|
||||
|
||||
//Limit the rotation speeds
|
||||
if (Math.abs(self.CurrentRotationSpeed) < 1) {
|
||||
self.CurrentRotationSpeed = 0;
|
||||
}
|
||||
if (Math.abs(ball.CurrentRotationSpeed) < 1) {
|
||||
ball.CurrentRotationSpeed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Move circle 1 out of the collision by multiplying
|
||||
//the overlap with the normalized vector and add it to
|
||||
//ball 1's position
|
||||
self.Circle.X += overlapV.X * d.X;
|
||||
self.Circle.Y += overlapV.X * d.Y;
|
||||
//Ocurren cosas diver al poner esto
|
||||
//ball.Circle.X += overlapV.X * overlapV.Y[0];
|
||||
//ball.Circle.Y += overlapV.X * overlapV.Y[1];
|
||||
|
||||
if (self.IsBounceOn) {
|
||||
//Create a collision vector object to represent the bounce surface
|
||||
//Find the bounce surface's X and Y properties
|
||||
//(This represents the normal of the distance vector between the circles)
|
||||
s = new Vector2(vector.Y, -vector.X);
|
||||
|
||||
//Bounce b1 off the surface
|
||||
self.BounceOffSurface(ball, s);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Bounces the current ball with other ball given the virtual surface between them.
|
||||
* @name BounceOffSurface
|
||||
* @function
|
||||
* @param {Ball} ball - The ball which will bounced.
|
||||
* @param {Vector2} s - The surface to bounce off.
|
||||
* @memberOf Ball
|
||||
*/
|
||||
Ball.prototype.BounceOffSurface = function (ball, s) {
|
||||
"use strict";
|
||||
//1. Calculate the collision surface's properties
|
||||
|
||||
|
||||
var self = this,
|
||||
//Find the surface vector's left normal
|
||||
leftNormalV = new Vector2(s.Y, -s.X),
|
||||
//s.lx = s.Y;
|
||||
//s.ly = -s.X;
|
||||
|
||||
//Find its magnitude
|
||||
sLength = s.Length(),
|
||||
|
||||
//Find its normalized/unit vector values
|
||||
dV = s.Normalize(),
|
||||
|
||||
//2. Bounce the ball off the surface (s)
|
||||
|
||||
//Find the dot product between the object and the surface
|
||||
dp1 = self.SpeedV.X * dV.X + self.SpeedV.Y * dV.Y,
|
||||
|
||||
//Project the object's velocity onto the collision surface
|
||||
p1V = new Vector2(dp1 * dV.X, dp1 * dV.Y),
|
||||
|
||||
//Find the dot product of the object and the surface's left normal (s.lx and s.ly)
|
||||
dp2 = self.SpeedV.X * (leftNormalV.X / sLength) + self.SpeedV.Y * (leftNormalV.Y / sLength),
|
||||
|
||||
//Project the object's velocity onto the surface's left normal
|
||||
p2V = new Vector2(dp2 * (leftNormalV.X / sLength), dp2 * (leftNormalV.Y / sLength)),
|
||||
bounceV = null;
|
||||
|
||||
//Reverse the projection on the surface's left normal
|
||||
p2V.X *= -1;
|
||||
p2V.Y *= -1;
|
||||
|
||||
//Add up the projections to create a new bounce vector
|
||||
bounceV = new Vector2(p1V.X + p2V.X, p1V.Y + p2V.Y);
|
||||
|
||||
//Assign the bounce vector to the object's velocity
|
||||
self.SpeedV.X = bounceV.X * self.BallBounceFriction;
|
||||
self.SpeedV.Y = bounceV.Y * self.BallBounceFriction;
|
||||
if (!ball.IsBeenDragged) {
|
||||
ball.SpeedV.X = -bounceV.X * ball.BallBounceFriction;
|
||||
ball.SpeedV.Y = -bounceV.Y * ball.BallBounceFriction;
|
||||
}
|
||||
};
|
150
src/JS/XgameJS/Camera.js
Normal file
@ -0,0 +1,150 @@
|
||||
/**
|
||||
* Defines the game camera.
|
||||
* @constructor
|
||||
* @param {Number} width - The width of the camera.
|
||||
* @param {Number} height - The height of the camera.
|
||||
* @param {Number} levelWidth - The width of the level.
|
||||
* @param {Number} levelHeight - The height of the level.
|
||||
* @param {Number} zoom - The zoom of the camera.
|
||||
*/
|
||||
function Camera(width, height, levelWidth, levelHeight, zoom) {
|
||||
"use strict";
|
||||
/*global Point, Vector2*/
|
||||
this.Width = width;
|
||||
this.Height = height;
|
||||
this.LevelWidth = levelWidth;
|
||||
this.LevelHeight = levelHeight;
|
||||
this.Zoom = zoom;
|
||||
this.Position = Point.Zero();
|
||||
this.SpeedV = Vector2.Zero(); //For parallax scrolling
|
||||
this.PreviousSpeedX = 0; //For parallax scrolling
|
||||
|
||||
//Camera constants
|
||||
this.upLeftMarginPercentage = 0.3;
|
||||
this.downRightMarginPercentage = 0.7;
|
||||
this.MaxZoom = 2.5;
|
||||
this.MinZoom = 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The camera's inner right scroll boundaries.
|
||||
* @name RightInnerBoundary
|
||||
* @function
|
||||
* @memberOf Camera
|
||||
*/
|
||||
Camera.prototype.RightInnerBoundary = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
return self.Position.X + (self.Width * self.downRightMarginPercentage / self.Zoom);
|
||||
};
|
||||
|
||||
/**
|
||||
* The camera's inner left scroll boundaries.
|
||||
* @name LeftInnerBoundary
|
||||
* @function
|
||||
* @memberOf Camera
|
||||
*/
|
||||
Camera.prototype.LeftInnerBoundary = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
return self.Position.X + (self.Width * self.upLeftMarginPercentage / self.Zoom);
|
||||
};
|
||||
|
||||
/**
|
||||
* The camera's inner top scroll boundaries.
|
||||
* @name TopInnerBoundary
|
||||
* @function
|
||||
* @memberOf Camera
|
||||
*/
|
||||
Camera.prototype.TopInnerBoundary = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
return self.Position.Y + (self.Height * self.upLeftMarginPercentage / self.Zoom);
|
||||
};
|
||||
|
||||
/**
|
||||
* The camera's inner bottom scroll boundaries.
|
||||
* @name BottomInnerBoundary
|
||||
* @function
|
||||
* @memberOf Camera
|
||||
*/
|
||||
Camera.prototype.BottomInnerBoundary = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
return self.Position.Y + (self.Height * self.downRightMarginPercentage / self.Zoom);
|
||||
};
|
||||
|
||||
/**
|
||||
* Increases the zoom by 0.1.
|
||||
* @name IncreaseZoom
|
||||
* @function
|
||||
* @memberOf Camera
|
||||
*/
|
||||
Camera.prototype.IncreaseZoom = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
if (self.Zoom < self.MaxZoom) {
|
||||
self.Zoom += 0.1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Decreases the zoom by 0.1.
|
||||
* @name DecreaseZoom
|
||||
* @function
|
||||
* @memberOf Camera
|
||||
*/
|
||||
Camera.prototype.DecreaseZoom = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
if (self.Zoom > self.MinZoom) {
|
||||
self.Zoom -= 0.1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates de camera depending on the player's position.
|
||||
* @name Update
|
||||
* @function
|
||||
* @param {Player} player - the player of the game.
|
||||
* @memberOf Camera
|
||||
*/
|
||||
Camera.prototype.Update = function (player) {
|
||||
"use strict";
|
||||
var self = this,
|
||||
playerSprite = player.Sprite;
|
||||
|
||||
//Scroll the camera
|
||||
if (playerSprite.Position.X < self.LeftInnerBoundary()) {
|
||||
self.Position.X = Math.floor(playerSprite.Position.X - (self.Width * self.upLeftMarginPercentage / self.Zoom));
|
||||
}
|
||||
if (playerSprite.Position.X + playerSprite.Width() > self.RightInnerBoundary()) {
|
||||
self.Position.X = Math.floor(playerSprite.Position.X + playerSprite.Width() - (self.Width * self.downRightMarginPercentage / self.Zoom));
|
||||
}
|
||||
if (playerSprite.Position.Y < self.TopInnerBoundary()) {
|
||||
self.Position.Y = Math.floor(playerSprite.Position.Y - (self.Height * self.upLeftMarginPercentage / self.Zoom));
|
||||
}
|
||||
if (playerSprite.Position.Y + playerSprite.Height() > self.BottomInnerBoundary()) {
|
||||
self.Position.Y = Math.floor(playerSprite.Position.Y + playerSprite.Height() - (self.Height * self.downRightMarginPercentage / self.Zoom));
|
||||
}
|
||||
|
||||
//The camera's world boundaries
|
||||
if (self.Position.X < 0) {
|
||||
self.Position.X = 0;
|
||||
}
|
||||
if (self.Position.X * self.Zoom + self.Width > self.LevelWidth * self.Zoom) {
|
||||
self.Position.X = (self.LevelWidth * self.Zoom - self.Width) / self.Zoom;
|
||||
}
|
||||
if (self.Position.Y < 0) {
|
||||
self.Position.Y = 0;
|
||||
}
|
||||
if (self.Position.Y * self.Zoom + self.Height > (self.LevelHeight * self.Zoom)) {
|
||||
self.Position.Y = (self.LevelHeight * self.Zoom - self.Height) / self.Zoom;
|
||||
}
|
||||
|
||||
//Figure out the camera's velocity by subtracting its position in the
|
||||
//previous frame from its position in this frame
|
||||
self.SpeedV.X = self.Position.X - self.PreviousSpeedX;
|
||||
};
|
300
src/JS/XgameJS/Circle.js
Normal file
@ -0,0 +1,300 @@
|
||||
/**
|
||||
* Defines a circle.
|
||||
* @constructor
|
||||
* @param {Number} radius - The radius of the circle.
|
||||
* @param {Number} x - The x-coordinate of the circle.
|
||||
* @param {Number} y - The y-coordinate of the circle.
|
||||
*/
|
||||
function Circle(radius, x, y) {
|
||||
"use strict";
|
||||
this.Radius = radius;
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the diameter of the circle.
|
||||
* @name Diameter
|
||||
* @function
|
||||
* @memberOf Circle
|
||||
*/
|
||||
Circle.prototype.Diameter = function () {
|
||||
"use strict";
|
||||
return this.Radius * 2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the upper-left value of the circle.
|
||||
* @name Location
|
||||
* @function
|
||||
* @memberOf Circle
|
||||
*/
|
||||
Circle.prototype.Location = function () {
|
||||
"use strict";
|
||||
/*global Point */
|
||||
return new Point(this.X, this.Y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the y-coordinate of the top of the circle.
|
||||
* @name Top
|
||||
* @function
|
||||
* @memberOf Circle
|
||||
*/
|
||||
Circle.prototype.Top = function () {
|
||||
"use strict";
|
||||
return this.Y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the y-coordinate of the bottom of the circle.
|
||||
* @name Bottom
|
||||
* @function
|
||||
* @memberOf Circle
|
||||
*/
|
||||
Circle.prototype.Bottom = function () {
|
||||
"use strict";
|
||||
return this.Y + this.Diameter();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the x-coordinate of the left side of the circle.
|
||||
* @name Left
|
||||
* @function
|
||||
* @memberOf Circle
|
||||
*/
|
||||
Circle.prototype.Left = function () {
|
||||
"use strict";
|
||||
return this.X;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the x-coordinate of the right of the circle.
|
||||
* @name Right
|
||||
* @function
|
||||
* @memberOf Circle
|
||||
*/
|
||||
Circle.prototype.Right = function () {
|
||||
"use strict";
|
||||
return this.X + this.Diameter();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the Point that specifies the center of the circle.
|
||||
* @name Center
|
||||
* @function
|
||||
* @memberOf Circle
|
||||
*/
|
||||
Circle.prototype.Center = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
//console.log(self.X);
|
||||
return new Point(self.X + self.Radius, self.Y + self.Radius);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether this circle contains a specified Point.
|
||||
* @name Contains
|
||||
* @function
|
||||
* @param {Point} point - The Point to evaluate.
|
||||
* @memberOf Circle
|
||||
*/
|
||||
Circle.prototype.Contains = function (value) {
|
||||
"use strict";
|
||||
/*global Vector2*/
|
||||
return (Vector2.Distance(this.Center(), value) <= this.Radius);
|
||||
};
|
||||
|
||||
/**
|
||||
* Pushes the edges of the circle out by the amount specified.
|
||||
* @name Inflate
|
||||
* @function
|
||||
* @param {Number} amount - Value to push the radius out by.
|
||||
* @memberOf Circle
|
||||
*/
|
||||
Circle.prototype.Inflate = function (amount) {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
self.Radius += amount;
|
||||
if (self.Radius < 0) {
|
||||
self.Radius = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether a specified Circle is inside this Circle, and by how much.
|
||||
* @name IsInsideCircle
|
||||
* @function
|
||||
* @param {Circle} circle - The Circle to evaluate.
|
||||
* @memberOf Circle
|
||||
*/
|
||||
Circle.prototype.IsInsideCircle = function (circle) {
|
||||
"use strict";
|
||||
var self = this,
|
||||
centerA = self.Center(),
|
||||
centerB = circle.Center(),
|
||||
vector = null,
|
||||
d = null,
|
||||
surfacePoint = null,
|
||||
distanceToSurface = 0;
|
||||
|
||||
//Check if circles have the same center
|
||||
if (Point.Equals(centerA, centerB)) {
|
||||
distanceToSurface = (self.Radius + circle.Radius);
|
||||
return new Vector2(0, distanceToSurface);
|
||||
|
||||
//Check if self circle is inside the other circle
|
||||
} else if (self.Radius < circle.Radius) {
|
||||
if (Vector2.Distance(centerA, centerB) <= Math.abs(circle.Radius - self.Radius)) {
|
||||
vector = new Vector2(centerA.X - centerB.X, centerA.Y - centerB.Y);
|
||||
d = vector.Normalize();
|
||||
surfacePoint = new Point((centerB.X + self.Radius) * d.X, (centerB.Y + self.Radius) * d.Y);
|
||||
distanceToSurface = Vector2.Distance(centerA, surfacePoint) + self.Radius;
|
||||
return new Vector2(distanceToSurface * d.X, distanceToSurface * d.Y);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether a specified Circle intersects with this Circle, and by how much.
|
||||
* @name Intersects
|
||||
* @function
|
||||
* @param {Circle} value - The Circle to evaluate.
|
||||
* @memberOf Circle
|
||||
*/
|
||||
Circle.prototype.Intersects = function (value) {
|
||||
"use strict";
|
||||
/*global Vector2 */
|
||||
var self = this,
|
||||
//Calculate the vector between the circles center points
|
||||
vector = new Vector2(
|
||||
self.Center().X - value.Center().X,
|
||||
self.Center().Y - value.Center().Y
|
||||
),
|
||||
//Find the distance between the circles
|
||||
magnitude = vector.Length(),
|
||||
//Add together the circles combined radius
|
||||
combinedRadius = self.Radius + value.Radius,
|
||||
overlap = 0,
|
||||
d = null;
|
||||
|
||||
//Figure out if there's a collision
|
||||
if (magnitude < combinedRadius) {
|
||||
//Yes, a collision is happening.
|
||||
//Find the amount of overlap between the circles
|
||||
overlap = combinedRadius - magnitude;
|
||||
|
||||
//Normalize the vector, these numbers tell us the direction of the collision.
|
||||
//d = vector.Normalize();
|
||||
|
||||
//Return the overlap and the vector between the circles center points
|
||||
return new Vector2(overlap, vector);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether a specified Segment intersects with this Circle, and by how much.
|
||||
* @name IntersectsSegment
|
||||
* @function
|
||||
* @param {Segment} segment - The Segment to evaluate.
|
||||
* @memberOf Circle
|
||||
*/
|
||||
Circle.prototype.IntersectsSegment = function (segment) {
|
||||
"use strict";
|
||||
/*global Vector2*/
|
||||
var self = this,
|
||||
pointA = new Point(segment.pointA.X - self.Radius, segment.pointA.Y - self.Radius),
|
||||
pointB = new Point(segment.pointB.X - self.Radius, segment.pointB.Y - self.Radius),
|
||||
// Calculate the euclidean distance between a & b
|
||||
distance = Vector2.Distance(pointA, pointB),
|
||||
// Compute the direction vector d from a to b
|
||||
dir = new Vector2((pointB.X - pointA.X) / distance, (pointB.Y - pointA.Y) / distance),
|
||||
// Now the line equation is x = dx*t + ax, y = dy*t + ay with 0 <= t <= 1.
|
||||
// compute the value t of the closest point to the circle center (cx, cy)
|
||||
t = (dir.X * (self.X - pointA.X)) + (dir.Y * (self.Y - pointA.Y)),
|
||||
// compute the coordinates of the point e on line and closest to c
|
||||
e = new Point((t * dir.X) + pointA.X, (t * dir.Y) + pointA.Y),
|
||||
// Calculate the euclidean distance between c & e
|
||||
eDistCtoE = Vector2.Distance(self, e);
|
||||
|
||||
Vector2.Add(e, self.Radius);
|
||||
|
||||
// test if the line intersects the circle
|
||||
if (eDistCtoE < self.Radius) {
|
||||
|
||||
// compute distance from t to circle intersection point
|
||||
var dt = Math.sqrt(Math.pow(self.Radius, 2) - Math.pow(eDistCtoE, 2));
|
||||
|
||||
// compute first intersection point
|
||||
var f = new Point(((t - dt) * dir.X) + pointA.X, ((t - dt) * dir.Y) + pointA.Y);
|
||||
// check if f lies on the line
|
||||
f.onLine = (Vector2.Distance(pointA, f) + Vector2.Distance(f, pointB) === Vector2.Distance(pointA, pointB));
|
||||
|
||||
// compute second intersection point
|
||||
var g = new Point(((t + dt) * dir.X) + pointA.X, ((t + dt) * dir.Y) + pointA.Y);
|
||||
// check if g lies on the line
|
||||
g.onLine = (Vector2.Distance(pointA, g) + Vector2.Distance(g, pointB) === Vector2.Distance(pointA, pointB));
|
||||
|
||||
Vector2.Add(f, self.Radius);
|
||||
Vector2.Add(g, self.Radius);
|
||||
|
||||
//return {points: {intersection1:f, intersection2:g}, pointOnLine: e};
|
||||
//console.log("Two intersections");
|
||||
var circleCenter = self.Center(),
|
||||
vectorAux1 = new Vector2(circleCenter.X - e.X, circleCenter.Y - e.Y),
|
||||
magnitude1 = vectorAux1.Length(),
|
||||
d = vectorAux1.Normalize(),
|
||||
vectorAux3 = new Vector2(circleCenter.X - pointA.X - self.Radius, circleCenter.Y - pointA.Y - self.Radius),
|
||||
magnitude3 = vectorAux3.Length(),
|
||||
vectorAux4 = new Vector2(circleCenter.X - pointB.X - self.Radius, circleCenter.Y - pointB.Y - self.Radius),
|
||||
magnitude4 = vectorAux4.Length(),
|
||||
overlap = 1;
|
||||
|
||||
if (magnitude1 < self.Radius && (f.onLine || g.onLine)) {
|
||||
|
||||
var pOnLine = null;
|
||||
|
||||
if ((f.onLine && !g.onLine) || (!f.onLine && g.onLine)) {
|
||||
|
||||
if (f.onLine) {
|
||||
pOnLine = f;
|
||||
} else {
|
||||
pOnLine = g;
|
||||
}
|
||||
|
||||
var vectorAux2 = new Vector2(circleCenter.X - pOnLine.X, circleCenter.Y - pOnLine.Y),
|
||||
magnitude2 = vectorAux2.Length();
|
||||
|
||||
d = vectorAux2.Normalize();
|
||||
|
||||
if (magnitude3 < self.Radius) {
|
||||
overlap = (new Vector2(pOnLine.X - pointA.X - self.Radius, pOnLine.Y - pointA.Y - self.Radius)).Length();
|
||||
} else if (magnitude4 < self.Radius) {
|
||||
overlap = (new Vector2(pOnLine.X - pointB.X - self.Radius, pOnLine.Y - pointB.Y - self.Radius)).Length();
|
||||
} else {
|
||||
overlap = (self.Radius - magnitude1);
|
||||
}
|
||||
|
||||
} else if (g.onLine && f.onLine) {
|
||||
|
||||
overlap = (self.Radius - magnitude1);
|
||||
|
||||
}
|
||||
|
||||
return new Vector2(overlap * d.X, overlap * d.Y);
|
||||
}
|
||||
}
|
||||
/*else if (parseInt(eDistCtoE) === parseInt(self.Radius)) {
|
||||
console.log("Only one intersection");
|
||||
//return {points: false, pointOnLine: e};
|
||||
return true;
|
||||
}*/
|
||||
|
||||
return false;
|
||||
};
|
108
src/JS/XgameJS/Enemy.js
Normal file
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Represents one enemy.
|
||||
* @constructor
|
||||
* @param {AnimatedSprite|Sprite} sprite - The enemys's sprite.
|
||||
*/
|
||||
function Enemy(sprite) {
|
||||
"use strict";
|
||||
/*globals Vector2, setInterval, AnimatedSprite, SpriteEffects*/
|
||||
|
||||
this.Sprite = sprite;
|
||||
|
||||
//Physics properties
|
||||
this.SpeedV = Vector2.Zero();
|
||||
this.Speed = 0;
|
||||
|
||||
//Platform game properties
|
||||
this.IsOnGround = undefined;
|
||||
|
||||
//Enemy States
|
||||
this.IDLE = 0;
|
||||
this.MOVING = 1;
|
||||
this.HITTED = 2;
|
||||
//this.TURNING = 3;
|
||||
//[...]
|
||||
this.CurrentState = 0;
|
||||
|
||||
//Enemy attributtes
|
||||
this.Life = 5;
|
||||
|
||||
//If the sprite is animated starts the sprite animation
|
||||
if (this.Sprite instanceof AnimatedSprite) {
|
||||
this.Sprite.StartAnimation();
|
||||
}
|
||||
|
||||
//Change the enemy state every 2 seconds
|
||||
setInterval(this.ChangeEnemyState.bind(this), 2000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates de enemy.
|
||||
* @name Update
|
||||
* @function
|
||||
* @param {Number} levelWidth - The width of the level.
|
||||
* @param {Array} platforms - The platforms array.
|
||||
* @param {Number} gravityForce - The gravity force.
|
||||
* @memberOf Enemy
|
||||
*/
|
||||
Enemy.prototype.Update = function (levelWidth, platforms, gravityForce) {
|
||||
"use strict";
|
||||
var self = this,
|
||||
enemySprite = self.Sprite,
|
||||
bounds = self.Bounds();
|
||||
|
||||
//TODO: Add your enemy's update logic here. Change this function arguments as you need
|
||||
|
||||
//Screen boundaries
|
||||
//Left
|
||||
if (bounds.X < 0) {
|
||||
self.SpeedV.X = 0;
|
||||
enemySprite.Position.X = enemySprite.Position.X - bounds.Position.X;
|
||||
}
|
||||
//Up
|
||||
if (bounds.Y < 0) {
|
||||
self.SpeedV.Y = 0;
|
||||
enemySprite.Position.Y = enemySprite.Position.Y - bounds.Position.Y;
|
||||
}
|
||||
//Right
|
||||
if (bounds.X + bounds.Width > levelWidth) {
|
||||
self.SpeedV.X = 0;
|
||||
enemySprite.Position.X = levelWidth - (enemySprite.Right() - bounds.Right()) - bounds.Width;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the enemy state randomly
|
||||
* @name ChangeEnemysState
|
||||
* @function
|
||||
* @memberOf Enemy
|
||||
*/
|
||||
Enemy.prototype.ChangeEnemyState = function () {
|
||||
"use strict";
|
||||
/*globals SpriteEffects*/
|
||||
var self = this,
|
||||
enemySprite = self.Sprite;
|
||||
|
||||
//TODO: Change your enemy state logic here
|
||||
};
|
||||
|
||||
/**
|
||||
* The enemys's collision rectangle.
|
||||
* @name Bounds
|
||||
* @function
|
||||
* @memberOf Enemy
|
||||
*/
|
||||
Enemy.prototype.Bounds = function () {
|
||||
"use strict";
|
||||
/*globals Rectangle*/
|
||||
var self = this,
|
||||
spriteBounds = self.Sprite.Bounds();
|
||||
|
||||
return new Rectangle(
|
||||
spriteBounds.X + spriteBounds.HalfWidth() / 2,
|
||||
spriteBounds.Y,
|
||||
spriteBounds.HalfWidth(),
|
||||
spriteBounds.Height
|
||||
);
|
||||
};
|
13
src/JS/XgameJS/GameStates.js
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Defines the Game object states.
|
||||
* @readonly
|
||||
* @enum {number}
|
||||
*/
|
||||
var GameStates = Object.freeze({
|
||||
Initializing: 0,
|
||||
Loading: 1,
|
||||
Playing: 2,
|
||||
Paused: 3,
|
||||
GameWin: 4,
|
||||
GameOver: 5
|
||||
});
|
11
src/JS/XgameJS/GravityDirections.js
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Defines the gravity directions.
|
||||
* @readonly
|
||||
* @enum {number}
|
||||
*/
|
||||
var GravityDirections = Object.freeze({
|
||||
"G_DOWN": 0,
|
||||
"G_UP": 1,
|
||||
"G_LEFT": 2,
|
||||
"G_RIGHT": 3
|
||||
});
|
37
src/JS/XgameJS/PickableObject.js
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Defines a pickable object.
|
||||
* @constructor
|
||||
* @param {Sprite|AnimatedSprite} sprite - The sprite of the object.
|
||||
* @param {PickableObjectTypes} type - The object type.
|
||||
*/
|
||||
function PickableObject(sprite, type) {
|
||||
"use strict";
|
||||
/*globals AnimatedSprite*/
|
||||
this.Sprite = sprite;
|
||||
this.Type = type;
|
||||
|
||||
//If th sprite is animated starts the sprite animation
|
||||
if (this.Sprite instanceof AnimatedSprite) {
|
||||
this.Sprite.StartAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The collision rectangle of the pickable object.
|
||||
* @name Update
|
||||
* @function
|
||||
* @memberOf PickableObject
|
||||
*/
|
||||
PickableObject.prototype.Bounds = function () {
|
||||
"use strict";
|
||||
/*globals Rectangle*/
|
||||
var self = this,
|
||||
spriteBounds = self.Sprite.Bounds();
|
||||
|
||||
return new Rectangle(
|
||||
spriteBounds.X + spriteBounds.HalfWidth() / 2,
|
||||
spriteBounds.Y + spriteBounds.HalfHeight() / 2,
|
||||
spriteBounds.HalfWidth(),
|
||||
spriteBounds.HalfHeight()
|
||||
);
|
||||
};
|
93
src/JS/XgameJS/Player.js
Normal file
@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Represents the player.
|
||||
* @constructor
|
||||
* @param {AnimatedSprite|Sprite} sprite - The player's sprite.
|
||||
*/
|
||||
function Player(sprite) {
|
||||
"use strict";
|
||||
/*globals Vector2, AnimatedSprite*/
|
||||
this.Sprite = sprite; //The player sprite
|
||||
|
||||
//Physics properties
|
||||
this.SpeedV = Vector2.Zero();
|
||||
this.AccelerationV = Vector2.Zero();
|
||||
this.SpeedLimit = 4;
|
||||
this.GroundFriction = 1;
|
||||
|
||||
//Platform game properties
|
||||
this.IsOnGround = undefined;
|
||||
this.JumpForce = -8;
|
||||
|
||||
//Player States
|
||||
this.IDLE = 0;
|
||||
this.MOVING = 3;
|
||||
this.JUMPING = 4;
|
||||
//this.CROUCHED = 4;
|
||||
//[...]
|
||||
this.CurrentState = 0;
|
||||
|
||||
this.Life = 10;
|
||||
|
||||
//If the sprite is animated starts the sprite animation
|
||||
if (this.Sprite instanceof AnimatedSprite) {
|
||||
this.Sprite.StartAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates de player.
|
||||
* @name Update
|
||||
* @function
|
||||
* @param {Boolean} moveLeft - Tells if the player moved left or not.
|
||||
* @param {Boolean} moveRight - Tells if the player moved right or not.
|
||||
* @param {Boolean} jump - Tells if the player jumped or not.
|
||||
* @param {Number} levelWidth - The width of the level.
|
||||
* @param {Number} gravityForce - The gravity force.
|
||||
* @memberOf Player
|
||||
*/
|
||||
Player.prototype.Update = function (moveLeft, moveRight, jump, levelWidth, gravityForce) {
|
||||
"use strict";
|
||||
/*globals SpriteEffects*/
|
||||
var self = this,
|
||||
playerSprite = self.Sprite,
|
||||
bounds = self.Bounds();
|
||||
|
||||
//TODO: Add your player's update logic here. Change this function arguments as you need
|
||||
|
||||
//Screen boundaries
|
||||
//Left
|
||||
if (bounds.X < 0) {
|
||||
self.SpeedV.X = 0;
|
||||
playerSprite.Position.X = playerSprite.Position.X - bounds.X;
|
||||
}
|
||||
//Up
|
||||
if (bounds.Y < 0) {
|
||||
self.SpeedV.Y = 0;
|
||||
playerSprite.Position.Y = playerSprite.Position.Y - bounds.Y;
|
||||
}
|
||||
//Right
|
||||
if (bounds.X + bounds.Width > levelWidth) {
|
||||
self.SpeedV.X = 0;
|
||||
playerSprite.Position.X = levelWidth - (playerSprite.Right() - bounds.Right()) - bounds.Width;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The player's collision rectangle.
|
||||
* @name Bounds
|
||||
* @function
|
||||
* @memberOf Player
|
||||
*/
|
||||
Player.prototype.Bounds = function () {
|
||||
"use strict";
|
||||
/*globals Rectangle*/
|
||||
var self = this,
|
||||
spriteBounds = self.Sprite.Bounds();
|
||||
|
||||
return new Rectangle(
|
||||
spriteBounds.X + spriteBounds.HalfWidth() / 2,
|
||||
spriteBounds.Y,
|
||||
spriteBounds.HalfWidth(),
|
||||
spriteBounds.Height
|
||||
);
|
||||
};
|
21
src/JS/XgameJS/Polygon.js
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Defines a polygon.
|
||||
* @constructor
|
||||
* @param {Array} segments - An array with the segments that conform the polygon.
|
||||
*/
|
||||
function Polygon(segments) {
|
||||
"use strict";
|
||||
this.Segments = segments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of vertex of the polygon.
|
||||
* @name NumberOfVertex
|
||||
* @function
|
||||
* @memberOf Polygon
|
||||
*/
|
||||
Polygon.prototype.NumberOfVertex = function () {
|
||||
"use strict";
|
||||
return this.Segments.length;
|
||||
};
|
||||
|
31
src/JS/XgameJS/Projectile.js
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Represents a projectile.
|
||||
* @constructor
|
||||
* @param {Sprite} sprite - The sprite of the punch.
|
||||
*/
|
||||
function Projectile(sprite) {
|
||||
"use strict";
|
||||
/*globals Vector2*/
|
||||
this.Sprite = sprite;
|
||||
this.Speed = 6;
|
||||
this.Power = 1;
|
||||
this.SpeedV = Vector2.Zero();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates de projectile.
|
||||
* @name Update
|
||||
* @function
|
||||
* @param {Sprite} playerSprite - The player's sprite.
|
||||
* @param {Number} levelWidth - The width of the level.
|
||||
* @memberOf Projectile
|
||||
*/
|
||||
Projectile.prototype.Update = function () {
|
||||
"use strict";
|
||||
/*globals SpriteEffects*/
|
||||
var self = this,
|
||||
projectileSprite = self.Sprite,
|
||||
bounds = projectileSprite.Bounds();
|
||||
|
||||
//TODO: Add your projectile's update logic here. Change this function arguments as you need
|
||||
};
|
39
src/JS/XgameJS/Segment.js
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Represents a 2D segment, which is composed of two points.
|
||||
* @constructor
|
||||
* @param {Point} pointA - The A point of the segment.
|
||||
* @param {Point} pointB - The B point of the segment.
|
||||
*/
|
||||
function Segment(pointA, pointB) {
|
||||
"use strict";
|
||||
/*global Vector2*/
|
||||
this.pointA = pointA;
|
||||
this.pointB = pointB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the distance of the segment.
|
||||
* @name Distance
|
||||
* @function
|
||||
* @memberOf Segment
|
||||
*/
|
||||
Segment.prototype.Distance = function () {
|
||||
"use strict";
|
||||
var self = this;
|
||||
|
||||
return Math.sqrt(Math.pow((self.pointB.X - self.pointA.X), 2) + Math.pow((self.pointB.Y - self.pointA.Y), 2));
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the direction vector of the segment.
|
||||
* @name DirectionVector
|
||||
* @function
|
||||
* @memberOf Segment
|
||||
*/
|
||||
Segment.prototype.DirectionVector = function () {
|
||||
"use strict";
|
||||
var self = this,
|
||||
distance = self.Distance();
|
||||
|
||||
return new Vector2((self.pointB.X - self.pointA.X) / distance, (self.pointB.Y - self.pointA.Y) / distance);
|
||||
};
|
145
src/JS/XgameJS/Sprite.js
Normal file
@ -0,0 +1,145 @@
|
||||
/**
|
||||
* Represents a sprite, which is composed of a Texture2D and other properties.
|
||||
* @constructor
|
||||
* @param {Texture2D} texture - The texture image.
|
||||
* @param {Vector2} scale - The scale vector of the image.
|
||||
* @param {Rectangle} sourceRect - The image source rectangle.
|
||||
* @param {Point} position - The sprite position in the canvas.
|
||||
* @param {Boolean} isVisible - Determines if the sprite is visible or not.
|
||||
*/
|
||||
function Sprite(texture, scale, sourceRect, position, isVisible) {
|
||||
"use strict";
|
||||
/*global SpriteEffects*/
|
||||
this.Texture = texture;
|
||||
this.Scale = scale;
|
||||
this.SourceRect = sourceRect;
|
||||
this.Position = position;
|
||||
this.IsVisible = isVisible;
|
||||
this.SpriteEffects = SpriteEffects.None;
|
||||
this.Rotation = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the width of the sprite.
|
||||
* @name Width
|
||||
* @function
|
||||
* @memberOf Sprite
|
||||
*/
|
||||
Sprite.prototype.Width = function () {
|
||||
"use strict";
|
||||
var self = this,
|
||||
aspectRatio = self.Texture.Width() / self.Texture.Height(),
|
||||
sourceAspectRatio = self.SourceRect.Width / self.SourceRect.Height;
|
||||
|
||||
if (aspectRatio !== sourceAspectRatio) {
|
||||
return (self.Texture.Width() * self.Scale.X) / aspectRatio;
|
||||
} else {
|
||||
return self.Texture.Width() * self.Scale.X;
|
||||
}
|
||||
//return this.Texture.Width() * this.Scale.X;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the height of the sprite.
|
||||
* @name Height
|
||||
* @function
|
||||
* @memberOf Sprite
|
||||
*/
|
||||
Sprite.prototype.Height = function () {
|
||||
"use strict";
|
||||
return this.Texture.Height() * this.Scale.Y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets half of the width of the texture.
|
||||
* @name HalfWidth
|
||||
* @function
|
||||
* @memberOf Sprite
|
||||
*/
|
||||
Sprite.prototype.HalfWidth = function () {
|
||||
"use strict";
|
||||
return this.Width() / 2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets half of the height of the texture.
|
||||
* @name HalfHeight
|
||||
* @function
|
||||
* @memberOf Sprite
|
||||
*/
|
||||
Sprite.prototype.HalfHeight = function () {
|
||||
"use strict";
|
||||
return this.Height() / 2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the Point that specifies the center of the sprite.
|
||||
* @name Center
|
||||
* @function
|
||||
* @memberOf Sprite
|
||||
*/
|
||||
Sprite.prototype.Center = function () {
|
||||
"use strict";
|
||||
/*global Point*/
|
||||
var self = this;
|
||||
|
||||
return new Point(self.Position.X + self.HalfWidth(), self.Position.Y + self.HalfHeight());
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the y-coordinate of the top of the sprite.
|
||||
* @name Top
|
||||
* @function
|
||||
* @memberOf Sprite
|
||||
*/
|
||||
Sprite.prototype.Top = function () {
|
||||
"use strict";
|
||||
return this.Position.Y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the y-coordinate of the bottom of the sprite.
|
||||
* @name Bottom
|
||||
* @function
|
||||
* @memberOf Sprite
|
||||
*/
|
||||
Sprite.prototype.Bottom = function () {
|
||||
"use strict";
|
||||
return this.Position.Y + this.Height();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the x-coordinate of the left side of the sprite.
|
||||
* @name Left
|
||||
* @function
|
||||
* @memberOf Sprite
|
||||
*/
|
||||
Sprite.prototype.Left = function () {
|
||||
"use strict";
|
||||
return this.Position.X;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the x-coordinate of the right side of the sprite.
|
||||
* @name Right
|
||||
* @function
|
||||
* @memberOf Sprite
|
||||
*/
|
||||
Sprite.prototype.Right = function () {
|
||||
"use strict";
|
||||
return this.Position.X + this.Width();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the rectangle bounds of the sprite.
|
||||
* @name Bounds
|
||||
* @function
|
||||
* @memberOf Sprite
|
||||
*/
|
||||
Sprite.prototype.Bounds = function () {
|
||||
"use strict";
|
||||
/*global Rectangle*/
|
||||
var self = this;
|
||||
|
||||
return new Rectangle(self.Position.X, self.Position.Y, self.Width(), self.Height());
|
||||
};
|
38
src/JS/XgameJS/requestAnimationFramePolyfill.js
Normal file
@ -0,0 +1,38 @@
|
||||
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
|
||||
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
|
||||
|
||||
// requestAnimationFrame polyfill by Erik Möller
|
||||
// fixes from Paul Irish and Tino Zijdel
|
||||
// JSLint and JSHint fixes by Víctor Hernández Molpeceres
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
/*global window, clearTimeout*/
|
||||
var lastTime = 0,
|
||||
vendors = ['ms', 'moz', 'webkit', 'o'],
|
||||
x;
|
||||
|
||||
for (x = 0; x < vendors.length && !window.requestAnimationFrame; x += 1) {
|
||||
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
|
||||
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
|
||||
}
|
||||
|
||||
if (!window.requestAnimationFrame) {
|
||||
window.requestAnimationFrame = function (callback, element) {
|
||||
var currTime = new Date().getTime(),
|
||||
timeToCall = Math.max(0, 16 - (currTime - lastTime)),
|
||||
id = window.setTimeout(function () {
|
||||
callback(currTime + timeToCall);
|
||||
}, timeToCall);
|
||||
lastTime = currTime + timeToCall;
|
||||
return id;
|
||||
};
|
||||
}
|
||||
|
||||
if (!window.cancelAnimationFrame) {
|
||||
window.cancelAnimationFrame = function (id) {
|
||||
clearTimeout(id);
|
||||
};
|
||||
}
|
||||
|
||||
}());
|