UNPKG

shaku

Version:

A simple and effective JavaScript game development framework that knows its place!

171 lines (141 loc) 9.1 kB
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Shaku</title> <meta name="description" content="Shaku - a simple and easy-to-use javascript library for videogame programming."> <meta name="author" content="Ronen Ness"> <link href="css/style.css" rel="stylesheet" type="text/css" media="all"> </head> <body> <div class="noselect"> <button class="view-code-btn" onclick="showSampleCode();">View Code</button> <h1 class="demo-title">Shaku: Collision Tilemap</h1> <p>This demo demonstrate a special collision shape: tilemap. <br /> Tilemaps create an even grid of collision rectangles that you can easily set or unset. Its an easy & efficient way to implement collision for tile-based levels.<br /> You can combine other shapes with tilemap shapes in your collision world, and even have multiple tilemaps (note however that tilemaps can't collide with each other).<br /> Move the shape with your mouse to test collision, press <b>1-4</b> to replace the shape you control.</p> <p id="stats-show"></p> <p id="show-data" style="color: red;"></p> <!-- include shaku --> <script src="js/demos.js"></script> <script src="js/shaku.js"></script> <!-- demo code --> <script> async function runGame() { // make shaku only listen to gfx canvas Shaku.input.setTargetElement(() => Shaku.gfx.canvas); // init shaku await Shaku.init(); // add shaku's canvas to document and set resolution to 800x600 document.body.appendChild(Shaku.gfx.canvas); Shaku.gfx.setResolution(25 * 64, 25 * 64, true); // element to show data let showDataParagraph = document.getElementById("show-data"); // create collision world let world = Shaku.collision.createWorld(25*64); // shape to use for test let userShapeType = 0; let sizeFactor = 0.2; // create the tilemap let offset = new Shaku.utils.Vector2(0, 0); let gridSize = new Shaku.utils.Vector2(25,25); let tileSize = new Shaku.utils.Vector2(64,64); let borderThickness = 32; let tilemap = new Shaku.collision.TilemapShape(offset, gridSize, tileSize, borderThickness); world.addShape(tilemap); // create a maze let maze = [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1],[1,0,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,0,1,0,1],[1,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,1],[1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,0,1],[1,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1],[1,0,1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1],[1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1],[1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,0,1,0,1,1,1,0,1],[1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1],[1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,0,1],[1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1],[1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,0,1],[1,0,1,0,1,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1],[1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1],[1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1],[1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1],[1,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,0,0,1],[1,0,1,1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,0,1,1,1],[1,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,1],[1,0,1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1],[1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,1],[1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1],[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]] for (let i = 0; i < maze.length; ++i) { for (let j = 0; j < maze[i].length; ++j) { if (maze[i][j]) { tilemap.setTile(new Shaku.utils.Vector2(i, j), true); } } } // do a single main loop step function step() { // reset stats world.resetStats(); // start new frame and clear screen Shaku.startFrame(); Shaku.gfx.clear(Shaku.utils.Color.aliceblue); // debug draw world world.debugDraw(null, null, 1); // create current collision shape to test let mouse = Shaku.input.mousePosition; var shapeToTest; switch (userShapeType) { case 0: shapeToTest = new Shaku.collision.RectangleShape(new Shaku.utils.Rectangle(mouse.x - 60 * sizeFactor, mouse.y - 60 * sizeFactor, 120 * sizeFactor, 120 * sizeFactor)); break; case 1: shapeToTest = new Shaku.collision.CircleShape(new Shaku.utils.Circle(mouse, 100 * sizeFactor)); break; case 2: shapeToTest = new Shaku.collision.PointShape(mouse); break; case 3: let second = mouse.add(85*sizeFactor, -35*sizeFactor); shapeToTest = new Shaku.collision.LinesShape([ new Shaku.utils.Line(mouse, second), new Shaku.utils.Line(second, second.add(65*sizeFactor, 75*sizeFactor)) ]); break; } // test collision with tilemap let collision = world.testCollision(shapeToTest); showDataParagraph.innerHTML = collision ? "Collide with tilemap!" : "Not collision."; showDataParagraph.style.color = collision ? "red" : "green"; tilemap.setDebugColor(collision ? Shaku.utils.Color.red : null); shapeToTest.setDebugColor(Shaku.utils.Color.red); shapeToTest.debugDraw(1, world.getOrCreateDebugDrawBatch()); // control the shape the user drags if (Shaku.input.down('1')) { userShapeType = 0; } if (Shaku.input.down('2')) { userShapeType = 1; } if (Shaku.input.down('3')) { userShapeType = 2; } if (Shaku.input.down('4')) { userShapeType = 3; } // show stats document.getElementById("stats-show").innerHTML = JSON.stringify(world.stats); // end frame and request next frame Shaku.endFrame(); Shaku.requestAnimationFrame(step); } // start main loop step(); } runGame(); </script> </div> <!-- code example part --> <div id="sample-code-modal" class="modal"> <div class="modal__overlay jsOverlay"></div> <div class="modal__container"> <p class="noselect">The following shows a code example to create a collision tilemap and set it to a maze.</i> </p> <pre><code class="language-js">// create collision tilemap let offset = new Shaku.utils.Vector2(0, 0); let gridSize = new Shaku.utils.Vector2(25,25); let tileSize = new Shaku.utils.Vector2(64,64); let borderThickness = 32; let tilemap = new Shaku.collision.TilemapShape(offset, gridSize, tileSize, borderThickness); world.addShape(tilemap); // create a maze let maze = [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1],[1,0,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,0,1,0,1],[1,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,1],[1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,0,1],[1,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1],[1,0,1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1],[1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1],[1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,0,1,0,1,1,1,0,1],[1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1],[1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,0,1],[1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1],[1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,0,1],[1,0,1,0,1,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1],[1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1],[1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1],[1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1],[1,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,0,0,1],[1,0,1,1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,0,1,1,1],[1,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,1],[1,0,1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1],[1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,1],[1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1],[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]] for (let i = 0; i < maze.length; ++i) { for (let j = 0; j < maze[i].length; ++j) { if (maze[i][j]) { tilemap.setTile(new Shaku.utils.Vector2(i, j), true); } } }</code></pre> <button class="modal__close" onclick="closeModal('sample-code-modal')">&#10005;</button> </div> </div> <link href="prism/prism.css" rel="stylesheet" /> <script src="prism/prism.js"></script> </body> </html>