Creating Point and Click Games with Escoria

Create Actions

Once the scene is created and Escoria template scripts are attached, the game should work. Everything should be there: the background, the character, and some action buttons imported with our game node. But actually, nothing happens if you try playing the game. We still have to add the logic and describe to Escoria what should happen and when. To do this, we will use Escoria scenario scripting, also known as Esc files.

The principle is:

  • each item receiving action will get an id, a kind of name that has to be unique in the scene and follow some naming conventions, this is the Global Id property of the items.
  • each item receiving action will have an Escoria file attached that will describe its behavior
  • each action will be related to an event, generally a button, but it can also be a timer.

The behavior can be made of several action types like:

  • talk
  • walk
  • use
  • look…

These actions are really common in point-and-click games, but others could be added. For now, we will stick to what is provided by Escoria templates files.

Make people talk

  1. So let’s go back to our project.
  2. Open back the old_man.tscn scene file.
  3. In the Inspector, find the Global Id property and set it to the name you want. Here we will use old_man. Generally, try to give explicit id, but keep it simple. On larger project, it’s a good idea to keep a file listing items with their id and eventually the scene they appear on. As you can see, our id is written small case and we replaced spaces by underscores _. Also, each global id should be unique for each item.
  4. If you want, you can set the Tooltip too (e.g. The panda master).
  5. Now, we can have a look at available actions. They are represented by the button on the bottom left. What we will need is to get the technical name of the action which can be different from the one we display to the user. Just open the ui/verb_menu.scn scene to have a look inside it. You will see a few buttons, and the node tree displaying each. If you need to change the UI of actions, this is the place. Actually, just have a look at node names.
    Action button in Godot Escoria
  6. We don’t have many things in our scene yet, so let’s just make him talk first.
  7. Open your text editor and save an empty file as old_man.esc in the device/scenes/intro-game/ in your project directory. Keep the names as consistent as possible, because there may be many of these files in your project.
  8. To attach the scenario script to the character or item, go back to Godot’s inspector and set the Events Path properties of the old_man node to the file we just created. If you launch the game nothing will happen because the action file is empty.
  9. So let’s edit our esc file and add a talk action. To do this, write the action name as defined in the verbs preceding it with ":", like this:
  10. This way, the talk action will be performed only when the talk button is pressed and the old_man selected. Let’s make him speak by adding the say keyword followed, by the global id of the one who should speak, and the content to write on screen. To make the old man speak, it could be :
    say old_man "Hello young panda, today is time for your first offering to the almighty panda god!"
  11. We can repeat this for each sentence we want to display at once and add a stop instructions. You can get something like this :
    say old_man "Hello young panda, today is time for your first offering to the almighty panda god!"
    say old_man "I have prepared a bamboo stick for you, pick it up and bring it to me."
    say old_man "Don't worry, you'll succeed."
  12. When launching the scene, click the talk button and the the old man. The first sentence should be displayed. The second will be shown when the user clicks anywhere or presses the space bar.

Of course you can alternate speakers to make dialogs. What is cool is that, once the Esc file is set, there is no need to open Godot to modify the game dialogs and interactions. Everything can be changed from this simple text file which is perfect for designers and scenarists.

Debugging errors

If the game does not respond correctly, maybe you introduced an error somewhere.

In the editor window, Godot should have displayed the Output/Debugger panel.

Click on Output at the bottom of the panel, and check the text above, it should give an indication (here, using spaces instead of tabs):

Due to a bug in this version of Godot, you may need to copy the text and paste it in your editor to be able to read it.

Setting up translations

A number of engine texts are defined by translations. Some common ones are shipped with the Escoria template, but they are not enabled by default. To do so:

Click on menu Import > Translation.
Under Source CSV, locate the translation/general.csv file.
Under Target Path, create a new device/translation/ directory, and select it.

New device/translations/general.*.xl files should appear.

This will immediately translate the demo game's New/Continue buttons, as well as the "Use xxx with xxx" texts when using inventory items below.

Note: if you test with a language different than Settings/Application/Tooltip Lang Default, all tooltip descriptions will be replaced by "global_id.tooltip" until you translate them. You can replace this setting with your language for now.

See Internationalisation for further information.

Define a Global Flag and use it

In some cases, some things might happen only if the user has performed some tests or grabbed an object, and so on. In fact, we will need two steps to do this:

  1. We will have to set an identifier to create a global flag. Global flags can contain a value which can be true or false
  2. We will have to check if the global flag is true or false when needed

We may give two examples of that. First what should the old_man say if the player use the talk action twice? Second, what should the old_man say if the good bamboo is taken and what if it’s the bad one? This way we can imagine as many conditions as we want to do different actions. This is part of the richness of the game to take care of this.

Set the global flag

To define that something has already been done, we can use the set_global command followed by the name of the flag (we may call it a variable) and assign it with a value to say if it is true or not (especially if an action reverses a flag). For example, when the old_man talks for the first time, we can say that it has already talked so that we don’t play the same dialog twice. Our dialog will become this:

say old_man "Hello young panda, today is time for your first offering to the almighty panda god!"
say old_man "I have prepared a bamboo stick for you, pick it up and bring it to me."
say old_man "Don't worry, you'll succeed."
set_global introduced true

We chose the name introduced for our flag and we say it is true.

Check the flag's value

Now, we could have a second dialog that could be launched if the player uses the talk action on the old man again. The principle is to make a block of commands. We start it with a > sign. Each line in the block needs to start with a tab character.

Next to this, we add the name of the flag between brackets to check if the value is true (add a ! before the flag name to check if it is false).

So, our old man should introduce himself only if he has not already spoken. The dialog we already wrote should be inserted in a block with the !introduced condition.

> [!introduced]
	say old_man "Hello young panda, today is time for your first offering to the almighty panda god!"
	say old_man "I have prepared a bamboo stick for you, pick it up and bring it to me."
	say old_man "Don't worry, you'll succeed."
	set_global introduced true

If the player tries to talk to him twice, nothing will happen. But we can now set the dialog that may happen when the talk action is used again and the good bamboo has been picked up. The new dialog should be displayed only if both actions have been performed. We do this by listing both flags, separated by commas.

> [picked_item, !god_appeared]
	say old_man "Now offer the bamboo to our almighty panda god, I'll summon him for you."
	set_global god_appeared true

We assume here that picked_item has been defined during a pick action performed by the user. We could store it in bad_bamboo.esc and good_bamboo.esc with a scenario file similar to this:

> [!picked_item]
	set_global picked_item true

As we can see, a flag can be used by any item of the scene, thus making it a global flag. It’s important to keep track of the timeline and not get confused. Since we now have a real interaction and several scenario file, our project is getting more difficult.

Add an object to the inventory

One important thing if the player picks an objects is that it may use it after in the adventure. We need to display the player the objects he has picked. The pick_up action on the bamboo should:

  • contain a flag that sets this characteristic
  • make the object available in the inventory area
  • hide the object in the scene

To add the object to the inventory just use a set_global to true with the global id of the object in the inventory preceded by i/. Our pick_up action would become:

> [!picked_item]
	set_global picked_item true
	set_global i/inv_good_bamboo true

Open the game/inventory_items.scn scene:

  • add a new TextureButton item that will represent the good bamboo in the inventory
    or, a (resizeable) Sprite with a Control child named area
  • attach the script to it
  • give it the inv_good_bamboo global id
  • tick the Use Combine property
  • define a Tooltip for the item

Do the same for inv_bad_bamboo.

You can reuse the sample items in inventory_items.scn in a first step. Make sure that Global Id's are correct and that Use Combine is ticked.

Make an item visible or invisible

Of course, as we said, if we pick a bamboo, it should not be in the scene anymore. We would at least have to hide it. This is simply done by using the set_active command followed by the name of the item and the value true to make it visible or false in the other case. For example:

set_active good_bamboo false

We could then modify two of our scenarios. The pick_up action of good_bamboo.esc should be modified to:

> [!picked_item]
	set_global picked_item true
	set_global i/inv_good_bamboo true
	set_active good_bamboo false

and the bad_bamboo.esc in the same way with the other bamboo global id.

And at last, we can modify the old_man's dialog to make the bamboo god appear if he already talked, and if the good bamboo was taken:

> [picked_item, !god_appeared]
	say old_man "Now offer the bamboo to our almighty panda god, I'll summon him for you."
	set_global god_appeared true
	set_active bamboo_god true

say old_man "Go give the bamboo stick to your god!" [god_appeared]

We just added a condition to the dialog to make the god appear. Note we can also add a condition at the end of a single line instead of creating a new block just for it.

Untick the god's Active property in the scene so it's hidden when the scene starts.

Using an inventory object

We have now reached the state where the player will know if he succeeded and if the adventure can go on. He will have to give the bamboo he picked up to the god. The god will thank the little panda or reject his offering and reset some values.

We can refer to the use action for this. We then need to add the name of the object as stored in the inventory. It could look like this:

:use inv_good_bamboo
say bamboo_god "Thank you for your kind offering young panda, you shall receive my blessings."

and for the bad bamboo:

:use inv_bad_bamboo
say bamboo_god "What is the meaning of this?! <<Made in China>>?!"
say bamboo_god "Be wary of my wrath as I shall curse you and all your lineage!" set_globals i/* false set_global god_appeared false set_global picked_item false set_active bamboo_god false set_active bad_bamboo true set_active good_bamboo true

We also added a default use for any other that does nothing

In many situations, items and characters can change after an action. In Godot-Escoria, it is generally done through animations. Those features are explained in Animations chapter.

Il y a une erreur de communication avec le serveur Booktype. Nous ne savons pas actuellement où est le problème.

Vous devriez rafraîchir la page.