Skip to main content

Direct Metric Updates

This guide explains how to directly update achievement metrics using the update() method. This is the most straightforward way to track progress in achievements-engine.

Overview

The core of direct metric updates is the engine.update() method. You pass an object where keys are metric names and values are the new metric values.

import { AchievementEngine } from 'achievements-engine';

const engine = new AchievementEngine({
achievements,
storage: 'localStorage'
});

engine.update({ metricName: value });

Basic Patterns

Score-Based Achievements

Track numeric values that increase over time:

const achievements = {
score: {
100: { title: 'Century!', description: 'Score 100 points', icon: '🏆' },
500: { title: 'High Scorer!', description: 'Score 500 points', icon: '⭐' },
1000: { title: 'Legend!', description: 'Score 1000 points', icon: '💎' },
},
};

// Usage
const engine = new AchievementEngine({ achievements, storage: 'localStorage' });
engine.update({ score: 150 }); // Unlocks "Century!" achievement

Boolean Achievements

Track completion or state changes:

const achievements = {
completedTutorial: {
true: { title: 'Tutorial Master', description: 'Complete the tutorial', icon: '📚' }
},
firstWin: {
true: { title: 'First Victory!', description: 'Win your first game', icon: '🎯' }
},
};

// Usage
engine.update({ completedTutorial: true }); // Unlocks achievement

String-Based Achievements

Track specific values or states:

const achievements = {
difficulty: {
easy: { title: 'Easy Mode', description: 'Complete on easy', icon: '😌' },
medium: { title: 'Medium Mode', description: 'Complete on medium', icon: '🤔' },
hard: { title: 'Hard Mode', description: 'Complete on hard', icon: '💪' },
},
};

// Usage
engine.update({ difficulty: 'hard' }); // Unlocks "Hard Mode"

Custom Condition Achievements

For complex logic involving multiple metrics:

const achievements = {
perfectGame: {
custom: {
title: 'Perfect Game',
description: 'Score 1000+ with 100% accuracy',
icon: '🎯',
condition: (metrics) => metrics.score >= 1000 && metrics.accuracy === 100
}
},
speedRunner: {
custom: {
title: 'Speed Runner',
description: 'Complete in under 5 minutes',
icon: '⚡',
condition: (metrics) => metrics.timeElapsed < 300 && metrics.completed === true
}
},
};

// Usage - track all relevant metrics
engine.update({ score: 1200 });
engine.update({ accuracy: 100 });
// Both metrics checked, unlocks if condition met

Updating Metrics

Use the update() method to track metrics:

import { AchievementEngine } from 'achievements-engine';

const engine = new AchievementEngine({
achievements,
storage: 'localStorage'
});

// Update single metric
engine.update({ score: 100 });

// Update multiple metrics at once
engine.update({
score: 1200,
accuracy: 100,
timeElapsed: 45,
completed: true
});

Incrementing Values

For metrics that increment over time:

// Track current value
let clicks = 0;

function handleClick() {
clicks++;
engine.update({ clicks });
}

// Or get current value from engine metrics
function incrementScore(points: number) {
const currentMetrics = engine.getMetrics<GameMetrics>();
const currentScore = currentMetrics.score || 0;
engine.update({ score: currentScore + points });
}

Complete Example

Here's a full working example combining multiple achievement types:

// achievements.ts
export const gameAchievements = {
// Score milestones
score: {
100: { title: 'Beginner', description: 'Score 100 points', icon: '🥉' },
500: { title: 'Intermediate', description: 'Score 500 points', icon: '🥈' },
1000: { title: 'Expert', description: 'Score 1000 points', icon: '🥇' },
},

// Completion tracking
completedTutorial: {
true: { title: 'Tutorial Complete', description: 'Finished the tutorial', icon: '📚' }
},

// Difficulty levels
difficulty: {
hard: { title: 'Hardened Warrior', description: 'Beat hard mode', icon: '💪' }
},

// Click counter
clicks: {
10: { title: 'Clicker', description: 'Click 10 times', icon: '👆' },
100: { title: 'Super Clicker', description: 'Click 100 times', icon: '👆👆' },
},

// Complex achievements
perfectRun: {
custom: {
title: 'Perfectionist',
description: 'Score 1000+ with 100% accuracy',
icon: '💎',
condition: (metrics) => metrics.score >= 1000 && metrics.accuracy === 100
}
},

speedDemon: {
custom: {
title: 'Speed Demon',
description: 'Complete in under 60 seconds',
icon: '⚡',
condition: (metrics) => {
return metrics.completed === true && metrics.timeElapsed < 60;
}
}
},
};
// game.ts
import { AchievementEngine } from 'achievements-engine';
import { gameAchievements } from './achievements';

class Game {
private engine: AchievementEngine;
private score: number = 0;
private clicks: number = 0;
private startTime: number = Date.now();

constructor() {
// Initialize engine
this.engine = new AchievementEngine({
achievements: gameAchievements,
storage: 'localStorage'
});
}

scorePoints(points: number) {
this.score += points;
this.engine.update({ score: this.score });
}

handleClick() {
this.clicks++;
this.engine.update({ clicks: this.clicks });
}

completeGame() {
const timeElapsed = (Date.now() - this.startTime) / 1000; // seconds

this.engine.update({
completed: true,
timeElapsed,
accuracy: 100 // Your accuracy calculation
});
}

setDifficulty(level: 'easy' | 'medium' | 'hard') {
this.engine.update({ difficulty: level });
}
}

// Usage
const game = new Game();
game.scorePoints(100);
game.handleClick();
game.setDifficulty('hard');
game.completeGame();

Browser Integration

Vanilla JavaScript Example

<!DOCTYPE html>
<html>
<head>
<title>Achievement Demo</title>
</head>
<body>
<h1>Score: <span id="score">0</span></h1>
<button id="scoreBtn">+100 Points</button>
<button id="clickBtn">Click Me!</button>
<button id="completeBtn">Complete Game</button>

<script type="module">
import { AchievementEngine } from 'achievements-engine';

const achievements = {
score: {
100: { title: 'Century!', icon: '🏆' },
500: { title: 'High Scorer!', icon: '⭐' }
},
clicks: {
10: { title: 'Clicker', icon: '👆' }
}
};

const engine = new AchievementEngine({
achievements,
storage: 'localStorage'
});

let score = 0;
let clicks = 0;

// Score button
document.getElementById('scoreBtn').addEventListener('click', () => {
score += 100;
document.getElementById('score').textContent = score;
engine.update({ score });
});

// Click button
document.getElementById('clickBtn').addEventListener('click', () => {
clicks++;
engine.update({ clicks });
});

// Complete button
document.getElementById('completeBtn').addEventListener('click', () => {
engine.update({ completed: true });
});
</script>
</body>
</html>