@web-engine-dev/ai
Game AI systems including FSM, behavior trees, GOAP, utility AI, and perception..
Features
- Finite State Machines: Traditional state-based AI
- Behavior Trees: Hierarchical decision making
- GOAP: Goal-Oriented Action Planning
- Utility AI: Score-based action selection
- Perception System: Sight, hearing, awareness
- Blackboard: Shared AI data storage
Installation
bash
npm install @web-engine-dev/ai
# or
pnpm add @web-engine-dev/aiQuick Start
typescript
import { BehaviorTree, Selector, Sequence, Action, Condition } from '@web-engine-dev/ai';
// Create behavior tree
const tree = new BehaviorTree(
new Selector([
new Sequence([new Condition('hasEnemy'), new Action('attack')]),
new Sequence([new Condition('isHungry'), new Action('findFood')]),
new Action('patrol'),
])
);
// Execute each frame
tree.update(entity, blackboard);API Overview
Finite State Machine
typescript
const fsm = new StateMachine({
initial: 'idle',
states: {
idle: {
enter: () => playAnimation('idle'),
update: (dt) => {
/* logic */
},
transitions: {
'enemy-spotted': 'chase',
},
},
chase: {
enter: () => playAnimation('run'),
update: (dt) => moveToward(enemy),
transitions: {
'in-range': 'attack',
'lost-target': 'idle',
},
},
},
});Behavior Tree Nodes
| Node Type | Description |
|---|---|
Selector | Try children until one succeeds |
Sequence | Run children until one fails |
Parallel | Run all children simultaneously |
Condition | Check a boolean condition |
Action | Execute an action |
Decorator | Modify child behavior |
GOAP
typescript
const planner = new GOAPPlanner({
actions: [
{ name: 'attack', preconditions: { hasWeapon: true }, effects: { enemyDead: true } },
{ name: 'findWeapon', effects: { hasWeapon: true } },
],
});
const plan = planner.plan({ hasWeapon: false, enemyDead: false }, { enemyDead: true });Utility AI
typescript
const utility = new UtilityAI({
actions: [
{ name: 'attack', score: (ctx) => ctx.enemyProximity * ctx.health },
{ name: 'flee', score: (ctx) => (1 - ctx.health) * ctx.enemyProximity },
{ name: 'heal', score: (ctx) => (1 - ctx.health) * ctx.hasPotion },
],
});
const action = utility.selectAction(context);