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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@mode-7/zap

v0.2.2

Published

Lightweight gesture-first 2D game engine for interactive demos and playable ads

Downloads

315

Readme

@mode-7/zap

A lightweight, gesture-first 2D game engine for creating interactive demos and playable ads. Built with TypeScript, designed for simplicity and small bundle sizes.

Perfect for: word games, match-3 games, card games, swipe mechanics, and interactive demos where touch/mouse interactions matter more than physics or AI.

Features

  • Gesture-First Design - Built-in tap, swipe, drag, and long-press recognition
  • Smooth Animations - Powerful tweening system with 37 easing functions
  • Image Support - Load remote images with automatic sizing and CORS support
  • Google Fonts Integration - Dynamically load any Google Font
  • Collision Detection - Automatic AABB collision system with events
  • Audio System - Sound effects and music with volume control
  • Camera Controls - Follow entities, zoom, and shake effects
  • Responsive Design - Automatic canvas scaling for any screen size
  • Scene Management - Scene transitions, backgrounds, and lifecycle hooks
  • Particle Effects - Emitters and burst particles for visual polish
  • UI Components - Button, NinePatch panels, touch trails
  • Layout Helpers - Grid, circle, row/column positioning utilities
  • Timer Utilities - Delay and interval with automatic cleanup
  • Storage API - LocalStorage wrapper for saving game data
  • Math Utilities - clamp, lerp, random, distance, angle calculations
  • Lightweight - Zero dependencies, tree-shakeable, ~15KB minified + gzipped
  • TypeScript Native - Full type safety and IntelliSense support

Installation

npm install @mode-7/zap

Quick Start

import { Game, Scene, Sprite } from '@mode-7/zap';

// Create a game
const game = new Game({
  width: 800,
  height: 600,
  backgroundColor: '#0f3460'
});

// Create a scene
const scene = new Scene();

// Create an interactive card
const card = new Sprite({
  x: 400,
  y: 300,
  width: 100,
  height: 140,
  color: '#e94560',
  radius: 8,
  interactive: true,
});

// Add tap interaction
card.on('tap', () => {
  card.tween(
    { rotation: Math.PI, scaleX: 1.2, scaleY: 1.2 },
    { duration: 300, easing: 'easeOutBack' }
  );
});

// Add to scene and start
scene.add(card);
game.setScene(scene);
game.start();

Core Concepts

Game

The main game instance manages the canvas, game loop, and scenes.

const game = new Game({
  width: 800,
  height: 600,
  backgroundColor: '#000000',
  parent: '#game-container', // Optional: selector or element
  responsive: true, // Optional: auto-scale to fit screen
  pixelRatio: 2, // Optional: defaults to window.devicePixelRatio
  antialias: true, // Optional: defaults to true
  enableTouchTrail: true, // Optional: visual touch/mouse trail
});

game.start(); // Start the game loop
game.stop(); // Stop the game loop
game.setScene(scene); // Switch to a different scene

Scene

Scenes contain and manage entities. Use scenes for different game states (menu, gameplay, game over).

const scene = new Scene({
  backgroundColor: '#0f3460', // Optional: solid background color
  backgroundImage: 'assets/bg.png', // Optional: image background
});

scene.add(entity); // Add an entity
scene.remove(entity); // Remove an entity
scene.getEntities(); // Get all entities
scene.getEntitiesByTag('enemy'); // Get entities by tag

// Lifecycle hooks
scene.on('enter', () => console.log('Scene entered'));
scene.on('exit', () => console.log('Scene exited'));

Entities

Base class for all game objects. Entities support transform hierarchy, tags, and events.

import { Entity } from '@mode-7/zap';

const entity = new Entity({
  x: 100,
  y: 100,
  rotation: 0,
  scaleX: 1,
  scaleY: 1,
  alpha: 1,
  width: 50,
  height: 50,
  anchorX: 0.5, // 0-1, default 0.5 (center)
  anchorY: 0.5,
  interactive: false,
  visible: true,
});

// Transform hierarchy
entity.addChild(childEntity);
entity.removeChild(childEntity);

// Tags for grouping
entity.addTag('enemy');
entity.hasTag('enemy');

// Position
entity.getWorldPosition(); // Get absolute position
entity.containsPoint(x, y); // Check if point is inside entity

Sprite

Visual entity for rendering images or colored shapes.

import { Sprite } from '@mode-7/zap';

// Colored rectangle
const rect = new Sprite({
  x: 100,
  y: 100,
  width: 100,
  height: 100,
  color: '#ff0000',
  radius: 10, // Rounded corners
});

// Image sprite (supports remote URLs!)
const sprite = new Sprite({
  x: 200,
  y: 200,
  width: 64,
  height: 64,
  image: 'https://example.com/image.png', // Auto-loads
  radius: 32 // Optional: circular crop
});

// Listen for image load
sprite.on('imageload', (img) => {
  console.log('Image loaded:', img.width, img.height);
});

// Or load manually
await sprite.loadImage('path/to/image.png');

Text

Text rendering entity with Google Fonts support.

import { Text, loadGoogleFont } from '@mode-7/zap';

// Load a Google Font first
await loadGoogleFont('Poppins', [400, 700]);

const text = new Text({
  text: 'Hello World',
  x: 400,
  y: 300,
  fontSize: 32,
  fontFamily: 'Poppins, sans-serif', // Use loaded font
  color: '#ffffff',
  align: 'center', // 'left' | 'center' | 'right'
  baseline: 'middle', // 'top' | 'middle' | 'bottom' | 'alphabetic'
});

// Load multiple fonts at once
import { loadGoogleFonts } from '@mode-7/zap';

await loadGoogleFonts([
  { family: 'Roboto', weights: [400, 700] },
  { family: 'Montserrat', weights: [600] }
]);

Gestures

Zap includes powerful gesture recognition out of the box.

Available Gestures

  • tap - Quick touch/click
  • longpress - Press and hold
  • swipe - Fast directional movement
  • drag - Move while pressed
  • dragstart - Drag begins
  • dragend - Drag ends

Using Gestures

const card = new Sprite({
  // ... options
  interactive: true, // Must be true for gestures
});

// Tap
card.on('tap', (event) => {
  console.log('Tapped at', event.position);
});

// Swipe with direction
card.on('swipe', (event) => {
  console.log('Swiped', event.direction); // 'up' | 'down' | 'left' | 'right'
  console.log('Velocity', event.velocity);
  console.log('Distance', event.distance);
});

// Drag
card.on('dragstart', (event) => {
  console.log('Drag started');
});

card.on('drag', (event) => {
  // Move card with drag
  card.x += event.delta.x;
  card.y += event.delta.y;
});

card.on('dragend', (event) => {
  console.log('Drag ended');
});

// Long press
card.on('longpress', (event) => {
  console.log('Long press detected');
});

Animations

Smooth, easy-to-use tweening system.

// Simple tween
entity.tween(
  { x: 400, y: 300, rotation: Math.PI },
  { duration: 1000, easing: 'easeOutQuad' }
);

// With callbacks
entity.tween(
  { alpha: 0 },
  {
    duration: 500,
    delay: 200,
    easing: 'easeInOutQuad',
    onUpdate: (progress) => {
      console.log('Progress:', progress);
    },
    onComplete: () => {
      console.log('Animation complete!');
      entity.destroy();
    }
  }
);

Easing Functions

Available easing functions:

  • linear
  • easeIn, easeOut, easeInOut (shortcuts for Quad)
  • easeInQuad, easeOutQuad, easeInOutQuad
  • easeInCubic, easeOutCubic, easeInOutCubic
  • easeInQuart, easeOutQuart, easeInOutQuart
  • easeInQuint, easeOutQuint, easeInOutQuint
  • easeInSine, easeOutSine, easeInOutSine
  • easeInExpo, easeOutExpo, easeInOutExpo
  • easeInCirc, easeOutCirc, easeInOutCirc
  • easeInBack, easeOutBack, easeInOutBack
  • easeInElastic, easeOutElastic, easeInOutElastic
  • easeInBounce, easeOutBounce, easeInOutBounce

You can also pass custom easing functions:

entity.tween(
  { x: 400 },
  {
    duration: 1000,
    easing: (t) => t * t * t // Custom cubic easing
  }
);

Particles

Add visual polish with particles.

import { ParticleEmitter } from '@mode-7/zap';

const emitter = new ParticleEmitter({
  x: 400,
  y: 300,
  rate: 20, // Particles per second
  colors: ['#ff0000', '#00ff00', '#0000ff'],
  sizeRange: { min: 2, max: 6 },
  lifetimeRange: { min: 0.5, max: 1.5 },
  velocityRange: {
    min: { x: -100, y: -100 },
    max: { x: 100, y: 100 },
  },
});

scene.add(emitter);

// Or burst particles all at once
emitter.burst(50);

Layout Helpers

Utilities for positioning entities.

import { Layout } from '@mode-7/zap';

// Grid layout
Layout.layoutGrid(entities, {
  columns: 3,
  rows: 3,
  cellWidth: 100,
  cellHeight: 100,
  spacing: 10,
  startX: 50,
  startY: 50,
});

// Circle layout
Layout.layoutCircle(entities, centerX, centerY, radius, startAngle);

// Row layout
Layout.layoutRow(entities, startX, y, spacing);

// Column layout
Layout.layoutColumn(entities, x, startY, spacing);

// Center on screen
Layout.center(entity, game.width, game.height);

Utility Functions

import { Layout } from '@mode-7/zap';

// Math utilities
Layout.clamp(value, min, max);
Layout.lerp(start, end, t);
Layout.map(value, inMin, inMax, outMin, outMax);

// Random utilities
Layout.randomInt(min, max);
Layout.randomFloat(min, max);
Layout.randomItem(array);

Collision Detection

Advanced collision system with automatic event-driven detection and physics response.

Features:

  • Continuous Collision Detection (CCD) - Prevents tunneling at high speeds
  • SAT for rotated rectangles - Accurate collision for rotated objects
  • Symmetric detection - Both entities receive events regardless of order
  • Circle and rectangle collision - Automatic shape detection
  • Physics integration - Automatic separation and bounce response
// Enable collision detection on an entity
const player = new Sprite({
  x: 100, y: 100,
  width: 50, height: 50,
  checkCollisions: true, // Enable automatic collision checking
  collisionTags: ['enemy', 'coin'], // Only collide with these tags
  bounciness: 0.8, // Optional: bounce energy retention
  static: false, // Dynamic object (can move)
});

const wall = new Sprite({
  x: 400, y: 300,
  width: 20, height: 600,
  checkCollisions: true,
  static: true, // Static object (immovable)
});

// Listen for collision events
player.on('collisionenter', (event) => {
  console.log('Hit:', event.other);
  if (event.other.hasTag('coin')) {
    score += 10;
    event.other.destroy();
  }
});

player.on('collide', (event) => {
  // Fires every frame while colliding
  console.log('Still colliding with:', event.other);
});

player.on('collisionexit', (event) => {
  console.log('Stopped colliding with:', event.other);
});

// Manual collision checks
if (entity1.intersects(entity2)) {
  console.log('Entities overlap');
}

// Utility methods
entity.distanceTo(other);     // Distance between entities
entity.getBounds();           // { left, right, top, bottom }
entity.containsPoint(x, y);   // Check if point is inside

Physics

Realistic physics simulation with velocity, gravity, friction, and force application.

const ball = new Sprite({
  x: 200, y: 100,
  width: 30, height: 30,
  radius: 15,
  vx: 100,        // Horizontal velocity (pixels/sec)
  vy: 0,          // Vertical velocity (pixels/sec)
  gravity: 980,   // Gravity acceleration (pixels/sec²)
  friction: 0.99, // Velocity decay (0-1)
  bounciness: 0.8,// Bounce energy retention
  mass: 1,        // Mass for force calculations
  checkCollisions: true,
});

// Apply forces (F=ma physics)
ball.applyForce(500, -1000); // Push right and up

scene.on('update', () => {
  // Continuous force application
  if (keys['arrowleft']) ball.applyForce(-800, 0);
  if (keys['arrowright']) ball.applyForce(800, 0);
});

// Bounce off surfaces
ball.bounce(normalX, normalY, restitution);

Asset Loading

Simple asset loading and caching.

import { assetLoader } from '@mode-7/zap';

// Load single image (supports remote URLs)
await assetLoader.loadImage('player', 'https://example.com/player.png');

// Load multiple images
await assetLoader.loadImages({
  player: 'assets/player.png',
  enemy: 'assets/enemy.png',
  background: 'https://cdn.example.com/bg.png', // Remote URLs work!
});

// Get loaded image
const playerImg = assetLoader.getImage('player');

// Use with sprite
const sprite = new Sprite({
  image: assetLoader.getImage('player'),
  width: 64,
  height: 64,
});

Audio

Play sound effects and music with the built-in audio system.

import { audioManager } from '@mode-7/zap';

// Play a sound effect
audioManager.playSound('coin', 'assets/coin.mp3');

// Play background music (loops automatically)
audioManager.playMusic('assets/music.mp3');

// Control volume (0-1)
audioManager.setMusicVolume(0.5);
audioManager.setSoundVolume(0.8);

// Mute/unmute
audioManager.muteMusic();
audioManager.unmuteMusic();
audioManager.muteSound();
audioManager.unmuteSound();

// Stop music
audioManager.stopMusic();

Camera

Camera controls for following entities, zooming, and screen shake effects.

import { Camera } from '@mode-7/zap';

const camera = new Camera(game.width, game.height);

// Follow an entity
camera.follow(player);

// Zoom
camera.zoom = 2.0; // 2x zoom
camera.zoom = 0.5; // Zoom out

// Screen shake
camera.shake(300, 10); // duration 300ms, intensity 10

// Manual positioning
camera.x = 100;
camera.y = 100;

Timers

Delay and interval utilities with automatic cleanup.

import { delay, interval, wait } from '@mode-7/zap';

// Delay execution
delay(1000, () => {
  console.log('1 second later');
});

// Repeat every interval
const timer = interval(100, () => {
  console.log('Every 100ms');
});

// Stop interval
timer.cancel();

// Wait (returns promise)
await wait(2000);
console.log('2 seconds later');

Storage

LocalStorage wrapper for saving game data.

import { Storage } from '@mode-7/zap';

const storage = new Storage('my-game'); // Prefix for keys

// Save data
storage.set('highScore', 1000);
storage.set('playerName', 'Alice');
storage.set('settings', { music: true, sound: false });

// Load data
const highScore = storage.get('highScore', 0); // Default value: 0
const settings = storage.get('settings', {});

// Check if key exists
if (storage.has('playerName')) {
  console.log('Player name saved');
}

// Remove data
storage.remove('highScore');

// Clear all
storage.clear();

Documentation & Examples

Visit the Interactive Documentation with runnable examples:

  • 📚 Complete API documentation
  • ⚡ 31 interactive guides with code examples
  • 🎮 Live playground with AI-powered code generation
  • 📖 Searchable documentation index
  • 💡 Copy-paste ready code snippets

For AI Assistants: Documentation index at https://mode7labs.github.io/zap/docs/api-docs.json

Run locally:

npm run docs

Bundle Size

Zap is designed to be lightweight:

  • Core library: ~15KB minified + gzipped
  • Zero dependencies
  • Tree-shakeable - only import what you use

Browser Support

  • Modern browsers with ES2020 support
  • Chrome, Firefox, Safari, Edge
  • Mobile browsers (iOS Safari, Chrome Mobile)

TypeScript

Zap is written in TypeScript and includes full type definitions. No need for @types packages!

import type { GameOptions, Entity, GestureEvent } from '@mode-7/zap';

License

MIT

Contributing

Contributions welcome! Please open an issue or PR on GitHub.


Made with care for interactive demos and playable ads.