A template project to quickly create incremental games with Typescript, knockout and Webpack.
Over the years of developing different incremental games, We have thought about a lot of game-related things. This project is an attempt to bundle it all together coherently. It should not be considered as a 'game engine' but mainly a collection of useful scripts that work together.
The static root object is called App
. When it is started, it creates an instance of Game
where you can inject different Feature
s.
This means that all your features are accessible with App.game.<feature>
.
Features can be implemented by extending the Feature
class. Features like this automatically get included in the game loop.
This means they get called with update(deltaTime: number)
automatically, as well as being saved and loaded.
Your game will consist of multiple features communicating with each other.
We use https://knockoutjs.com/ to automatically update the UI when variable changes.
App.game
is bound to the UI with knockout to make the observables accessible.
Have your class implement Saveable
and create a <class>SaveData
object that extends SaveData
.
export class Example implements Saveable {
...
saveKey = "example";
load(data: ExampleSaveData): void {
this.clicks = data.clicks
}
parseSaveData(json: Record<string, unknown>): SaveData {
return new ExampleSaveData(json?.clicks as number ?? 0);
}
save(): ExampleSaveData {
return new ExampleSaveData(this.clicks)
}
Allows you to have multiple currencies in your game without code duplication.
// Add raw values directly
App.game.wallet.gainCurrency(new Currency(10, CurrencyType.money));
// Custom function to apply possible multipliers
App.game.wallet.gainMoney(10);
Statistics provide an easily extensible system for storing any increasing number you can think of.
Instead of having your Feature
s depend on Statistics
, it works the other way around.
Statistics
subscribe on events triggered by Feature
s.
this.registerStatistic(new NumberStatistic('totalMoneyGained'))
App.game.wallet.onMoneyGain.subscribe(amount => this.incrementNumberStatistic('totalMoneyGained', amount));
Lets you easily create settings for the user to configure. Supports boolean and multiple choice settings with booleans, numbers and strings
App.game.settings.add(new BooleanSetting('exampleSetting', 'Doesnt do much really', true));
if (App.game.settings.getSetting('exampleSetting').value) {
console.log("This setting is true")
}
<h2>Example setting: <span data-bind="text: settings.getSetting('exampleSetting').value"> </span>!</h2>
<button data-bind="click: () => settings.getSetting('exampleSetting').toggle()">Toggle setting</button>
Requirement
s are a generic way to lock things like Feature
s behind requirements.
The most used Requirement is the StatisticRequirement
, but you can also create custom target.
const requirement = new TotalMoneyRequirement(10);
if (!requirement.isCompleted()) {
console.log(requirement.lockedReason());
console.log(requirement.getProgress());
}
Achievements are based on Requirements. You can create any achievement by passing in a custom requirement.
Each Achievement
triggers an event on completion, which can be subscribed to, to display a notification for example.
// Achievements.ts
this.addAchievement(new Achievement('10-money', 'Gain 10 money', new TotalMoneyRequirement(10)))
The following frameworks/libraries are currently included
- Typescript
- Webpack
- Knockout
- jQuery
- ESLint
- Jest testing
Other libraries can easily be added via Webpack.