{"id":15722565,"url":"https://github.com/halfstardev/matchanovel","last_synced_at":"2025-06-24T21:39:26.163Z","repository":{"id":57328637,"uuid":"524743992","full_name":"HalfstarDev/matchanovel","owner":"HalfstarDev","description":"A visual novel framework library for Defold.","archived":false,"fork":false,"pushed_at":"2024-09-06T13:36:59.000Z","size":4071,"stargazers_count":49,"open_issues_count":2,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-05T22:49:00.291Z","etag":null,"topics":["adventure-game-engine","defold","defold-game-engine","defold-library","game-engine","multiplatform","visual-novel","visual-novel-engine","visual-novel-framework","visualnovel"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HalfstarDev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"HalfstarDev","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2022-08-14T18:02:41.000Z","updated_at":"2025-03-18T10:45:11.000Z","dependencies_parsed_at":"2024-09-06T15:28:36.121Z","dependency_job_id":"41554455-1e7f-4dc4-9bf2-3db6c42cdc34","html_url":"https://github.com/HalfstarDev/matchanovel","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HalfstarDev%2Fmatchanovel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HalfstarDev%2Fmatchanovel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HalfstarDev%2Fmatchanovel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HalfstarDev%2Fmatchanovel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HalfstarDev","download_url":"https://codeload.github.com/HalfstarDev/matchanovel/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248836291,"owners_count":21169370,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adventure-game-engine","defold","defold-game-engine","defold-library","game-engine","multiplatform","visual-novel","visual-novel-engine","visual-novel-framework","visualnovel"],"created_at":"2024-10-03T22:08:24.636Z","updated_at":"2025-04-14T06:36:59.813Z","avatar_url":"https://github.com/HalfstarDev.png","language":"Lua","funding_links":["https://github.com/sponsors/HalfstarDev"],"categories":[],"sub_categories":[],"readme":"MatchaNovel\n==========\n\n## A visual novel engine.\n\nFor an example, try the web demo: [https://halfstar.itch.io/matchanovel](https://halfstar.itch.io/matchanovel)\n\n![screenshot](/docs/images/screenshot_1.jpg)\n\n---\n\n## What is MatchaNovel?\nMatchaNovel is an open source multiplatform engine for narrative works, like visual novels and adventure games. \nIt can be integrated with the [Defold](https://defold.com/) game engine or other Lua based engines, to use narrative features like a writer friendly scripting system and automatic textboxes in other genres as well.\n\nIt consists of these parts:\n\n- **MatchaScript:** a Lua based scripting language for narrative works, that can be imported into an engine\n\n- **MatchaNovel:** a Lua backend for visual novels that extends MatchaScript, and allows renpy-like scripting\n\n- **MatchaNovel for Defold:** a library and GUI for the open source 2D+3D game engine Defold\n\n- **Jasmine:** a textbox library for Defold\n\nCurrently working fully on these platforms: **Windows**, **Linux**, **macOS**, **Android**, **iOS**, **HTML5**\n\nPlatforms it can export to, but I could not test yet without a devkit: **Nintendo Switch**\n\n---\n\n## Some key features:\n- writer friendly scripting language\n- you can make a full release with only MatchaScript code, or you can use Defold to edit the GUI and scenes in a WYSIWYG editor\n- strong math and logic support by using Lua expressions and math libraries in the script, or import full Lua files as extensions\n- Spine support\n- FMOD support\n- particle effects\n- inbuilt pronoun system\n- make your own syntax by changing the MatchaScript definitions\n- can be used as dialogue system in a full Defold game, or use mini games made in Defold in your visual novel\n- small build size: less than 5 MB, plus your assets\n---\n\n## How to install:\nYou can use MatchaNovel either:\n- by opening the [empty template project](https://github.com/HalfstarDev/matchanovel/releases/download/v0.2.0/MatchaNovel.Empty.Defold.project.English.zip) in Defold **(recommended for releasing a visual novel)**\n- (There is also a [seperate template that includes Japanese fonts](https://github.com/HalfstarDev/matchanovel/releases/download/v0.2.0/MatchaNovel.Empty.Defold.project.Japanese.zip), which are not in the English version to keep the file size down.)\n- or by downloading the [standalone reader](https://github.com/HalfstarDev/matchanovel/releases/download/v0.2.0/MatchaNovel.Reader.demo.Windows.zip) and editing the script and asset files **(recommended for quick prototyping without advanced features)**\n- or by importing the [library](https://github.com/HalfstarDev/matchanovel/archive/refs/tags/v0.2.0.zip) in Defold or another Lua based engine **(recommended for integrating into a larger non-VN game)**\n\nIf you import the MatchaNovel library into an existing Defold project, you should also install the [DefOS](https://github.com/subsoap/defos) library, so that the fullscreen setting will work.\n\n---\n\n## How to use:\nYou can play a project by pressing `Project -\u003e Build (Ctrl+B)` in Defold, or by starting `matchanovel.exe` in the reader project.\n\nYour assets should be put into the folders in `/assets`. The most important is the script, which contains your text and logic.\n\nLet's try our first script. Write this line in `assets/scripts/script.txt`:\n\n```\nHello World!\n```\nThat's enough for a hello world program. If you start the project, it will repeat the text you wrote in the script. \nThis works because any text that is not recognized as another valid action will be used as \"say\" action, and printed to the textbox.\n\n### Label and jump:\nNow some more actions:\n```\nlabel start\n```\nThis defines the current line as the label called `start`. The label name can be any name valid as Lua variable, so it should start with a letter, and consist only of letters, numbers and underscores. \nThe label `start` is a special label, this is where the script will start when starting a new game.\n\nTo jump to a label, use\n```\njump label_name\n```\n\n### Speak:\nIf you want a text to be spoken by a specific character, use a colon:\n```\nAlice: Hello.\n```\n\nThe name before the colon will be displayed above the text. If you don't want to write out the full name every time, you can assign a character to a variable, like this:\n```lua\na.name = \"Alice\"\na: Hello.\na: How are you?\n```\n\nLine breaks will be added automatically according to the size of the text and the box. You can also add manual line breaks by using `\\n`.\n```\nFirst line\\nSecond line\n```\n\nIf you want for example \"jump\" to be spoken, but not by a character, you can't just write\n```\njump\n```\nas that's a keyword already. But you could write\n```\n: jump\n```\nto explicitly let it be a say command, but without a speaker.\n\n\n### Variables:\nIn general, the line\n```lua\nx = z\n```\nwill set the variable named `x` to `z`, and\n```lua\nx.y = z\n```\nwill set the property `y` of the object `x` to `z`.\n\nVariables can also be used directly in text, by putting them in curly brackets:\n```\na: My name is {a.name}.\n```\n\nIf you need a string capitalized, just write the name capitalized when calling it.\n```lua\nabc = \"test\"\na: {abc} {Abc} {ABC}.\n```\nwill be displayed as:\n\n\u003e Alice: test Test TEST.\n\nYou can use Lua expessions to set a variable:\n```\na = 1 + 2\nb = a^2 * math.random(2, 10) + (a % 2)\nc = d or a\n```\n\nYou can even use Lua expressions in curly brackets:\n```\na: 97 * 63 + x = {97 * 63 + x}.\na: Random number from 1 to 100: {math.random(1,100)}.\na: You are running this demo on {system.name}.\na: Is x larger than or equal to 9? {x \u003e= 9 and \"Yes\" or \"No\"}.\na: Turn all vowels into stars: {string.gsub(\"Turn all vowels into stars\", \"[AEIOUaeiou]\", \"*\")}\n```\n\nAdditionally there are some operators that MatchNovel has that are not part of standard Lua:\n```lua\na++          -- same as a = a + 1\na += 2       -- same as a = a + 2\na -= 1       -- same as a = a - 1\na *= 4       -- same as a = a * 4\na /= 2       -- same as a = a / 2\na %= 3       -- same as a = a % 3  (modulo)\na ..= \"two\"  -- same as a = a .. \"two\"  (string concatenation)\n```\nNote that unlike similar operators in other languages, these will also work if the first variable is not yet defined. \nUsing `a += 2` when `a == nil`, will result in `a` being treated as being `0`, so after the operator it will end up with `a = 2`. \nSo if you want to create a flag and set it to true, using `flag++` is functionally the same as `flag = true`, although slightly less efficent, using a number instead of a boolean. \n\nAlso note that `a++` is a whole action taking its own line, and can not be used inside other expressions, and does not have variations. \nThere is NO `a = b++`, or `++a`, or `a--`, or `--a`, as these would clash with standard Lua syntax. \nIt's a shortcut to increase a variable by one, and that's all.\n\n### Sprites:\n#### Show:\nTo show a sprite for a character, use\n```lua\na.sprite = \"alice.png\"\nshow a\n```\nwhere `a.sprite` must be either a file in `/assets/images/sprites`, or the path from your project folder to the file, like\n```lua\na.sprite = \"/custom_folder/spr/a01.png\"\n```\nNote that any folder outside of `/assets` that you use this way must be added to Custom Resources in your `game.project` file.\n\nIf you don't specify a position, the character will be automatically positioned, see section [Automatic sprite positioning](https://github.com/HalfstarDev/matchanovel#automatic-sprite-positioning).\n\nTo define a position, define a variable with properties x and y:\n```lua\npos_right.x = 0.75\npos_right.y = 0\n\nshow a at=pos_right\n```\nThe units of x and y are fractions of the screen size. So the position x=0 is at the left of the screen, x=1 at the right, x=0.5 at the center, and x=0.75 between center and right. y=0 is the bottom, y=1 the top, and so on. \nYou can also use numbers smaller than 0 or larger than 1, so for example y=-0.5 would start a half screen height below the bottom.\n\nYou can even set a scale to a position. Sprites that are shown on that position will be scaled with the factor of that position. So a character with scale `1.2` on a position with scale `0.5` will be shown with a scale of `0.6`.\n```lua\npos_back.x = 0.3\npos_back.y = 0.2\npos_back.scale = 0.5\n\nshow a at=pos_back\n```\n\nIf you don't want a character to appear instantly, you can also use transitions, like\n```lua\nshow a transition=fade\nshow a transition=move_up\nshow a transition=grow duration=0.5\n```\nwhere `transition` is the name of the transition you would like to use, and `duration` the time the transition will use in seconds. If no duration is given, the default value will be used.\n\nBy default, a new character will be shown in front of all previous characters. You can also specify to shown them in front of a certain character, below a character, at the back, or at the front:\n```\nshow a above=b\nshow a below=b\nshow a above=back\nshow a below=front\n``` \n\nYou can also change the default arguments for show. If you want all characters to fade in with a duration of 1.2 seconds and added to the back instead of the front, as long as no other values are used, you can do this:\n```lua\nshow.transition = \"fade\"\nshow.duration = 1.2\nshow.above = \"back\"\n```\n\n#### Hide:\nTo hide a character again, use:\n```lua\nhide a\n```\n\nYou can also hide all characters at once:\n```lua\nhide all\n```\n\nYou can again use transitions for this, or the value `to` to give a vector to move in, like:\n```lua\nhide a transition=instant\nhide a transition=fade\nhide a transition=move_down duration=1\nhide a transition=shrink\npos_down.y = -0.5\nhide a to=pos_down\n```\n\n\n#### Move:\nYou can also move a shown sprite to a new position:\n\n```lua\nmove a to=left\n```\n\nLike with `show`, you can also move a character above or below another character (or the front, or the back). You don't have to specify a `to` value, without it the sprite will stay in place, and just change the order.\n```lua\nmove a above=b\n```\n\nFor movement animations, you can also change the easing:\n```lua\nmove a to=left easing=INOUTSINE\n```\n\nThe default easing if none is specified is INOUTSINE.\nThere are the following easing types:\nLINEAR, INBACK, EASING_OUTBACK, INOUTBACK, OUTINBACK, INBOUNCE, OUTBOUNCE, INOUTBOUNCE, OUTINBOUNCE, INELASTIC, OUTELASTIC, INOUTELASTIC, OUTINELASTIC, INSINE, OUTSINE, INOUTSINE, OUTINSINE, INEXPO, OUTEXPO, INOUTEXPO, \nOUTINEXPO, INCIRC, OUTCIRC, INOUTCIRC, OUTINCIRC, INQUAD, OUTQUAD, INOUTQUAD, OUTINQUAD, INCUBIC, OUTCUBIC, INOUTCUBIC, OUTINCUBIC, INQUART, OUTQUART, INOUTQUART, OUTINQUART, INQUINT, OUTQUINT, INOUTQUINT, OUTINQUINT. \nFor details on how those easings work, see the [MatchaNovel demo](https://halfstar.itch.io/matchanovel), or the [Defold manual](https://defold.com/manuals/property-animation/).\n\n#### Flip:\nYou can flip a sprite horizontally with the flip action. By default, it will show a rotation on the z axis with a duration of 1 second, but you can also change the duration.\n```\nflip alice\nflip alice duration=0.5\nflip alice duration=0.0\n```\n\nIf instead of a flip animation, you want to show a sprite flipped in the first place, you set the values `flip_x` or `flip_y` directly before showing it.\n```\nalice.flip_x = true\nalice.flip_y = false\nshow alice\n```\n\n### Automatic sprite positioning:\nYou can change at which position a new sprite without a position will be placed.\nBy default, they will be put at the highest number, so if there are 3 automatically positioned sprites already, the new one will be placed at position 4.\nIf you want it at another position, use a number as position argument. For example, if you want the fourth new sprite to be put at position 3, and the old 3 at 4, use:\n```\nshow alice at=3 \n```\n\nYou can customize the rules for automatic sprite positioning.\n\nTo set the width of screen that the sprites are spread on, use `sprites.auto_n.width`, with `n` being the total number of sprites, and the width 1.0 being the whole width of the screen.\n```lua\nsprites.auto_2.width = 0.4\nsprites.auto_3.width = 0.6\nsprites.auto_4.width = 0.75\nsprites.auto_5.width = 0.9\n```\n\nYou can also set the positions individually using `sprites.auto_i_n`, with `n` being the total number of sprites, and i the number of the individual sprite.\n```lua\nsprites.auto_1_1.x = 0.5\nsprites.auto_1_1.y = 0.1\n\nsprites.auto_1_2.x = 0.25\nsprites.auto_1_2.y = 0.1\n\nsprites.auto_2_2.x = 0.75\nsprites.auto_2_2.y = 0.1\n```\n\nThe duration of the automatic ordering of sprites if set by the variable `sprites.auto.duration`:\n```\nsprites.auto.duration = 1\n```\n\n### Expressions:\nTo change the image of a shown character, you can just change its sprite variable. This will change the sprite immediately and permanently.\n```lua\nalice.sprite = \"alice_happy.png\".\n```\n\nTo make changing sprites easier, the expression system exists. You can manually define expressions with different sprites.\n```lua \nalice.sad.sprite = \"alice_sad.png\"\n```\n\nIf you now call that expression with `alice.sad`, the character `alice` will change its expression to `sad`, which means it will change its sprite to `alice_sad.png`.\n```lua \nalice.sad\n```\n\nIf an expression is used in its own line, it will stay until changed again.\nYou can also use an expression on the speaker of a \"say\" line. In this case, the sprite will change as well, but only for this one line. So the next line it will revert again.\n```lua\nalice.sad: Now I am sad.\n```\n\nThe pattern of the filename in the example above, `charactername_expressionname.png`, will be used by default if you call an expression that you have not defined. So even without a manual definition, you can just use\n```lua\nalice.angry\n```\nas long as the file `/assets/images/sprites/alice_angry.png` exists.\n\n### Scenes:\nTo show a background scene, either use a filename:\n```lua\nscene room.jpg\n```\nor a scene name:\n```lua\nroom.image = \"room.jpg\"\nscene room\n```\n\nThe scene name follows similar rules as sprites, but with the default folder for filenames without a path being `/assets/images/background`.\n\nYou can again use the same syntax for transitions and their duration:\n\n```lua\nscene room transition=instant\nscene room transition=fade duration=1.5\nscene room transition=fade_to_black\nscene room transition=shrink\nscene room transition=grow\nscene room transition=grow_horizontal\nscene room transition=grow_vertical\nscene room transition=zoom_out\nscene room transition=zoom_in\nscene room transition=slide_horizontal\nscene room transition=slide_horizontal_reverse\nscene room transition=slide_vertical\nscene room transition=slide_vertical_reverse\n```\n\nYou can also change the default transition and duration, so you don't have to change it to the same values every time.\n```lua\nscene.transition = \"fade\"\nscene.duration = 0.5\n```\n\nA new argument is `color`, which can be used to change the tint of the image. \n```lua\nscene room color=red\n```\nThis will tint the image red. For colors you can either use HTML names, hex colors, or variables with RGB values (from 0 to 1). These will all do the same:\n```lua\nscene room color=cyan\n\nscene room color=#00FFFF\n\ncustom_cyan.r = 0.0\ncustom_cyan.g = 1.0\ncustom_cyan.b = 1.0\nscene room color=custom_cyan\n```\nYou can also use a color instead of an image file to create a solid color background, like\n```\nscene DeepSkyBlue\n```\nFurthermore, you can use the argument `transition_color` to change the color of a transition (if it has any), like:\n```\nscene green transition=fade_to_black transition_color=red\n```\n\n### If:\nYou can add branches based on the value of a variable, with if, else, and elseif:\n```\nif strength \u003e 9000 or found_key\n  You opened the door.\n  open = true\n  jump door_opened\nelseif strength \u003e 7000\n  The door moved a little bit, but you didn't get it to open.\nelse\n  You can't open the door at all.\n  \nAs you couldn't open the door, you left the room.\n```\n\nIf the expression after if is true, then the action block starting in the next line will be started, even if it is indented. Usually, deeper indented lines will be ignored. Only ifs, jumps and choices can access them.\n\nIf at the end of the action block you did not jump out of it, you will jump to the next line with a lower indention. \nFor longer branches, it is recommended to use jumps to the base line instead of having a big tree-like indention structure.\n\nYou can use Lua expressions in the `if` statement. Some useful operators:\n\nLogical: `and`, `or`, `not`\n\nRelational: `==`, `~=`, `\u003c`, `\u003e`, `\u003c=`, `\u003e=`\n\nArithmetic: `+`, `-`, `*`, `/`, `^`, `%`\n\n### Choices:\nThis will give the reader a number of choices to pick, and execute a different branch according to the picked choice:\n```\nWhere do you want to go?\n\u003e Go left.\n  You went left.\n  jump left\n\u003e Go right.\n  You went right.\n  jump right\n\u003e Go back.\n  You went back.\n  jump back\n```\nThe structure works like with `if` again, with the difference that if you reach the end of the block without a jump, the rest of the choices will be ignored.\n\nYou can also use variable expressions and line breaks like in say commands in the choice text:\n```\nWho are you?\n\u003e My name is {a.name}.\n  jump answer_1\n\u003e I won't tell you.\n  jump answer_2\n\nWhat will you do next?\n\u003e Read a book\\n(Knowledge + 1)\n  knowledge += 1\n  You read a book. This increased your knowledge.\n\u003e Go jogging\\n(Stamina + 2)\n  stamina += 2\n  You went jogging. This increased your stamina.\n```\n\n### Random:\nTo get a random result, you can use the standard math library from Lua.\n\nIf you want a random real number in the range `[0,1)`, you can call `math.random()` without an argument:\n```\nYour chance to win the lottery is 2%.\nif math.random() \u003c= 0.02\n  You won.\nelse\n  You lost.\n```\n\nTo get an integer in the range `[1, n]`, call `math.random(n)`:\n```\ndice = math.random(6)\nYou rollled a {dice}.\nif dice \u003e 2\n  You hit the enemy with your fireball.\nelse\n  You missed the enemy.\n```\n\n### Comments:\nComments are denoted with `--`, as usual in Lua. You can use those to structure your script and leave annotations.\n\n### Particles:\nYou can create particle effects in the Defold editor. More on that will be explained in an advanced manual soon. Some particle effects are already predefined with scene.weather.\n```lua\nscene.weather = \"none\"\nscene.weather = \"rain\"\nscene.weather = \"snow\"\nscene.weather = \"blizzard\"\nscene.weather = \"fireflies\"\nscene.weather = \"clear\"\n```\n\n### Music and sound:\nTo play music, you have to first add the file to the `sound.go` game object in Defold. Clone the `bgm` or `sfx` component, depending on if you need a background music or sound effect. Then change the sound property. \nYou can also change gain, pan, and speed for each file. Make sure that looping is checked if you want the file to repeat until it is stopped.\n\nYou can play music and sound with:\n```\nplay music bgm_name\nplay sound sfx_name\n```\n\nBackground music will play until another music is played, or until you stop it manually:\n```\nstop music\n```\n\n### Return to title:\nTo return to the title, simply use `title`.\n```\nWhat will you do?\n\u003e Run away\n  You escaped.\n  jump chapter_2\n\u003e Talk to the monster\n  You died.\n  GAME OVER\n  title\n```\n\n### Using multiple script files:\nTo add more script files (like `chapter_1.txt`, `chapter_2.txt`, etc.), add the name of the new files to `scripts.txt`. Labels are global, so you can use `jump` to jump to other scripts.\n\n### Print to console:\nIf you are running your project from Defold or a debug build with a console, you can print text to the console, using the same syntax as say.\n```\ndebug.print Starting timer.\na = system.os_clock\nClick to continue.\nb = system.os_clock\ndebug.print The message was displayed for {b - a} seconds.\n```\n\n### Pronouns:\nMatchaNovel can be extended with Lua modules. As an example, a preinstalled pronoun system is implemented as a Lua extension. To set pronouns, simply use\n```lua\npronouns = \"she\"\npronouns = \"he\"\npronouns = \"they\"\n```\nThese will set multiple useful variables, like this:\n```\n\"Did {they} change {their} hair style? {They} look{verb_end} amazing now.\" \"{THEY} {plural and \"DO\" or \"DOES\"}!\"\n```\nwill be displayed like this, if you chose 'she' as your pronouns:\n\n\u003e \"Did she change her hair style? She looks amazing now.\" \"SHE DOES!\"\n\nIf you have variable pronouns for multiple characters, you can also link those to a name:\n```\na.name = \"Alice\"\na.pronouns = \"she\"\nb.name = \"Bob\"\nb.pronouns = \"he\"\n\n{a.name} prefers {a.they}, {b.name} prefers {b.they}.\n```\n\n\u003e Alice prefers she, Bob prefers he.\n\n### FMOD:\n\nThe FMOD library is not preinstalled in the open source version of MatchaNovel,\nbut you can either install the library in your Defold project yourself (see next section),\nor use the [FMOD template project](https://github.com/HalfstarDev/matchanovel/releases/download/v0.2.0/MatchaNovel.FMOD.template.zip) with preinstalled FMOD.\n\nTo use a FMOD bank, copy the `.bank` files into the folder `/assets/audio/fmod`.\n\nThe bank `Master.bank` (including `Master.strings.bank`) will be loaded automatically. If you want to load more banks on start, set their names (without extension) as `fmod.bank_*` in the init script:\n```\nfmod.bank_1 = \"My_bank\"\nfmod.bank_2 = \"My_bank.strings\"\nfmod.bank_3 = \"Another_bank\"\nfmod.bank_4 = \"Another_bank.strings\"\n```\n\nTo start an FMOD event from the Master bank, use the `fmod play` action:\n```\nfmod play sound event_name \n```\nIf the event is in another bank than the Master bank, then use the argument fmod_bank:\n```\nfmod play sound car fmod_bank=vehicles \n```\nFor 3D events, you can also use the `source` command as for regular MatchaNovel sounds to use the position of a sprite as sound source:\n```\nfmod play sound shout_alice source=alice \n```\n\n### Installing FMOD:\n\nOnly if you don't use the FMOD template, but want to add MatchaNovel to an existing Defold project, you have to install FMOD before you can use it.\n\nSee https://github.com/dapetcu21/defold-fmod for the newest release, like https://github.com/dapetcu21/defold-fmod/archive/v2.6.1.zip. \n\nEither copy the fmod folder into your project, or use it as an dependency in your `game.project` file and fetch it.\n\nTo set a speaker mode, add this to your `game.project` file, and change the speaker mode to your preference:\n```\n[fmod]\nspeaker_mode = stereo\n```\n\nTo run your project directly from the Defold editor, you also have to copy `fmod/res` into your project, and put the path into `game.project`:\n```\n[fmod]\nlib_path = fmod/res\n```\n\n### More Actions:\n\n#### Exit:\nYou can close the whole application with the `system.exit` action.\n```\nThe game will close now.\nsystem.exit\n```\n\n#### Stop skipping:\n\nTo manually stop the skipping function on a certain line, use `skip.stop`.\n```\nskip.stop\n```\n\n#### Open URLs:\n\nTo open an URL, use `system.open_url`.\n```\nsystem.open_url www.google.com\nsystem.open_url C:\\some\\folder\nsystem.open_url save.folder\n```\n\n#### Change window title:\n\nYou can set the title of the window on boot in the `game.project` file.\n```\n[project]\ntitle = My Visual Novel\n```\n\nTo change the title of the window in the script at any time, set the variable `system.window_title`.\n```\nsystem.window_title = \"This is now the new window title\"\n```\n\n### Variables:\nThere are some variables that MatchaNovel provides automatically:\n\n| Name                  | Values                                                                                        | Description                                                                                         |\n| --------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |\n| system.name           | String: `\"Windows\"`, `\"Linux\"`, `\"Darwin\"`, `\"Android\"`, `\"iPhone OS\"`, `\"HTML5\"`, `\"Switch\"` | The currently used operating system.                                                                |\n| system.is_windows     | Boolean: `true`, `false`                                                                      | `true` if the currently used operating system is Windows.                                           |\n| system.is_linux       | Boolean: `true`, `false`                                                                      | `true` if the currently used operating system is Linux.                                             |\n| system.is_macos       | Boolean: `true`, `false`                                                                      | `true` if the currently used operating system is Mac OS.                                            |\n| system.is_android     | Boolean: `true`, `false`                                                                      | `true` if the currently used operating system is Android.                                           |\n| system.is_ios         | Boolean: `true`, `false`                                                                      | `true` if the currently used operating system is iPhone OS.                                         |\n| system.is_html        | Boolean: `true`, `false`                                                                      | `true` if running in a browser.                                                                     |\n| system.is_switch      | Boolean: `true`, `false`                                                                      | `true` if running on a Nintendo Switch.                                                             |\n| system.is_mobile      | Boolean: `true`, `false`                                                                      | `true` if the currently used operating system is Android or iPhone OS (but not for HTML on mobile). |\n| system.language       | String: `\"en\"`, `\"fr\"`, `\"de\"`, ...                                                           | The current system language.                                                                        |\n| system.is_debug       | Boolean: `true`, `false`                                                                      | `true` if the project is running in debug mode.                                                     |\n| system.engine_version | String: `\"1.4.8\"`, `\"1.4.7\"`, ...                                                             | The current engine version of Defold.                                                               |\n|                       |                                                                                               |                                                                                                     |\n| system.time           | Number: `1689370000`, etc.                                                                    | The current Unix time (in whole seconds).                                                           |\n| system.time_string    | String: `\"2022-12-31 23:59:30\"`, ...                                                          | The current date and time as readable string, in the format `YYYY-MM-DD HH:MM:SS`.                  |\n| system.time_date      | String: `\"2022-12-31\"`, ...                                                                   | The current date as readable string, in the format `YYYY-MM-DD`.                                    |\n| system.time_clock     | String: `\"23:59:30\"`, ...                                                                     | The current time as readable string, in the format `HH:MM:SS`.                                      |\n| system.time_year      | String: `\"2022\"`, ...                                                                         | The current year.                                                                                   |\n| system.time_month     | String: `\"01\"`, `\"02\"`, `\"03\"`, ..., `\"12\"`                                                   | The current month as string, with `01` being January.                                               |\n| system.time_day       | String: `\"01\"`, `\"02\"`, `\"03\"`, ..., `\"31\"`                                                   | The current day of the month.                                                                       |\n| system.time_hour      | String: `\"00\"`, `\"01\"`, `\"02\"`, ..., `\"23\"`                                                   | The current hour.                                                                                   |\n| system.time_minute    | String: `\"00\"`, `\"01\"`, `\"02\"`, ..., `\"59\"`                                                   | The current minute.                                                                                 |\n| system.time_second    | String: `\"00\"`, `\"01\"`, `\"02\"`, ..., `\"59\"`                                                   | The current second.                                                                                 |\n| system.time_weekday   | String: `\"1\"`, `\"2\"`, `\"3\"`, `\"4\"`, `\"5\"`, `\"6\"`, `\"7\"`                                       | The current weekday, with `1` being monday, and `7` being sunday.                                   |\n| system.time_hour12    | String: `\"01\"`, `\"02\"`, `\"03\"`, ..., `\"12\"`                                                   | The current hour in the 12-hour clock convention.                                                   |\n| system.time_ampm      | String: `\"a.m.\"`, `\"p.m\".`                                                                    | The current time period, \"a.m.\" before midday, \"p.m.\" after midday.                                 |\n| system.os_clock       | Number: `0.001`, `1.002`, `9876.000`, ...                                                     | The current CPU time used by the executable (in seconds).                                           |\n|                       |                                                                                               |                                                                                                     |\n| settings.text_speed   | Number: `0`, ..., `100`                                                                       | The current text speed setting.                                                                     |\n| settings.auto_speed   | Number: `0`, ..., `100`                                                                       | The current auto text speed setting.                                                                |\n| settings.volume_music | Number: `0`, ..., `100`                                                                       | The current music volume setting.                                                                   |\n| settings.volume_sound | Number: `0`, ..., `100`                                                                       | The current sound volume setting.                                                                   |\n| settings.font         | String: `\"sans\"`, `\"serif\"`, ...                                                              | The current font setting.                                                                           |\n| settings.fullscreen   | Boolean: `true`, `false`                                                                      | The current fullscreen setting. `true` if fullscreen.                                               |\n| settings.skip_all     | Boolean: `true`, `false`                                                                      | The current skip setting. `true` if skipping all text, `false` if only read text.                   |\n| settings.lock         | Boolean: `true`, `false`                                                                      | The current quickmenu lock setting. `true` if locked.                                               |\n|                       |                                                                                               |                                                                                                     |\n| save.folder           | String: `\"C:\\Users\\MyName\\AppData\\Roaming\\MyGame\\\"`, ...                                      | The save folder path.                                                                               |\n|                       |                                                                                               |                                                                                                     |\n| sprites.scale         | Number: `1.0`, `2.5`, `0.8`, ...                                                              | The global scale of all sprites.                                                                    |\n|                       |                                                                                               |                                                                                                     |\n| audio.volume          | Number: `0.0`, ..., `1.0`                                                                     | The master volume, applied to music, sounds, and voices. Multiplies with user settings.             |\n| music.volume          | Number: `0.0`, ..., `1.0`                                                                     | The volume applied to music only. Multiplies with user settings and `audio.volume`.                 |\n| sound.volume          | Number: `0.0`, ..., `1.0`                                                                     | The volume applied to sound only. Multiplies with user settings and `audio.volume`.                 |\n|                       |                                                                                               |                                                                                                     |\n| skip.all              | Boolean: `true`, `false`                                                                      | Overwrites `settings.skip_all` if `true`. If `false`, behaviour depends on setting.                 |\n|                       |                                                                                               |                                                                                                     |\n| show.transition       | String: `fade`, `instant`, ...                                                                | The default transition type for the action `show`, if used without a `transition` argument.         |\n| show.duration         | Number: `0.5`, `0`, `2.0`, ...                                                                | The default duration for the action `show`, if used without a `duration` argument.                  |\n| show.easing           | String: `\"INOUTSINE\"`, `\"LINEAR\"`, ...                                                        | The default easing type for the action `show`, if used without an `easing` argument.                |\n| hide.transition       | String: `fade`, `instant`, ...                                                                | The default transition type for the action `hide`, if used without a `transition` argument.         |\n| hide.duration         | Number: `0.5`, `0`, `2.0`, ...                                                                | The default duration for the action `hide`, if used without a `duration` argument.                  |\n| hide.easing           | String: `\"INOUTSINE\"`, `\"LINEAR\"`, ...                                                        | The default easing type for the action `hide`, if used without an `easing` argument.                |\n| move.duration         | Number: `0.5`, `0`, `2.0`, ...                                                                | The default duration for the action `move`, if used without a `duration` argument.                  |\n| move.easing           | String: `\"INOUTSINE\"`, `\"LINEAR\"`, ...                                                        | The default easing type for the action `move`, if used without an `easing` argument.                |\n| flip.duration         | Number: `0.5`, `0`, `2.0`, ...                                                                | The default duration for the action `flip`, if used without a `duration` argument.                  |\n|                       |                                                                                               |                                                                                                     |\n| loremipsum            | String: `\"Lorem ipsum dolor sit amet, consetetur sadipscing elitr\"...`                        | An example text of length 36 words. Can be used to fill a textbox without typing a lot.             |\n\n\nAs other variables, these can be used in text, or as an argument in other actions:\n```\nalice: The current time is {system.time_clock}.\n\nif system.name == \"Linux\"\n  You are using Linux.\n```\n\nBut keep in mind that variables from `system.time_*` that represent numbers are actually strings, so you either have to compare them to strings, or convert them to numbers.\n```\nif system.time_month == 1\n  It is January.\n  -- This will not work, even if it is January, because \"01\" does not equal 1.\n  \nif system.time_month == \"01\"\n  It is January.\n  -- This will work.\n  \nif tonumber(system.time_month) == 1\n  It is January.\n  -- This will work as well.\n  \nif system.time_month + 1 == 2\n  Next month is February.\n  -- Even this works, because Lua can add a number to a string of a number, and will return a number.\n```\n\n---\n\n## More\nI will add manuals for advanced features soon:\n- How to edit the GUI\n- Creating custom commands\n- Bundle distribution\n- Packing atlas files\n\nFor more questions, you can ask on the [official Discord channel](https://discord.gg/uUtEVtr9tm).\n\n---\n\n## Roadmap\nFeatures currently in work:\n- More animation options\n- More text formatting options\n- Multiple text boxes\n- Different log types\n- CG and music gallery\n- Map\n- Gyro\n- Auto character highlight\n- Translation support\n- Controller support\n\nFuture plans:\n- Self voicing\n- Flowcharts\n- Mod support\n\nFeel free to ask for more features.\n\n---\n\n## Support\nBecause this is still in early development, I will change much of the code base frequently, so pull requests don't make much sense at this point. \n(Although you are free to experiment with the code however you like, it's open source).\n\nIf you want to help right now, either creating small projects with MatchaNovel, or adding useful features to the [Defold](https://github.com/defold/defold) engine would be best. \n\nOr donate on [GitHub Sponsor](https://github.com/sponsors/HalfstarDev).\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhalfstardev%2Fmatchanovel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhalfstardev%2Fmatchanovel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhalfstardev%2Fmatchanovel/lists"}