# Sprite(​properties)

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.

### Sprite Parameters

`properties`

  Object. Properties of the sprite.

`properties.x`

  Number. X coordinate of the position vector.

`properties.y`

  Number. Y coordinate of the position vector.

`properties.dx` Optional

  Number. X coordinate of the velocity vector.

`properties.dy` Optional

  Number. Y coordinate of the velocity vector.

`properties.ddx` Optional

  Number. X coordinate of the acceleration vector.

`properties.ddy` Optional

  Number. Y coordinate of the acceleration vector.

`properties.color` Optional

  String. Fill color for the sprite if no image or animation is provided.

`properties.width` Optional

  Number. Width of the sprite.

`properties.height` Optional

  Number. Height of the sprite.

`properties.ttl` Optional

  Number. How many frames the sprite should be alive. Used by Pool. Defaults to `Infinity`.

`properties.rotation` Optional

  Number. Sprites rotation around the origin in radians. Defaults to `0`.

`properties.anchor` Optional

  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 `{x:0,y:0}`.

`properties.context` Optional

  Canvas​Rendering​Context2D. The context the sprite should draw to. Defaults to core.getContext().

`properties.image` Optional

  Image or HTMLCanvasElement. Use an image to draw the sprite.

`properties.animations` Optional

  Object. An object of Animations from a Spritesheet to animate the sprite.

`properties.update` Optional

  Function. Function called every frame to update the sprite.

`properties.render` Optional

  Function. Function called every frame to render the sprite.

`properties.*` Optional

  Any type. Any additional properties you need added to the sprite. For example, if you pass `Sprite({type: 'player'})` then the sprite will also have a property of the same name and value. You can pass as many additional properties as you want.

## Rectangle Sprite #

In its most basic form, a sprite is a rectangle with a fill color. To create a rectangle sprite, pass the arguments `width`, `height`, and `color`. A rectangle sprite is great for initial prototyping and particles.

    let { Sprite } = kontra

    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'
    });

    sprite.render();

    import { Sprite } from 'path/to/kontra.mjs'

    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'
    });

    sprite.render();

    import { Sprite } from 'kontra';

    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'
    });

    sprite.render();

## Image Sprite #

A sprite can use an image instead of drawing a rectangle. To create an image sprite, pass the `image` argument. The size of the sprite will automatically be set as the width and height of the image.

    let { Sprite } = kontra

    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
      });

      sprite.render();
    };

    import { Sprite } from 'path/to/kontra.mjs'

    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
      });

      sprite.render();
    };

    import { Sprite } from 'kontra';

    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
      });

      sprite.render();
    };

## Animation Sprite #

A sprite can use a spritesheet animation as well. To create an animation sprite, pass the `animations` argument. The size of the sprite will automatically be set as the width and height of a frame of the spritesheet.

A sprite can have multiple named animations. The easiest way to create animations is to use SpriteSheet. All animations will automatically be cloned so no two sprites update the same animation.

    let { Sprite, SpriteSheet, GameLoop } = kontra

    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
      });

      // use kontra.gameLoop to play the animation
      let loop = GameLoop({
        update: function(dt) {
          sprite.update();
        },
        render: function() {
          sprite.render();
        }
      });

      loop.start();
    };

    import { Sprite, SpriteSheet, GameLoop } from 'path/to/kontra.mjs'

    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
      });

      // use kontra.gameLoop to play the animation
      let loop = GameLoop({
        update: function(dt) {
          sprite.update();
        },
        render: function() {
          sprite.render();
        }
      });

      loop.start();
    };

    import { Sprite, SpriteSheet, GameLoop } from 'kontra';

    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
      });

      // use kontra.gameLoop to play the animation
      let loop = GameLoop({
        update: function(dt) {
          sprite.update();
        },
        render: function() {
          sprite.render();
        }
      });

      loop.start();
    };

## Custom Properties #

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.

    let { Sprite } = kontra

    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();
      }
    });

    sprite.render();

    import { Sprite } from 'path/to/kontra.mjs'

    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();
      }
    });

    sprite.render();

    import { Sprite } from 'kontra';

    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();
      }
    });

    sprite.render();

## Extending a Sprite #

If you want to extend a Sprite, you can do so by extending the Sprite class. The one caveat is that `Sprite` is not the Sprite class, but actually is a factory function.

To extend the Sprite class, use the `.class` property of the constructor.

    let { Sprite } = kontra;

    class CustomSprite extends Sprite.class {
      // ...
    }

    import { Sprite } from 'path/to/kontra.mjs';

    class CustomSprite extends Sprite.class {
      // ...
    }

    import { Sprite } from 'kontra';

    class CustomSprite extends Sprite.class {
      // ...
    }

## Sprite​.acceleration #

The sprites acceleration vector.

## Sprite​.advance(​[dt]) #

Move the sprite by its acceleration and velocity. If the sprite is an animation sprite, it also advances the animation every frame.

If you override the sprites update() function with your own update function, you can call this function to move the sprite normally.

    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 < 0  or  or
            this.x - this.width > this.context.canvas.width) {
          this.dx = -this.dx;
        }
        if (this.y < 0  or  or
            this.y - this.height > this.context.canvas.height) {
          this.dy = -this.dy;
        }
      }
    });

    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 < 0  or  or
            this.x - this.width > this.context.canvas.width) {
          this.dx = -this.dx;
        }
        if (this.y < 0  or  or
            this.y - this.height > this.context.canvas.height) {
          this.dy = -this.dy;
        }
      }
    });

    import { Sprite } from '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 < 0  or  or
            this.x - this.width > this.context.canvas.width) {
          this.dx = -this.dx;
        }
        if (this.y < 0  or  or
            this.y - this.height > this.context.canvas.height) {
          this.dy = -this.dy;
        }
      }
    });

### advance Parameters

`dt` Optional

  Number. Time since last update.

## Sprite​.anchor #

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.

    let { Sprite } = kontra

    let sprite = Sprite({
      x: 150,
      y: 100,
      color: 'red',
      width: 50,
      height: 50,
      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();

    import { Sprite } from 'path/to/kontra.mjs'

    let sprite = Sprite({
      x: 150,
      y: 100,
      color: 'red',
      width: 50,
      height: 50,
      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();

    import { Sprite } from 'kontra';

    let sprite = Sprite({
      x: 150,
      y: 100,
      color: 'red',
      width: 50,
      height: 50,
      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();

## Sprite​.animations #

An object of Animations from a SpriteSheet to animate the sprite. Each animation is named so that it can can be used by name for the sprites playAnimation() function.

    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('idle');

    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('idle');

    import { Sprite, SpriteSheet } from '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('idle');

## Sprite​.collidesWith(​object) #

Check if the sprite collide with the object. Uses a simple Axis-Aligned Bounding Box (AABB) collision check. Takes into account the sprites anchor.

NOTE: Does not take into account sprite rotation. If you need collision detection between rotated sprites you will need to implement your own `collidesWith()` function. I suggest looking at the Separate Axis Theorem.

    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);  //=> false

    sprite2.x = 115;

    sprite.collidesWith(sprite2);  //=> true

    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);  //=> false

    sprite2.x = 115;

    sprite.collidesWith(sprite2);  //=> true

    import { Sprite } from '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);  //=> false

    sprite2.x = 115;

    sprite.collidesWith(sprite2);  //=> true

If you need a different type of collision check, you can override this function by passing an argument by the same name.

    // 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 < 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);  //=> true

    // 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 < 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);  //=> true

    // 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 < 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);  //=> true

### collidesWith Parameters

`object`

  Object. Object to check collision against.

### collidesWith Return value

`true` if the objects collide, `false` otherwise. Will return `null` if the either of the two objects are rotated.

## Sprite​.color #

The color of the sprite if it was passed as an argument.

## Sprite​.context #

The context the sprite will draw to.

## Sprite​.currentAnimation #

The currently playing Animation object if `animations` was passed as an argument.

## Sprite​.ddx #

X coordinate of the acceleration vector.

## Sprite​.ddy #

Y coordinate of the acceleration vector.

## Sprite​.draw(​) #

Draw the sprite at its X and Y position. This function changes based on the type of the sprite. For a rectangle sprite, it uses `context.fillRect()`, for an image sprite it uses `context.drawImage()`, and for an animation sprite it uses the currentAnimation `render()` function.

If you override the sprites `render()` function with your own render function, you can call this function to draw the sprite normally.

    let { Sprite } = kontra;

    let sprite = Sprite({
     x: 290,
     y: 80,
     color: 'red',
     width: 20,
     height: 40,

     render: function() {
       // draw the rectangle sprite normally
       this.draw();

       // outline the sprite
       this.context.strokeStyle = 'yellow';
       this.context.lineWidth = 2;
       this.context.strokeRect(this.x, this.y, this.width, this.height);
     }
    });

    sprite.render();

    import { Sprite } from 'path/to/kontra.mjs';

    let sprite = Sprite({
     x: 290,
     y: 80,
     color: 'red',
     width: 20,
     height: 40,

     render: function() {
       // draw the rectangle sprite normally
       this.draw();

       // outline the sprite
       this.context.strokeStyle = 'yellow';
       this.context.lineWidth = 2;
       this.context.strokeRect(this.x, this.y, this.width, this.height);
     }
    });

    sprite.render();

    import { Sprite } from 'kontra';

    let sprite = Sprite({
     x: 290,
     y: 80,
     color: 'red',
     width: 20,
     height: 40,

     render: function() {
       // draw the rectangle sprite normally
       this.draw();

       // outline the sprite
       this.context.strokeStyle = 'yellow';
       this.context.lineWidth = 2;
       this.context.strokeRect(this.x, this.y, this.width, this.height);
     }
    });

    sprite.render();

## Sprite​.dx #

X coordinate of the velocity vector.

## Sprite​.dy #

Y coordinate of the velocity vector.

## Sprite​.height #

The height of the sprite. If the sprite is a rectangle sprite, it uses the passed in value. For an image sprite it is the height of the image. And for an animation sprite it is the height of a single frame of the animation.

## Sprite​.image #

The image the sprite will use when drawn if passed as an argument.

## Sprite​.init(​properties) #

Use this function to reinitialize a sprite. It takes the same properties object as the constructor. Useful it you want to repurpose a sprite.

### init Parameters

`properties`

  Object. Properties of the sprite.

## Sprite​.isAlive(​) #

Check if the sprite is alive. Primarily used by Pool to know when to recycle an object.

### isAlive Return value

`true` if the sprites ttl property is above `0`, `false` otherwise.

## Sprite​.playAnimation(​name) #

Set the currently playing animation of an animation sprite.

    let { Sprite, SpriteSheet } = kontra;

    let spriteSheet = SpriteSheet({
      // ...
      animations: {
        idle: {
          frames: 1
        },
        walk: {
          frames: [1,2,3]
        }
      }
    });

    let sprite = Sprite({
      x: 100,
      y: 200,
      animations: spriteSheet.animations
    });

    sprite.playAnimation('idle');

    import { Sprite, SpriteSheet } from 'path/to/kontra.mjs';

    let spriteSheet = SpriteSheet({
      // ...
      animations: {
        idle: {
          frames: 1
        },
        walk: {
          frames: [1,2,3]
        }
      }
    });

    let sprite = Sprite({
      x: 100,
      y: 200,
      animations: spriteSheet.animations
    });

    sprite.playAnimation('idle');

    import { Sprite, SpriteSheet } from 'kontra';

    let spriteSheet = SpriteSheet({
      // ...
      animations: {
        idle: {
          frames: 1
        },
        walk: {
          frames: [1,2,3]
        }
      }
    });

    let sprite = Sprite({
      x: 100,
      y: 200,
      animations: spriteSheet.animations
    });

    sprite.playAnimation('idle');

### playAnimation Parameters

`name`

  String. Name of the animation to play.

## Sprite​.position #

The sprites position vector.

## Sprite​.render(​) #

Render the sprite. Calls the sprites draw() function.

## Sprite​.rotation #

The rotation of the sprite around the origin in radians.

## Sprite​.ttl #

How may frames the sprite should be alive. Primarily used by Pool to know when to recycle an object.

## Sprite​.update(​[dt]) #

Update the sprites position based on its velocity and acceleration. Calls the sprites advance() function.

### update Parameters

`dt` Optional

  Number. Time since last update.

## Sprite​.velocity #

The sprites velocity vector.

## Sprite​.width #

The width of the sprite. If the sprite is a rectangle sprite, it uses the passed in value. For an image sprite it is the width of the image. And for an animation sprite it is the width of a single frame of the animation.

## Sprite​.x #

X coordinate of the position vector.

## Sprite​.y #

Y coordinate of the position vector.