UNPKG

kontra

Version:

Kontra HTML5 game development library

1,589 lines (1,402 loc) 60.8 kB
<!DOCTYPE html> <html lang="en"> <head> <title>Kontra.js – Sprite</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <base href="https://straker.github.io/kontra/"> <script> // adjust path based on location (github pages required kontra url) if (window.location.host.indexOf('localhost') !== -1) { let base = document.querySelector('base'); base.setAttribute('href', '/'); } </script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.16.0/themes/prism.min.css"> <link rel="stylesheet" href="assets/styles.css"> <script src="assets/js/kontra.js"></script> </head> <body> <div class="content"> <header class="main-nav"> <div id="kontra-heading" class="nav-heading">Kontra</div> <a href="#main">Skip navigation</a> <nav> <button class="menu-button" aria-expanded="false" aria-controls="menu"><span aria-hidden="true">☰</span> Menu</button> <!-- add role=list back to list so screen readers still read it as list when css list-style: none is set @see https://web-a11y.slack.com/archives/C042TSFGN/p1501699529181172 --> <ul id="menu" role="list"> <li><a href="." >Introduction</a></li> <li><a href="getting-started" >Getting Started</a></li> <li><a href="download" >Download</a></li> <li><a href="tutorials" >Tutorials</a></li> <li><a href="made-with-kontra" >Made With Kontra</a></li> <li> <span id="api" class="nav-api-heading">API</span> <ul aria-labelledby="api"> <li><a href="api/animation" >Animation</a></li> <li><a href="api/assets" >Assets</a></li> <li><a href="api/core" >Core</a></li> <li><a href="api/events" >Events</a></li> <li><a href="api/gameLoop" >GameLoop</a></li> <li><a href="api/keyboard" >Keyboard</a></li> <li><a href="api/plugin" >Plugin</a></li> <li><a href="api/pointer" >Pointer</a></li> <li><a href="api/pool" >Pool</a></li> <li><a href="api/quadtree" >Quadtree</a></li> <li><a href="api/sprite" aria-current="page">Sprite</a></li> <li><a href="api/spriteSheet" >SpriteSheet</a></li> <li><a href="api/store" >Store</a></li> <li><a href="api/tileEngine" >TileEngine</a></li> <li><a href="api/vector" >Vector</a></li> </ul> </li> </ul> </nav> <div class="scroll-indicator" aria-hidden="true"><span>^</span></div> </header> <main id="main"> <div> <a href="https://github.com/straker/kontra" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a> <h1>Sprite(&#8203;properties) </h1> <p>A versatile way to update and draw your game objects. It can handle simple rectangles, images, and sprite sheet animations. It can be used for your main player object as well as tiny particles in a particle engine.</p> <h3 id="title-Sprite"><span class="visually-hidden">Sprite</span> Parameters</span></h3> <dl aria-labelledby="title-Sprite"> <dt> <code>properties</code> </dt> <dd><p>Object. Properties of the sprite.</p> </dd> <dt> <code>properties.x</code> </dt> <dd><p>Number. X coordinate of the position vector.</p> </dd> <dt> <code>properties.y</code> </dt> <dd><p>Number. Y coordinate of the position vector.</p> </dd> <dt> <code>properties.dx</code> <span class="optional">Optional</span> </dt> <dd><p>Number. X coordinate of the velocity vector.</p> </dd> <dt> <code>properties.dy</code> <span class="optional">Optional</span> </dt> <dd><p>Number. Y coordinate of the velocity vector.</p> </dd> <dt> <code>properties.ddx</code> <span class="optional">Optional</span> </dt> <dd><p>Number. X coordinate of the acceleration vector.</p> </dd> <dt> <code>properties.ddy</code> <span class="optional">Optional</span> </dt> <dd><p>Number. Y coordinate of the acceleration vector.</p> </dd> <dt> <code>properties.color</code> <span class="optional">Optional</span> </dt> <dd><p>String. Fill color for the sprite if no image or animation is provided.</p> </dd> <dt> <code>properties.width</code> <span class="optional">Optional</span> </dt> <dd><p>Number. Width of the sprite.</p> </dd> <dt> <code>properties.height</code> <span class="optional">Optional</span> </dt> <dd><p>Number. Height of the sprite.</p> </dd> <dt> <code>properties.ttl</code> <span class="optional">Optional</span> </dt> <dd><p>Number. How many frames the sprite should be alive. Used by <a href="Pool">Pool</a>. Defaults to <code>Infinity</code>.</p> </dd> <dt> <code>properties.rotation</code> <span class="optional">Optional</span> </dt> <dd><p>Number. Sprites rotation around the origin in radians. Defaults to <code>0</code>.</p> </dd> <dt> <code>properties.anchor</code> <span class="optional">Optional</span> </dt> <dd><p>Number. The x and y origin of the sprite. {x:0, y:0} is the top left corner of the sprite, {x:1, y:1} is the bottom right corner. Defaults to <code>{x:0,y:0}</code>.</p> </dd> <dt> <code>properties.context</code> <span class="optional">Optional</span> </dt> <dd><p>Canvas​Rendering​Context2D. The context the sprite should draw to. Defaults to <a href="api/core#getContext">core.getContext()</a>.</p> </dd> <dt> <code>properties.image</code> <span class="optional">Optional</span> </dt> <dd><p>Image or HTMLCanvasElement. Use an image to draw the sprite.</p> </dd> <dt> <code>properties.animations</code> <span class="optional">Optional</span> </dt> <dd><p>Object. An object of <a href="animation">Animations</a> from a <a href="Spritesheet">Spritesheet</a> to animate the sprite.</p> </dd> <dt> <code>properties.update</code> <span class="optional">Optional</span> </dt> <dd><p>Function. Function called every frame to update the sprite.</p> </dd> <dt> <code>properties.render</code> <span class="optional">Optional</span> </dt> <dd><p>Function. Function called every frame to render the sprite.</p> </dd> <dt> <code>properties.*</code> <span class="optional">Optional</span> </dt> <dd><p>Any type. Any additional properties you need added to the sprite. For example, if you pass <code>Sprite({type: &#39;player&#39;})</code> then the sprite will also have a property of the same name and value. You can pass as many additional properties as you want.</p> </dd> </dl> <section class="toc"> <h2 id="toc"><a href="#toc" class="section-link">Table of Contents<span aria-hidden="true">#</span></a></h2> <ul aria-labelledby="toc"> <li> <ul> <li><a href="api/sprite#rectangle-sprite">Rectangle Sprite</a></li> <li><a href="api/sprite#image-sprite">Image Sprite</a></li> <li><a href="api/sprite#animation-sprite">Animation Sprite</a></li> <li><a href="api/sprite#custom-properties">Custom Properties</a></li> <li><a href="api/sprite#extending-a sprite">Extending a Sprite</a></li> </ul> </li> <li> <h3 id="properties">Properties</h3> <ul aria-labelledby="properties"> <li> <a href="api/sprite#acceleration"> <span>Sprite&#8203;.acceleration</span> </a> </li> <li> <a href="api/sprite#anchor"> <span>Sprite&#8203;.anchor</span> </a> </li> <li> <a href="api/sprite#animations"> <span>Sprite&#8203;.animations</span> </a> </li> <li> <a href="api/sprite#color"> <span>Sprite&#8203;.color</span> </a> </li> <li> <a href="api/sprite#context"> <span>Sprite&#8203;.context</span> </a> </li> <li> <a href="api/sprite#currentAnimation"> <span>Sprite&#8203;.currentAnimation</span> </a> </li> <li> <a href="api/sprite#ddx"> <span>Sprite&#8203;.ddx</span> </a> </li> <li> <a href="api/sprite#ddy"> <span>Sprite&#8203;.ddy</span> </a> </li> <li> <a href="api/sprite#dx"> <span>Sprite&#8203;.dx</span> </a> </li> <li> <a href="api/sprite#dy"> <span>Sprite&#8203;.dy</span> </a> </li> <li> <a href="api/sprite#height"> <span>Sprite&#8203;.height</span> </a> </li> <li> <a href="api/sprite#image"> <span>Sprite&#8203;.image</span> </a> </li> <li> <a href="api/sprite#position"> <span>Sprite&#8203;.position</span> </a> </li> <li> <a href="api/sprite#rotation"> <span>Sprite&#8203;.rotation</span> </a> </li> <li> <a href="api/sprite#ttl"> <span>Sprite&#8203;.ttl</span> </a> </li> <li> <a href="api/sprite#velocity"> <span>Sprite&#8203;.velocity</span> </a> </li> <li> <a href="api/sprite#width"> <span>Sprite&#8203;.width</span> </a> </li> <li> <a href="api/sprite#x"> <span>Sprite&#8203;.x</span> </a> </li> <li> <a href="api/sprite#y"> <span>Sprite&#8203;.y</span> </a> </li> </ul> </li> <li> <h3 id="methods">Methods</h3> <ul aria-labelledby="methods"> <li> <a href="api/sprite#advance"> <span>Sprite&#8203;.advance(&#8203;[dt])</span> </a> </li> <li> <a href="api/sprite#collidesWith"> <span>Sprite&#8203;.collidesWith(&#8203;object)</span> </a> </li> <li> <a href="api/sprite#draw"> <span>Sprite&#8203;.draw(&#8203;)</span> </a> </li> <li> <a href="api/sprite#init"> <span>Sprite&#8203;.init(&#8203;properties)</span> </a> </li> <li> <a href="api/sprite#isAlive"> <span>Sprite&#8203;.isAlive(&#8203;)</span> </a> </li> <li> <a href="api/sprite#playAnimation"> <span>Sprite&#8203;.playAnimation(&#8203;name)</span> </a> </li> <li> <a href="api/sprite#render"> <span>Sprite&#8203;.render(&#8203;)</span> </a> </li> <li> <a href="api/sprite#update"> <span>Sprite&#8203;.update(&#8203;[dt])</span> </a> </li> </ul> </li> </ul> </section> <section> <h2 id="rectangle-sprite"> <a href="#rectangle-sprite" class="section-link"> <span>Rectangle Sprite</span> <span aria-hidden="true">#</span> </a> </h2> <p>In its most basic form, a sprite is a rectangle with a fill color. To create a rectangle sprite, pass the arguments <code>width</code>, <code>height</code>, and <code>color</code>. A rectangle sprite is great for initial prototyping and particles.</p> <canvas id="game-canvas-0"></canvas> <div class="tablist"> <ul role="tablist"> <li role="presentation" data-tab="global"> <button role="tab" id="game-canvas-0-global-tab">Global Object</button> </li> <li role="presentation" data-tab="es"> <button role="tab" id="game-canvas-0-es-tab">ES Module Import</button> </li> <li role="presentation" data-tab="bundle"> <button role="tab" id="game-canvas-0-bundle-tab">Module Bundler</button> </li> <li role="presentation"></li> </ul> <section role="tabpanel" aria-labelledby=game-canvas-0-global-tab data-tabpanel="global"> <pre><code class="lang-js">let { Sprite } &#x3D; kontra let sprite &#x3D; Sprite({ x: 300, y: 100, anchor: {x: 0.5, y: 0.5}, // required for a rectangle sprite width: 20, height: 40, color: &#x27;red&#x27; }); sprite.render();</code></pre> </section> <section role="tabpanel" aria-labelledby=game-canvas-0-es-tab data-tabpanel="es"> <pre><code class="lang-js">import { Sprite } from &#x27;path/to/kontra.mjs&#x27; let sprite &#x3D; Sprite({ x: 300, y: 100, anchor: {x: 0.5, y: 0.5}, // required for a rectangle sprite width: 20, height: 40, color: &#x27;red&#x27; }); sprite.render();</code></pre> </section> <section role="tabpanel" aria-labelledby=game-canvas-0-bundle-tab data-tabpanel="bundle"> <pre><code class="lang-js">import { Sprite } from &#x27;kontra&#x27;; let sprite &#x3D; Sprite({ x: 300, y: 100, anchor: {x: 0.5, y: 0.5}, // required for a rectangle sprite width: 20, height: 40, color: &#x27;red&#x27; }); sprite.render();</code></pre> </section> </div> <script>(function() { kontra.init("game-canvas-0"); var canvas = document.querySelector("#game-canvas-0"); canvas.width = 600; canvas.height = 200; var context = canvas.getContext("2d"); // exclude-code:start let { Sprite } = kontra; // exclude-code:end let sprite = Sprite({ x: 300, y: 100, anchor: {x: 0.5, y: 0.5}, // required for a rectangle sprite width: 20, height: 40, color: 'red' }); // exclude-code:start sprite.context = context; // exclude-code:end sprite.render(); })();</script> </section> <section> <h2 id="image-sprite"> <a href="#image-sprite" class="section-link"> <span>Image Sprite</span> <span aria-hidden="true">#</span> </a> </h2> <p>A sprite can use an image instead of drawing a rectangle. To create an image sprite, pass the <code>image</code> argument. The size of the sprite will automatically be set as the width and height of the image.</p> <canvas id="game-canvas-1"></canvas> <div class="tablist"> <ul role="tablist"> <li role="presentation" data-tab="global"> <button role="tab" id="game-canvas-1-global-tab">Global Object</button> </li> <li role="presentation" data-tab="es"> <button role="tab" id="game-canvas-1-es-tab">ES Module Import</button> </li> <li role="presentation" data-tab="bundle"> <button role="tab" id="game-canvas-1-bundle-tab">Module Bundler</button> </li> <li role="presentation"></li> </ul> <section role="tabpanel" aria-labelledby=game-canvas-1-global-tab data-tabpanel="global"> <pre><code class="lang-js">let { Sprite } &#x3D; kontra let image &#x3D; new Image(); image.src &#x3D; &#x27;assets/imgs/character.png&#x27;; image.onload &#x3D; function() { let sprite &#x3D; Sprite({ x: 300, y: 100, anchor: {x: 0.5, y: 0.5}, // required for an image sprite image: image }); sprite.render(); };</code></pre> </section> <section role="tabpanel" aria-labelledby=game-canvas-1-es-tab data-tabpanel="es"> <pre><code class="lang-js">import { Sprite } from &#x27;path/to/kontra.mjs&#x27; let image &#x3D; new Image(); image.src &#x3D; &#x27;assets/imgs/character.png&#x27;; image.onload &#x3D; function() { let sprite &#x3D; Sprite({ x: 300, y: 100, anchor: {x: 0.5, y: 0.5}, // required for an image sprite image: image }); sprite.render(); };</code></pre> </section> <section role="tabpanel" aria-labelledby=game-canvas-1-bundle-tab data-tabpanel="bundle"> <pre><code class="lang-js">import { Sprite } from &#x27;kontra&#x27;; let image &#x3D; new Image(); image.src &#x3D; &#x27;assets/imgs/character.png&#x27;; image.onload &#x3D; function() { let sprite &#x3D; Sprite({ x: 300, y: 100, anchor: {x: 0.5, y: 0.5}, // required for an image sprite image: image }); sprite.render(); };</code></pre> </section> </div> <script>(function() { kontra.init("game-canvas-1"); var canvas = document.querySelector("#game-canvas-1"); canvas.width = 600; canvas.height = 200; var context = canvas.getContext("2d"); // exclude-code:start let { Sprite } = kontra; // exclude-code:end let image = new Image(); image.src = 'assets/imgs/character.png'; image.onload = function() { let sprite = Sprite({ x: 300, y: 100, anchor: {x: 0.5, y: 0.5}, // required for an image sprite image: image }); // exclude-code:start sprite.context = context; // exclude-code:end sprite.render(); }; })();</script> </section> <section> <h2 id="animation-sprite"> <a href="#animation-sprite" class="section-link"> <span>Animation Sprite</span> <span aria-hidden="true">#</span> </a> </h2> <p>A sprite can use a spritesheet animation as well. To create an animation sprite, pass the <code>animations</code> argument. The size of the sprite will automatically be set as the width and height of a frame of the spritesheet.</p> <p>A sprite can have multiple named animations. The easiest way to create animations is to use <a href="SpriteSheet">SpriteSheet</a>. All animations will automatically be <a href="animation#clone">cloned</a> so no two sprites update the same animation.</p> <canvas id="game-canvas-2"></canvas> <div class="tablist"> <ul role="tablist"> <li role="presentation" data-tab="global"> <button role="tab" id="game-canvas-2-global-tab">Global Object</button> </li> <li role="presentation" data-tab="es"> <button role="tab" id="game-canvas-2-es-tab">ES Module Import</button> </li> <li role="presentation" data-tab="bundle"> <button role="tab" id="game-canvas-2-bundle-tab">Module Bundler</button> </li> <li role="presentation"></li> </ul> <section role="tabpanel" aria-labelledby=game-canvas-2-global-tab data-tabpanel="global"> <pre><code class="lang-js">let { Sprite, SpriteSheet, GameLoop } &#x3D; kontra let image &#x3D; new Image(); image.src &#x3D; &#x27;assets/imgs/character_walk_sheet.png&#x27;; image.onload &#x3D; function() { // use spriteSheet to create animations from an image let spriteSheet &#x3D; SpriteSheet({ image: image, frameWidth: 72, frameHeight: 97, animations: { // create a named animation: walk walk: { frames: &#x27;0..9&#x27;, // frames 0 through 9 frameRate: 30 } } }); let sprite &#x3D; Sprite({ x: 300, y: 100, anchor: {x: 0.5, y: 0.5}, // required for an animation sprite animations: spriteSheet.animations }); // use kontra.gameLoop to play the animation let loop &#x3D; GameLoop({ update: function(dt) { sprite.update(); }, render: function() { sprite.render(); } }); loop.start(); };</code></pre> </section> <section role="tabpanel" aria-labelledby=game-canvas-2-es-tab data-tabpanel="es"> <pre><code class="lang-js">import { Sprite, SpriteSheet, GameLoop } from &#x27;path/to/kontra.mjs&#x27; let image &#x3D; new Image(); image.src &#x3D; &#x27;assets/imgs/character_walk_sheet.png&#x27;; image.onload &#x3D; function() { // use spriteSheet to create animations from an image let spriteSheet &#x3D; SpriteSheet({ image: image, frameWidth: 72, frameHeight: 97, animations: { // create a named animation: walk walk: { frames: &#x27;0..9&#x27;, // frames 0 through 9 frameRate: 30 } } }); let sprite &#x3D; Sprite({ x: 300, y: 100, anchor: {x: 0.5, y: 0.5}, // required for an animation sprite animations: spriteSheet.animations }); // use kontra.gameLoop to play the animation let loop &#x3D; GameLoop({ update: function(dt) { sprite.update(); }, render: function() { sprite.render(); } }); loop.start(); };</code></pre> </section> <section role="tabpanel" aria-labelledby=game-canvas-2-bundle-tab data-tabpanel="bundle"> <pre><code class="lang-js">import { Sprite, SpriteSheet, GameLoop } from &#x27;kontra&#x27;; let image &#x3D; new Image(); image.src &#x3D; &#x27;assets/imgs/character_walk_sheet.png&#x27;; image.onload &#x3D; function() { // use spriteSheet to create animations from an image let spriteSheet &#x3D; SpriteSheet({ image: image, frameWidth: 72, frameHeight: 97, animations: { // create a named animation: walk walk: { frames: &#x27;0..9&#x27;, // frames 0 through 9 frameRate: 30 } } }); let sprite &#x3D; Sprite({ x: 300, y: 100, anchor: {x: 0.5, y: 0.5}, // required for an animation sprite animations: spriteSheet.animations }); // use kontra.gameLoop to play the animation let loop &#x3D; GameLoop({ update: function(dt) { sprite.update(); }, render: function() { sprite.render(); } }); loop.start(); };</code></pre> </section> </div> <script>(function() { kontra.init("game-canvas-2"); var canvas = document.querySelector("#game-canvas-2"); canvas.width = 600; canvas.height = 200; var context = canvas.getContext("2d"); // exclude-code:start let { Sprite, SpriteSheet, GameLoop } = kontra; // exclude-code:end let image = new Image(); image.src = 'assets/imgs/character_walk_sheet.png'; image.onload = function() { // use spriteSheet to create animations from an image let spriteSheet = SpriteSheet({ image: image, frameWidth: 72, frameHeight: 97, animations: { // create a named animation: walk walk: { frames: '0..9', // frames 0 through 9 frameRate: 30 } } }); let sprite = Sprite({ x: 300, y: 100, anchor: {x: 0.5, y: 0.5}, // required for an animation sprite animations: spriteSheet.animations }); // exclude-code:start sprite.context = context; // exclude-code:end // use kontra.gameLoop to play the animation let loop = GameLoop({ // exclude-code:start clearCanvas: false, // exclude-code:end update: function(dt) { sprite.update(); }, render: function() { // exclude-code:start context.clearRect(0,0,context.canvas.width,context.canvas.height); // exclude-code:end sprite.render(); } }); loop.start(); }; })();</script> </section> <section> <h2 id="custom-properties"> <a href="#custom-properties" class="section-link"> <span>Custom Properties</span> <span aria-hidden="true">#</span> </a> </h2> <p>If you need to draw a different shape, such as a circle, you can pass in custom properties and a render function to handle drawing the sprite.</p> <canvas id="game-canvas-3"></canvas> <div class="tablist"> <ul role="tablist"> <li role="presentation" data-tab="global"> <button role="tab" id="game-canvas-3-global-tab">Global Object</button> </li> <li role="presentation" data-tab="es"> <button role="tab" id="game-canvas-3-es-tab">ES Module Import</button> </li> <li role="presentation" data-tab="bundle"> <button role="tab" id="game-canvas-3-bundle-tab">Module Bundler</button> </li> <li role="presentation"></li> </ul> <section role="tabpanel" aria-labelledby=game-canvas-3-global-tab data-tabpanel="global"> <pre><code class="lang-js">let { Sprite } &#x3D; kontra let sprite &#x3D; Sprite({ x: 300, y: 100, color: &#x27;red&#x27;, // custom properties radius: 20, render: function() { this.context.fillStyle &#x3D; this.color; this.context.beginPath(); this.context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); this.context.fill(); } }); sprite.render();</code></pre> </section> <section role="tabpanel" aria-labelledby=game-canvas-3-es-tab data-tabpanel="es"> <pre><code class="lang-js">import { Sprite } from &#x27;path/to/kontra.mjs&#x27; let sprite &#x3D; Sprite({ x: 300, y: 100, color: &#x27;red&#x27;, // custom properties radius: 20, render: function() { this.context.fillStyle &#x3D; this.color; this.context.beginPath(); this.context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); this.context.fill(); } }); sprite.render();</code></pre> </section> <section role="tabpanel" aria-labelledby=game-canvas-3-bundle-tab data-tabpanel="bundle"> <pre><code class="lang-js">import { Sprite } from &#x27;kontra&#x27;; let sprite &#x3D; Sprite({ x: 300, y: 100, color: &#x27;red&#x27;, // custom properties radius: 20, render: function() { this.context.fillStyle &#x3D; this.color; this.context.beginPath(); this.context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); this.context.fill(); } }); sprite.render();</code></pre> </section> </div> <script>(function() { kontra.init("game-canvas-3"); var canvas = document.querySelector("#game-canvas-3"); canvas.width = 600; canvas.height = 200; var context = canvas.getContext("2d"); // exclude-code:start let { Sprite } = kontra; // exclude-code:end let sprite = Sprite({ x: 300, y: 100, color: 'red', // custom properties radius: 20, render: function() { this.context.fillStyle = this.color; this.context.beginPath(); this.context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); this.context.fill(); } }); // exclude-code:start sprite.context = context; // exclude-code:end sprite.render(); })();</script> </section> <section> <h2 id="extending-a sprite"> <a href="#extending-a sprite" class="section-link"> <span>Extending a Sprite</span> <span aria-hidden="true">#</span> </a> </h2> <p>If you want to extend a Sprite, you can do so by extending the Sprite class. The one caveat is that <code>Sprite</code> is not the Sprite class, but actually is a factory function.</p> <p>To extend the Sprite class, use the <code>.class</code> property of the constructor.</p> <div class="tablist"> <ul role="tablist"> <li role="presentation" data-tab="global"> <button role="tab" id="extending-a-sprite-global-tab">Global Object</button> </li> <li role="presentation" data-tab="es"> <button role="tab" id="extending-a-sprite-es-tab">ES Module Import</button> </li> <li role="presentation" data-tab="bundle"> <button role="tab" id="extending-a-sprite-bundle-tab">Module Bundler</button> </li> <li role="presentation"></li> </ul> <section role="tabpanel" aria-labelledby=extending-a-sprite-global-tab data-tabpanel="global"><pre><code class="language-js">let { Sprite } = kontra; class CustomSprite extends Sprite.class { // ... }</code></pre></section> <section role="tabpanel" aria-labelledby=extending-a-sprite-es-tab data-tabpanel="es"><pre><code class="language-js">import { Sprite } from 'path/to/kontra.mjs'; class CustomSprite extends Sprite.class { // ... }</code></pre></section> <section role="tabpanel" aria-labelledby=extending-a-sprite-bundle-tab data-tabpanel="bundle"><pre><code class="language-js">import { Sprite } from &#39;kontra&#39;; class CustomSprite extends Sprite.class { // ... }</code></pre></section> </div> </section> <section> <h2 id="acceleration"> <a href="api/sprite#acceleration" class="section-link"> <span>Sprite&#8203;.acceleration</span> <span aria-hidden="true">#</span> </a> </h2> <p>The sprites acceleration vector.</p> </section> <section> <h2 id="advance"> <a href="api/sprite#advance" class="section-link"> <span>Sprite&#8203;.advance(&#8203;[dt])</span> <span aria-hidden="true">#</span> </a> </h2> <p>Move the sprite by its acceleration and velocity. If the sprite is an <a href="#animation-sprite">animation sprite</a>, it also advances the animation every frame.</p> <p>If you override the sprites <a href="#update">update()</a> function with your own update function, you can call this function to move the sprite normally.</p> <div class="tablist"> <ul role="tablist"> <li role="presentation" data-tab="global"> <button role="tab" id="advance-global-tab">Global Object</button> </li> <li role="presentation" data-tab="es"> <button role="tab" id="advance-es-tab">ES Module Import</button> </li> <li role="presentation" data-tab="bundle"> <button role="tab" id="advance-bundle-tab">Module Bundler</button> </li> <li role="presentation"></li> </ul> <section role="tabpanel" aria-labelledby=advance-global-tab data-tabpanel="global"><pre><code class="language-js">let { Sprite } = kontra; let sprite = Sprite({ x: 100, y: 200, width: 20, height: 40, dx: 5, dy: 2, update: function() { // move the sprite normally sprite.advance(); // change the velocity at the edges of the canvas if (this.x &lt; 0 || this.x + this.width &gt; this.context.canvas.width) { this.dx = -this.dx; } if (this.y &lt; 0 || this.y + this.height &gt; this.context.canvas.height) { this.dy = -this.dy; } } });</code></pre></section> <section role="tabpanel" aria-labelledby=advance-es-tab data-tabpanel="es"><pre><code class="language-js">import { Sprite } from 'path/to/kontra.mjs'; let sprite = Sprite({ x: 100, y: 200, width: 20, height: 40, dx: 5, dy: 2, update: function() { // move the sprite normally sprite.advance(); // change the velocity at the edges of the canvas if (this.x &lt; 0 || this.x + this.width &gt; this.context.canvas.width) { this.dx = -this.dx; } if (this.y &lt; 0 || this.y + this.height &gt; this.context.canvas.height) { this.dy = -this.dy; } } });</code></pre></section> <section role="tabpanel" aria-labelledby=advance-bundle-tab data-tabpanel="bundle"><pre><code class="language-js">import { Sprite } from &#39;kontra&#39;; let sprite = Sprite({ x: 100, y: 200, width: 20, height: 40, dx: 5, dy: 2, update: function() { // move the sprite normally sprite.advance(); // change the velocity at the edges of the canvas if (this.x &lt; 0 || this.x + this.width &gt; this.context.canvas.width) { this.dx = -this.dx; } if (this.y &lt; 0 || this.y + this.height &gt; this.context.canvas.height) { this.dy = -this.dy; } } });</code></pre></section> </div> <h3 id="title-advance"><span class="visually-hidden">advance</span> Parameters</span></h3> <dl aria-labelledby="title-advance"> <dt> <code>dt</code> <span class="optional">Optional</span> </dt> <dd><p>Number. Time since last update.</p> </dd> </dl> </section> <section> <h2 id="anchor"> <a href="api/sprite#anchor" class="section-link"> <span>Sprite&#8203;.anchor</span> <span aria-hidden="true">#</span> </a> </h2> <p>The x and y origin of the sprite. {x:0, y:0} is the top left corner of the sprite, {x:1, y:1} is the bottom right corner.</p> <canvas id="game-canvas-4"></canvas> <div class="tablist"> <ul role="tablist"> <li role="presentation" data-tab="global"> <button role="tab" id="game-canvas-4-global-tab">Global Object</button> </li> <li role="presentation" data-tab="es"> <button role="tab" id="game-canvas-4-es-tab">ES Module Import</button> </li> <li role="presentation" data-tab="bundle"> <button role="tab" id="game-canvas-4-bundle-tab">Module Bundler</button> </li> <li role="presentation"></li> </ul> <section role="tabpanel" aria-labelledby=game-canvas-4-global-tab data-tabpanel="global"> <pre><code class="lang-js">let { Sprite } &#x3D; kontra let sprite &#x3D; Sprite({ x: 150, y: 100, color: &#x27;red&#x27;, width: 50, height: 50, render: function() { this.draw(); // draw origin this.context.fillStyle &#x3D; &#x27;yellow&#x27;; this.context.beginPath(); this.context.arc(this.x, this.y, 3, 0, 2*Math.PI); this.context.fill(); } }); sprite.render(); sprite.anchor &#x3D; {x: 0.5, y: 0.5}; sprite.x &#x3D; 300; sprite.render(); sprite.anchor &#x3D; {x: 1, y: 1}; sprite.x &#x3D; 450; sprite.render();</code></pre> </section> <section role="tabpanel" aria-labelledby=game-canvas-4-es-tab data-tabpanel="es"> <pre><code class="lang-js">import { Sprite } from &#x27;path/to/kontra.mjs&#x27; let sprite &#x3D; Sprite({ x: 150, y: 100, color: &#x27;red&#x27;, width: 50, height: 50, render: function() { this.draw(); // draw origin this.context.fillStyle &#x3D; &#x27;yellow&#x27;; this.context.beginPath(); this.context.arc(this.x, this.y, 3, 0, 2*Math.PI); this.context.fill(); } }); sprite.render(); sprite.anchor &#x3D; {x: 0.5, y: 0.5}; sprite.x &#x3D; 300; sprite.render(); sprite.anchor &#x3D; {x: 1, y: 1}; sprite.x &#x3D; 450; sprite.render();</code></pre> </section> <section role="tabpanel" aria-labelledby=game-canvas-4-bundle-tab data-tabpanel="bundle"> <pre><code class="lang-js">import { Sprite } from &#x27;kontra&#x27;; let sprite &#x3D; Sprite({ x: 150, y: 100, color: &#x27;red&#x27;, width: 50, height: 50, render: function() { this.draw(); // draw origin this.context.fillStyle &#x3D; &#x27;yellow&#x27;; this.context.beginPath(); this.context.arc(this.x, this.y, 3, 0, 2*Math.PI); this.context.fill(); } }); sprite.render(); sprite.anchor &#x3D; {x: 0.5, y: 0.5}; sprite.x &#x3D; 300; sprite.render(); sprite.anchor &#x3D; {x: 1, y: 1}; sprite.x &#x3D; 450; sprite.render();</code></pre> </section> </div> <script>(function() { kontra.init("game-canvas-4"); var canvas = document.querySelector("#game-canvas-4"); canvas.width = 600; canvas.height = 200; var context = canvas.getContext("2d"); // exclude-code:start let { Sprite } = kontra; // exclude-code:end let sprite = Sprite({ x: 150, y: 100, color: 'red', width: 50, height: 50, // exclude-code:start context: context, // exclude-code:end render: function() { this.draw(); // draw origin this.context.fillStyle = 'yellow'; this.context.beginPath(); this.context.arc(this.x, this.y, 3, 0, 2*Math.PI); this.context.fill(); } }); sprite.render(); sprite.anchor = {x: 0.5, y: 0.5}; sprite.x = 300; sprite.render(); sprite.anchor = {x: 1, y: 1}; sprite.x = 450; sprite.render(); })();</script> </section> <section> <h2 id="animations"> <a href="api/sprite#animations" class="section-link"> <span>Sprite&#8203;.animations</span> <span aria-hidden="true">#</span> </a> </h2> <p>An object of <a href="animation">Animations</a> from a <a href="SpriteSheet">SpriteSheet</a> to animate the sprite. Each animation is named so that it can can be used by name for the sprites <a href="#playAnimation">playAnimation()</a> function.</p> <div class="tablist"> <ul role="tablist"> <li role="presentation" data-tab="global"> <button role="tab" id="animations-global-tab">Global Object</button> </li> <li role="presentation" data-tab="es"> <button role="tab" id="animations-es-tab">ES Module Import</button> </li> <li role="presentation" data-tab="bundle"> <button role="tab" id="animations-bundle-tab">Module Bundler</button> </li> <li role="presentation"></li> </ul> <section role="tabpanel" aria-labelledby=animations-global-tab data-tabpanel="global"><pre><code class="language-js">let { Sprite, SpriteSheet } = kontra; let spriteSheet = SpriteSheet({ // ... animations: { idle: { frames: 1, loop: false, }, walk: { frames: [1,2,3] } } }); let sprite = Sprite({ x: 100, y: 200, animations: spriteSheet.animations }); sprite.playAnimation(&#39;idle&#39;);</code></pre></section> <section role="tabpanel" aria-labelledby=animations-es-tab data-tabpanel="es"><pre><code class="language-js">import { Sprite, SpriteSheet } from 'path/to/kontra.mjs'; let spriteSheet = SpriteSheet({ // ... animations: { idle: { frames: 1, loop: false, }, walk: { frames: [1,2,3] } } }); let sprite = Sprite({ x: 100, y: 200, animations: spriteSheet.animations }); sprite.playAnimation(&#39;idle&#39;);</code></pre></section> <section role="tabpanel" aria-labelledby=animations-bundle-tab data-tabpanel="bundle"><pre><code class="language-js">import { Sprite, SpriteSheet } from &#39;kontra&#39;; let spriteSheet = SpriteSheet({ // ... animations: { idle: { frames: 1, loop: false, }, walk: { frames: [1,2,3] } } }); let sprite = Sprite({ x: 100, y: 200, animations: spriteSheet.animations }); sprite.playAnimation(&#39;idle&#39;);</code></pre></section> </div> </section> <section> <h2 id="collidesWith"> <a href="api/sprite#collidesWith" class="section-link"> <span>Sprite&#8203;.collidesWith(&#8203;object)</span> <span aria-hidden="true">#</span> </a> </h2> <p>Check if the sprite collide with the object. Uses a simple <a href="https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection#Axis-Aligned_Bounding_Box">Axis-Aligned Bounding Box (AABB) collision check</a>. Takes into account the sprites <a href="#anchor">anchor</a>.</p> <p><strong>NOTE:</strong> Does not take into account sprite rotation. If you need collision detection between rotated sprites you will need to implement your own <code>collidesWith()</code> function. I suggest looking at the Separate Axis Theorem.</p> <div class="tablist"> <ul role="tablist"> <li role="presentation" data-tab="global"> <button role="tab" id="collideswith-global-tab">Global Object</button> </li> <li role="presentation" data-tab="es"> <button role="tab" id="collideswith-es-tab">ES Module Import</button> </li> <li role="presentation" data-tab="bundle"> <button role="tab" id="collideswith-bundle-tab">Module Bundler</button> </li> <li role="presentation"></li> </ul> <section role="tabpanel" aria-labelledby=collideswith-global-tab data-tabpanel="global"><pre><code class="language-js">let { Sprite } = kontra; let sprite = Sprite({ x: 100, y: 200, width: 20, height: 40 }); let sprite2 = Sprite({ x: 150, y: 200, width: 20, height: 20 }); sprite.collidesWith(sprite2); //=&gt; false sprite2.x = 115; sprite.collidesWith(sprite2); //=&gt; true</code></pre></section> <section role="tabpanel" aria-labelledby=collideswith-es-tab data-tabpanel="es"><pre><code class="language-js">import { Sprite } from 'path/to/kontra.mjs'; let sprite = Sprite({ x: 100, y: 200, width: 20, height: 40 }); let sprite2 = Sprite({ x: 150, y: 200, width: 20, height: 20 }); sprite.collidesWith(sprite2); //=&gt; false sprite2.x = 115; sprite.collidesWith(sprite2); //=&gt; true</code></pre></section> <section role="tabpanel" aria-labelledby=collideswith-bundle-tab data-tabpanel="bundle"><pre><code class="language-js">import { Sprite } from &#39;kontra&#39;; let sprite = Sprite({ x: 100, y: 200, width: 20, height: 40 }); let sprite2 = Sprite({ x: 150, y: 200, width: 20, height: 20 }); sprite.collidesWith(sprite2); //=&gt; false sprite2.x = 115; sprite.collidesWith(sprite2); //=&gt; true</code></pre></section> </div> <p>If you need a different type of collision check, you can override this function by passing an argument by the same name.</p> <div class="tablist"> <ul role="tablist"> <li role="presentation" data-tab="global"> <button role="tab" id="collideswith-global-tab">Global Object</button> </li> <li role="presentation" data-tab="es"> <button role="tab" id="collideswith-es-tab">ES Module Import</button> </li> <li role="presentation" data-tab="bundle"> <button role="tab" id="collideswith-bundle-tab">Module Bundler</button> </li> <li role="presentation"></li> </ul> <section role="tabpanel" aria-labelledby=collideswith-global-tab data-tabpanel="global"><pre><code class="language-js">// circle collision function collidesWith(object) { let dx = this.x - object.x; let dy = this.y - object.y; let distance = Math.sqrt(dx * dx + dy * dy); return distance &lt; this.radius + object.radius; } let sprite = Sprite({ x: 100, y: 200, radius: 25, collidesWith: collidesWith }); let sprite2 = Sprite({ x: 150, y: 200, radius: 30, collidesWith: collidesWith }); sprite.collidesWith(sprite2); //=&gt; true</code></pre></section> <section role="tabpanel" aria-labelledby=collideswith-es-tab data-tabpanel="es"><pre><code class="language-js">// circle collision function collidesWith(object) { let dx = this.x - object.x; let dy = this.y - object.y; let distance = Math.sqrt(dx * dx + dy * dy); return distance &lt; this.radius + object.radius; } let sprite = Sprite({ x: 100, y: 200, radius: 25, collidesWith: collidesWith }); let sprite2 = Sprite({ x: 150, y: 200, radius: 30, collidesWith: collidesWith }); sprite.collidesWith(sprite2); //=&gt; true</code></pre></section> <section role="tabpanel" aria-labelledby=collideswith-bundle-tab data-tabpanel="bundle"><pre><code class="language-js">// circle collision function collidesWith(object) { let dx = this.x - object.x; let dy = this.y - object.y; let distance = Math.sqrt(dx * dx + dy * dy); return distance &lt; this.radius + object.radius; } let sprite = Sprite({ x: 100, y: 200, radius: 25, collidesWith: collidesWith }); let sprite2 = Sprite({ x: 150, y: 200, radius: 30, collidesWith: collidesWith }); sprite.collidesWith(sprite2); //=&gt; true</code></pre></section> </div> <h3 id="title-collidesWith"><span class="visually-hidden">collidesWith</span> Parameters</span></h3> <dl aria-labelledby="title-collidesWith"> <dt> <code>object</code> </dt> <dd><p>Object. Object to check collision against.</p> </dd> </dl> <h3><span class="visually-hidden">collidesWith</span> Return value</h3> <p><p><code>true</code> if the objects collide, <code>false</code> otherwise. Will return <code>null</code> if the either of the two objects are rotated.</p> </p> </section> <section> <h2 id="color"> <a href="api/sprite#color" class="section-link"> <span>Sprite&#8203;.color</span> <span aria-hidden="true">#</span> </a> </h2> <p>The color of the sprite if it was passed as an argument.</p> </section> <section> <h2 id="context"> <a href="api/sprite#context" class="section-link"> <span>Sprite&#8203;.context</span> <span aria-hidden="true">#</span> </a> </h2> <p>The context the sprite will draw to.</p> </section> <section> <h2 id="currentAnimation"> <a href="api/sprite#currentAnimation" class="section-link"> <span>Sprite&#8203;.currentAnimation</span> <span aria-hidden="true">#</span> </a> </h2> <p>The currently playing Animation object if <code>animations</code> was passed as an argument.</p> </section> <section> <h2 id="ddx"> <a href="api/sprite#ddx" class="section-link"> <span>Sprite&#8203;.ddx</span> <span aria-hidden="true">#</span> </a> </h2> <p>X coordinate of the acceleration vector.</p> </section> <section> <h2 id="ddy"> <a href="api/sprite#ddy" class="section-link"> <span>Sprite&#8203;.ddy</span> <span aria-hidden="true">#</span> </a> </h2> <p>Y coordinate of the acceleration vector.</p> </section> <section> <h2 id="draw"> <a href="api/sprite#draw" class="section-link"> <span>Sprite&#8203;.draw(&#8203;)</span> <span aria-hidden="true">#</span> </a> </h2> <p>Draw the sprite at its X and Y position. This function changes based on the type of the sprite. For a <a href="#rectangle-sprite">rectangle sprite</a>, it uses <code>context.fillRect()</code>, for an <a href="#image-sprite">image sprite</a> it uses <code>context.drawImage()</code>, and for an <a href="#animation-sprite">animation sprite</a> it uses the <a href="#currentAnimation">currentAnimation</a> <code>render()</code> function.</p> <p>If you override the sprites <code>render()</code> function with your own render function, you can call this function to draw the sprite normally.</p> <div class="tablist"> <ul role="tablist"> <li role="presentation" data-tab="global"> <button role="tab" id="draw-global-tab">Global Object</button> </li> <li role="presentation" data-tab="es"> <button role="tab" id="draw-es-tab">ES Module Import</button> </li> <li role="presentation" data-tab="bundle"> <button role="tab" id="draw-bundle-tab">Module Bundler</button> </li> <li role="presentation"></li> </ul> <section role="tabpanel" aria-labelledby=draw-global-tab data-tabpanel="global"><pre><code class="language-js">let { Sprite } = kontra; let sprite = Sprite({ x: 290, y: 80, color: &#39;red&#39;, width: 20, height: 40, render: function() { // draw the rectangle sprite normally this.draw(); // outline the sprite this.context.strokeStyle = &#39;yellow&#39;; this.context.lineWidth = 2; this.context.strokeRect(this.x, this.y, this.width, this.height); } });