npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

pixi-game-camera

v1.0.2

Published

A flexible and non-opinionated way to add camera effects to your PIXI application via containers.

Downloads

18

Readme

NPM version Known Vulnerabilities npm NPM downloads Gitter

pixi-game-camera allows you to apply camera effects to any PIXI Container without requiring you to use PIXI in any certain way. PIXI is not bundled with this package resulting in a small file size but it also means that some effects need you to pass PIXI components to them.

Table of Contents

Installation

To install pixi-game-camera, use:

$ npm install pixi-game-camera

or you can use the script from unpkg like so:

<script type="module" src="https://unpkg.com/pixi-game-camera@latest/pixi-game-camera.js"></script>

Importing

Each part and effect of pixi-game-camera is exported on its own so you can import just the effects you need. Below is an example of importing all parts (so far) of pixi-game-camera:

import {
  Fade,
  PanTo,
  Shake,
  Rotate,
  ZoomTo,
  Camera,
} from './pixi-game-camera.js';

The Camera object is necessary to be instantiated in order to use the effects so the first thing you would do is initialize that:

const camera = new Camera();

When initializing pixi-game-camera, you can also pass in the following options:

| param | type | description | default | |---------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------| | ticker | PIXI.Ticker | A reference to the PIXI ticker if it's being used. If you are not using the ticker and instead just using a custom loop with requestAnimationFrame then the app will call its own internal game loop and remove it as necessary to run the camera effects. | |

Example:

// 1. Using PIXI ticker from a basic setup.
const app = new PIXI.Application({ width: 500, height: 300 });

const options = {
  ticker: app.ticker
};

const camera = new Camera(options);

// 2. Using requestAnimationFrame.
const renderer = new PIXI.Renderer({ width: 500, height: 300 });

const camera = new Camera();

Effects

Once you've created a camera, you can use the following effects. Each effect has to be initialized with its properties before it can be passed to the camera to be used. All of the effects assume a camera has been made with the name of camera.

Note: Some of the effects can take an easing function as their last parameter. To keep file size low, only a default linear ease has been included to be used when no easing function is passed to these effects. If you would like to use a different easing function you can pass in any function that takes a single number as a parameter such as the easings from d3-ease or from easings.net. Also note that the effects will affect timing and pixi-game-camera will do its best to make sure that the effect finishes at the specified duration but easings like bounce can affect the accuracy of that.

Shake

Causes the container to shake for a specified amount of time and for a certain duration.

| param | type | description | default | |------------|-----------------|------------------------------------------------------------------------|----------| | container | PIXI.Container | The container to apply the shake effect to. | | | intensity | number | The intensity of the shake with 1 being lowest and 10 being highest. | 5 | | duration | number | The amount of time, in milliseconds, that this effect should last for. | Infinity |

example:

// Shake the main container at an intensity of 3 for 5 seconds.
const mildShake = new Shake(app.stage, 3, 5000);
camera.effect(mildShake);

// Shake a sub container at an intensity of 10 for 2 seconds.
const intenseShake = new Shake(container2, 10, 2000);
camera.effect(intenseShake);

ZoomTo

Zooms in or out on a container with an optional easing.

| param | type | description | default | |------------|----------|---------------------------------------------------------------------------------------------------------------------------|------------| | container | PIXI.Container | The container to apply the zoom effect to. | | | xZoomLevel | number | The zoom level to zoom horizontally with values larger than 1 being zoomed in and values smaller than 1 being zoomed out. | | | yZoomLevel | number | The zoom level to zoom vertically with values larger than 1 being zoomed in and values smaller than 1 being zoomed out. | | | duration | number | The amount of time it should take for the zoom to complete. | | | easing | Function | The easing function to apply to the zoom. | easeLinear |

example:

// Zoom in on the container at 2x over 5 seconds with the default linear ease.
const zoomIn = new ZoomTo(app.stage, 2, 2, 5000);
camera.effect(zoomIn);

// Zoom in at 2x horizontally and 1.5x vertically over 3 seconds with a bouncing effect.
import { easeBounceIn } from 'd3-ease';

const zoomMixed = new ZoomTo(app.stage 2, 1.5, 3000, easeBounceIn);
camera.effect(zoomMixed);

PanTo

Pans to a specific location on the container with an optional easing.

| param | type | description | default | |-----------|----------------|------------------------------------------------------------|------------| | container | PIXI.Container | The container to apply the PanTo effect to. | | | x | number | The x coordinate of the location to pan to. | | | y | number | The y coordinate of the location to pan to. | | | duration | number | The amount of time it should take for the pan to complete. | | | easing | Function | The easing function to apply to the pan. | easeLinear |

example:

// Pan to (200, 250) over 5 seconds.
const panToCenter = new PanTo(app.stage, 200, 250, 5000);
camera.effect(panToCenter);

// Pan to (1050, 870) over 3 seconds with a cubic easing.
import { easeCubicIn } from 'd3-ease';

const panToBottomRight = new PanTo(1050, 870, 3000, easeCubicIn);
camera.effect(panToBottomRight);

Fade

Fades in or out to a specified opacity of a color with an optional easing. This effect requires a PIXI.Sprite with a white texture to be passed to it.

| param | type | description | default | |-----------|----------------|----------------------------------------------------------------------------|------------| | container | PIXI.Container | The container to apply the fade effect to. | | | sprite | PIXI.Sprite | The sprite with a white texture to be used for the fade effect | | | color | number | The hex of the color to fade in or out of. | | | opacity | number | The opacity to fade to with 1 being fully to the color and 0 being opaque. | | | duration | number | The amount of time it should take for the fade to complete. | | | easing | Function | The easing function to apply to the fade. | easeLinear |

example:

// Fade to black over 5 seconds with the default linear easing.
const fadeToBlack = new FadeTo(app.stage, new PIXI.Sprite(PIXI.Texture.WHITE), 0x000000, 1, 5000);
camera.effect(fadeToBlack);

// Fade to mostly blue over 3 seconds with a cubic easing.
import { easeCubicIn } from 'd3-ease';

const fadeToBlue = new FadeTo(app.stage, new PIXI.Sprite(PIXI.Texture.WHITE), 0x337ab7, 0.7, 3000, easeCubicIn);
camera.effect(fadeToBlue);

rotate

Rotates to a specified angle with an optional easing.

| param | type | description | default | |----------|----------|----------------------------------------------------------------------------------------------------------------------------------|------------| | container | PIXI.Container | The container to apply the rotate effect to. | | | angle | number | The angle to rotate to, from 0 to 360 with 0 being the default state and 360 being all the way around back to the default state. | | | duration | number | The amount of time it should take for the rotation to complete. | | | easing | Function | The easing function to apply to the rotation. | easeLinear |

example:

// Rotate to 45 degrees in 3 seconds with the default linear easing.
const rotate45Deg = new Rotate(app.stage, 45, 3000);
camera.effect(rotate45Deg);

// Rotate to 365 degrees in 5 seconds with a cubic easing.
import { easeCubicIn } from 'd3-ease';

const rotate365Deg = new Rotate(app.stage, 365, 5000, easeCubicIn);
camera.effect(rotate365Deg);

Creating Your Own Effects

Creating your own effects can be done by extending the Effect abstract class. Let's go through the step-by-step process of creating an effect that shakes the camera (essentially going over how the Shake method is created).

  1. First, you have to import the Effect module and extend your class with it like so:
import { Effect } from 'pixi-game-camera';

export class MyCustomShake extends Effect {
}
  1. Let's see the values we need for this effect.

We need the following private variables to keep track of the animation:

  • The intensity of the shake, from a scale of 1-10.
  • The initial pivot of the container so we can reset the pivot after the shake effect is complete.

The reference to the container and other time keeping properties are handld by the Effect parent class.

Now as far as user input, we need the following things:

  • The container to apply the shake effect to.
  • The intensity of the shake effect.
  • The length of time the shake effect should last for.

So now let's see what our custom effect class looks like now:

/**
 * A Shake effect involves shaking the camera at various amounts up to a sepcified intensity.
 */
export class MyCustomShake extends Effect {
  /**
   * The intensity of the shake, from 1-10.
   * 
   * @private
   * 
   * @property {number}
   * 
   * @default 5
   */
  private _intensity = 5;

  /**
   * A reference to the initial pivot of the container.
   * 
   * @private
   * 
   * @property {Vector}
   */
  private _initialPivot: Vector;

  /**
   * @param {Container} container A reference to the container to apply the shake effect to.
   * @param {number} intensity The intensity of the shake, from a scale of 1 to 10.
   * @param {number} duration The duration of the shake effect.
   */
  constructor(container: PIXI.Container, intensity: number, duration: number) {
    super(container);

    this._intensity = intensity;
    this.duration = duration;
    this._initialPivot = { x: this.container.pivot.x, y: this.container.pivot.y };

    this.started = performance.now();
  }
}

What we do above is keep track of the intensity and duration like we discussed earlier and also set the started property that's on the Effect class to the current time.

  1. Next we need to override the update and criteriaMet abstract methods of the Effect class.

The update method is called every frame and it'll check to see if the effect is complete and if so it dispatches the finished signal which is used by the Effect class to cancel the game loop. If the effect is not finished then we need to specify what needs to be done this frame.

The criteraMet method has to return a boolean which represents whether the effect has finished or not.

For our example, we'll use the update method to check if the effect is complete and if so we reset the container's pivot and dispatch the finished signal. Otherwise, we pick a random value to apply to the container's pivot to create a shaking effect and then if a PIXI.Ticker isn't being used we have to call requestAnimationFrame on update again to keep the shake effect going. The criteriaMet method simply checks to see if the current time - the time we started the effect at, which exists on the Effect class, is greater than or equal to the desired effect duration which would indicate that the effect is complete.

/**
 * Updates the status of the shake.
 */
update() {
  if (this.criteriaMet()) {
    this.container.pivot.x = this._initialPivot.x;
    this.container.pivot.y = this._initialPivot.y;

    this.finished.dispatch();
    return;
  }

  this.current = performance.now();

  const dx = Math.random() * this._intensity;
  const dy = Math.random() * this._intensity;

  this.container.pivot.x = dx;
  this.container.pivot.y = dy;

  if (this.useRAF) this.id = requestAnimationFrame(() => this.update());
}

/**
 * Checks to see if the shake effect is done.
 * 
 * @returns {boolean} Returns true if the shake effect is done or not.
 */
criteriaMet(): boolean {
  if (this.current - this.started >= this.duration) return true;
  return false;
}

Lastly we just create an instance of our effect and add it to the camera:

const customShake = new MyCustomShake(app.stage, 5, 5000);
camera.effect(customShake);

That's it! The Effect class will handle the logic of the game loop and what not. If you would like a more complex example that involves easing just check out the Rotate or ZoomTo effect which will look largely similar to this example but a bit more complicated. All of the effects have a similar structure which makes it easy to understand effects and create new ones.

If you create any cool effects make sure to create a pull request and I'll gladly add them.

Tests

The tests for pixi-game-camera are browser based so to run them you need to first run:

$ npm run test

Which starts up a local server at localhost:3000 and if you navigate to it you can see all of the effects being tested.

License

MIT