Hi.
I’ve just released (under GPLv3) Rez, a system I have been building for creating interactive fiction HTML games. I started it in response to the feeling that Twine was hindering, rather than helping, me to build the game I had in mind.
In terms of complexity, Rez is aimed at the gap between Twine and something like Inform or TADS. It’s primarily declarative, with embedded Javascript callbacks to handle events and a standard library that includes items, inventories, actors and a save/load system that round-trips through JSON. Anyone with basic Javascript skills should be able to create something that pleases them. The Rez compiler outputs a dist folder containing the HTML/JS/CSS and any assets included in the game.
Rez uses a scene/card concept to keep complexity under control. A scene represents a situation for the player and cards represent content & actions that can be played as part of a scene. Scenes have a layout and can display a card at a time or a sequence of cards. Cards have content that is wrapped in the scene layout. Both have many event hooks to customise them.
Here’s an incredibly simple coin-toss example game to give you an idea of what writing in Rez looks like:
@game begin
name: "Test Game"
author_name: "Matt Mower"
author_email: "self@mattmower.com"
IFID: "D3C31250-53B4-11ED-9A26-3AF9D3B0DD88"
archive_format: 1
initial_scene: #play_game
layout: """
{{{scene}}}
"""
@actor player begin
score: 0
end
@scene play_game begin
initial_card: #play_round
blocks: [#sidebar]
layout_mode: :single
layout: """
<div class="columns">
<div class="column">{{{sidebar}}}</div>
<div class="column">{{{content}}}</div>
</div>
"""
end
@card sidebar begin
bindings: {player: "player"}
content: """
Score: {{$ player "score"}}
"""
end
@card play_round begin
on_start: (card, event) => {
card.setAttribute("coin", coin_flip());
}
content: """
Do you [[Choose heads]] or [[Choose tails]]?
"""
end
@alias result_card = card # begin
bindings: {player: "player"}
content: """
{{$ card "response"}}
[[Play again|play_round]]
"""
end
@result_card choose_heads begin
on_start: (card, event) => {
const flip = card.$("play_round").getAttribute("coin");
won_or_lost(card, flip == "heads");
}
end
@result_card choose_tails begin
on_start: (card, event) => {
const flip = card.$("play_round").getAttribute("coin");
won_or_lost(card, flip == "tails");
}
end
@script begin
function won_or_lost(card, winner) {
const player = card.$("player");
if(winner) {
card.setAttribute("response", "Congratulations");
player.incAttribute("score", 2);
} else {
card.setAttribute("response", "Bad luck");
player.decAttribute("score");
}
}
function coin_flip() {
return (Math.random() < 0.5) ? "heads" : "tails";
}
end
end
For more, see the language guide.
They say that if you aren’t embarrassed by your first release, you waited too long. No fear of that here. Rez is probably mature enough to build a game, although many bits are placeholders for future functionality, including the beginnings of support for the procedural generation of content.
I’m posting now to see if I can find some early adopters to check it out and give me feedback.
Matt