@joshtol/emotive-engine
v3.2.3
Published
Open-source animation engine for AI-controlled emotional visualizations with musical time synchronization
Maintainers
Keywords
Readme
Emotive Engine
Expressive AI mascots for modern interfaces
Real-time character animation engine with Canvas 2D and WebGL 3D rendering.
Live Demos | Documentation | NPM
Features
3D WebGL Rendering
- Custom GLSL shaders with subsurface scattering
- Physically-based materials and bloom effects
- 8 moon phases with tidal lock camera
- Solar and lunar eclipse simulations
- Runtime geometry morphing
2D Canvas Rendering
- Lightweight pure Canvas 2D
- Dynamic particle effects
- Shape morphing animations
- Gaze tracking
- Mobile-optimized
Shared across both modes:
- 15 emotional states with smooth transitions
- 40+ expressive gestures
- Natural language
feel()API for LLM integration - TypeScript definitions
- Unified API
Demo Gallery
3D WebGL Examples
2D Canvas Examples
Installation
npm install @joshtol/emotive-engineOr via CDN:
<!-- 2D Engine -->
<script src="https://unpkg.com/@joshtol/emotive-engine/dist/emotive-mascot.umd.js"></script>
<!-- 3D Engine (includes Three.js) -->
<script src="https://unpkg.com/@joshtol/emotive-engine/dist/emotive-mascot-3d.umd.js"></script>Quick Start
3D Mode (WebGL)
import { EmotiveMascot3D } from '@joshtol/emotive-engine/3d';
const mascot = new EmotiveMascot3D({
coreGeometry: 'crystal', // crystal, moon, sun, heart, sphere
enableParticles: true,
enablePostProcessing: true,
});
mascot.init(document.getElementById('container'));
mascot.start();
// Control emotions and gestures
mascot.setEmotion('joy');
mascot.express('bounce');
mascot.morphTo('heart');2D Mode (Canvas)
import { EmotiveMascot } from '@joshtol/emotive-engine';
const mascot = new EmotiveMascot({
canvasId: 'mascot',
defaultEmotion: 'neutral',
});
await mascot.init(document.getElementById('container'));
mascot.start();
// Same API as 3D
mascot.setEmotion('joy');
mascot.express('bounce');LLM Integration with feel()
The feel() method lets LLMs control the mascot using natural language:
// Simple emotion
mascot.feel('happy')
// Emotion with gesture
mascot.feel('curious, leaning in')
// With undertone modifier
mascot.feel('happy but nervous')
// With shape morph
mascot.feel('loving, heart shape, sparkle')
// With intensity
mascot.feel('very angry, shaking')The engine parses ~1400 synonyms to understand natural expressions. For full documentation, see LLM Integration Guide.
LLM System Prompt Example
After each response, output: FEEL: <emotion>, <gesture>
Examples:
- Greeting: FEEL: happy, wave
- Thinking: FEEL: focused, leaning in
- Celebrating: FEEL: euphoric, star shape, sparkleEmotions
15 built-in emotional states with unique visual characteristics:
| Emotion | Description | Emotion | Description |
|---------|-------------|---------|-------------|
| neutral | Default calm | joy | Happy, upbeat |
| calm | Peaceful | love | Affectionate |
| excited | High energy | euphoria | Peak happiness |
| sadness | Melancholy | anger | Frustrated |
| fear | Anxious | surprise | Startled |
| disgust | Repulsed | focused | Concentrated |
| suspicion | Wary | resting | Idle/sleep |
| glitch | Digital artifact | | |
mascot.setEmotion('joy');
mascot.setEmotion('calm', 'peaceful'); // with undertoneGestures
40+ expressive gestures in three categories:
Motion: bounce, pulse, shake, nod, sway, float, wiggle, lean
Transform: spin, jump, morph, stretch, tilt, orbital, twist
Effects: wave, flicker, burst, flash, glow, breathe, expand
mascot.express('bounce');
mascot.chain('bounce > spin > pulse'); // sequential
mascot.chain('sway+breathe+float'); // simultaneous3D Geometries
| Geometry | Description | Shader |
|----------|-------------|--------|
| crystal | Faceted hexagonal crystal | Subsurface scattering |
| moon | Realistic lunar surface | Custom phase shader |
| sun | Solar sphere with corona | Emissive + corona layers |
| heart | Heart-shaped crystal | Subsurface scattering |
| sphere | Smooth sphere | Standard PBR |
mascot.morphTo('heart'); // Runtime geometry morphingMoon Phase Control
import { setMoonPhase, MOON_PHASES } from '@joshtol/emotive-engine/3d';
setMoonPhase(mascot.core3D, MOON_PHASES.FULL);
setMoonPhase(mascot.core3D, MOON_PHASES.CRESCENT_WAXING);
// All phases: NEW, CRESCENT_WAXING, FIRST_QUARTER, GIBBOUS_WAXING,
// FULL, GIBBOUS_WANING, LAST_QUARTER, CRESCENT_WANINGEclipse Effects
// Solar eclipse with corona
mascot.core3D.setSolarEclipse(0.8); // 0-1 coverage
// Lunar eclipse (blood moon)
mascot.core3D.setLunarEclipse(1.0); // Full umbraConfiguration
3D Options
new EmotiveMascot3D({
// Geometry
coreGeometry: 'crystal',
// Rendering
enableParticles: true,
enablePostProcessing: true, // Bloom effects
enableShadows: false,
// Camera
enableControls: true, // Orbit controls
autoRotate: true,
cameraDistance: 3,
// Animation
enableBlinking: true,
enableBreathing: true,
targetFPS: 60,
});2D Options
new EmotiveMascot({
canvasId: 'mascot',
targetFPS: 60,
enableParticles: true,
maxParticles: 300,
adaptive: true, // Auto quality adjustment
});API Reference
Core Methods (Both Modes)
// Lifecycle
mascot.init(container);
mascot.start();
mascot.stop();
mascot.destroy();
// Natural language control (LLM-friendly)
mascot.feel('happy, bouncing');
mascot.feel('curious, leaning in');
// Emotions
mascot.setEmotion(name);
mascot.setEmotion(name, undertone);
// Gestures
mascot.express(gesture);
mascot.chain('gesture1 > gesture2');
// Shapes
mascot.morphTo(shape);3D-Specific Methods
// Toggle features
mascot.enableParticles();
mascot.disableParticles();
mascot.enableAutoRotate();
mascot.disableAutoRotate();
// Camera
mascot.setCameraPreset('front'); // front, side, top, angleRunning Locally
git clone https://github.com/joshtol/emotive-engine.git
cd emotive-engine
npm install
npm run build
npm run local
# Open http://localhost:3001Or view the live demo gallery.
Browser Support
| Browser | Version | |---------|---------| | Chrome/Edge | 90+ | | Firefox | 88+ | | Safari | 14+ | | iOS Safari | 14+ | | Chrome Android | 90+ |
3D mode requires WebGL 2.0 support.
Performance Tips
- Disable post-processing on mobile for 60fps
- Use
enableShadows: falseunless needed - Lower
maxParticleson constrained devices - 2D mode is lighter weight for simple use cases
License
MIT License - see LICENSE.md
Created by Joshua Tollette
