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

vivid-tui

v1.0.1

Published

A framework for building TUI games

Downloads

4

Readme

Vivid TUI

A powerful framework for building Terminal User Interface (TUI) games with physics, audio, particles, and more.

Features

  • Physics Engine - Gravity, collisions, forces, and realistic movement
  • Audio System - Music and sound effects with WAV support
  • Particle Effects - Explosions, trails, and customizable visual effects
  • Camera System - Static and following camera modes with smooth tracking
  • Sprite Animations - Frame-based animations with customizable timing
  • Scene Management - Easy scene transitions and lifecycle management
  • Game State - Centralized state management for scores, lives, and progression

Installation

npm install vivid-tui

Quick Start

const { GameEngine } = require('vivid-tui');

const game = new GameEngine({ title: 'My Game' });

const player = game.createEntity(10, 10, 3, 3, {
  style: { fg: 'white', bg: 'blue' },
  content: 'P'
});

game.addGameObject(player);
game.start();

Core Concepts

Game Engine

Create a game instance with optional configuration:

const game = new GameEngine({ 
  title: 'My Game',
  audio: true,      // Enable audio system
  effects: true,    // Enable particle effects
  scenes: true      // Enable scene management
});

Entities

Create game objects with position, size, and styling:

const player = game.createEntity(x, y, width, height, {
  style: { fg: 'white', bg: 'blue' },
  content: 'P',
  hasGravity: true,    // Apply physics
  isStatic: true,      // Static objects don't move
  onCollision: function(other) {
    // Handle collisions
  }
});

Physics System

Gravity and Forces

// Create object with gravity
const ball = game.createEntity(10, 5, 3, 3, {
  hasGravity: true
});

// Apply forces
game.screen.key(['space'], () => {
  ball.applyForce({ x: 0, y: -8 });  // Jump
});

game.screen.key(['left'], () => {
  ball.applyForce({ x: -2, y: 0 });  // Move left
});

Collision Detection

const platform = game.createEntity(5, 13, 20, 2, {
  isStatic: true,
  onCollision: function(other) {
    console.log('Collision detected!');
    // Change appearance on collision
    this.element.style.bg = 'yellow';
  }
});

Camera System

Following Camera

// Set camera to follow an entity
game.setCameraTarget(player);

// Cycle through camera modes
game.screen.key(['c'], () => {
  const newMode = game.cycleCameraMode();
  console.log('Camera mode:', newMode);
});

Camera modes:

  • Static - Fixed camera position
  • Following - Smooth camera tracking

Particle System

Built-in Explosions

game.screen.key(['space'], () => {
  game.createExplosion(x, y);
});

Custom Particle Effects

// Emit custom particles
game.particles.emit(x, y, 20, {
  content: ['○', '●', '◎'],  // Particle characters
  style: { fg: 'cyan' },
  life: 2.0                   // Duration in seconds
});
game.particles.addToScreen(game.screen);

Particle Trails

let trailEnabled = false;

player.update = function(deltaTime) {
  // ... existing update code
  
  if (trailEnabled) {
    game.particles.emit(this.position.x, this.position.y, 2, {
      content: ['.', '·'],
      style: { fg: 'gray' },
      life: 0.5
    });
    game.particles.addToScreen(game.screen);
  }
};

Audio System

Loading Audio

const game = new GameEngine({ audio: true });

// Load music (looping background audio)
await game.loadMusic('background', './assets/music.wav', { 
  loop: true,
  volume: 0.7
});

// Load sound effects
await game.loadSound('explosion', './assets/explosion.wav');
await game.loadSound('beep', './assets/beep.wav');

Playing Audio

// Play music
game.screen.key(['1'], async () => {
  await game.playMusic('background');
});

// Stop music
game.screen.key(['2'], () => {
  game.stopMusic();
});

// Play sound effects
game.screen.key(['3'], () => {
  game.playSound('explosion');
});

// Toggle mute
game.screen.key(['m'], () => {
  const muted = game.audio.toggleMute();
  console.log(muted ? 'Muted' : 'Unmuted');
});

Sprite Animations

Creating Animated Sprites

const walker = game.createSprite(x, y, width, height, {
  frames: ['>O>', '|O|', '<O<', '|O|'],  // Animation frames
  frameDelay: 0.2,                        // Seconds per frame
  style: { fg: 'green', bg: 'black' }
});

// Add custom update logic
walker.onUpdate = function() {
  this.position.x = 5 + Math.sin(Date.now() / 1000) * 10;
};

Game State Management

Setting Up Game State

const { GameEngine, GameState } = require('vivid-tui');

const game = new GameEngine({ title: 'My Game' });
game.gameState = new GameState();

// Initialize state values
game.gameState.set('score', 0);
game.gameState.set('lives', 3);
game.gameState.set('level', 1);

Using Game State

// Get values
const score = game.gameState.get('score');

// Update values
game.gameState.set('score', score + 10);

// Game over state
game.gameState.setGameOver(true);
if (game.gameState.isGameOver) {
  console.log('Game Over!');
}

// Reset state
game.gameState.reset();

HUD Display

const hud = game.createEntity(2, 18, 50, 1, {
  style: { fg: 'white', bg: 'black' },
  content: 'Score: 0 | Lives: 3 | Level: 1',
  isStatic: true
});

function updateHUD() {
  const score = game.gameState.get('score') || 0;
  const lives = game.gameState.get('lives') || 0;
  const level = game.gameState.get('level') || 1;
  
  hud.element.setContent(`Score: ${score} | Lives: ${lives} | Level: ${level}`);
}

Scene Management

Creating Scenes

const game = new GameEngine({ scenes: true });

const menuScene = {
  name: 'menu',
  onEnter: function() {
    console.log('Menu loaded');
    // Create menu objects
    const title = game.createEntity(10, 5, 20, 5, {
      style: { fg: 'white', bg: 'red' },
      content: 'MAIN MENU',
      isStatic: true
    });
    game.addGameObject(title);
    this.title = title;
  },
  onExit: function() {
    // Clean up scene objects
    if (this.title && this.title.element) {
      this.title.element.detach();
    }
  }
};

Managing Scenes

// Add scenes
game.scenes.addScene('menu', menuScene);
game.scenes.addScene('gameplay', gameplayScene);
game.scenes.addScene('gameover', gameoverScene);

// Switch scenes
game.scenes.switchTo('menu');

// Switch with keyboard
game.screen.key(['1'], () => game.scenes.switchTo('menu'));
game.screen.key(['2'], () => game.scenes.switchTo('gameplay'));

Input Handling

// Keyboard input
game.screen.key(['up', 'w'], () => {
  player.applyForce({ x: 0, y: -5 });
});

game.screen.key(['space'], () => {
  // Jump or shoot
});

// Multiple key options
game.screen.key(['left', 'a'], () => {
  player.applyForce({ x: -2, y: 0 });
});

Game Loop

The engine handles the game loop automatically. You can hook into updates:

// Custom update logic
const originalUpdate = game.update.bind(game);
game.update = function(deltaTime) {
  originalUpdate(deltaTime);
  
  // Your custom update code
  if (timer > 3.0) {
    // Do something every 3 seconds
    timer = 0;
  }
};

Complete Example

const { GameEngine, GameState } = require('vivid-tui');

const game = new GameEngine({ 
  title: 'Platform Game',
  audio: true,
  effects: true
});

game.gameState = new GameState();
game.gameState.set('score', 0);

// Player
const player = game.createEntity(10, 10, 3, 3, {
  style: { fg: 'white', bg: 'blue' },
  content: 'P',
  hasGravity: true
});

// Platform
const platform = game.createEntity(0, 15, 80, 2, {
  style: { fg: 'white', bg: 'gray' },
  isStatic: true
});

// Camera follows player
game.setCameraTarget(player);

// Controls
game.screen.key(['space'], () => {
  player.applyForce({ x: 0, y: -8 });
  game.createExplosion(player.position.x, player.position.y);
});

game.screen.key(['left'], () => {
  player.applyForce({ x: -2, y: 0 });
});

game.screen.key(['right'], () => {
  player.applyForce({ x: 2, y: 0 });
});

// Start game
game.addGameObject(player);
game.addGameObject(platform);
game.start();

API Reference

GameEngine

Constructor Options:

  • title - Window title
  • audio - Enable audio system
  • effects - Enable particle effects
  • scenes - Enable scene management

Methods:

  • createEntity(x, y, width, height, options) - Create game object
  • createSprite(x, y, width, height, options) - Create animated sprite
  • addGameObject(entity) - Add entity to game
  • start() - Start game loop
  • setCameraTarget(entity) - Set camera follow target
  • cycleCameraMode() - Switch camera modes
  • createExplosion(x, y) - Create explosion effect
  • loadMusic(name, path, options) - Load music file
  • loadSound(name, path) - Load sound effect
  • playMusic(name) - Play loaded music
  • stopMusic() - Stop music
  • playSound(name) - Play sound effect

GameState

Methods:

  • set(key, value) - Set state value
  • get(key) - Get state value
  • setGameOver(boolean) - Set game over state
  • reset() - Reset all state

Particle System

Methods:

  • particles.emit(x, y, count, options) - Emit particles
  • particles.addToScreen(screen) - Add particles to screen