Introduction Last updated: 2019-06-01

If you’re reading this, you’re probably thinking about making a visual novel. That is, a videogame of the genre Visual Novel, subgenre of Interactive Fiction. It's important to define what this means, because it will give you a framework in which you can develop the game more easily.

For example, visual novels often tell a rich story aided by static visuals. There are many more rules and conventions of visual novels that you should familiarize yourself before starting to write such a game. Of course, you can bend, break and subverse these guidelines, but knowing them will help you write better games.

To make a visual novel with RenJS it doesn’t matter if you’ve never made a videogame before, or if you don't know any programming. As said above, one of the most important aspects of the genre is the story. RenJS lets you focus on it, by providing a way to use movie-script like text files and easily configurable visuals, to create the game you envision.

RenJS, broadly speaking, is a tool to help you make visual novels. You’ve probably heard about other game engines, like Unity or Game Maker. Those tools provide a whole environment for developing many kinds of games. RenJS is a bit different.

To build the games, you only need to create text files for story and visual configuration. There’s no program you have to install or open to make your game. RenJS is just a library that you import into an html file, that knows how to read a story and show it in a web browser.

To write the story and make up your visuals, you can use any tools you like and know already. Some great open source and free tools to use can be:

  • Brackets: for text processing.
  • Inkscape: for vectorial graphics (great to make GUI!).
  • GIMP: for Image edition.
  • Audacity: for Sound and Audio design.
Here's a sneak peek of the story script, from the Quickstart project.

	start:
	  - play morningBGM:
	  - show room: WITH FADE CONTINUE
	  - show deuzi: happy AT CENTER WITH FADE
	  - deuzi says: "Hello, welcome to (bold)the Quickstart!(end)"
	  - wait: 300
	  - deuzi says normal: "Are you ready to create great visual novels?"
	  - choice:
	    - "Yes!":
	      - deuzi says happy: "That's great! Go ahead!"
	    - "Not yet!":
	      - deuzi says: "Well, I'll be here when you're ready!"
	  - deuzi says normal: "If you're new, don't forget to play (bold)the Tutorial(end) game, where me and my friends will show you around the basic features of RenJS."
	  - deuzi says happy: "And if you already have some experience, you can go ahead and start writing!"
	  - scene: endGame
								

All of the story files are in a standard format called YAML, a human-readable data-serialization language. A key aspect of this language is that indentation is very important, as it marks the start and end of the different sections.

Indentation is the amount of spaces at the start of the line, before any text. You can choose between two or four whitespaces, or a tab character, but you can't mix between them once you decided on one.

In the script example above you can see the indentation at play. The first word, marking the name of the scene starts at zero level of indentation, and all the actions inside it are at level one. The choice action has a list of options inside (that will be displayed to the player to make a decision), and each is indented one extra level.Furthermore, each possible option in the action has inside a list of actions that will be played if the player chooses that path, and each of these actions are indented one more level.

The Tutorial

If this is your very first encounter with RenJS, you should play the Tutorial. This tutorial is a game made with RenJS itself, that showcases the most important features of RenJS.

Play the Tutorial

The Quickstart

If you want to go straight to writing, the Quickstart is a minimal game with a few resources already set and configured, for you to try and test.

Download the Quickstart

RenJS Glosary

To create a visual novel with RenJS, we're going to use many different elements to compose both the game and the story itself. When reading this documentation, you will find references to all of these concepts, so it's better to get familiar with them first.

Game elements

To make the game structure more easy to design, there are four main elements that compose it. These are:

  • Story
  • Setup
  • GUI
  • Configuration

Each of these elements correspond normally to a file with the same name. If you check the Quickstart example, you will find them inside the story directory. The story is roughly speaking, the text of your story. A succession of actions such as displaying text and showing images. But before telling a story, you need to declare all of the story elements that compose it, such as locations, characters, etc. The setup is where you do this. The GUI, or Graphical User Interface is to define all the elemnts of the game that are not strictly part of the story, like menus and the Head Up Display. Finally, the configuration lets you set some important parameters for the story to look just as you want.

Story Elements

A story in a Visual Novel is told mostly through text and dialogue, just as any other story, but with the additional feature of visual support, hence the name. The text elements can be of two kinds, normal messages that will display inside a message box, and dialogue, that will also display the name of the character speaking inside another box, called the name box.

To help with structuring, the visual elements can belong to a specific category, each with their own way of appearing in the screen and properties. If you've played other Visual Novels, you're probably familiar with most or all of these elements already:

  • Backgrounds: A background is an image that normally stretches to occupy the whole screen, and will be shown behind all other elements.
  • CGs: CG stands for Computer Graphics, and it's a name given to any static image shown in the screen. These images can be placed anywhere on the screen and can be animated as a spritesheet and programatically (i.e. moving them, changing the alpha and scale).
  • Characters: The characters in a Visual Novel differ from a normal CG, because each one can have many images associated with it. Each of these images is called a look, and it normally represent a state of that character, such as emotional expressions, different outfits or body poses. Characters are not only a Visual element, since they can be made to talk.

The visual elements are related to the part of the story being told, so they will often appear, dissappear and change their position in the screen. The way in which they will show or hide is called a transition. Some examples of transitionsare:

  • CUT: Simply show or hide a visual element immediately.
  • FADE: Fade in or out a visual element by slowly making them transparent or solid. If changin from one image to another, the first one will disappear completely before the new one will start appearing.
  • FUSION: Similar to FADE, the new image will transition from transparent to solid on top of the old one, but without waiting for the old one to disappear.
  • FADETOBLACK and FADETOWHITE: A black or white overlay will cover the screen, then the image will be set behind it, and finally the overlay will disappear. The transition for the overlay will be a FADE transition.
  • MOVE: This transition is usen when you want to change the position of one visual element in the screen, and animate the movement.

Besides visual elements, music and sound is very important for setting the atmosphere of the story. In RenJS there are three types of audio elements:

  • BGM (Background music)
  • SFX (special effect)
  • BGS (Background sound)

Another big part of a Visual Novel is interactivity, by giving the player a list of options that they can choose from. In RenJS, there are two ways of doing that. Choices and interrupts. They both present the player with a list of options to choose from, that will make the story branch itself. The difference is that the choices will stop the game until the player interacts with them, while the interrupts will show in the screen, but the story will continue, and the player can choose or not to interact with them.

It is also possible to keep track of the player choices and use them to branch the story at any later point too. For example, a decision taken during the begining of the story could affect its ending. This brings the concept of variables, a way to store and read information, and logic operations that can compare these variables to make the story take different paths.

Story structure

Now that we know what elements can be inside a story, we can see how to organize them inside it. The story script is separated in scenes. Each scene contains a list of actions, and each action is related to any of the previously mentioned story elements. This is a list of the main actions that can be used in the story script:

  • Say and Text: Display text, word for word, in a message box, and wait for the player to click to continue with the story. A say action will also show the name of the character inside a name box.
  • Show and Hide: Show or hide a visual element with a transition. Optionally, it can take a position where to show it, and in the case of the characters, which look to show.
  • Animate: Only valid for CGs, it can animate programatically properties like position, alpha and rotation, or start a spritesheet animation, or a combination of both.
  • Play and stop: Play and stop music and SFX.
  • Choice and interrupt: Display a list of options for the player to choose from. Each option will have a list of actions to execute if it's chosen.
  • Variables: This action allows for storing information with key value. Variables can be read with its key, for logic and arithmetical operations and to display them in text, by using curly braces.
  • If and Else: This action contains a condition and list of actions that will be executed if the condition is true. It can optionally be followed by an else action containing a list of actions to execute if the condition is false.
  • Scene: Start another scene. You would normally use this action at the end of the current scene, for advancing the story, but it can be called at any point, for example, inside a choice or an if, to branch the story.
  • Wait time or click: Simply wait for a moment before continuing with the story, or force the player to click to continue.
  • Effects and ambients: Special effects, both visual and auditory. The different between them is that effects are a one off thing (e.g. a thunder flashing in the screen with its corresponding SFX and screen shake), while the ambients perdure over time until you remove them (e.g. a rain effect with particles falling and a rain BGS).
  • Call: RenJS allows you to add whatever custom action you might need in your story alongside the ones listed above. The call action will execute a javascript function in a plugin, and it will also send any parameters that you want. Inside this function you can use any of the game elements used by RenJS, for example, the visual elements currently showing, and all the variables created by the story. And since RenJS is based on PhaserJS, all of its API is available to add new graphical elements, and even create minigames.

Files Structure

RenJS games falls into the multiplatform HTML5/Web category. This means they will run as a web page in a browser. The multiplatform part comes from the fact that most devices nowadays can run an internet browser, like any computer and most mobile phones and tablets.

The game, then, is made up of a webpage, the RenJS library, and all the story assets, such as the story text and configuration and the images and audio files.

The Quickstart is a minimal game that comes with all of the necesary files, organized so that it will be easier for you to start writing. Let's use this project as an example to explore the required files.

What you should find inside the Quickstart directory.

Index File

The index file is located at the root of the directory, and it's the starting execution point of the game. When this file is loaded in the browser, it will load the RenJS library (renjs.js) and boot.js file, that will give it some instructions on how to create the game. Both of these files are located in a directory called RenJS.

You can see that not much else is happening in this file. In this case, the game will create a new canvas object and add it to the document's body. If you want to use a specific canvas element, you can create it and then specify its id in the Boot file.

Boot File

The boot file contains very elementary information for the game to start correctly, even before the story itself is loaded. For example, to create the game, it will need to know the screen resolution, and how to set up a very basic loading page.

This file is in the javascript language. You don't need to know any programming, but it's important to look at the RenJSConfig object and check what parameters have to be changed to conform to your game. Let's explore each of the options that we can define here:

  • Name: The name of your game.
  • H and W: The height and width of the game canvas.
  • Background Color: By changing the background color you ensure all FADETOBLACK transitions, including those between the menus and game, will be to this background color, instead of pure black.
  • Renderer and Scale Mode: These two parameters are related to the Phaser game creation.
  • Loading Screen: The loading screen for the game, that will be shown while downloading the resources and setting up the game. It can have a background and a loading bar that will fill up, from left to right, as the game is loaded. The loading bar is a spritesheet with one (full bar) or two frames (empty and full bar), and it will be placed at the x and y pixel location indicated in this configuration.
  • Fonts: To be able to use different webfonts in the game, they have to be loaded as css. This parameter points to this file in the assets directory.
  • GUI Config, Story Config and Story Setup: Where to find these key story files.
  • Story Text: This parameter is a list of files that will contain the scenes of the story. In this case, and for short games, you can have everything in a single file. But as the story grows, keeping the story separated in different files is a great way to organize your writing.

Story Setup

The story setup contains all the references to the visual and audio story elements, contained in one YAML file. During the story, you will not be referencing images and audio files directly, but a key associated with them into this setup file. In this way, you can create your story using placeholder assets, that you can later change.

In this file you can also setup lazy loading for the game, in case you want to use this feature.

Backgrounds

The backgrounds are usually static images, so the only parameter you need to add, besides the key name, is the file location (normally inside the assets directory). The key names have to be unique and can't have white spaces or dashes, but underscores are allowed.


	backgrounds:
	  room: assets/backgrounds/room_day.jpg
	  room_night: assets/backgrounds/room_night.jpg
	  room_night_light: assets/backgrounds/room_night_light.jpg
						

After the backgrounds tag, three backgrounds are declared with key name and file.

Characters

The characters are declared under the characters tag, with an unique key name and a few parameters:

  • Display Name: The display name is the name that will be shown in the name box when the character speaks. If this property is omited, the key name will be used as the display name, but contrary to the key name, the display name can have whitespaces and special characters such as accents and dashes.
  • Speech Colour: A color associated with this character, that will be used for the text color when displaying the name.
  • Looks: A list of images representing a state of the character. As with all key names, the look identifiers have to be unique for the character (but re used for a different character), and can't have whitespaces or dashes.

characters:
  deuzi:
    displayName: Deuzilene
    speechColour: "#ca90cf"
    looks:
      normal_school: assets/characters/Char3NormalSchool.png
      happy_school: assets/characters/Char3HappySchool.png
      angry_school: assets/characters/Char3AngrySchool.png
      normal_casual: assets/characters/Char3Normal.png
      happy_casual: assets/characters/Char3Happy.png
      angry_casual: assets/characters/Char3Angry.png
  liz:
    displayName: Liz
    speechColour: "#d5e6e7"
    looks:
      normal_school: assets/characters/Char2NormalSchool.png
      happy_school: assets/characters/Char2HappySchool.png
      angry_school: assets/characters/Char2AngrySchool.png
      normal_casual: assets/characters/Char2Normal.png
      happy_casual: assets/characters/Char2Happy.png
      angry_casual: assets/characters/Char2Angry.png
						

In the code above, two characters are declared, each with six different looks.

The different looks of the character deuzi.

CGs

The CGs (Computer Graphics) are images that can be displayed and animated. CGs can be a static image or a spritesheet. A spritesheet is a single image that contains all the frames of one or more animations.

As with the other elements, the cgs tag starts the section where the cgs are declared, each with unique key name. If the cgs is static, only the file information is needed. If it's a spritesheet, it needs not only the file, but also the frame size inside the image, and a list of all the animations that it contains.

The animations are declared with a key name, and are defined by their start and end frames, and the framerate. The frames inside a spritesheet are numbered starting with zero, and counting all the frames that fit inside the image, by going from the top left corner to the bottom right one.


	cgs:
	  phone1: assets/objects/phone1.png
	  phone2: assets/objects/phone2.png
	  horse:
	    spritesheet: assets/objects/horse.png 192 144
	    animations:
	      head: 1 4 20
	      run: 5 11 20
						

In this example, there are two static cgs called phone1 and phone2, and one spritesheet cgs called horse.

The spritesheet contains frames of 192x144 pixels, and two animations:

  • head:With the frames 1 to 4, and a framerate of 20 fps.
  • run:With the frames 5 to 11, and a framerate of 20 fps.

The first frame, with number zero, represents the normal state of the cgs.

The spritesheet with the animations color coded. First frame, or normal view, in orange; head animation in pink and run animation in blue.

Audio

The audio for the game can be declared under two different tags, music and sfx. The only information needed for these elements is key name and file, and the file should be in a web friendly audio format, such as mp3 or ogg. The difference between music and sfx is how they will be treated when playing them: Music will be looped by default, and sfx only played once.


	music:
	  morningBGM: assets/audio/Evan_Schaeffer_-_03_-_Glow.mp3
	  storeBGM: assets/audio/Evan_Schaeffer_-_18_-_Big_Tree.mp3
	sfx:
	  ringtonePinkPhone: assets/audio/nokia6210-24-elise.mp3
	  ringtoneGreenPhone: assets/audio/alcatel-top_secret.mp3
						

Here we declare two background music elements, and two sound effects corresponding to ringtones.

Extra assets

Any other asset (images, audio, spritesheets, etc) you need for your game, that don't enter in the previous categories can be declared here. Why would you need extra resources? One of the usual cases is to use paired with the ambient and effect actions. For example, the RAIN ambient needs a water drop image to use for the particles, and a looping background sound. Another action that normally needs extra assets is the call action, that allows you to execute plain javascript code. If you were to show images or play sounds, you can declare them here and when the code will be executed they assets will be preloaded.

Since the extra assets can be of many types, this section is further indexed by the types of assets you're declaring:

  • image: Declare static images under this tag, with key name and file.
  • audio: For audio files of any kind.
  • spritesheets: Besides the key and the file name, the spritesheet needs two numbers that for the height and width of each of the frames it contains.
  • scripts: You can load javascript files that will be added to the page, instead of including them into the index file.

  extra:
    image:
      rain: assets/ambient/rain.png
      thunder: assets/effects/Thunder_Effect.png
    audio:
      rainBGS: assets/audio/Rain.mp3
      thunderSFX: assets/audio/thunder_strike_1.mp3
    spritesheets:
      explosion: assets/effects/explosion.png 450 274
    scripts:
      lightbeam: assets/ambient/LightBeam.js
						

After the extra tag, we load a few assets of each category.

Configuration

The Story Configuration lets you set up many parameters and special values to use in the story. All of these values are inside a single YAML file (normally Config.yaml), that has to be pointed at from the boot file, just like the Setup file.

Special Positions

When showing characters, you can use the keyword AT to specify where in the screen they will appear. The character looks, that is the images that represent them, are anchored from its bottom center, so the pixel coordinates in the screen have to be chosen to coincide with this point. Normally, images are anchored from its top left corner, but since we'll want most characters to align from their feet, this change of anchor makes things easier.

The special positions in the Quickstart and Tutorial, marked with a pink line. The characters anchor point is marked in blue, Deuzi is in CENTER, Jair in OUTRIGHT.

Since the characters will be shown roughly in the same positions througout the game, it's possible to define a list of special positions that can be referenced by name, after the keyword AT in a show action. This is done in the configuration file, under the positions tag.

You can define as many special positions as you want. If you have a DEFAULT position, it will be used when the position is not specified.


positions:
  DEFAULT: 
    x: 400
    y: 600
  OUTLEFT: #Outside of the screen, left side
    x: -133
    y: 600 #The y should be at the bottom of the screen
  LEFT: 
    x: 133
    y: 600
  CENTER: 
    x: 400
    y: 600
  RIGHT: 
    x: 666
    y: 600
  OUTRIGHT: #Outside of the screen, right side
    x: 933
    y: 600
						

In the Quickstart example, there are five different positions, and the DEFAULT is the same as the CENTER. The screen resolution for this game is 800x600 pixels, and since we want the character's feet to be at the very bottom of the screen, the y coordinate is 600 for all the options. The positions OUTLEFT and OUTRIGHT are outside the screen, when showing characters in these positions, they will not really appear, but they're useful for simulating a character entering from the sides of the screen.

Default Transitions

A transition is the way in which a image will be shown, hidden or exchanged for another one. The most usual transitions are CUT, that will simply show or hide the image at once, and FADE, that will make appear or dissappear slowly by changing the transparency of the image, but there are a few others. Check the whole list of transitions here.

When using the actions show or hide, you can specify a transition to use, by using the keyword WITH. If the transition is not specified, the default transition defined in this section, under the defaults tag, will be used.

When characters talk, by using the say action, they can also change their look. In this case, the transition can't be specified in the action itself, and it will always use the one defined here under the say tag.

It's also possible to set here what transitions to use for showing/hiding choices, both text and visual choices, and the game menus.

Another important option to define about the transitions is if the player can skip them. When the option skippable is set to true, if the player clicks in the middle of a transition, the transition will jump to the end. This was the default behaviour in the first version of RenJS, but now you can opt out of it.


transitions:
  defaults: # Default transition when showing/hiding
    characters: FADE
    backgrounds: FADE
    cgs: FADE
    music: FADE
  say: CUT #How to change character expression in say action
  # Transition to use when showing/hiding choices
  visualChoices: FADE
  textChoices: CUT
  menus: FADE
  # Transitions can be skipped by the player by tapping
  skippable: false
						

In this example, the default transitions for all visual elements will be FADE, but when using the say action, the character looks will change immediately with a CUT transition. The visual choices and the menus will be faded into the screen, but the text choices (along with their boxes) will be shown with CUT.

Timers

The timers section lets you tweak the waiting time for:.

  • Fade time: How much it will take, in miliseconds, to complete the FADE transition. If fading in and out at the same time (changing one image for the other) the total time will not change, but each part will take about half the defined time.
  • Auto time: In automatic mode, the game will advance on its own. The story actions that require the attention of the player, like text and say will remain in place for a while, so that they can be read. How much time it will wait is defined here, in miliseconds. If you want the auto mode to go faster, this number should be lower.
  • Skip time: Skip mode is roughly the same as auto mode, but very fast.
  • Timeout: When doing a wait action, if the time is not specified, this value will be used.

	# Fade transition time, in miliseconds
	fadetime : 750
	# Time in each action that waits (e.g. text and say) when skipping
	skiptime: 50
	# Time in each action that waits (e.g. text and say) when auto playing
	autotime: 150
	# Default waiting time for timeouts if not specified
	timeout: 5000
						

Logs

Two features can be used optionally by setting these two properties:

  • Log choices: This features keeps track of all the player decisions when facing a choice action. When replaying the game, the choice boxes of the previously taken paths will be tinted, and more easily identifiable. If you don't want to use this feature in your game, set the property logChoices to false.
  • Log text: This feature keeps track of all the say and text the player has seen, no matter the different paths they could have taken, and allows them to read them again. The text will be shown again in the message box, and the game will be paused until reaching the most recent action. For this feature to work, the HUD needs to have the buttons for navigating the log (show previous log message, show next log message, go to last log message).

	# If logChoices is true, previously chosen choices will be shown in a different color
	logChoices: true
	# If logText is true, all executed say and text actions will be kept in a log that can be checked
	logText: true
						

Lazy Loading

Normally, when you want to play a RenJS Visual Novel, the first step is to load the entire game into the webpage. When loading the assets (setup in this same Setup.yaml file), the player will see a loading screen that can include a bar showing the progress. For short and small games, this is not a problem, since the game will be loaded fairly quickly. But for long games with lots of assets in higher quality, the waiting time could become a problem.

The main idea of lazy loading is that the player can start playing the game before the whole game is really loaded. The assets will be loaded in batches, sorted by priority according to what the player needs to see next. In big games, where the player is expected to play in different session, the game will not need to load the totality of the assets, and the player will never see any difference.

In esence, what this module does is to delay the loading of the assets until the moment they are needed, grouping them by scene. Just as before, the player will see a loading screen while the assets are loaded. But this doesn't mean there will be a loading screen at the start of each scene. The assets have to be loaded just once, and they will be available for all subsequent scenes that need to use it. If all the assets used in a scene were loaded previously, then no loading screen is needed and the scene can start immediately.

The assets can be further grouped into episodes. That is, an episode is a group of scenes, that will all be loaded together at the same time. So when a scene from an episode starts, the assets from that scene, and from all the scenes in that episode will be loaded. This will effectively skip any loading phase for any other scene in the same episode.

To add lazy loading to your game you will need to setup a few things. The main information needed is which assets will be used in each scene. This can be obtained directly from the story, but analyzing the whole script to do this extraction is costly. Furthermore, some assets, like the ones set in the extra section of the file, may be harder to find, since they could be used internally by Ambients, Effects or Plugins, without being explicitly written in the story. For these reasons, the first configuration under the lazy loading tag will be assetsPerScene, that will have, per each scene in the game, a list of the assets it needs. To make things easy, when the option findAssets is set to true, the story script will be analysed in its entirety when loading the game, and the assets per scene list (minus the extra assets) will be printed in the console, ready to be copied and pasted into this setup. Extra assets should be added manually into the scenes that use them.

Another configurable parameter is backgroundLoading. To further minimize waiting time, this option starts loading further episodes in the background. This means that the player will see a loading screen for the first episode, and while playing it, the assets for the next one will start loading. When the player gets to the next episode, there is a possibility most or all of the assets for it will be already loaded. The benefit of this option will depend on the nature of the game you're writing. If the game is mostly linear, at least in the use of its assets, then this feature will save lots of waiting time. But if the game can take wildly different paths (again, in terms of assets) then predicting what asset will be used next won't be as easy, and the benefits of background loading will be minimal.


lazyloading: 
  findAssets: false
  loadingScreen: true
  backgroundLoading: true
  episodes: 
    - [start, enterSchool]
    - [storySetup, writingTheStory]
    - [interval, storeAtNight,backToTheRoom]
    - [day2, lessonStoryFlux,lastClass,graduation]
  assetsPerScene:
    start:
      morningBGM: music
      street_morning: backgrounds
      deuzi: characters
    enterSchool:
      title: image
      school_morning: backgrounds
      deuzi: characters
      folders: cgs
      lessonRenJSConfig: cgs
						

GUI

The GUI, or Graphic User Interface, is everything that is not strictly part of the story, like the menus and the HUD. The GUI is just as important for the story, since it sets the mood for the player even before she starts the game. There are many resources about how to choose the best interface for your game. There’s also a rich community of visual novel developers who create and distribute their own art and designs, sometimes as free creative commons assets.

To setup the GUI you need a configuration YAML file (identified as the guiConfig in the boot file). In this file, you will describe each part of the GUI. For example, a menu is usually composed of a background and a few buttons. In the file, you would have to write where to find the background image, same for the buttons, adding also where they should be located and what they do when clicked.

This configuration file can be done in two ways: you can write it it manually, or using the RenJS GUIBuilder tool, that lets you create the file visually by dragging and dropping the components.

But before diving into the design, let's define exactly how is a GUI composed: Which components do we need, which menus are mandatory, etc.

Menus

A menu is a set of options presented to the player, to help them start the game, find information, change settings, or save and load the current game.

In RenJS, there's only one mandatory menu, the Main Menu. This menu is the first screen the players will see after the game is loaded, and it should allow them to (at least) start a new game. Other menus, such as the Settings Menu or the Save and Load Menu, are optional.

The usual components you can find in these menus are:

  • Background: A background image, normally occuping the whole screen.
  • Buttons: The buttons have an event asociated to their interaction. This event can be, for example, starting a new game, changing the menu, loading a game, etc.
  • Images and Animations: Static or moving decorations that you can place anywhere on the menu.
  • Labels: Written text that you can place anywhere on the menu.
  • Background Music: An audio file that will play when the menu is opened.
  • Sliders: A component to set a numeric value to a property, for example, the music volume. Normally, you'll use this component on the Settings Menu.
  • Save/Load Slot: A thumbnail showing a screenshot of the saved game in that slot. A default image will be shown when the slot is empty.Normally, you'll use this component on the Save and Load Menu.

Main Menu

This menu is the first thing the player will see after the game is loaded. From here, the player should be able to start the game, and could also access the Settings Menu and/or the Save and Load Menu. If you don't want to use a Save and Load Menu, but want to have a simpler scheme with one only save slot, you could add here a continue button that will load the last saved game.

The main menu for the Tutorial and Quickstart games.

Settings Menu

This menu should allow the player to change the game settings. A return button will also close this menu return to either the Main Menu or the game (if called from the HUD). There are currently four properties available for the player to change:

  • Music Volume: The volume of the background music.
  • SFX Volume: The volume of the sound effects.
  • Text Speed: How fast the text appears in the message box in HUD, during game.
  • Auto Speed: In autoplay, the game will not wait for the player to click after text is displayed, but will continue after a brief pause. The Auto Speed will determine how long this wait is.
The settings menu for the Tutorial and Quickstart games.

Save and Load Menu

This menu should allow the player to save and load games in different slots. Each slot is represented by three components, the Save/Load Slot (a thumnail of the saved game), a Save Button and Load Button. As with the Settings Menu, it's usefull for this menu to have a return button.

The save/load menu for the Tutorial and Quickstart games.

HUD

The HUD (heads-up display), is the method by which information is visually relayed to the player as part of a game's user interface; that is, everything you see in the screen while playing the game, that is not strictly part of the stort itself. This includes the message box where the story text and dialogues will be displayed, and buttons for using the Skip/Auto features or accessing the Menus.

Let's see in detail which elements can be part of the HUD:

  • Message Box: A box, usually ocuppying the bottom of the screen, where the story text will be displayed.
  • Name Box: When the text displaying in the Message Box is part of a dialogue, the an extra box will be shown containing the name of the character talking.
  • Click to Continue (CTC): To give the players all the time they need to read the contents of the Message Box, the game will not continue until they click anywhere on the screen. The Click to Continue is simply an animated image that will indicate to the players that the game is waiting for them to click to continue.
  • Choice Box: The choice action allows the players to make decisions during the game by choosing between different options. These options will be presented each in their own box, that the player can click as a button.
  • Interrupt Box: Very similar to the Choice Box, the Interrupt Box can have two states: One normal interruption, and one urgent state, that indicated the interrupt is about to be lost.
  • Buttons: Apart from opening the Settings and Save/Load Menus, during the game the player can choose to use the Skip and Auto features. All of this should be available through buttons on the HUD.
  • Images and Animations: You can add other images and animations to the HUD to achieve some kind of aesthetics.
The HUD for the Tutorial and Quickstart games, featuring Message Box, Name Box, CTC, Choice and Interrupt Boxes and four buttons: Open Settings Menu, Open Save Menu, Skip and Auto.

Fonts

As we mentioned before a few times already, a RenJS game is actually a webpage. In webpages, when you want to use special fonts and styles, you need css files. CSS, or Cascading Style Sheets is a style sheet language used for describing the presentation of a document written in a markup language such as HTML.

The fonts you use for written text in the game are also part of the aesthetic of the game, so you'll want to choose them carefully. For example, you might want to use a cursive or gothic font for an historical or fantasy game. You can find a multitude of free fonts to use around the internet, usually in the ttf (TrueType Font) format. These files will have to be included in the game, and the way to include them is through the css font file.

The css font file will list all the fonts you will use in the game, and where to find the corresponding ttf font files. Finally, this file has to be included into RenJS, by way of pointing at it from the boot file, fonts property.

Let's see an example of a css font file. The font-family will be the name you will use to refer to that font in the GUI configuration file, and the src is a path on where to find the ttf font file. The path should be relative to the css font file, so if the css file and ttf file are in the same directory, the src should be only the name of the ttf file.




	@font-face {
	  font-family: 'audimat-mono';
	  src: url('assets/gui/audimat-mono.ttf');
	  src: url('assets/gui/audimat-mono.ttf').format('truetype');
	  font-weight: normal;
	  font-style: normal;
	}
	@font-face {
	  font-family: 'old-standard';
	  src: url('assets/gui/OldStandard-Regular.ttf');
	  src: url('assets/gui/OldStandard-Regular.ttf') format('truetype');
	  font-weight: normal;
	  font-style: normal;
	}
	@font-face {
	  font-family: 'playfair';
	  src: url('assets/gui/PlayfairDisplaySC-Regular.ttf');
	  src: url('assets/gui/PlayfairDisplaySC-Regular.ttf') format('truetype');
	  font-weight: normal;
	  font-style: normal;
	}
						

If you're using the RenJS GUI Builder tool this file will be created automatically.

Manual Configuration

Warning

This is the old way of setting up the GUI and it's somewhat limited. If you want an easier and more flexible way to make your GUI check the GUI Builder.

One of the ways to configurate the GUI is by manually writing the configuration file (GUI.yaml). This file is written in a way that is easy to understand and, therefore, easy to write.

The GUI file (identified in the boot file as guiConfig) has three main sections:

  • Assets: The list of assets used to build the gui, with key and file name.
  • HUD: The head-up display, this is what the player will see during the game, and it includes the text box to show the dialogs, the name box to show the name of the character talking and any button the player can use during game like autoplay, skip or save.
  • Menus: All the different menus of the game. You should at least have one main menu to start the game, but you can have as many extra menus as you want. Some examples of what extra menus you could need are a settings menu, a load game menu, a scenes menu, etc.

Assets

A list of all the assets, ordered by their types: images, spritesheets (for the buttons), audio, etc. The spritesheets take two extra parameters that indicate the width and height of each of its frames.

You can call each of this assets whatever you like, but it’s a good practice to use descriptive names for each one. The following example is a list of the assets for the Tutorial/Quickstart game GUI.


assets:
  fonts:
    - audimat-mono
  images:
    mainBackground: assets/gui/menu.png
    settingsBackground: assets/gui/settings.png
    sliderFull: assets/gui/slider.png
    messageBox:  assets/gui/textbox.png
    nameBox:  assets/gui/namebox.png
    ctc: assets/gui/ctc.png
  spritesheets:
    startButton: assets/gui/startbutton.png 163 83
    loadButton: assets/gui/loadbutton.png 163 83
    saveButton: assets/gui/savebutton.png 163 83
    settingsButton: assets/gui/settingsbutton.png 163 83
    returnButton: assets/gui/returnbutton.png 163 83
    qmAutoButton: assets/gui/qmenuauto.png 47 45
    qmSkipButton: assets/gui/qmenuskip.png 47 45
    qmSettingsButton: assets/gui/qmenusettings.png 47 45
    qmMuteButton: assets/gui/Mute.png 50 50
    qmSaveButton: assets/gui/qmenusave.png 47 45
    choice: assets/gui/choice.png 716 65
    interrupt: assets/gui/interrupt.png 716 95
  audio:
    mainMusic: assets/audio/Evan_Schaeffer_-_01_-_Aqueduct.mp3
						

HUD

The hud, as explained above, is the part of the user interface shown during the game. The HUD configuration for the Tutorial/Quickstart games is the following:


hud:
  area:
    - 640 450 748 554
  message:
    position: 
      x: 46 
      y: 435
    textPosition: 
      x: 36 
      y: 36
    textStyle:
      font: 16pt audimat-mono
      wordWrap: true
      wordWrapWidth: 545
      fill: "#ac9393"
  name:
    position: 
      x: 36 
      y: -40
    textStyle:
      font: 20pt audimat-mono
      boundsAlignH: center
      boundsAlignV: middle
  ctc: 
    position:
      x: 570 
      y: 90
    animated: false
  choice:
    separation: 95
    textStyle:
      font: 20pt audimat-mono
      boundsAlignH: center
      boundsAlignV: middle
      fill: "#666666"
  interrupt:
    textStyle:
      font: 20pt audimat-mono
      boundsAlignH: center
      boundsAlignV: middle
      fill: "#664b4b"        
  buttons:
    auto: 
      position:
        x: 647
        y: 502
      sprite: qmAutoButton
    skip: 
      position:
        x: 694
        y: 502
      sprite: qmSkipButton
    save: 
      position:
        x: 694
        y: 457
      sprite: qmSaveButton
    settings: 
      position:
        x: 647
        y: 457
      sprite: qmSettingsButton
						

The area refers to a space defined by two points in the screen (x1 y1 x2 y2) inside of which the clicks of the player don’t count as game clicks. So, if the game is waiting for the player to click, to continue with the story, but the player clicks inside this area, the game will not continue. We need this area to manage the interaction with the buttons on the HUD. If the player clicks in the Save Button, it just means they want to save, not continue with the story. This area doesn’t have to be exactly the size of the menu, and it can actually cover more parts of the screen. You can define as many non clickable areas as you like by adding more lines to this section.

The message is where we define the Message Box. It takes a position in the screen to show the image (relative to its top left corner), a text position to define where to start writing the text, relative to the message position, not the screen; and the text style defined by font, if it should wordwrap, and the width and the text color. You can add more text style options as long as they are valid for a Phaser Text Object.

The name tag defines the Name Box. Its position should be relative to the Message Box, and you also need to define a text style for it.

For the CTC (click to continue) you just need to define a position relative to the text box, and say if it’s animated or not. If not animated (not a spritesheet) it will blink.

The choice is the Choice Box. Unless you specify a position, it will be centered in the screen. You also need to define a text style and a separation, in pixels, to show all of the choices as a list.

In interrupt you can only define a different text style, since it will take the same parameters defined for the choice.

In interrupt you can only define a different text style, since it will take the same parameters defined for the choice.

Under the buttons tag we define each button by key. This key will be used to determine what the button will do. For example, the button save will call the save action, the button skip will call the skip action, and so on. The button has also a position and a sprite.

You proably noticed that there’s no sprites declared for message, name, etc. This is because the names of the assets are the default ones. If you change the asset name, then you would need to define also a sprite name in each of these elements.

Menus

The menus section is a list with the different available menus of the game. The only mandatory one has to be called main, and it’s the menu that will be called when the game loads. Each menu has a background (if not declared, it will take the default asset _menuname_Background), optionally music, and a list of buttons. To make it easier for making a settings menu, you can define also sliders, for things like volume or game speed.

As with the HUD, the buttons and sliders keys will also define what they do (or what property they change).


menus:
  main: 
    music: mainMusic
    buttons: 
      start: 
        position:
          x: 112
          y: 462
        sprite: startButton
      load:  
        position:
          x: 320
          y: 462
        sprite: loadButton
      settings:
        position:
          x: 528
          y: 462
        sprite: settingsButton
  settings:
    buttons:
      return: 
        position:
          x: 112
          y: 500
        sprite: returnButton
      start:  
        position:
          x: 320
          y: 500
        sprite: startButton
      load:
        position:
          x: 528
          y: 500
        sprite: loadButton
    sliders:
      textSpeed: 
        position:
          x: 436
          y: 235
        sprite: sliderFull
      autoSpeed:
        position:
          x: 436
          y: 364
        sprite: sliderFull
      bgmv:
        position:
          x: 147
          y: 235
        sprite: sliderFull
      sfxv:
        position:
          x: 147
          y: 364
        sprite: sliderFull

						

RenJS GUI Builder

RenJS GUI Builder is a tool to automate the creation of the GUI configuration file. This tool allows you to create the GUI by adding components visually, moving them around easily and adjusting every little detail until you have exactly the GUI you want. When everything is ready, you can build it, and this will create a template for your game where you'll only have to add the parts of your story.

Story Actions

With RenJS, you make your game by writing a script. This script is structured as a group of interconected scenes, and each scene contains a list of actions that will be executed one after the other.

The actions are the way to tell the story. In the visual novel genre, a story is normally told by showing images, such as backgrounds and characters, and displaying text, and this is what you can do with each action.

There are many types of actions and each one has its own syntax, but usually they follow this pattern:


	- action actor: extra parameters
							

The action will be the name of the action, the actor the object over whom it will apply, and the extra parameters can be anything. For example, the actions show, hide and play all follow this format exactly. There are some exceptions, like the action text, that doesn’t require an actor, or say, that is inverted as “actor says” to be written more naturally.

Other important aspects of the syntax are the dash, the colon and the indentation. The scripts are written in a format called YAML that is then translated to format a bit more computer friendly called json. For this translations to go smoothly, these three key points need to be respected. The indentation should be the same for all the actions in the list. Each action has to start with a dash followed a whitespace, to indicate it's an element of a list. And the colon separates both sides of the action. Even when the action doesn't have any extra parameters, the colon has to be present.

Syntax Cheatsheet

Show and Hide

	- show [background]: WITH [transition]
	- show [character]: [character_look] WITH [transition] AT [position]
	- show [cgs]: WITH [transition] AT [position]
	# hide anything
	- hide [background|character|cgs]: WITH [transition]
						
Say and text

	- [character] says: Text
	- text: Text

	# Use text styles: bold italic and color
	- text: (bold)This text is bold(end), (italic)and this is italic(end).
	- text: This word is (color:#f593e6)colored(end)!
						
Play and stop

	- play [music|sfx]: WITH [FADE|CUT]
	- stop bgm: WITH [FADE|CUT]
						
Choice and interrupt

 	- choice:
	    - Option 1 text:
	      	- ACTIONS FOR OPTION1
	    - Option 2 text:
	      	- ACTIONS FOR OPTION2
	    - Option 3 text !if(condition):
	      	- ACTIONS FOR OPTION3
  	- interrupt NUMBER:
	    - Interrupt 1 text:
	      	- ACTIONS FOR INTERRUPT1
	    - Interrupt 2 text:
	      	- ACTIONS FOR INTERRUPT2
						
Variables

	# define a variable and assign a value 
	- var [variable_name]: [TEXT|NUMBER|BOOLEAN]

	# show variable in a text
  	- text: foo {variable_name} bar

  	# counter variable
  	- var counter: 0
	- var counter: {counter} + 1
						
If

	- if (CONDITION):
		- ACTIONS FOR CONDITION TRUE
	- else:
		- ACTIONS FOR CONDITION FALSE
						
Scene

SCENE1:
	- ACTIONS FOR SCENE 1
	# call another scene
	- scene: SCENE2

SCENE2:
	- ACTIONS FOR SCENE 2

						
Wait for time or click

    - wait: [miliseconds|click]
						

Show and hide

The show action allows you to display images in the screen, while the hide action removes them.

RenJS has three different types of images that you can use: backgrounds, characters and cgs. This elements have to be declared in the Setup file before they can be used.

Show Backgrounds

A background is an image that normally stretches to occupy the whole screen, and will be shown behind all other elements. Since only one background can be displayed at a time, if there is already a background on screen, the previous one will be hidden automatically.

With the keyword WITH you can choose the transition to use when showing or hiding the background.


	# show background with id school_morning
	- show school_morning: WITH FADE
	# change one background for another
	- show school_afternoon: WITH FUSION
						

Show Characters

The characters in a Visual Novel are represented by many images, each one called a look, meaning a state of that character, such as emotional expressions, different outfits or body poses. Showing a character, therefore, means showing one of its looks. If the look id parameter is omited, the default look to show will be called normal.

With the keyword AT you can define where in the screen the character image will appear. The position can be a coordinate, two numbers separated by a comma (no whitespaces), or a special location, and will be relative to the center bottom of the images, more or less where the character's feet should be. If the position parameter is omited, the default position will be the DEFAULT position defined in the Config file.

Just like with backgrounds, a transition can be specified to define the way to show them.


	# show character with id deuzi, look id happy, centered in the screen
	- show deuzi: happy AT CENTER WITH FADE
	# show character entering from the side of the screen
	- show liz: AT OUTRIGHT WITH CUT
	- show liz: AT RIGHT WITH MOVE
	# show character at a specific coordinate in the screen
	- show liz: sad AT 500,600
						

Show a CGs

CG stands for Computer Graphics, and it's a name given to any image that is not a background or a character. These images are anchored in their center, which means, the position used in the show action will align with this center point.

By default, the cgs will be shown in a layer on top of characters and behind the GUI, but they can also be forced to be shown behind the characters (always on top of the backgrounds).

In addition to the transition and the position parameters, it's possible to change the scale (zoom) and angle of the image. If you want to move or animate a CG, use the animate action.

Just like with backgrounds and characters, a transition can be specified to define the way to show them.


	# show CG with id phone1 at a specific coordinate in the screen
	- show phone1: WITH FADE AT 200,200
	# show CG scaled and rotated
	- show phone2: WITH FADE AT 400,300
	  zoom: 0.5
	  angle: 180
	# show CG behind the character layer
	- show horse: AT 180,350 BEHIND
						

Hide images

You can hide any type of element with the action hide and its id.

If you want to hide all of the characters at the same time, you can use the special id CHARS, and if you want to hide everything, characters, backgrounds and cgs, there's the special id ALL.

Just like with the show action, a transition can be specified to define the way to hide them.


	# hide a character
	- hide deuzi: WITH FADE
	# hide all characters
	- hide CHARS:
	# hide all
	- hide ALL: WITH CUT
						

Show, hide and continue

Sometimes you want to show (or hide) many elements at the same time. For example, show a background and a character at the same time, show or hide two characters, or show one character when another one is being hidden.

All of this can be achieved with the keyword CONTINUE. By default when showing or hiding elements, you will use a transition that takes a little bit of time, the most common one being FADE. When you Fade In or Out an image, the game will wait until the transition is over to execute the next action.

What the CONTINUE keyword does is make it so the game will execute the next action immediately after, without waiting for the transition to be over. This will effectively create the illusion that both actions are executed at the same time.


	# show a background and character at the same time
	- show school_morning: WITH FADE CONTINUE
	- show deuzi: WITH FADE
	# hide one character and show another at the same time
	- hide deuzi: WITH FADE CONTINUE
	- show liz: WITH FADE
	# show three characters at the same time
	- show deuzi: AT CENTER WITH FADE CONTINUE
	- show liz: AT RIGHT WITH FADE CONTINUE
	- show jair: AT LEFT WITH FADE
						

Animate

The animate action allows you to animate cgs. The animation can be a tween of the sprite properties, a spritesheet animation or a combination of the two approaches.

Tweening

Tweening means to change the properties of an element in time, linearly, from the original values to the new values. For example, we can tween the transparency of an image to make it transparent, by tweening its alpha property to zero. The time it takes to tween should be specified in miliseconds.

You can tween one or more of these properties:

  • Alpha: The transparency of the image. It goes from 0 (completely transparent) to 1 (completely solid).
  • Zoom: The scale of the image, as a proportion of the original size. For example, 1 is the same as the original, 0.5 is half of it, and 2 is twice it’s original size.
  • Position: Where is the image located in the screen, as a coordinate given as x y. The x and y numbers are relative to the top left corner of the canvas, and they can be outside of it too.
  • Angle: The rotation of the image, in degrees, from 0 to 360.

   - animate cgs_id:
      time: number
      [alpha: number]
      [zoom: number]
      [position: coordinate]
      [angle: number]
						

In the next example we first show the cgs called phone1 and then we tween the position and alpha in 1000 miliseconds (1 second). The effect this will give is the phone moving from one side of the screen to the other while disappearing.


  - show phone1: AT 100,100
  - animate phone1:
    time: 1000
    position:
    	x: 500
    	y: 100
    alpha: 0
						

Spritesheet Animation

Spritesheet animation is more like traditional animation: you have different frames for an image, and change them every few miliseconds to give the ilusion of movement. For this type of animation you need to load the cgs as a spritesheet in the setup.

A spritesheet animation can run once or looped, and in case of the latter, it can have a time limit or not. If the animation is looped and it doesn't have a time limit, the game will continue to the next action immediately, and you will have to stop the animation explicitly from the script.

Let's see how to use each mode with examples, by animating the horse spritesheet already used in the setup.

In this first example we simply show the horse and we animate the head animation. After the animation is get to the last frame, the action is finished, and the cgs image will stay as the last frame of the head animation. Then we do another action, and finally we repeat the animation, but backwards.


  - show horse: AT 180,350
  - animate horse:
    spritesheet: head
  - text: The animations can be player normally or backwards!
  - animate horse:
    spritesheet: head BACKWARDS
						

In the next example we animate the run animation, looped, by 1 second. After this time, the animation stops and the game continues to the next action. When the animation stops, the image will freeze in whatever frame it gets to. Finally, to reset it to the normal view, we call the animation stop.


  - animate horse:
    spritesheet: run LOOPED
    time: 1000
  - animate horse:
    spritesheet: stop
						

The next example does something similar, but starts the animation without a timer. Another action is then executed (a say action) and finally the animation is stopped.


  - animate horse:
    spritesheet: run LOOPED
  - deuzi says: The horse will stop after this dialogue.
  - animate horse:
    spritesheet: stop
						

In the last example, we will combine the run animation with tweening the position, making it so the horse will run across the screen.


  - animate horse:
    spritesheet: run LOOPED
    position:
      x: 650
      y: 350
    time: 2000
						

Say and Text

The actions say and text let you display a message inside the text box. The difference between them is that the say action will also display the name of the character inside the name box, in the colour of the propery speechText defined for that character in the setup. The text will be shown with a transition, letter by letter, until the message is complete. This transition can be skipped by the player by tapping anywhere.

After the message is shown whole, the click to continue image will be shown (if present in the GUI) and the game will wait until the player clicks to continue with the next action.

The say action can also include a look parameter, to quickly change the look of the character before the message is displayed.


	# display a message with text
	- text: You see someone approaching.
	- show liz: WITH FADE
	# display a message with say
	- liz says: Hey! What are you doing here?
	# display a message with say, changing the look
	- liz says angry: We were all looking for you! 
						

Play and Stop

These actions allow you to play and stop sounds. Sounds can be of two types, background music and sound effects. Each one should be defined in the right section in the setup.

You can play only one background music, or bgm at a time. If you do a play bgm action and another bgm is already playing, the first one will be stopped before starting the new one.

Background music can be played looped whole with the LOOPED parameter. You can also loop a bgm from a specific time with the LOOPED FROM time parameter. In this case, the music will start as usual, and when it reaches the end, it will restart but from the specified time (in seconds).

Sound effects, or sfx will only play once, and you can play as many as you want on top of each other.

To stop the bgm you don't need the id of the music currently playing, but simply use the bgm tag.

You can use the transitions CUT and FADE for both play and stop.


	# play a bgm once with fade in
	- play morningBGM: WITH FADE
	# play a sfx with tag ringtoneSFX
	- play ringtoneSFX:
	# change the music to schoolBGM looping the whole bgm
	- play schoolBGM: LOOPED
	# stop the background music
	- stop bgm:
	# play another bgm looping from the 2.5 seconds mark
	- play storeBGM: LOOPED FROM 2.5
						

Choice and Interrupt

The choice action is one of the most important actions you can use, since it's the main way for the player to interact with the game.

This action will show a list of options to the player for them to choose, and each of these options will have a list of actions to execute only if the player chose them. This list of actions can be anything you do in a normal scene, including another choice, or a change of scene.

Normally, after executing the chosen option actions, the game will continue with the actions directly after the choice, but if a change of scene is triggered, any action after that one will be discarded.

In the next example three options will be displayed. If the player chooses the first option (with text "Yes!"), the scene will change after the dialogue, and the actions after the choice will be discarded. If the player choses any other option, the game will continue with the actions after the choice, as normal.


    - choice:
      - Yes!:
        - deuzi says happy: That's great, let's go!
        - scene: leaveWithDeuzi
      - No!:
        - deuzi says: Ok, but I'm leaving!
        - hide deuzi:
      - Uh, I'm not sure?:
        - deuzi says: Well, think about it while I get my coat.
        - hide deuzi:
    - text: Deuzilene disappears in the crowd and you find yourself alone.
    - scene: stayInParty
						

Interrupt

An interrupt is like a choice action, but while the choice waits for the player to make a decision, the interrupt will display the option, but will not stop the game. If the player decides to interrupt, then the actions of the interrupt will be executed, before continuing.

The interrupt can include a number of actions to wait before disappearing (thus disallowing the player the interruption), but if the scene changes, any interrupt still showing will automatically disappear.

In the next example, the interrupt will be shown only for the next 6 actions.


  - deuzi says: I know you're new in town, so I thought I could show you around a bit.
  - deuzi says: What do you think?
  - interrupt 6:
    - Isn't it a bit awkward???:
      - deuzi says angryC: What do you mean?  Because I'm your teacher?  
      - deuzi says happyC: We're almost the same age!
      - deuzi says normalC: You might be teaching some years from now too. 
      - deuzi says angryC: Then you'll see how awkward it is to be called professor and be treated like and old person.
      - deuzi says normalC: Anyway, as I was saying...
  - deuzi says: You probably know it already, but this is a small town.
  - deuzi says: There's not much to see, really.
						

Visual Choices

The options of a choice can be images instead of text, in which case you will use the tag visualchoice, and each option should be the image id (it can be setup as a CG or as extra) and where it will be shown.


  - liz says: Choose a phone!
  - visualchoice:
    - phone1 AT 620,300:
      - play ringtoneSFX:
      - text: Tururu Ruru Ruru Ruruuuu
      - liz says: You chose the pink phone.
    - phone2 AT 180,300:
      - play ringtoneSFX2:
      - text: Pi Pi Ri Pi Ripi Pi Ri
      - liz says: You chose the light blue phone.
						

Show Message along with Choices

If you want to show a message along with the choices you can use the first line inside the choice action for this purpose.


  - show deuzi: happy
  - choice:
    - deuzi says: Choose a partner!
    - Deuzilene:
      - text: You chose Deuzilene!
    - Liz:
      - text: You chose Liz!
 					
Say action along with choices.

Conditional Options

Sometimes you need to show an option only if a condition is met. In these cases, the conditional option can be used for either choices, visual choices or interrupts. If the condition is not satisfied, that option will not be shown.

To make an option conditional you need to add an if like structure, followed by a condition, exactly like the ones used in the if action.

In the following example, the last option will only show if the variable readBook is set to true.


  - choice:
    - Choose Deuzilene:
      - marco says: Good choice
      - var partner: "deuzi"
    - Choose Jair:
      - marco says: You really like a challenge, right?
      - var partner: "jair"
    - Choose no one !if ({readBook}):
      - show marco: surprise
      - marco says: No one has ever completed this task alone before!
      - var partner: "no one"
      - show marco: normal
  	- marco: So you've chosen {partner}, are you happy with it?
 					

Variables

The var action allows you to store values during the story. These values then can be displayed in text or dialogues and can be used to compare and form conditions. The values will also be saved and restored when the player saves and loads games.

If you try to use a variable before it's defined in the story, the value will be undefined, and in the case of booleans, it will be false. What the var action does is declare and assign a value to a variable identified with a specific name.

This kind of behaviour is often called an asignation. An asignation is said to have two parts, left and rigth, separated by a colon. The left part has information about the variable being set, and in our case, also includes the name of the action. The right part contains the value that will be assigned to that variable, and it can be of three types: Strings (Text), Numbers or Booleans (Value true or false).

String Variables

String variables are text, and as such, they can be displayed in text and say actions. To get the value of a variable as text, you use the variable name surrounded by curly braces, i.e. {var_id}. You can also do this same thing when assigning String values to variables.


	# Create String variable with id name
    - var name: Spike
    # Create Number variable with id score
    - var score: 10
    # Create String variable with id report, using previous variables in the value
    - var report: "Hi {name}, you have {score} points!"
    # Show the contents of the variables
    - text: {report}
    - spike says: "What? Only {score} points? I though I was doing so well."
 					

Numeric Variables

A numeric variable will be assigned a number. This can be a constant number, but it can also be an arithmetic operation that resolves into a numeric value: like addition, subtraction, etc.

To write an operation you need to use special symbols, like:

  • + (Plus): Addition
  • - (Dash): Subtraction
  • * (Asterisk): Multiplication
  • / (Slash): Division

The operations also can use parenthesis () to change the solving order of the operation. As with normal arithmetic operations, multiplication and division have precedence over addition and subtraction.

When writing operations, they should usually be between inverted commas. This is because the parser will sometimes freakout if it finds strange symbols. To ensure it reads the whole line as one text to analyse, better to be safe and surround it by inverted commas.


# create some variables with constant values
- var score: 0
- var extraPoints: 3
# modify the value of the score variable, by adding 10
- var score: "{score} + 10"
# create some more variables and do complex operations
- var bonus: "{extraPoints} - 1"
- var totalScore: "({score} + {extraPoints}) * {bonus}"
# display the value of the variable totalScore
- text: The total score is {totalScore}.
 					

Boolean Variables

Boolean variables can store one of two values, a true or a false. But, as with numeric variables, they can be assigned operations that resolve into a boolean value.

The symbols used for these operations are:

  • && (AND): The operation will be true if both values between the AND are true.
  • || (OR): The operation will be true if either value between the OR is true.
  • ! (NOT): The operation will be true if the value next to the NOT is false.

# assign boolean values directly
- var lightOn: true
- var lampOn: true
# do some operations
- var lightOff: "!{lightOn}"
- var allLightsOn: "{lightOn} && {lampOn}"
- var canRead: "{lightOn} || {lampOn}"
 						

In the previous example the variables allLightsOn will be true only if both lightsOn and lampOn variables are true, but the canRead variable only need one of them to be true.

Another way of getting a boolean value is by comparing numbers and numeric variables. In this case, the symbols used for these operations are:

  • > (Greater than): The operation will be true if the left value is greater than the right value.
  • >= (Greater than or equal to): The operation will be true if the left value is greater than or equal to the right value.
  • == (Equal): The operation will be true if both values are equal.
  • <= (Less than or equal to): The operation will be true if the left value is less than or equal to the right value.
  • < (Less than): The operation will be true if the left value is less than the right value.

As with the previous operations, parenthesis () are allowed.


- highScore: "{score} > 10"
- perfectScore: "{score} == {maxScore}"
- lowScore: "{score} <= {maxScore} / 2"
 						

In the previous example we use the numeric variables score and maxScore to decide the values of the boolean variables defined. The highScore variable will be true only if the score variable is greater then 10.

String variables can also be compared in this way using the equal operator.


- choseDeuzi: "{partner} == 'deuzi'"
 						

If and Else

The if action allows you to branch your story. It contains a condition and a list of actions that will be executed only if the condition is true.

Optionally, it can also have a list of actions to execute if the condition is false, this is called an else action and it can only appear after an if. The lists of actions can contain whatever action available, including other ifs. After executing this list, the story will continue with the actions after the if (or else, if present).

The condition can be any boolean variable or operation, as seen in the var action.


  # if action with an operation
  - if ({partner} == "deuzi"):
    - show deuzi: happy
    - deuzi says: I knew it would be me!
  # else action
  - else:
    - text: Deuzilene looks disappointed but tries to hide it.
    # nested if, without elses
    - if ({goingSolo}):
    	- deuzi says: Let's see if you can beat my score.
  # unconditional actions after the if-else
  - text: You and your partner leave together.
						

Scene and End Game

The scene action is used to change from one scene to the other. Every scene in the story has a name and a list of actions that conform it. If no scene is called before or at the end of a scene, the game will simply stop.

You can name the scenes whatever you want, but the names can't have spaces or dashes (but you can use underscores and camelCase). Remember also that you need to have a starting scene called start.


# first scene
start:
  - show marco: WITH FADE
  - marco says: Good morning students, are you ready to choose your partner?
  - choice:
    - Yes:
      - scene: choosePartner
    - No:
      - marco says: What's the problem?
      #other actions

# second scene
choosePartner: 
  - marco says: We should go to the teachers room
  - show teachersRoom:
  # other actions
						

If you want to end the game and return to the main menu you have to call the endgame action. Another way to end the game is through the strong>effect ROLLINGCREDITS. This effect takes a parameter called endGame, that, when set to true, will automatically end the game and return to the main menu after the effect is over.


  - text: What kind of ending?
  - choice:
    - End immediately:
      # end the game right now and return to main menu
      - endgame:
    - End after credits:
      # end the game after the rolling credits
      - effect ROLLINGCREDITS:
        endGame: true
        text:
          - This example made by
          - lunafromthemoon
						

Wait

The wait action allows you to force the player to wait for some time (in miliseconds) or until they click anywhere on the screen.


	- deuzi says: Ok, tell me when you're ready!
	- wait: click
	- deuzi says: I'm still not ready!
	- wait: 1000
	- deuzi says: Ok, let's go then!
						

Call

The call action allows you to execute javascript functions from a Plugin. You can send to this function as many parameters as you want.


  # this plugin will simply print the two words sent as parameters
  - call helloWorld:
    firstWord: 'hello'
    secondWord: 'world'
  # this plugin will add the given number of animated starts randomly in the screen
  - call addStars: 5

						

Ambients and Effects

These actions allow you to show visual and sound effects. The difference between them is that effect is a nuclear action that ends after its execution, while ambient effects perdure over time. For example, an effect can be a thunder, while an ambient can be rain.

RenJS comes with a few ambients and effects, and you can tailor them a bit to better suit the aesthetic of your game. All the assets used for these screen effects, either images, spritesheets, music and even code should be loaded in the extra section of the setup file.

You can add more screen effects, you can do so in the form of Plugins.

Ambients

The ambient action starts an ambient by name. Calling the special ambient CLEAR instead will stop any ambient still on. The available ambients are:

  • RAIN: Starts a particle emitter and background sound for a rain mood. You need two extra assets: rain (spritesheet) and rainBGS (looping audio)
  • SAKURA: Starts two particle emitters to look like cherry blossoms falling slowly, carried by a faint breeze. You need one extra asset called sakura (spritesheet).
  • SNOW: Starts three particles emitters for a snowy mood. You will need two extra assets: snowflakes (spritesheet) and snowflakes_large (spritesheet).
  • CLEAR: Destroys the particle emitters and background sound.

  # start ambient RAIN
  - ambient RAIN:
  - jair says: It started raining, when will it stop?
  # stop ambient
  - ambient CLEAR:
  - jair says: Well, that was fast.
						

Effects

The effect action executes a screen effect by name. The available effects are:

  • SHAKE: A screen shake.
  • FLASHIMAGE: It will flash an image for a moment, optionally accompanied by a sound effect and a screenshake. Parameters:
    • image: The tag of the image to show. This image has to be declared in the setup, usually in the extra section.
    • screenShake (optional): Boolean value. If true, there will be a screenshake.
    • sfx (optional): The tag of the sound effect to play.
  • ROLLINGCREDITS: Fades to black and starts scrolling a list of text like the rolling credits of a film. Parameters:
    • text: The list of text to show. If you want to leave some spaces between the lines, you can fill it with null lines.
    • music (optional): Music to start with the effect.
    • timePerLine (optional): How fast you want the scrolling, per each line, in miliseconds. Default value is 700ms.
    • endGame (optional): Boolean value. If true, the story will end when the scrolling is over and the game will return to the main menu. Default value is false.

	# screenshake
	- effect SCREENSHAKE:
	- marco says: It looks like there's going to be a storm.
	# show thunder
	- effect FLASHIMAGE:
		screenShake: true
		sfx: thunderSFX
		image: thunder
	- marco says: That's it, time to go home.
	# show credits and end game
	- effect ROLLINGCREDITS:
		endGame: true
		text:
			- Example made by
			- lunafromthemoon
			# empty line next
			- Made with 
			- RenJS
						

Transitions

A transition is the way in which a image will be shown, hidden or exchanged for another one. Changing the position of an image, or flipping it, follows the same process with a show action, therefore it can happen that an image will be changed by that same image. There are a few transitions ready to use, but you can make your own transitions as Plugins and use them transparently.

The available transitions are:

  • CUT: The image will simply appear or disappear at once. When exchanging images, for example, one character look to another, the effect will be immediate.
  • FADE: This transition will interpolate the alpha (transparency) of the image in time. To show an image it will go from alpha 0 to alpha 1, in a FADE IN; to hide it, it will do the contrary, going from alpha 1 to alpha 0 in a FADE OUT. To change on image for another, it will first do a complete FADE OUT and then a FADE IN.
  • FUSION: If used to show or hide an image, FUSION will behave exactly like FADE; but when changing images, FUSION will place the new image on top of the old one, with alpha 0, and do a FADE IN. This will look aproximately like one image is fusing with the other one. This transition will work best with images that have the exact same outline, for example, backgrounds, or characters that don't change their look shape.
  • FADETOBLACK, FADETOWHITE, FADETOBG: In this transition the whole screen will be covered by a color in a FADEIN, then the changes to the images will be performed, and then a FADEOUT of the overlay will reveal the changes. In FADETOBG, the color is the background color defined in the boot configuration of the game.
  • MOVE: This transition, normally used for characters, will interpolate the current position of the image to the new one. For example, to show a character entering the screen from the right first you would show it in the position OUTRIGHT (outside of the screen, to the right side), and then show it at another position, using the MOVE transition.

Multilanguage Games

RenJS provides an Internationalization (I18N) module, that allows you to distribute your game with many languages all in one.

When translating games there's one approach often used, where each dialogue and text in the game has an identification key that is replaced by the correct phrase in runtime. This way of doing I18N brings its share of problems. For example, it makes the script a lot less legible. But the biggest issue is that it limits the translations themselved, since each text would have to be in the same order and about the same length, a rule that is very inconvenient to follow.

For these reasons, the way I18N works in RenJS is by having different resources for each language. These resources can be anything, such as images and sounds, but also the script of the story itself.

In this way, each resource in the game will be labeled with each language tag, or as neutral. When starting a game, the player will have to choose the language, and the corresponding resources will be loaded.

You can use this feature for any case in which you might want to have different resources for the same game. One other usual use case could be using different resources for a NSFW game with a censured version.

Language Selection Screen

One of the first things to do when adding multilanguage support is setting up the Language Selection Screen. This screen will be the first thing a player sees, even before loading the rest of the game, which means it has to be configured in the boot.js file.

Let's see a simple language selection screen for the Quickstart game.


const globalConfig =  {
  ...
  i18n: {
    background: 'assets/gui/i18nscreen.png',
    langs: {
      "en": {
        'asset': 'assets/gui/i18n/en.png',
        'position': {
          'x': 200,
          'y': 458
        },
        'size': {
          'w': 163,
          'h': 83
        }
      },
      "es":{
        'asset': 'assets/gui/i18n/es.png',
        'position': {
          'x': 450,
          'y': 458
        },
        'size': {
          'w': 163,
          'h': 83
        }
      }}
  }
  ...
}

const RenJSGame = new RenJS.game(globalConfig)
RenJSGame.launch()
						

The Language Selection Screen is setup under the i18n tag, and it's somewhat similar to the Loading Screen configuration. It has a background, that simply points to a background, and then a list of languages under the lang tag.

Each language is configured under a Tag, that is the key name of the language. In this example we have two languages: English with tag en and Spanish with tag es. These tags have to be unique for each language, but they can be whatever you want. The configuration itself is for a button that when pressed, will start loading the game in that language.

  • Asset: The spritesheet representing the language button. It should have two or three frames for: Normal View, Hover View and Pressed View.
  • Size: The height and width of each frame in the button spritesheet.
  • Position: The position where the button will be displayed.

Resources Configuration

Once you have your Language Selection Screen setup, we need to be able to pick the different resources for each language tag. For this you will place the segregated resources in diferent directories, named after these tags. For example, if you normally have a directory called story where you put the file Story.yaml, now you could have inside it two more directories, en and es, each one with the correct story file inside.

The second step is pointing at the right files from the boot.js/GUI.yaml/Setup.yaml files, by using the special tag LANG. This tag will be converted into the chosen language tag in runtime, making it point to the right resources.


const globalConfig =  {
  ...
  'loadingScreen': {
    'background': 'assets/gui/quickstartbg.png',
    'loadingBar': {
      'asset': 'assets/gui/LANG/loaderloading-bar.png',
      'position': {
        'x': 109,
        'y': 458
      },
      'size': {
        'w': 578,
        'h': 82
      }
    }
  },
  ...
  'fonts': 'assets/gui/fonts.css',
  'guiConfig': 'story/LANG/GUI.yaml',
  'storyConfig': 'story/Config.yaml',
  storySetup: 'story/Setup.yaml',
  'storyText': [
    'story/LANG/Story.yaml'
  ],
  ...
}

const RenJSGame = new RenJS.game(globalConfig)
RenJSGame.launch()
						

In this example, we can see some of the resources are separated into languages, but some others are not. The Loading Screen has the same background, but the Loading Bar asset will be different depending on the language.

Same thing for the yaml files, some of them are neutral, such as Setup.yaml, but others like the story itself and the GUI are picked for the language.

Observing this example we can see also that we will have two places where the resources will be segregated: One in the story directory, and one in the assets directory.

You can check the Internationalization example and see it in action!

Plugins

With RenJS you can create a classic Visual Novel just by writting your script (and a few configuration files), no need to know any programming. But what if you need some extra feature? For example, you could want to add a hidden-object minigame, a very complex HUD, or a gallery of scenes or achievements.

To do this, to extend RenJS, we have the Plugins. Plugins are pieces of javascript code that you can call from inside the game. With the Plugins you can do anything you want, from simply doing some calculations to extending RenJS and using it as a base to create a game of a completely different genre.

To create and add a Plugin to a RenJS game, you'll have to create a javascript object extending the RenJS.Plugin class. This plugin object will have a property called game (called with this.game) that will refer to the RenJS game, that is in itself, a PhaserJS game. With this property you will have access to any of the contents of your game (e.g. the current background displayed), but also to the whole suite of tools that Phaser provides.

In short, anything you can do with javascript, and in particular, anything you can do with PhaserJS is possible to do from within a RenJS game.


	class HelloWorld extends RenJS.Plugin {

		onCall(params) {
			console.log('Hello World Plugin');
			console.log(params.firstWord + ' ' +params.secondWord);
			this.game.resolveAction();
		}
	}

	RenJSGame.addPlugin('helloWorld',HelloWorld)
							

In this minimalistic example, the plugin is created, extending the RenJS.Plugin class, with just one function. The funtion onCall will be called from the story script, when using the call action. This example does nothing but printing on the console the parameters sent, and finally, it calls the this.game.resolveAction() function to let the game know it can continue with the next action in the script.

Plugin Structure

As seen in already, the function onCall, allows you to call a function from the story script. But there are many other ways to use the Plugins besides this specific use case. The RenJS.Plugin Class provides handles for each phase of the game where you might need to add your own functions, that you need to simply overwrite.

Let's see in more detail the structure of a Plugin, and what handles can be overwritten.


	export default class Plugin implements PluginInterface {

		protected game: RJS;
		protected name: string

		constructor(name, game){
			this.game = game;
			this.name = name
		}
		// plugin handles
		onInit(): void {}

		onStart(): void {}

		onCall(params): void {}

		onLoad(slot,data): void {}

		onSave(slot,data): void {}

		onTeardown(): void {}
	}
						

This is the class definition of the RenJS Plugins. As you can see, the constructor receives a name and the game object, that will be later available to use from any of the handles. Then handles themselves are empty and do nothing unless you redefine them.

On Init

The onInit() handle will be called when the game is loaded, but not yet started. The only phase previous to this one is preloading of the game and initialization of the game itself. So, the game will be fully loaded, the GUI will be created (but no menus are shown yet), and the story text, setup and configuration will all be available for you to use.

This handle is perfect for adding new features to the GUI, since no part of the GUI, except the loading screen, is shown yet. For example, you could add new menus like a gallery, a glosary, etc.

On Start

This handle will be executed at the start of a new game, just before the first action of the script is executed. Use it to set up things you need to do in a per game run basis. For example, if you want to change some things in a New Game + run.

On Call

The onCall handle will be called from the story script, by way of the call action. You can send to this handle as many parameters as you want (and in any format), and there is no limit to what you can do inside it. The only mandatory thing is that, at some point, there has to be a call to the this.game.resolveAction() function.

The functions you call during the story can be, as previously said, basically anything. RenJS can't make any asumptions on when the action is over to continue executing the next action, since these functions can be either syncronous (when the function is over, the action is over) or asyncronous (the function is over, but the action is still pending). For example, if you want to use an external API called as a REST service, you'll normally need to wait for the asyncronous response.

Let's see an example of the same Hello World plugin we saw before, but this time we will make it asyncronous.


	class HelloWorld extends RenJS.Plugin {

		onCall(params) {
			console.log('Hello World Plugin');
			console.log(params.firstWord + ' ' +params.secondWord);
			setTimeout(() => {
				console.log("Goodbye World");
				this.game.resolveAction();
			}, 1500);
		}
	}

	RenJSGame.addPlugin('helloWorld',HelloWorld)
						

In this case, when each line of the function is done executing, the function is technically over, but the action still waits for the timeout callback to finish, and let the game know it can continue with the next action in the script.

On Save and On Load

These two handles are called, as you might imagine, when saving and loading the game. RenJS saves games in slots (identification number), locally into the player's browser. The onSave handle is called just before the game is saved, and onLoad is called when the data is retrieved, but just before setting the game up.

You could use these handles to save and load data to and from an external API, and so have your players data online, making it available in different devices. You might also want to use them to add other information to the saved game, for example, a timestamp.

On Teardown

This handle will only be called when the player goes from the story to the main menu, usually, after finishing the game. If the player simply closes the game, it will not be executed. Use to clean up any big memory objects you might be using during the story, but avoid saving data or doing anything else that is of big importance for the story.

Plugins as Transitions

Another way to use the Plugins is to add new transitions to the game. For this, the onCall handle has to be overloaded with the right parameters to conform to a transition, but then it can be used as any other transition during the story.

When using the onCall handle in this way, the function doesn't have to call this.game.resolveAction(), but it will have to return a Javascript Promise, to let the game know when the transition is over.

Let's see an easy example on how to do a Transition Plugin. This example will do a transition from one sprite to another one by first hiding the old sprite, then waiting for one second, and finally shoing the new sprite. It is probably not really useful in a story, but it's a good way to see what does what.


	class MoveAfterOneSecond extends RenJS.Plugin {
	    // Transitions don't need to call resolveAction, but return a Promise
		onCall(from, to, position, scaleX) {
	       return new Promise(resolve => {
	            // set new properties 
	            to.x = position.x;
	            to.y = position.y;
	            to.scale.x = scaleX;
	            //hide old sprite
	            from.alpha = 0;
	            //wait for one second
	            setTimeout(() => {
	            	// show new sprite
					to.alpha = 1;
					// finish transition
					resolve();
				}, 1500);
	        }); 
		}
	}

	RenJSGame.addPlugin('MOVEONESECOND',MoveAfterOneSecond)
						

When using the Plugins as Transitions, the onCall handle will receive all the parameters a normal transition would receive, and it has to return a Promise, to let the game know when the transition has finished.

The parameters are:

  • From: A Phaser Sprite representing the RenJS element (a background, character look or cgs) to hide. When showing an element for the first time, this property will be null.
  • To: A Phaser Sprite representing the RenJS element (a background, character look or cgs) to show. When hiding elements, this property will be null.
  • Position: An object with properties x and y where the To element should appear.
  • ScaleX: A number with the scale in the x axis for the To element. This number is usually either 1 or -1, and represents the sprite as flipped or not.

Something to take into account is that if you're using the transition to show elements for the first time, or to hide them, th

RenJS Internals

We said that when creating a Plugin, the this.game property will contain a reference to the RenJS game, and that you can take advantage of this to do whatever you want with it. But this means little if you don't know what's inside a RenJS game itself.

While you shouldn't care too much about how RenJS does things, knowing where to find some key elements will make the programming of your Plugins much more easy.

The Managers

The different parts of the story are all taken care by different managers, and you can access them with the property this.game.managers. Knowing what each manager does and what information they keep is key to understand how RenJS works. Let's see what managers there are:

  • Background: Access this manager through this.managers.background. This manager takes care of the backgrounds of the story.
    • Current Background: Access the current background (Phaser Sprite) with this.managers.background.current.
  • Character: Access this manager through this.managers.character. This manager takes care of the characters of the story.
    • Characters Metadata: A map of all the characters metadata, such as displayName and speechColour. Access it with this.managers.character.characters[character_tag]. If the character is currently showing on screen, the currentLook property will be the corresponding Phaser Sprite.
    • Current Characters Showing: A map of all the characters currently on screen, with look, position and scaleX. Access it with this.managers.character.showing[character_tag].
  • CGs: Access this manager through this.managers.cgs. This manager takes care of the cgs of the story.
    • Current CGs: The information of the currently on screen cgs is contained in two maps. With this.managers.cgs.current[cgs_tag] you can access all the metadata from the cgs, such as position, zoom, angle, layer (it determines whether they're shown in front or behind the characters) and flipped. The Phaser Sprites, meanwhile, are contained in the map this.managers.cgs.cgs[cgs_tag].
  • Audio: Access this manager through this.managers.audio. This manager takes care of all the audio of the story.
    • Current Music and Sound: You can obtain the Phaser.Sound objects for bgm(background music) and bgs (background sound) with this.managers.audio.current.
  • Logic: Access this manager through this.managers.logic. This manager takes care of the permanent variables set with the Var Action, and branching the story by way of choices and ifs.
    • Variables: You can obtain the map of all the variables that have been set throughout the game with this.managers.logic.vars. You can read, modify and even completely change this map to whatever you want.
    • Choices Log: The property this.managers.logic.choicesLog contains a log of all the choices the player has taken in the current run of the game, with an identifier for the choice (in the actions stack), the index of the option and the text itself.

Transitions

You already know that Transitions are the effect we use to show, hide or interchange sprites (backgrounds, character looks, CGs). You can reuse these transitions in your plugins, not only to create more types of transitions, but also in other cases where you might need to show or hide sprites.

You can find all of the transitions, by tag name, inside the object this.game.screenEffects.transition. All transitions return a Promise to let you know when they finished transitioning.

  • FADEIN(to, position?, scaleX?): Use this to show any sprite fading in.
  • FADEOUT(from): Use this to hide any sprite fading in.
  • FADETOCOLOUR(from, to, colour, position?, scaleX?): This transition is used internally when doing FADETOBLACK, FADETOWHITE and FADETOBG, and you can use it to fade the screen to any color you want.

The GUI

The GUI Configuration lets you describe how the GUI will be created, but you might want to add your own parts to it programatically, and for that you need to know where to find the actual Phaser objects representing the GUI.

While the GUI is quite complex, each of the big subdivisions (each menu and the HUD) is all contained into their own object, with all the sprites inside their own Phaser.Group.

Some of the things you can find inside the GUI object are:

  • GUI Configuration: The original configuration, as a json file, is available in this.game.gui.config.
  • Menus: The Phaser Groups holding each of the menus can be found in this.game.gui.menus[menu_name]. If you want to add graphical elements to the menus, you have to add them to these groups.
  • HUD: The Phaser Group holding the HUD can be found in this.game.gui.hud.
  • Choices: The Phaser Group for the choices can be found in this.game.gui.hud. This group will be empty most of the time, since the Choice Boxes will be created on the fly when executing a Choice Action.

Setup and Configuration Files

You might want to access the setup and configuration files of the game. While these files have some structure they should follow, you can also add as many elements as you want. This can be very handy when creating Plugins with lots of setup. You could have this information hardcoded into the Plugin (e.g. as a json object), but it can be easier to use the YAML files and have everything tidy in the setup file.

  • Story Setup: The story setup (Setup.YAML file) will be in this.game.setup.
  • Story Config: The story configuration (Config.YAML file) will be in this.game.storyConfig.
  • Game Config: The game configuration (object sent to the game in boot.js) will be in this.game.config.

Phaser JS

And finally, as RenJS is based on PhaserJS, the this.game property is also a reference to a Phaser Game, and you can use it to create sprites, groups, phyiscs, particle systems, and much more. Don't forget to check out their examples page and their API documentation.

Can't find what you're looking for? Join us in Discord and tell us what's missing!

Join Us!