Building a Scoring System

Implementing a scoring mechanism is a common patten in interactive videos. Different paths throughout the project update the score, a scoreboard UI component provides a visual representation of the current score and a score-based decision affects the storyline.

The variables plugin can help you implement that pattern.

Register a variable

First we need to register a variable to hold the score.

player.variables.register('score', {initialValue: 0});

Update the score

You can update the score by using the getValue and setValue APIs. In the following example, the score updates are based on the viewer’s path. The scoring object maps relevant nodes to scoring rules. When nodes are pushed to the playlist for playback the score is updated accordingly.

playlistpush event is the earliest time we know that a node is expected to be played. You can listen on nodestart event instead to update the score when the node actually plays.

const scoring = {
    node_ok: 5,   // Earn 5 points when getting to node ok
    node_wow: 20,  // Earn 20 points when getting to node wow
    node_oops: -10  // Lose 10 points when getting to node oops
};

// Get the array of keys (node ids)
Object.keys(scoring)
    // Map them to an array of node objects
    .map(nodeId => player.repository.get(nodeId))
    // Attach a "playlistpush" listener to each of the nodes
    .forEach(node => {
        node.on('playlistpush', () => {
            let oldScore = player.variables.getValue('score');
            let newScore = oldScore + scoring[node.id];
            player.variables.setValue('score', newScore);
        });
    });

The scoreboard

It is assumed that you are already familiar with the UI development concepts explained in ui for interactive video and state and redux.

A scoreboard is a UI component that displays the score value. The scoreboard is a React component that works against the redux store. The variables plugin exposes variables values in its redux state. Here is an example of a simple scoreboard component:

// functional example
export default function Scoreboard(props){
    let score = props.player.ui.useSelector(globalState => globalState.variables['score'] || 0);
    return <div className='scoreboard'>{score}</div>;

}

// class-based example
import EkoUIComponents from "EkoUIComponents";

class Scoreboard extends React.Component {
    render() {
        let score = this.props.score;
        return <div className='scoreboard'>{score}</div>;
    }
}

let mapStateToProps = (globalState, ownProps) => {
 score: globalState.variables['score'] || 0
}

export default EkoUIComponents.connect(mapStateToProps)(Scoreboard);

In your app.js import the scoreboard component and add it like this:

player.ui.add('scoreboard', Scoreboard);

Score based decisions

Nodes can be pushed to the playlist according to the score. Here is a simple example using a decider:

let decision = player.decision.get('node_game_end');
decision.decider = function(node, children, options) {
    let score = player.variables.getValue('score');
    return score >= 200 ? 'node_win' : 'node_lose';
}

Learn about decisions and deciders in the Managing Decisions tutorial.

For a simpler implementation and walkthrough, check out the Value Accumulation snippet.

Rate this page: X
Tell us more!