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

vue-visual-novel-engine

v0.1.1

Published

A visual novel / interactive storytelling engine for Vue 3 — dialogue system, save/load, character management, choice branching, audio control

Downloads

347

Readme

vue-visual-novel-engine

A visual novel / interactive storytelling engine for Vue 3 + TypeScript + Pinia.

npm version npm downloads License: MIT

🇨🇳 中文文档 | 🇬🇧 English


English

Features

  • 📖 Typewriter Effect — Adjustable speed, click to skip
  • 🌳 Branching Choices — Multiple choice options with bond/affection tracking
  • 💾 Save System — 6 manual save slots + auto-save + quick-save
  • 🎭 Character Sprites — Multi-character display with themed styling
  • 🎵 Audio Control — BGM + SFX, auto-switch on scene change
  • 🔓 Chapter Unlock — Choice-based chapter progression
  • ❤️ Affection System — Choices affect character bond points
  • TypeScript — Full type definitions, IDE-friendly
  • 🎨 Customizable — Override styles via CSS or scoped components

Installation

npm install vue-visual-novel-engine pinia
# or
pnpm add vue-visual-novel-engine pinia

Quick Start

1. Register Pinia

// main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
app.use(createPinia())
app.mount('#app')

2. Prepare Game Data

// game-data.ts
export const gameData = {
  prologue: {
    bg: '/images/bg-room.jpg',
    dialogues: [
      { speaker: 'Narrator', text: 'Morning sunlight filters through the curtains.' },
      { speaker: 'Tang Xin', text: 'A new day begins.' },
      {
        speaker: 'Narrator',
        text: 'You decide...',
        choices: [
          { text: 'Take a walk in the park', next: 'park', bond: { linwanxing: 2 } },
          { text: 'Rest at home', next: 'home' },
        ],
      },
    ],
  },
  park: {
    bg: '/images/bg-park.jpg',
    dialogues: [
      { speaker: 'Narrator', text: 'The park is bustling with people.' },
      { speaker: 'Lin Wanxing', text: 'Hey! You came for a walk too?' },
    ],
  },
}

3. Use VNScreen Component

<template>
  <VNScreen :game-data="gameData" initial-chapter="prologue" />
</template>

<script setup lang="ts">
import { VNScreen } from 'vue-visual-novel-engine'
import { gameData } from './game-data'
</script>

API Reference

VNScreen Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | gameData | Record<string, ChapterData> | Required | Chapter data | | initialChapter | string | First chapter | Initial chapter ID | | config | VNEngineConfig | - | Engine configuration |

VNScreen Events

| Event | Description | |-------|-------------| | complete | Emitted when game completes |

Store Methods

import { useVNStore } from 'vue-visual-novel-engine'

const store = useVNStore()

// Initialize
store.init(gameData, 'prologue')

// Navigation
store.nextDialogue()      // Next dialogue
store.completeText()      // Skip typewriter
store.makeChoice(0)       // Select choice

// Save/Load
store.saveProgress()      // Save to storage
store.loadFromStorage()   // Load from storage

// Settings
store.setTextSpeed(50)
store.setAutoPlayInterval(3000)
store.toggleAutoPlay()

// Cleanup
store.cleanup()

Save Manager

import { SaveManager } from 'vue-visual-novel-engine'

const saveManager = new SaveManager('my-game')

// Save
saveManager.saveToSlot(0, {
  chapterId: 'chapter1',
  dialogueIndex: 5,
  flags: { met_late_star: true },
  bond: { linwanxing: 10 },
})

// Load
const data = saveManager.loadFromSlot(0)

// Auto-save
saveManager.autoSave(gameState)

// Chapter unlock
saveManager.unlockChapter('chapter2')
const unlocked = saveManager.getUnlockedChapters()

Audio Manager

import { AudioManager } from 'vue-visual-novel-engine'

const audio = new AudioManager()

// Play
audio.playBGM('/music/theme.mp3')
audio.playSFX('/sfx/click.mp3')

// Control
audio.pauseBGM()
audio.resumeBGM()
audio.setBGMVolume(0.7)
audio.setSFXVolume(0.8)

// Cleanup
audio.destroy()

Custom Styling

Components use scoped CSS. Override globally:

.vn-screen {
  font-family: 'Your Font', sans-serif;
}

.vn-dialogue-box {
  background: rgba(0, 0, 0, 0.9);
}

Project Structure

vue-visual-novel-engine/
├── src/
│   ├── engine/
│   │   ├── DialogueEngine.ts   # Core dialogue engine
│   │   ├── SaveManager.ts      # Save/load manager
│   │   └── AudioManager.ts     # Audio manager
│   ├── stores/
│   │   └── useVNStore.ts       # Pinia store
│   ├── components/
│   │   ├── VNScreen.vue        # Main screen component
│   │   ├── DialogueBox.vue     # Dialogue box
│   │   ├── CharacterSlot.vue   # Character sprite
│   │   └── ChoicePanel.vue     # Choice panel
│   ├── types.ts                # TypeScript types
│   └── index.ts                # Entry point
├── vite.config.ts
├── tsconfig.json
└── package.json

Development

# Install dependencies
npm install

# Dev mode
npm run dev

# Build
npm run build

# Type check
npm run type-check

Related Projects

License

MIT © chuangzaozhe1


中文文档

特性

  • 📖 打字机效果 — 可调节速度,支持点击跳过
  • 🌳 分支选择 — 支持多选项剧情分支,可关联好感度
  • 💾 存档系统 — 6个手动存档槽位 + 自动存档 + 快速存档
  • 🎭 角色立绘 — 支持多角色同时显示,自动主题色
  • 🎵 音频管理 — BGM + 音效,场景切换自动切换音乐
  • 🔓 章节解锁 — 基于选择的章节解锁机制
  • ❤️ 好感度系统 — 选择影响角色好感度
  • TypeScript — 完整类型定义,IDE 友好
  • 🎨 可定制 — 组件样式可通过 CSS 变量或 scoped 覆盖

安装

npm install vue-visual-novel-engine pinia
# 或
pnpm add vue-visual-novel-engine pinia

快速开始

1. 注册 Pinia

// main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
app.use(createPinia())
app.mount('#app')

2. 准备游戏数据

// game-data.ts
export const gameData = {
  prologue: {
    bg: '/images/bg-room.jpg',
    dialogues: [
      { speaker: '旁白', text: '清晨的阳光透过窗帘照进来。' },
      { speaker: '唐信', text: '新的一天开始了。' },
      {
        speaker: '旁白',
        text: '你决定...',
        choices: [
          { text: '去公园散步', next: 'park', bond: { linwanxing: 2 } },
          { text: '在家休息', next: 'home' },
        ],
      },
    ],
  },
  park: {
    bg: '/images/bg-park.jpg',
    dialogues: [
      { speaker: '旁白', text: '公园里人来人往。' },
      { speaker: '林晚星', text: '嘿!你也来散步?' },
    ],
  },
}

3. 使用 VNScreen 组件

<template>
  <VNScreen :game-data="gameData" initial-chapter="prologue" />
</template>

<script setup lang="ts">
import { VNScreen } from 'vue-visual-novel-engine'
import { gameData } from './game-data'
</script>

API 文档

VNScreen 属性

| 属性 | 类型 | 默认值 | 说明 | |------|------|--------|------| | gameData | Record<string, ChapterData> | 必填 | 章节数据 | | initialChapter | string | 第一个章节 | 初始章节 ID | | config | VNEngineConfig | - | 引擎配置 |

VNScreen 事件

| 事件 | 说明 | |------|------| | complete | 游戏完成时触发 |

Store 方法

import { useVNStore } from 'vue-visual-novel-engine'

const store = useVNStore()

// 初始化
store.init(gameData, 'prologue')

// 导航
store.nextDialogue()      // 下一句
store.completeText()      // 跳过打字
store.makeChoice(0)       // 选择选项

// 存档
store.saveProgress()      // 保存到本地
store.loadFromStorage()   // 从本地加载

// 设置
store.setTextSpeed(50)
store.setAutoPlayInterval(3000)
store.toggleAutoPlay()

// 清理
store.cleanup()

存档管理

import { SaveManager } from 'vue-visual-novel-engine'

const saveManager = new SaveManager('my-game')

// 保存
saveManager.saveToSlot(0, {
  chapterId: 'chapter1',
  dialogueIndex: 5,
  flags: { met_late_star: true },
  bond: { linwanxing: 10 },
})

// 加载
const data = saveManager.loadFromSlot(0)

// 自动存档
saveManager.autoSave(gameState)

// 章节解锁
saveManager.unlockChapter('chapter2')
const unlocked = saveManager.getUnlockedChapters()

音频管理

import { AudioManager } from 'vue-visual-novel-engine'

const audio = new AudioManager()

// 播放
audio.playBGM('/music/theme.mp3')
audio.playSFX('/sfx/click.mp3')

// 控制
audio.pauseBGM()
audio.resumeBGM()
audio.setBGMVolume(0.7)
audio.setSFXVolume(0.8)

// 清理
audio.destroy()

自定义样式

组件使用 scoped CSS,可通过以下方式覆盖:

/* 全局覆盖 */
.vn-screen {
  font-family: 'Your Font', sans-serif;
}

.vn-dialogue-box {
  background: rgba(0, 0, 0, 0.9);
}

项目结构

vue-visual-novel-engine/
├── src/
│   ├── engine/
│   │   ├── DialogueEngine.ts   # 对话引擎核心
│   │   ├── SaveManager.ts      # 存档管理
│   │   └── AudioManager.ts     # 音频管理
│   ├── stores/
│   │   └── useVNStore.ts       # Pinia 状态管理
│   ├── components/
│   │   ├── VNScreen.vue        # 主屏幕组件
│   │   ├── DialogueBox.vue     # 对话框组件
│   │   ├── CharacterSlot.vue   # 角色立绘组件
│   │   └── ChoicePanel.vue     # 选择面板组件
│   ├── types.ts                # TypeScript 类型定义
│   └── index.ts                # 入口文件
├── vite.config.ts              # Vite 构建配置
├── tsconfig.json               # TypeScript 配置
└── package.json

开发

# 安装依赖
npm install

# 开发模式
npm run dev

# 构建
npm run build

# 类型检查
npm run type-check

相关项目

许可证

MIT © chuangzaozhe1