UNPKG

jrpg-stellar-engine

Version:
988 lines (900 loc) 51.1 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>JRPG Stellar Engine Demo</title> <style type="text/css"> html, body { width: 100%; height: 100%; margin: 0; padding: 0; } body { overflow: hidden; background-color: #0ec4e1; user-select: none; } #canvas { display: block; image-rendering: optimizeSpeed; image-rendering: -moz-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: -o-crisp-edges; image-rendering: optimize-contrast; -ms-interpolation-mode: nearest-neighbor; } #touchpad { display: none; position: absolute; width: 80px; height: 80px; left: calc(50% - 40px); top: calc(50% - 40px); border-radius: 50%; background-color: rgba(255,255,255,0.5); border: 4px solid rgba(255,255,255,0.5); } #fps { position: absolute; bottom: 10px; left: 10px; color: white; font-size: 14px; } </style> </head> <body> <!-- Scripts --> <script src="../src/cache.js"></script> <script src="../src/spawnpoint.js"></script> <script src="../src/respawnpoint.js"></script> <script src="../src/stairs.js"></script> <script src="../src/sprite.js"></script> <script src="../src/animsprite.js"></script> <script src="../src/tileset.js"></script> <script src="../src/actor.js"></script> <script src="../src/mob.js"></script> <script src="../src/level.js"></script> <script src="../src/loader-acx.js"></script> <script src="../src/loader-tsx.js"></script> <script src="../src/loader-tmx.js"></script> <script src="../src/utils.js"></script> <script src="../src/view.js"></script> <!-- Resources --> <div style="display: none;"> <img id="char1" src="../public/sprites/characters/chara_0.png"> <img id="mob1" src="../public/sprites/characters/pinguin_22x22.png"> <img id="blob1" src="../public/sprites/characters/blob_green.png"> <img id="jinn" src="../public/sprites/characters/jinn.png"> <img id="env1" src="../public/sprites/environment/ground.png"> <img id="env2" src="../public/sprites/environment/water.png"> <img id="props" src="../public/sprites/environment/props.png"> <img id="sky" src="../public/sprites/environment/sky.png"> <img id="chest1" src="../public/sprites/items/chest.png"> </div> <!-- TSX --> <script id="test-tsx" type="text/xml"> <tileset version="1.10" tiledversion="1.10.2" name="test" tilewidth="16" tileheight="16" tilecount="87" columns="29"> <image source="../public/sprites/environment/ground.png" width="464" height="48"/> </tileset> </script> <script id="water-tsx" type="text/xml"> <tileset version="1.10" tiledversion="1.10.2" name="water" tilewidth="16" tileheight="16" tilecount="9" columns="3"> <image source="../public/sprites/environment/water.png" width="48" height="48"/> </tileset> </script> <script id="props-tsx" type="text/xml"> <tileset version="1.10" tiledversion="1.10.2" name="props" tilewidth="16" tileheight="16" tilecount="4" columns="4"> <image source="../public/sprites/environment/props.png" width="64" height="16"/> <tile id="0"> <animation> <frame tileid="0" duration="100"/> <frame tileid="1" duration="100"/> <frame tileid="2" duration="100"/> <frame tileid="3" duration="100"/> </animation> </tile> </tileset> </script> <!-- TMX --> <script id="test-tmx" type="text/xml"> <map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="30" height="30" tilewidth="16" tileheight="16" infinite="0" nextlayerid="14" nextobjectid="13"> <tileset firstgid="1" source="test.tsx"/> <tileset firstgid="88" source="water.tsx"/> <tileset firstgid="97" source="props.tsx"/> <imagelayer id="9" name="Sky" locked="1" parallaxx="0" parallaxy="0" repeatx="1" repeaty="1"> <image source="../public/sprites/environment/sky.png" width="256" height="256"/> </imagelayer> <imagelayer id="11" name="Sun" locked="1" offsetx="0" offsety="-120"> <image source="../public/sprites/environment/sun.png" width="256" height="256"/> </imagelayer> <imagelayer id="10" name="Clouds" locked="1" parallaxx="0.5" parallaxy="0.2" repeatx="1" repeaty="1"> <image source="../public/sprites/environment/clouds.png" width="256" height="256"/> </imagelayer> <layer id="8" name="WaterSW" width="30" height="30" locked="1" offsetx="-240" offsety="240"> <data encoding="csv"> 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90, 0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93, 0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96, 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90, 0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93, 0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96, 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90, 0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93, 0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96, 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 </data> </layer> <layer id="7" name="WaterSE" width="30" height="30" locked="1" offsetx="240" offsety="240"> <data encoding="csv"> 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0, 88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0, 94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0, 88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0, 94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0, 88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0, 94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0, 88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 </data> </layer> <layer id="6" name="WaterNE" width="30" height="30" locked="1" offsetx="240" offsety="-240"> <data encoding="csv"> 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 0,0,34,0,0,0,0,0,0,0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0, 0,0,34,0,0,0,0,0,0,0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0, 0,0,34,0,0,0,0,0,0,0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0 </data> </layer> <layer id="5" name="WaterNW" width="30" height="30" locked="1" offsetx="-240" offsety="-240"> <data encoding="csv"> 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0,0,0,0,0,0,0,34,0,0, 0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0,0,0,0,0,0,0,34,0,0, 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0,0,0,0,0,0,0,34,0,0, 0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,88,89,90,88,89,90,88,89,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,91,92,93,91,92,93,91,92,93,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,94,95,96,94,95,96,94,95,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 </data> </layer> <layer id="1" name="Ground" width="30" height="30" locked="1"> <data encoding="csv"> 34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34, 34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34, 46,34,7,8,8,8,9,34,46,34,34,34,34,34,34,34,34,34,34,34,34,34,34,7,8,8,8,9,34,34, 34,34,36,37,37,37,38,34,34,34,34,34,34,34,34,34,34,34,34,34,34,46,34,36,37,37,37,38,34,34, 34,34,36,37,37,37,38,46,34,34,34,34,45,34,34,34,34,47,34,34,34,34,34,36,37,37,37,38,34,34, 34,34,36,37,37,37,38,34,34,34,34,34,45,34,34,34,34,47,34,34,34,34,34,36,37,37,37,38,34,34, 34,34,36,37,37,37,38,34,34,34,34,34,45,34,34,34,34,47,34,34,34,34,46,36,37,37,37,38,34,46, 34,34,36,37,37,37,38,34,34,34,34,34,34,34,34,34,78,34,34,34,34,34,46,36,37,37,37,38,34,34, 34,34,36,37,37,37,38,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,36,37,37,37,38,34,34, 34,34,36,37,37,37,38,34,34,1,2,2,2,2,2,2,2,2,2,2,3,34,34,36,37,37,37,38,34,34, 34,34,65,66,66,66,67,34,34,30,31,31,31,31,31,31,31,31,31,31,32,34,34,65,66,66,66,67,34,34, 34,34,34,34,34,34,34,34,34,30,31,31,31,31,31,31,31,31,31,31,32,34,34,34,34,34,34,34,34,34, 34,34,34,34,34,34,34,34,34,30,31,31,4,5,5,5,5,6,31,31,32,34,34,34,34,34,34,34,46,34, 34,34,34,34,34,34,34,34,46,30,31,31,33,34,34,34,34,35,31,31,32,34,34,34,46,34,34,34,34,34, 34,34,34,34,34,34,34,34,34,30,31,31,33,34,34,34,34,35,31,31,32,34,34,34,34,34,34,34,34,34, 34,34,34,34,34,46,34,34,34,30,31,31,33,34,34,34,34,35,31,31,32,34,34,34,34,34,34,34,34,34, 34,34,34,46,34,34,34,34,34,30,31,31,33,34,34,34,34,35,31,31,32,34,34,34,46,34,34,34,34,34, 34,34,34,34,34,34,34,34,34,30,31,31,62,63,63,63,63,64,31,31,32,34,34,34,34,34,34,34,34,34, 34,34,34,34,34,34,34,34,34,30,31,31,31,31,31,31,31,31,31,31,32,34,34,34,34,34,34,34,34,34, 34,34,7,8,8,8,9,34,34,30,31,31,31,31,31,31,31,31,31,31,32,46,34,7,8,8,8,9,34,34, 34,34,36,37,37,37,38,34,34,59,60,60,60,60,60,60,60,60,60,60,61,34,34,36,37,37,37,38,34,34, 34,34,36,37,37,37,38,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,36,37,37,37,38,34,34, 34,34,36,37,37,37,38,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,36,37,37,37,38,34,34, 34,34,36,37,37,37,38,34,34,34,34,34,34,34,34,34,34,34,34,34,46,34,34,36,37,37,37,38,34,34, 34,34,36,37,37,37,38,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,36,37,37,37,38,34,34, 34,34,36,37,37,37,38,46,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,36,37,37,37,38,34,34, 34,34,36,37,37,37,38,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,36,37,37,37,38,34,34, 34,34,65,66,66,66,67,34,46,34,34,34,34,34,34,34,34,34,46,46,34,34,46,65,66,66,66,67,34,34, 34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34, 34,34,46,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34 </data> </layer> <layer id="2" name="Colliders" class="Colliders" width="30" height="30" locked="1"> <data encoding="csv"> 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,19,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,20,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,16,17,17,17,17,18,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,34,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,68,69,70,0,0,0,0,0,0,74,75,75,75,0,76,0,0,0,0,0,0,68,69,70,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,48,17,17,17,17,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,17,17,17,17,49,0, 0,0,0,0,0,0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0,0,0,0,0,0, 0,0,0,0,0,0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0,0,0,0,0,0, 0,0,0,0,0,0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0,0,0,0,0,0, 0,0,71,72,73,0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0,71,72,73,0,0, 0,0,0,0,0,0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0,0,0,0,0,0, 0,0,0,0,0,0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0,0,0,0,0,0, 0,19,75,75,77,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,74,75,77,75,75,20,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,68,69,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,69,70,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0, 0,48,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,49,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 </data> </layer> <objectgroup id="4" name="Objects" locked="1"> <object id="2" name="player" type="Spawn" x="168" y="240"> <point/> </object> <object id="3" name="mob:penguin-acx" type="Spawn" x="312" y="240"> <point/> </object> <object id="4" name="Slope-E" type="Stairs" x="272.25" y="48.375"> <polygon points="0,0 15.625,15.5 15.75,79.25 -0.25,63.75"/> </object> <object id="5" name="Slope-W" type="Stairs" x="207.875" y="47.875"> <polygon points="0,0 -15.75,16 -15.75,79.75 0.125,64.125"/> </object> <object id="6" name="cave-tmx:East" type="Portal" x="400" y="294" width="16" height="12"/> <object id="7" name="cave-tmx:West" type="Portal" x="64" y="294" width="16" height="12"/> <object id="8" name="Out-W" type="Spawn" x="72" y="320"> <point/> </object> <object id="9" name="Out-E" type="Spawn" x="408" y="320"> <point/> </object> <object id="10" name="item:chest-acx" type="Spawn" x="232" y="90"> <point/> </object> </objectgroup> <layer id="3" name="Cover" width="30" height="30" locked="1"> <data encoding="csv"> 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,10,11,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,11,12,0,0,0, 0,0,0,39,40,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,40,41,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,14,15,0,0, 0,0,42,43,44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,43,44,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,10,11,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,11,12,0,0,0, 0,0,0,39,40,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,40,41,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 </data> </layer> <layer id="12" name=".Hidden" width="30" height="30" locked="1" offsetx="0" offsety="-240"> <data encoding="csv"> 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,34,0,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,34,34,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,34,0,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 </data> </layer> <objectgroup id="13" name="Air"> <object id="12" name="mob:jinn-acx" type="Spawn" x="128" y="96"> <point/> </object> </objectgroup> </map> </script> <!-- TMX --> <script id="cave-tmx" type="text/xml"> <map version="1.10" tiledversion="1.10.2" orientation="orthogonal" renderorder="right-down" width="17" height="14" tilewidth="16" tileheight="16" infinite="0" nextlayerid="6" nextobjectid="8"> <tileset firstgid="1" source="props.tsx"/> <tileset firstgid="5" source="test.tsx"/> <imagelayer id="5" name="Background" locked="1" offsetx="-512" offsety="-512" repeatx="1" repeaty="1"> <image source="../public/sprites/environment/soil.png" width="16" height="16"/> </imagelayer> <layer id="1" name="Ground" width="17" height="14" locked="1"> <data encoding="csv"> 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,83,83,27,83,56,56,87,57,83,87,28,83,83,83,83,0, 0,83,27,54,54,87,83,86,83,83,28,83,83,83,54,25,0, 0,83,83,58,27,54,54,54,83,83,83,25,25,83,54,25,0, 0,83,25,83,83,83,83,83,83,83,83,83,83,83,83,25,0, 83,83,83,83,83,83,83,25,83,83,83,83,83,83,83,83,83, 83,83,83,83,83,83,54,83,83,83,83,83,83,83,54,83,83, 0,83,54,54,83,83,83,83,83,25,83,83,25,25,54,83,0, 0,25,25,54,83,83,83,54,83,83,83,83,83,83,83,83,0, 0,25,83,27,54,83,83,83,83,83,83,27,87,83,25,25,0, 0,83,27,27,58,83,83,83,83,83,27,56,56,86,56,54,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 </data> </layer> <layer id="2" name="Colliders" class="Colliders" width="17" height="14" locked="1"> <data encoding="csv"> 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, 31,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,30, 31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30, 31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30, 60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59, 89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, 30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31, 30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31, 30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31, 30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31, 59,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,60, 88,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,89 </data> </layer> <objectgroup id="4" name="Objects" locked="1"> <object id="1" name="East" type="Spawn" x="240" y="112"> <point/> </object> <object id="2" name="West" type="Spawn" x="32" y="112"> <point/> </object> <object id="3" name="test-tmx:Out-E" type="Portal" x="256" y="92" width="16" height="32"/> <object id="4" name="test-tmx:Out-W" type="Portal" x="0" y="93" width="16" height="32"/> <object id="7" name="mob:blob-acx" type="Spawn" x="112" y="80"> <point/> </object> </objectgroup> <layer id="3" name="Cover" width="17" height="14" locked="1"> <data encoding="csv"> 33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,33, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 </data> </layer> </map> </script> <!-- ACX --> <script id="player-acx" type="text/xml"> <actor version="0.2" name="player" type="Actor" resource="#char1" width="48" height="80" cols="3" rows="4"> <movement speed="80" /> <collider x="4" y="16" width="8" height="4"/> <animation name="idleUp"> <frame tileid="10" duration="100"/> </animation> <animation name="idleDown"> <frame tileid="1" duration="100"/> </animation> <animation name="idleLeft"> <frame tileid="4" duration="100"/> </animation> <animation name="idleRight"> <frame tileid="7" duration="100"/> </animation> <animation name="moveUp"> <frame tileid="9" duration="100"/> <frame tileid="10" duration="100"/> <frame tileid="11" duration="100"/> </animation> <animation name="moveDown"> <frame tileid="0" duration="100"/> <frame tileid="1" duration="100"/> <frame tileid="2" duration="100"/> </animation> <animation name="moveLeft"> <frame tileid="3" duration="100"/> <frame tileid="4" duration="100"/> <frame tileid="5" duration="100"/> </animation> <animation name="moveRight"> <frame tileid="6" duration="100"/> <frame tileid="7" duration="100"/> <frame tileid="8" duration="100"/> </animation> </actor> </script> <script id="penguin-acx" type="text/xml"> <actor version="0.2" name="penguin1" type="MOB" resource="#mob1" width="88" height="88" cols="4" rows="4"> <movement speed="20" /> <collider x="4" y="15" width="14" height="6"/> <animation name="idle"> <frame tileid="1" duration="100"/> </animation> <animation name="moveUp"> <frame tileid="8" duration="100"/> <frame tileid="9" duration="100"/> <frame tileid="10" duration="100"/> </animation> <animation name="moveDown"> <frame tileid="0" duration="100"/> <frame tileid="1" duration="100"/> <frame tileid="2" duration="100"/> </animation> <animation name="moveLeft"> <frame tileid="12" duration="100"/> <frame tileid="13" duration="100"/> <frame tileid="14" duration="100"/> </animation> <animation name="moveRight"> <frame tileid="4" duration="100"/> <frame tileid="5" duration="100"/> <frame tileid="6" duration="100"/> </animation> </actor> </script> <script id="blob-acx" type="text/xml"> <actor version="0.2" name="blob1" type="MOB" resource="#blob1" width="57" height="57" cols="3" rows="3"> <movement speed="20" /> <collider x="0" y="0" width="19" height="19"/> <animation name="idle"> <frame tileid="0" duration="100"/> <frame tileid="1" duration="100"/> <frame tileid="2" duration="100"/> </animation> <animation name="moveUp"> <frame tileid="0" duration="100"/> <frame tileid="1" duration="100"/> <frame tileid="2" duration="100"/> </animation> <animation name="moveDown"> <frame tileid="0" duration="100"/> <frame tileid="1" duration="100"/> <frame tileid="2" duration="100"/> </animation> <animation name="moveLeft"> <frame tileid="3" duration="100"/> <frame tileid="4" duration="100"/> <frame tileid="5" duration="100"/> </animation> <animation name="moveRight"> <frame tileid="6" duration="100"/> <frame tileid="7" duration="100"/> <frame tileid="8" duration="100"/> </animation> </actor> </script> <script id="jinn-acx" type="text/xml"> <actor version="0.2" name="jinn" type="MOB" resource="#jinn" width="144" height="192" cols="3" rows="4"> <movement speed="40" /> <collider x="12" y="32" width="24" height="16"/> <animation name="idle"> <frame tileid="1" duration="100"/> </animation> <animation name="moveUp"> <frame tileid="9" duration="100"/> <frame tileid="10" duration="100"/> <frame tileid="11" duration="100"/> </animation> <animation name="moveDown"> <frame tileid="0" duration="100"/> <frame tileid="1" duration="100"/> <frame tileid="2" duration="100"/> </animation> <animation name="moveLeft"> <frame tileid="3" duration="100"/> <frame tileid="4" duration="100"/> <frame tileid="5" duration="100"/> </animation> <animation name="moveRight"> <frame tileid="6" duration="100"/> <frame tileid="7" duration="100"/> <frame tileid="8" duration="100"/> </animation> </actor> </script> <script id="chest-acx" type="text/xml"> <actor version="0.2" name="chest" type="Actor" resource="#chest1" width="32" height="16" cols="2" rows="1"> <collider x="-4" y="-4" width="24" height="24"/> <animation name="open"> <frame tileid="1" duration="1000"/> </animation> <animation name="close"> <frame tileid="0" duration="1000"/> </animation> </actor> </script> <!-- Main canvas window --> <canvas id="main"></canvas> <!-- Mobile joystick --> <div id="touchpad"></div> <!-- Frames per second counter --> <div id="fps">FPS:</div> <!-- Init --> <script type="text/javascript"> // Loop control let pause = false; // Rendering let level = null; let view = null; const scale = 4; // Loaders let loaderTSX = null; let loaderTMX = null; let loaderACX = null; // Player character let player = null; // Input actions const input = { up: false, down: false, left: false, right: false, action: false }; // Mobile input const mobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); const touchCenter = {x: 0, y: 0}; const touchPad = document.getElementById('touchpad'); const keyDownHandler = (event) => { if (event.code == 'ArrowRight' || event.code == 'KeyD') { input.right = true; } else if (event.code == 'ArrowLeft' || event.code == 'KeyA') { input.left = true; } if (event.code == 'ArrowUp' || event.code == 'KeyW') { input.up = true; } else if (event.code == 'ArrowDown' || event.code == 'KeyS') { input.down = true; } if (event.code == 'Space' || event.code == 'ControlRight' || event.code == 'ControlLeft' || event.key == 'Enter') { input.action = true; } }; const keyUpHandler = (event) => { if (event.code == 'ArrowRight' || event.code == 'KeyD') { input.right = false; } if (event.code == 'ArrowLeft' || event.code == 'KeyA') { input.left = false; } if (event.code == 'ArrowUp' || event.code == 'KeyW') { input.up = false; } if (event.code == 'ArrowDown' || event.code == 'KeyS') { input.down = false; } if (event.code == 'Space' || event.code == 'ControlRight' || event.code == 'ControlLeft' || event.key == 'Enter') { input.action = false; } player.idle(); }; const touchStartHandler = (event) => { const firstTouch = event.touches[0]; touchPad.style.display = 'block'; touchCenter.x = firstTouch.pageX; touchCenter.y = firstTouch.pageY; touchPad.style.left = `${touchCenter.x - 44}px`; touchPad.style.top = `${touchCenter.y - 44}px`; }; const touchMoveHandler = (event) => { event.preventDefault(); const firstTouch = event.touches[0]; const posX = firstTouch.pageX; const posY = firstTouch.pageY; touchPad.style.left = `${posX - 44}px`; touchPad.style.top = `${posY - 44}px`; input.right = false; input.left = false; input.up = false; input.down = false; const threshold = 10; if (posX + threshold < touchCenter.x) { input.left = true; // touchCenter.y = posY; } else if (posX - threshold > touchCenter.x) { input.right = true; // touchCenter.y = posY; } if (posY + threshold < touchCenter.y) { input.up = true; // touchCenter.x = posX; } else if (posY - threshold > touchCenter.y) { input.down = true; // touchCenter.x = posX; } }; const touchEndHandler = (event) => { touchPad.style.display = 'none'; input.right = false; input.left = false; input.up = false; input.down = false; }; // Keyboard input if (!mobile) { document.addEventListener('keydown', keyDownHandler); document.addEventListener('keyup', keyUpHandler); } // Mobile touch else { document.addEventListener('touchstart', touchStartHandler); document.addEventListener('touchmove', touchMoveHandler); document.addEventListener('touchend', touchEndHandler); } // Disable native context menu window.addEventListener('contextmenu', function(event) { event.preventDefault(); }); // Load Level const loadLevel = async (map, spawn) => { // Load Map level = await loaderTMX.parseLevel({ xml: document.getElementById(map).innerText, scale, view, prefetch: false }); // Insert player in layer level.actors['player'] = { 'player': player }; level.getLayer('objects').actors.push('player'); // Move player to spawn point const {x, y} = level.getSpawnPoint(spawn.toLowerCase(), {x: 0, y: 0}); player.level = level; player.position(x, y); player.idle(); // Centre view context on player view.centre(player.transform); }; // Init window.addEventListener('load', () => { // Initialize view context view = new View({ canvas: document.getElementById('main'), bounds: {top: -150, bottom: 150, left: -150, right: 150}, debug: true }); // Loaders loaderACX = new LoaderACX(); loaderTSX = new LoaderTSX(); // Load tielsets const tilesets = {'test.tsx': null, 'water.tsx': null, 'props.tsx': null}; loaderTSX.parseTileSet({ xml: document.getElementById('test-tsx').innerText, resource: '#env1', scale }).then(result => { tilesets['test.tsx'] = result; loaderTSX.parseTileSet({ xml: document.getElementById('water-tsx').innerText, resource: '#env2', scale }).then(result => { tilesets['water.tsx'] = result; loaderTSX.parseTileSet({ xml: document.getElementById('props-tsx').innerText, resource: '#props', scale }).then(result => { tilesets['props.tsx'] = result; // Load level data loaderTMX = new LoaderTMX({tilesets}); // Load Player player = loaderACX.parseActor({ xml: document.getElementById('player-acx').innerText, scale }); player.view = view; // Load Level loadLevel('test-tmx', 'player').then(() => start()); }); }); }); }); // Player movement const playerMoveUp = (deltaTime) => { // Direction player.transform.vec.y = -1; // Collide const [x, y] = player.collide(level.getColliders(), deltaTime); // Move player.move(x, y); // Animate player.animate('moveUp', deltaTime); // Scrol view if (player.transform.y + view.offset.y < view.bounds.top) view.offset.y -= y; }; const playerMoveDown = (deltaTime) => { // Direction player.transform.vec.y = 1; // Collide const [x, y] = player.collide(level.getColliders(), deltaTime); // Move player.move(x, y); // Animate player.animate('moveDown', deltaTime); // Scrol view if (player.transform.y + view.offset.y > view.bounds.bottom) view.offset.y -= y; }; const playerMoveLeft = (deltaTime) => { // Direction player.transform.vec.x = -1; // Collide let [x, y] = player.collide(level.getColliders(), deltaTime); // Stairs const [stx, sty] = player.stairsLeft(level.getStairs(), deltaTime); x += stx; y += sty; // Move player.move(x, y); // Animate player.animate('moveLeft', deltaTime); // Scrol view if (player.transform.x + view.offset.x < view.bounds.left) view.offset.x -= x; }; const playerMoveRight = (deltaTime) => { // Direction player.transform.vec.x = 1; // Collide let [x, y] = player.collide(level.getColliders(), deltaTime); // Stairs const [stx, sty] = player.stairsRight(level.getStairs(), deltaTime); x += stx; y += sty; // Move player.move(x, y); // Animate player.animate('moveRight', deltaTime); // Scrol view if (player.transform.x + view.offset.x > view.bounds.right) view.offset.x -= x; }; // Start loop const start = () => { pause = false; requestAnimationFrame(function(currentTime) { lastTime = currentTime; mainLoop(currentTime); }); }; // Stop loop const stop = () => { pause = true; }; // Main loop let lastTime = 0; let fpsContainer = document.querySelector('#fps'); const mainLoop = (currentTime) => { // Universal frame time const deltaTime = Math.min((currentTime - lastTime) / 1000, 0.1); // Calculate FPS fpsContainer.textContent = `FPS: ${Math.round(1 / deltaTime)}`; // Clear screen view.cls(); // Player movement if (input.up) { playerMoveUp(deltaTime); } else if (input.down) { playerMoveDown(deltaTime); } else if (input.left) { playerMoveLeft(deltaTime); } el