4ian / GDevelop

๐ŸŽฎ Open-source, cross-platform 2D/3D/multiplayer game engine designed for everyone.
https://gdevelop.io
Other
11.53k stars 880 forks source link

Idea: Bundle Yarn - a dialogue editor for interactive stories #511

Closed blurymind closed 6 years ago

blurymind commented 6 years ago

Description

Stories,often told through text are a very common thing in games. Especially indie games- be it rpg, action rpg, visual novels or even simple platformers. This is so common that every time I start writing my own dialogue/story system- it feels like I am reinventing the wheel rather than making my game fun.

Some engines are built for telling stories- the rpg maker engines (http://www.rpgmakerweb.com/) for example are very popular for that reason. But so is renpy (https://www.renpy.org/) and others like twinery (http://twinery.org/) They all have very vibrant communities, full of creative people with stories to tell

Looking at gdevelop- its a very good and user friendly engine- but it doesnt have a strong storytelling toolset like the others listed. The user has to do a lot of work to create and manage a dialogue tree system and the editor has no tools to write non linear stories

Solution suggested

A few years ago I discovered YARN - a story system and editor already used on some commercially successful games: https://github.com/InfiniteAmmoInc/Yarn The yarn editor is all web based, very tiny (500 kb) and super easy to use. Its written in javascript/nodejs and the story files it outputs are simple json format. Now the editor hasnt seen much updates officially, but the indie game community has been quietly using it on more and more games-focusing more on developing more implementations of the story parser. welcome-1

While the official yarn story parser was written for the Unity3d engine, recently I found out that somebody has rewritten it in js and released it as an npm package here: https://www.npmjs.com/package/bondage screenshot2

There is already an npm library that interprets yarn story files that we can use - bondage.js. I was able to succesfully integrate it with yarn itself and add the capability to test the story https://github.com/jhayley/bondage.js

The library takes care of remembering user made choices (storing and checking yarn variables without leaving yarn or having to write event sheet logic in gdevelop) I added text scrolling and support for bbcode ontop of it. My code is embeddable, so in theory should be easy to integrate into gdevelop as well. The only bulk of the job is exposing all of this to gdevelop as an object and event sheet actions/conditions to trigger it. yarnrunner

My suggestion is to bundle Yarn editor and the bondage.js yarn story parser with gdevelop. It will make creation of story based games much easier on gdevelop.

The reason I am suggesting it is that I already had looked into its source code and ported Yarn to electron for another personal project that integrates it with three.js :p

The question is - is there any interest in having Yarn bundled with gdevelop? I know it's kind of becoming my shtick to glue open source projects recently, but after playing some of the games made with Yarn editor and using it myself - I definitely see a lot of value in it. It might help us attract some twinery users to gdevelop imo

What would be hard and new for me in the case is implementing a yarn parser behavior for gdevelop - to print out text on the screen. I am not sure how this is done and would appreciate any examples or code that might help me understand this :) Getting yarn editor itself inside gdevelop and have it communicate with gdevelop would be easy- as I already know how to do that.

In any case, are you interested in this? Without approval from @4ian I wont even attempt it

4ian commented 6 years ago

What do you mean by "refusing"? What is the output/error message? What does it do? Where are your files located and how do you check that they are properly copied or not?

blurymind commented 6 years ago

Basically I need to include these two files in index.html like this:

<script src="yarn/bondage.min.js"/> 
<script src="yarn/yarnParser.js"/> 

In order to initiate the parser inside gdevelop. I tried placing them in a subfolder called yarn, also in the same folder and even inside libs.

When I run the script it updates index.html, but when I run the game itself (playest), gdevelop's runtime fails to find them. When I open this directory,while the game is running: C:\Users\blury\AppData\Local\Temp\preview I can see that the two files are nowhere to be found. They are not being used by the game, thus why the index is failing to find them.

blurymind commented 6 years ago

Perhaps I can just copy them to the project folder? How do I make gdevelop just include them in the game folder where the index will be :)

4ian commented 6 years ago

Strange, the script should copy recursively all JS files that are in GDJS/Runtimeand Extensions/. So I would say that if you add your yarn folder to GDJS/Runtime and launch it it should be copied to C:\Users\blury\AppData\Local\Temp\preview if you run CopyRuntimeToGD.bat C:\Users\blury\AppData\Local\Temp\preview.

blurymind commented 6 years ago

It says Copying GDJS and extensions runtime files (*.js) to "..\..\Binaries\Output\Release_Windows\JsPlatform\Runtime and it does indeed copy them to that folder

But when I platest the game, the yarn folder is gone - it doesnt exist in C:\Users\blury\AppData\Local\Temp\preview

4ian commented 6 years ago

Normally if you run

CopyRuntimeToGD.bat C:\Users\blury\AppData\Local\Temp\preview

This should indicate that files are copied in C:\Users\blury\AppData\Local\Temp\preview If that's not the case, then something is wrong inside the script.

But when I platest the game, the yarn folder is gone

Yes it's normal as only the files that are needed by extensions are copied. Can you double check if you can have CopyRuntimeToGD.bat make the copy directly inside C:\Users\blury\AppData\Local\Temp\preview?

blurymind commented 6 years ago

Running this CopyRuntimeToGD.bat C:\Users\todor.imreorov\AppData\Local\Temp\preview copies the missing files:

Copying GDJS and extensions runtime files (*.js) to C:\Users\todor.imreorov\AppData\Local\Temp\preview...
29 File(s) copied
45 File(s) copied
ร”ยฃร  Copied GDJS and extensions runtime files (*.js) to 'C:\Users\todor.imreorov\AppData\Local\Temp\preview'.

Unfortunatelly when I playtest, gdevelop wipes them out, as it decides it doesnt need them

So I guess the only way to include them is by writing an extension and recompiling gdjs?

4ian commented 6 years ago

Unfortunatelly when I playtest, gdevelop wipes them out, as it decides it doesnt need them So I guess the only way to include them is by writing an extension and recompiling gdjs?

No need for this. Launch the preview, launch the script and reload the game (Open Developer tools in the preview and hit Ctrl+R).

blurymind commented 6 years ago

@4ian it works that way - but every time I launch the game I have to open developer tools,run the script and then update? :) This is no solution if I want to actually export the game- I need to write an extension to make it usable at all

4ian commented 6 years ago

@4ian it works that way - but every time I launch the game I have to open developer tools,run the script and then update? :)

Yes. Note that if you're working on JS files, you'll probably just end up launch the script, hitting Ctrl+R to see if it works, then do it again.

If you want to export the game you have to manually copy yarn folder (so won't work for automatic online builds - in which as anyway you'll need to make an extension but wait for having something that is working).

blurymind commented 6 years ago

Would be nice if we had some way of including js script files in the project and calling their methods inside the event sheet :D It would make the event sheet so much more hackable without need to recompiling ..

4ian commented 6 years ago

There is something called SourceFile in GDevelop core allowing to bundle custom JS files but it's not exposed in GDevelop 5 as it wasn't being used a lot in GD4. Might expose it in GDevelop 5 as part of "Developer tools" that you can enable in the preferences.

blurymind commented 6 years ago

I guess it would be a step towards having a more accessible js extension system that doesn't require any recompilation of gdjs :)

You can already kind of access the runtime via the JS event. Add ability to include external js files and we can kind of do it in the event sheet. But the event sheet can not modify the editor itself.

Godot engine does it in a very interesting way where anything inside project/addons/myaddon is automatically detected by the engine as an addon to interpret. Inside that folder there is a bunch of script files that can alter the editor's interface (using 'tool' key word) and describe what the addon does, with instructions to add new game objects and all. It is quite powerful and easy to use - also doesnt require recompiling godot http://docs.godotengine.org/en/3.0/tutorials/plugins/editor/making_plugins.html

But anyways- I am going offtopic with this :) If gdevelop had this, you will see new community made functionality so much more. We will start getting new stuff on a monthly basis! I mean look how well it is working for godot: https://godotengine.org/asset-library/asset

bil-ash commented 6 years ago

@4ian That would be a quite useful feature. Specially if there are 5-6 line js functions which need to be called multiple times in a game then writing the whole thing in events editor multiple times isn't a very convenient option( I am currently facing this). Instead if there is an external js file where we write the function and just call it in javascript section in the events editor,then that is a better option.

blurymind commented 6 years ago

@4ian I can move this to a sepparate issue if you like the idea :)

4ian commented 6 years ago

@blurymind Yes please do :) Please write something quite specific in this separate issue because it's still vague for me and I'm not sure we're all talking about the same thing. Also include precise examples of what it would help to achieve.

I ask all of this to avoid feature creep - don't want to spend hours and hours working on something that will end up being too complicated and used by no one (which has been the case in the past for GDevelop 4). The newIDE is already open-source and written in JavaScript so virtually anyone could already start creating Pull Requests to improve it. I'm not sure if yet another extension system would improve things - so that's why I'm asking you to be as precise as possible and include examples.

But the event sheet can not modify the editor itself.

Not sure if it's a problem. Events sheet are part of the game. It's not their role to be used to modify the editor. I think you're mixing your need of creating some new feature for the game with another need which is to be able to change the editor.

blurymind commented 6 years ago

@4ian I created it here: https://github.com/4ian/GD/issues/540 Hope I explain it well. Will provide more examples if required. I have actually written some addons for godot in the past and thats why I am pointing this out.

In any case, I am going to try to create a yarn extension by forking the shopify one. Hacking the index.html file is unsustainable imo

4ian commented 6 years ago

Ok thanks :) I've answered on the thread. Hope I don't feel too harsh when reading me - it's not the case ๐Ÿ˜‡ It's just that the issue is complex and we have to be VERY precise about what is really needed to avoid losing a huge amount of time into working on an extension system that will complexify the whole software.

blurymind commented 6 years ago

@4ian quick question - in my extension I want to point to a json file in the project folder path. Should I use a "string" parameter of the action? :) Can json files be treated as a type of a project resource?

Also would you like me to submit the progress I make in the form of a pull request? From my understanding the c++ script adds the actions/conditions to gdjs, it also tells it to include a bunch of js files. In the js script I add the functionality I want, then test it after recompiling gdjs. Whenever I make changes to the extension - I recompile gdjs, then run that batch script that copies gdjs to the newide and finaly restart the newIde, then test?

Can I skip recompiling and copying If my only changes are to the js files somehow? If so , which js files should I edit for testing? Seems like a lot of steps between itteration I started writing a test extension file, but will need to try doing the compilation stuff back home - as it seems to require a lot of work

Lizard-13 commented 6 years ago

Compiling GDevelop.js exposes the C++ extension code in the IDE, so the IDE knows about the actions, conditions and the .js files it has to export. If you'll modify the .js files only there is no need to recompile GDevelop.js (it just stores the filenames). Then you can change the .js files at GD/Extensions (modifications kept through app "builds"), newIDE/app/resources/GDJS/Runtime/Extensions (modifications kept through electron-app builds), newIDE/electron-app/dist/your-build-system-unpacked/resources/GDJS/Runtime/Extensions (modifications kept through preview), or on the preview folder at preview/Extensions (faster/just reload the game, but modifications get lost on each preview). I can be wrong as I don't know the entire proces, though

blurymind commented 6 years ago

@Lizard-13 thank you for explaining. So really recompiling gdjs is only required to register the actions/conditions in the editor? That means that after I get the c++ part right once, I no longer need to recompile it :) This is so strange- the editor is web based, but needs c++ recompilation to get access to functionality in custom js files in its event sheet. Is that designed to keep them available in gdevelop4?

I think that we need better documentation on writing js extensions with the newide in mind, but I will try to stop requesting that and get on with getting this to work ๐Ÿ‘

4ian commented 6 years ago

So really recompiling gdjs is only required to register the actions/conditions in the editor? That means that after I get the c++ part right once, I no longer need to recompile it :)

Yes and yes :) Extensions, still written in C++ contains declarations only of actions/conditions and the JS function names to be called. All the implementation of these functions are done in your extension JS files. So if you don't change the action/condition/extension interface, you don't need to recompile.

blurymind commented 6 years ago

@4ian thank you for clarifying! In that case there really is no need to rewrite the extension system or dramatically refactor it, just to enable a way to bypass recompiling gdjs to expose the newIde to custom actions/conditions. That is the only thing needed to close #540

But anyways, with this knowledge now, developing this as an extension doesnt seem that intimidating to me :)

blurymind commented 6 years ago

Some progress with this - it looks likely the electron port I made on Yarn will get merged - the reviewer has some notes that I will address tonight.

I also got contacted by an Australian game developer interested in my work on porting yarn to electron. They said that they have also been working on a tool+parser similar to Yarn - using Reactjs. I think the intent was to steer me towards their project - as its overlapping with some of my goals: https://github.com/StirfireStudios/Jacquard @4ian if you are interested I can cc you in the email. I did mention that my interest is to integrate it in gdevelop, but it looks like they are working with Unity/Unreal - so their tool is primarily targetting those two.

After a quick look at the source code and comits - their tool seems more advanced but less polished. Unfortunately due to its architecture - it would be harder to integrate and use in other projects. I think of staying with Yarn for this because:

The part of preparing yarn to bundle with other electron software is largely solved, now what is left is to do is write the extension to parse yarn files during runtime :)

I wonder wether to keep the yarn data inside sepparate json files - to be used as a resource. Or should the yarn data be kept inside game objects. I really want to make this competitive with the popular rpg game maker engines for the storytelling aspect of it. Keeping it in external files will make games easier to translate to other languages, also allow for cleaner project tracking on github for gdevelop game projects using it

4ian commented 6 years ago

Hey ๐Ÿ‘‹ I've put this issue on the roadmap (so that anyone can vote for it!) there: https://trello.com/c/vcRqzoGk/74-bundle-yarn-a-dialogue-editor-for-interactive-stories

I'm closing this issue as open issues on Github is now be dedicated to bugs only :) (But it's still possible to continue the discussion on this issue even if it's closed)

blurymind commented 6 years ago

I am getting a bit closer to making this a reality- recently added the missing parts to communicate between the yarn data and gdevelop.js to bondage.js - the parser. See: https://github.com/jhayley/bondage.js/pull/41 https://github.com/jhayley/bondage.js/pull/40 https://github.com/jhayley/bondage.js/pull/39

Now I need to also update the debugger I implemented in yarn-electron to display them - get that merged.

Then see how to read/write to the runner state of bondage.js - for save/load game states

After that is all done the next step is to try to write a yarn data parser for gdevelop.js that will use bondage.js

Alyks commented 5 years ago

I would certainly need a tutorial or more features in GDevelop to make story driven game. @blurymind could you please tell me what was the consensus on this matter? Would it be possible to have a simple system that fit in the GDevelop roadmap ? Are you making something as a tiers features maker that you would maintain ? Is GDevelop working on new features that would make it possible to develop narrative game ? Because, at this time, people have tried and it makes the event sheet a mess and it doesn't accomplish completely the goal : be able to make something like Night in the Wood with a lot of text and actions according to text conditions (click, store variable, input, character sprite animation according to line like line happy = sprite animation happy etc...). Maybe as Florian says, it just that there's no tutorial for such a game or maybe GDevelop needs some new features. Let me know your thought on this @blurymind and @4ian please :)

blurymind commented 5 years ago

The main element required to do this is not Yarn itself. I can add yarn's editor to gdevelop in a weekend. It's the runtime parser that parses the yarn file during the game's execution. Unity has such a parser and it's called yarn spinner. It's what was used for Night in the Woods.

Now, there is a parser written in javascript. It's a parser that I have even contributed some code to - in order to make it more flexible. I have used that parser both on a personal project and inside Yarn itself - to preview stories in Yarn-electron. It's called Bondage.js. This is the thing I need to include with a JS extension for gdevelop- in order to be able to parse the data that yarn creates in the game. Unfortunately this can not be done within gdevelop's new behaviour extensions api. It's not allowed to include external js files in the event sheet at all, even though you can write some js. The thing is writing any JS in the embedded monaco editor does not allow you to import classes from actual js files. I think construct3's implementation of writing js allows you to do that and even store any js you write to files that are attached to the game object- very similar to all the other traditional game engines (Unity, godot, etc - they are all designed in a way where you write your code to external files and they can import other classes) As I see it, this fully prohibits me from using anything cool that makes it worth writing any js code in the first place. I can't import bondage.js or any other cool library, so what's the point of writing js to do what can already be achieve with the event sheet.

So the only option is really to write it as a pure js extension - not using the new behaviours and in it to import bondage.js and create a wrapper for it to communicate with GD.

This is the exact same blocking issue for mod files and bundling bassoon tracker with GD. I have no way of actually treating the mod files as a new resource and read them during gameplay.

When I figure out how to do that on some weekend and have the yarn json data parsed inside a GD game, then I will bundle Yarn with GD and it will be super easy to make story driven games in GD.

To add to all this- there is another problem to overcome. Gdevelop can not treat json files as a resource. This means that all the yarn data you write will have to be stored as metadata inside project.json. This is vastly inconvenient because one has to literally open the entire game to create translations for it or to fix some typos and gramatical errors in a dialogue tree. So really, when we edit files with yarn bundled, it should save the files inside the project folder - not inside project.json. It should treat them as resources, so the user wouldnt have to make boilerplate event logic to load them every time into the yarn parsing behaviour. This is not something you have to do in rpg maker for example.

Until then, you have to do it with what's available. You can still make a story type game in GD, you will just have to do it from scratch with the event sheet. There are some hurdles to overcome to do this nicely

4ian commented 5 years ago

@blurymind You can still write a classic JavaScript extension and include the library file right?

For JSON, it's true that it's hard to add them in the file resources, but if you work around this (by for example, pasting the JSON in a JS event to use it), I'm happy to help adding some capabilities to avoid this work around. :) It's just that I have so much to do lately that I prefer to do things if I'm 100% sure about how they are going to be used, rather than a feature that turns out not to be what we exactly need and will bloat GDevelop for the rest of its days (GD4 really had too much of these :)).

Alyks commented 5 years ago

Hi. @4ian I aggree, a feature must be added if it used by many. As a user i love GDevelop for its approach on game development but when it comes to make dialogs for story driven narrative game with conditions, variables and actions based on user clicks to display lines that condition the display of sprites and events before, during and after a line, like some narrative game engine do, it's very difficult and the event sheet can become a mess for a complete narrative game. I think the work around for this is to produce an example of a powerful dialog system with new GD core features if necessary working along with an extension if needed to make something working for any dialog based game/scene like adventure game, rpg game, visual novel games etc... But i think a powerful dialog system will be a great attractive feature for people like me who want to add complex narrative scenes in their game.

Some one helped me on the french community forum with a dialog example. If @4ian could check here. It does basically a small percentage of what i need but it seems to me very complex to work with for a entire game. In the example the condition for the dialog to appear is when the player collide with a png, but sometime you just want the condition to be a click on space key, and actions should be fired line after line like following a series of line > actions > line > action > line etc.... So, that was just to say that if @blurymind solution can improve productivity for dialog based games on GD, it would be so cool !

blurymind commented 5 years ago

@Alyks thank you for sharing that with us. I will have a look :)

@4ian I was thinking of storing them as metadata- similar to piskel. I am not sure how exactly it will work yet. Been looking for inspiration from other engines that are focused on story based games