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 🙏

© 2026 – Pkg Stats / Ryan Hefner

zimporter-phaser

v1.0.59

Published

A TypeScript library for importing and managing zStudio scenes in Phaser applications.

Readme

zImporter

The zImporter is a TypeScript package designed to import and manage graphical hierarchies created in zStudio. This package allows seamless integration of assets and scenes built in zStudio into your JavaScript or TypeScript-based projects, particularly those using Phaser.

Features

  • Import and manage scenes and graphical hierarchies from zStudio

  • Works with Phaser to display and interact with imported assets

  • Provides a flexible and easy-to-use API for handling assets and scenes.

  • Download zStudios to get started: https://zstudiosltd.com/

Installation

To install the zImporter package from the npm registry:

npm install [email protected]

Or to always get the latest version:

npm install zimporter-phaser@latest

Note: Your tsconfig.json should include:

"module": "ESNext",
"moduleResolution": "bundler"

HTML Setup

To use zImporter in a browser (without a bundler), include the following scripts in your HTML file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>zImporter Phaser Example</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js"></script>
    <!-- Load your compiled zImporter bundle -->
    <script src="./dist/zimporter-phaser.min.js"></script>
    <!-- Spine plugin for Phaser -->
    <script src="./node_modules/@esotericsoftware/spine-phaser/dist/iife/spine-phaser.js"></script>
    <style>
        body { margin: 0; overflow: hidden; }
        #game-container { width: 100vw; height: 100vh; }
    </style>
</head>
<body>
    <div id="game-container"></div>
    <script>
        // All zImporter classes are available under the `zimporter` global namespace:
        // zimporter.ZScene, zimporter.ZTimeline, zimporter.ZUpdatables, etc.

        const sceneJsonPath = './assets/myScene/';

        class MyPhaserScene extends Phaser.Scene {
            create() {
                zimporter.ZUpdatables.init(24);
                this._frameCount = 0;
                this._lastTime = performance.now();
                this._fpsText = this.add.text(10, 10, 'FPS: --', {
                    fontSize: '16px', fill: '#ffffff'
                }).setDepth(9999);

                this.zScene = new zimporter.ZScene('testScene', this);
                this.zScene.load(sceneJsonPath, () => {
                    this.zScene.loadStage(this);

                    const stage = this.zScene.sceneStage;
                    for (const child of stage.list) {
                        if (child instanceof zimporter.ZTimeline) {
                            child.play();
                        }
                    }
                });
            }

            update(time, delta) {
                this._frameCount++;
                const now = performance.now();
                const elapsed = now - this._lastTime;
                if (elapsed >= 1000) {
                    const fps = (this._frameCount / elapsed) * 1000;
                    this._fpsText.setText(`FPS: ${fps.toFixed(1)}`);
                    this._frameCount = 0;
                    this._lastTime = now;
                }
                zimporter.ZUpdatables.update();
            }
        }

        const config = {
            type: Phaser.AUTO,
            width: window.innerWidth,
            height: window.innerHeight,
            parent: 'game-container',
            scene: [MyPhaserScene],
            backgroundColor: '#000000',
            scale: {
                mode: Phaser.Scale.RESIZE,
                autoCenter: Phaser.Scale.CENTER_BOTH
            },
            plugins: {
                scene: [{
                    key: 'SpinePlugin',
                    plugin: spine.SpinePlugin,
                    mapping: 'spine'
                }]
            }
        };

        const game = new Phaser.Game(config);

        window.addEventListener('resize', () => {
            const scene = game.scene.scenes[0];
            if (scene && scene.zScene) {
                scene.zScene.resize(window.innerWidth, window.innerHeight);
            }
        });
    </script>
</body>
</html>

Building

npm run package

Usage

Importing zImporter into Your Project

You can find an example project here: https://github.com/yonnyzohar/zImporter_Phaser_Example

Basic import:

import { ZTimeline } from 'zimporter-phaser';

Example: Creating a New Phaser Game

import Phaser from 'phaser';
import * as spine from '@esotericsoftware/spine-phaser';
import { ZScene, ZTimeline, ZUpdatables } from 'zimporter-phaser';

const sceneJsonPath = './assets/myScene/';

class GameScene extends Phaser.Scene {
  private zScene!: ZScene;
  private _frameCount = 0;
  private _lastTime = 0;
  private _fpsText!: Phaser.GameObjects.Text;

  preload() {
    // Optionally preload assets here
  }

  create() {
    ZUpdatables.init(24);

    // Optional FPS display
    this._lastTime = performance.now();
    this._fpsText = this.add.text(10, 10, 'FPS: --', {
      fontSize: '16px',
      color: '#ffffff'
    }).setDepth(9999);

    // Load the zStudio scene
    this.zScene = new ZScene('testScene', this);
    this.zScene.load(sceneJsonPath, () => {
      this.zScene.loadStage(this);

      // Play any top-level timelines
      const stage = this.zScene.sceneStage;
      for (const child of stage.list) {
        if (child instanceof ZTimeline) {
          child.play();
        }
      }
    });
  }

  update(time: number, delta: number) {
    // FPS counter
    this._frameCount++;
    const now = performance.now();
    const elapsed = now - this._lastTime;
    if (elapsed >= 1000) {
      const fps = (this._frameCount / elapsed) * 1000;
      this._fpsText.setText(`FPS: ${fps.toFixed(1)}`);
      this._frameCount = 0;
      this._lastTime = now;
    }

    // delta is in ms — advance all registered updatables (timelines, etc.)
    ZUpdatables.update();
  }
}

const config: Phaser.Types.Core.GameConfig = {
  type: Phaser.AUTO,
  width: window.innerWidth,
  height: window.innerHeight,
  parent: 'game-container',
  backgroundColor: '#000000',
  scene: [GameScene],
  scale: {
    mode: Phaser.Scale.RESIZE,
    autoCenter: Phaser.Scale.CENTER_BOTH
  },
  plugins: {
    scene: [{
      key: 'SpinePlugin',
      plugin: spine.SpinePlugin,
      mapping: 'spine'
    }]
  }
};

const game = new Phaser.Game(config);

// Handle window resize
window.addEventListener('resize', () => {
  const scene = game.scene.scenes[0] as any;
  if (scene?.zScene) {
    scene.zScene.resize(window.innerWidth, window.innerHeight);
  }
});

This sets up a Phaser game and integrates zImporter's update system.

Example: Loading a Stage Created in zStudio

// Inside your Phaser Scene's create():
const scene = new ZScene('testScene', this);
scene.load('./assets/myScene/', () => {
  scene.loadStage(this);

  // Access spawned objects by name
  const stage = scene.sceneStage;
  const btn = stage.get('myButton') as ZButton;
  if (btn) {
    btn.setCallback(() => console.log('clicked'));
  }
});

API

The package exposes several classes and methods for interacting with imported assets:

ZScene

  • Container for your entire scene.
  • Handles screen resizing.
  • Allows spawning of assets or loading full stages.

ZContainer

  • Core class for all visual elements.

  • Extends Phaser.GameObjects.Container and adds:

    • Anchoring support
    • Orientation data from zStudio
  • Set .resizeable = false to disable responsive behavior.

Working with Text

In ZStudio, texts are always wrapper in a container, and are called "label" by default. If you know a specific container holds a text fields, you can acces it via: getTextField():Phaser.GameObjects.Text | null You can also set a string on the text via the container using: setText(text:string):void

Transform Properties — Orientation-Aware vs Global

ZContainer maintains separate transform data for portrait and landscape orientations. Because of this, position, scale, width, and height must be accessed through ZContainer methods so the values are stored correctly and survive an orientation change:

container.setX(100);
container.setY(200);
container.setScaleX(1.5);
container.setScaleY(1.5);
container.setWidth(300);
container.setHeight(150);

Setting x, y, scaleX, etc. directly on the object will work visually but the values will be overwritten the next time the scene resizes or orientation changes.

Visibility, alpha, and rotation are orientation-independent — they apply to both portrait and landscape at once, so you can set them directly or via their helper methods:

container.setVisible(false);   // hides in both orientations
container.setAlpha(0.5);       // applies to both orientations
container.rotation = Math.PI;  // applies to both orientations

Working with Spine

Spine assets are loaded automatically by the scene. Once the stage is loaded, retrieve the SpineGameObject from any ZContainer using getSpine() and then interact with it through the standard Spine API:

import { SpineGameObject } from '@esotericsoftware/spine-phaser';

const spineContainer = stage.get('mySpineAsset');
const spineObj: SpineGameObject | undefined = spineContainer?.getSpine();

if (spineObj) {
    // Play an animation on track 0, looping
    spineObj.animationState.setAnimation(0, 'run', true);

    // Change the active skin
    spineObj.skeleton.setSkinByName('mySkin');
    spineObj.skeleton.setToSetupPose();

    // Listen for animation completion
    spineObj.animationState.addListener({
        complete: (entry) => {
            console.log('Animation complete:', entry.animation?.name);
        }
    });
}

ZButton

  • Extends ZContainer.

  • Has .enable() / .disable() methods.

  • Supports child containers with special names:

    • upState, downState, overState, disabledState, labelContainer

When these are defined in zStudio, the button works automatically.

ZTimeline

  • Extends ZContainer.

  • Manages frame-based timeline animations.

  • API includes:

    • .play(), .stop()
    • .gotoAndPlay(frameNum), .gotoAndStop(frameNum)
    • .addStateEndEventListener(cb), .removeStateEndEventListener(cb)

ZState

  • Extends ZContainer.
  • Only one child is visible at a time.
  • Use .setState(name: string) to switch visible content.
  • Can contain nested ZTimeline objects.

Contributing

We welcome contributions! To contribute:

  1. Fork the repository.
  2. Create a feature branch.
  3. Submit a pull request.

Please follow the existing code style and add tests where relevant.

License

This project is licensed under the MIT License. See the LICENSE file for details.