Skip to content

Commit

Permalink
feat: animations, better docs, new dialog panel options (#170)
Browse files Browse the repository at this point in the history
* feat: animations and docs and things

* feat: animations working

* feat: docs updates

* chore: docs and inputs improvements
  • Loading branch information
liana-p committed Oct 17, 2023
1 parent 6f0e596 commit ac9e567
Show file tree
Hide file tree
Showing 63 changed files with 983 additions and 116 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1169,10 +1169,10 @@ Usage example:

```narrat
test_sprites:
var sprite1 (create_sprite img/sprites/mannequin.webp 200 500)
var sprite1 (create_sprite img/sprites/test_sprite.webp 200 500)
set sprite1.anchor.y 1
set sprite1.scale 0.5
var sprite2 (create_sprite img/sprites/mannequin.webp 500 700)
var sprite2 (create_sprite img/sprites/test_sprite.webp 500 700)
set sprite2.anchor.y 1
var pos 200
wait 20
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Or try editing the default narrat game easily:

With Codeflow you can test Narrat quickly without setting up an IDE

More info on the [narrat website](https://narrat.dev). There is an [online demo](https://narrat.dev/demo/) available to try in the browser.
More info on the [narrat website](https://narrat.dev). There is an [online demo](https://demo.narrat.dev) available to try in the browser.

## Development (for contributors)

Expand Down
4 changes: 2 additions & 2 deletions demo-template/public/data/characters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ config:
imagesPath: "./img/characters/"
characters:
game:
name: ''
name: ""
color: white
player:
style:
Expand All @@ -28,6 +28,7 @@ characters:
idle: helper_cat.webp
style:
color: green
portraitCssClass: test
name: Helper Cat
music_cat:
sprites:
Expand All @@ -46,4 +47,3 @@ characters:
style:
color: red
name: Inner Voice

7 changes: 7 additions & 0 deletions docs/.vitepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const config = {
collapsible: true,
items: [
{ text: 'Getting Started', link: '/guides/getting-started' },
{ text: 'Overview of Narrat', link: '/guides/narrat-overview' },
{
text: 'Editing the game',
link: '/guides/editing-game',
Expand All @@ -80,6 +81,7 @@ const config = {
text: 'Feature Guides',
collapsible: true,
items: [
{ text: 'Animations', link: '/features/animations' },
{ text: 'Achievements', link: '/features/achievements' },
{ text: 'Audio', link: '/features/audio' },
{
Expand All @@ -94,6 +96,10 @@ const config = {
text: 'Characters and portraits',
link: '/features/characters-and-portraits',
},
{
text: 'Dialog Panel',
link: '/features/dialog-panel',
},
{ text: 'Game Settings', link: '/features/game-settings' },
{ text: 'Gamepad support', link: '/features/gamepad' },
{
Expand Down Expand Up @@ -171,6 +177,7 @@ const config = {
],
logo: '/logo.svg',
nav: [
{ text: 'Playground', link: 'https://demo.narrat.dev' },
{ text: 'Troubleshooting', link: '/troubleshooting/troubleshooting' },
{ text: 'FAQ', link: '/others/faq' },
{ text: 'Get Started', link: '/guides/getting-started' },
Expand Down
123 changes: 123 additions & 0 deletions docs/features/animations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
title: Animations in Narrat
description: Narrat has a powerful animations feature which lets you animate any element on screen using CSS animations.
---

# {{ $frontmatter.title }}

Narrat animations leverage the versatility of [CSS animations](https://www.w3schools.com/css/css3_animations.asp) to let you animate any element on screen.

Animations can be defined in the `animations.yaml` file, and then used in scripts with the `animate` command.

## Example

<video controls="controls" src="./animations/animations-demo.mp4" type="video/mp4" autoplay="true"></video>

### Code for the example above:

**config.yaml**

```yaml
animations: data/animations.yaml
```
**animations.yaml**
```yaml
animations:
rotate:
keyframes: rotate
options:
duration: 1000
iterations: 1
long-screenshake:
# narrat-screenshake is a built-in animation that already comes with narrat
keyframes: narrat-screenshake
options:
# Here we're taking the built-in screenshake but using it with different options
duration: 150
iterations: 5

keyframes:
rotate:
- transform: rotate(0deg)
- transform: rotate(360deg)
```
**animations.narrat**
```narrat
test_animations:
choice:
"Animation test"
"Screenshake":
run test_screenshake
"Rotate":
run test_rotate
"Long screenshake":
run long_screenshake
jump test_animations

test_screenshake:
animate #narrat-app narrat-screenshake

long_screenshake:
animate .dialog long-screenshake 150 20
test_rotate:
animate_wait .dialog rotate
```
## How it works
Animations in narrat use the [animate](https://developer.mozilla.org/en-US/docs/Web/API/Element/animate) browser function. This function is an API to control [CSS animations](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations) via code.
Narrat will find the relevant element via the DOM selector you provide, then find the animation data from config files, and finally call the `animate` function with the relevant parameters.

## How to use the `animate` command

The format for the `animate` command in narrat is the following:

`animate [DOM selector] [animation name] [duration (optional)] [iterations (optional)]`

- `DOM selector`: A CSS selector to select the element to animate. If you want to animate the whole game screen, you can use `#narrat-app` as the selector for example. Use `#my-id` to get an element by its id, or `.my-class` to get an element by its class. With this you should be able to get most things on screen easily
- `animation name`: The name of the animation to use. This is the name of the animation as defined in the animations list of your `animations.yaml` file. If an animation doesn't exist, it can fall back to default built-in animations
- `duration`: The duration of the animation in milliseconds. This is optional and will default to the duration defined in the animation config
- `iterations`: The number of times the animation should repeat. This is optional and will default to the number of iterations defined in the animation config (note: to specify this option, you have to also specify duration)

::: tip
There is an `animate_wait` command, which works exactly the same but will wait until the animation is over. By default, `animate` will play the animation in background and continue the script immediately.
:::

## Animation config

Animations are defined in the `animations.yaml` file. The format is the following:

```yaml
animations:
[animation name]:
keyframes: [keyframes name OR keyframes object] # If it's a string, it will pick keyframes from the keyframes list. If it's an object, it will use the object directly
options: [animation options]
keyframes:
[keyframes name]: # This is an array of keyframes
- [keyframe object] # Those are individual steps of the animation. See the mozilla animation docs for examples
- [keyframe object]
- [keyframe object]
```

- `animation options`: Options when playing the animation. Can include things like `duration` (in ms) and `iterations` (number of times the animation is played). See list of animation options [there](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options)
- `keyframe object`: An object defining one key frame of the animation. The keyframes array is a list of them, and they get played in order as the animation progresses. Keyframes have keys that are CSS properties and their values, like when using css transitions. They can also have an `offset` property to specify when in the animation they should be played. See [mozilla docs](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats) for examples

## Built-in animations

At time of writing there is only the `narrat-screenshake` animation. This is a simple animation that just shakes an element for a bit.

## Code for more info:

- [utils/animations.ts](https://github.com/liana-p/narrat-engine/blob/main/packages/narrat/src/utils/animations.ts): File where the animation code is and where the default built-in animations are defined.
- [config/animations-config.ts](https://github.com/liana-p/narrat-engine/blob/main/packages/narrat/src/config/animations-config.ts): File definine the shape of the animations config and their options

## Relevant external documentation

- [Mozilla MDN page on animate](https://developer.mozilla.org/en-US/docs/Web/API/Element/animate): Explains how the animation API works with some example
- [Keyframe formats](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats): Explains how to define keyframes
- [Keyframe options](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/KeyframeEffect#options) list of available keyframe options
Binary file added docs/features/animations/animations-demo.mp4
Binary file not shown.
34 changes: 30 additions & 4 deletions docs/features/characters-and-portraits.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,33 @@ A character's config can have the following values:
- `name`: The name the character will appear as
- `sprites`: A key-value object of pose names to the url of the picture to use for that pose. Poses are used with the talk command (the command `talk player idle "A sentence"` would use the character "player" with the picture for the pose named "idle")
- `style`: An object to customise how that character looks with the following options:
- color: a CSS color (ie. "red", or #FFF)
- boxCss: [CSS style object](https://www.w3schools.com/jsref/dom_obj_style.asp) for custom-styling of the box encapsulating a dialogue from that character.
- nameCss: Same as above, but the styling will apply to the name of the character specifically
- textCss: Same as above, but will apply to the text "spoken" by the character
- `portraitCssClass`: A CSS class name to give to the portrait window for that character. This allows you to apply custom CSS styling to any character's portrait window
- `color`: a CSS color (ie. "red", or #FFF)
- `boxCss`: [CSS style object](https://www.w3schools.com/jsref/dom_obj_style.asp) for custom-styling of the box encapsulating a dialogue from that character.
- `nameCss`: Same as above, but the styling will apply to the name of the character specifically
- `textCss`: Same as above, but will apply to the text "spoken" by the character

## Character portrait styling

::: tip
Character portraits automatically get given the id of the character as a CSS class, so you can easily use this CSS class to style portraits per character
:::

Individual character poses can also specify their own width and height, if you want to have different sizes for different poses:

```yaml
helper:
sprites:
idle: # Instead of putting the image directly, have an object with an image property, and width/height values
image: helper_cat.webp
width: 150
height: 200
videoPose:
video: helper_video.mp4
width: 200
height: 355
style:
color: green
portraitCssClass: test
name: Helper Cat
```
66 changes: 66 additions & 0 deletions docs/features/dialog-panel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# The Dialog Panel

The Dialog Panel is where all the text in the game appears. When characters talk, the dialog panel opens, and shows what they say. It is also where the player can make choices and advance in the story.

The dialog panel is where most of the content of a Narrat game usually takes place, while the viewport below it is where visuals are displayed. Sometimes the viewport can have clickable buttons or sprites, but most of the interaction tends to take place in the dialog panel.

![Dialog Panel screenshot](./dialog-panel/dialog-panel.png)

## How the dialog panel works

Whenever the game is **doing something** (that is, running narrat script), the dialog panel will appear. If the narrat script ends, the dialog panel will close.

::: NOTE
This doesn't apply to games in overlay mode, or on mobile, where the dialog panel is always visible.
:::

## Dialog panel config options

The dialog panel has the following options available, which are set in the `dialogPanel` part of `config.yaml`:

```yaml
textSpeed: 30
animateText: true
timeBetweenLines: 100
overlayMode: true
rightOffset: 100
bottomOffset: 50
width: 475
height: 680
hideDuringTransition: false
showAfterScriptEnd: false
```
- `textSpeed`: [number] The speed at which text appears in the dialog panel, in characters per second. Defaults to 30. If `animateText` is off, this still controls the speed of auto play. Players can override this setting in the system menu
- `animateText`: [boolean] Whether text should appear one character at a time. Defaults to true. Players can override this setting in the system menu
- `timeBetweenLines`: [number] Time to wait between two lines of dialog in auto mode
- `overlayMode`: [boolean] Whether the dialog panel should be in overlay mode. Defaults to true. Overlay mode means that the dialog panel will appear on top of the viewport. In games where overlay mode is off, the dialog panel is instead to the side of the viewport
- `rightOffset`: [number] How far from the right edge of the screen the dialog panel should be, in pixels.
- `bottomOffset`: [number] How far from the bottom edge of the screen the dialog panel should be, in pixels.
- `width`: [number] The width of the dialog panel, in pixels.
- `height`: [number] The height of the dialog panel, in pixels.
- `hideDuringTransition`: [boolean] Whether the dialog panel should be hidden during screen transitions. Defaults to true.
- `showAfterScriptEnd`: [boolean] Whether the dialog panel should stay on even if the narrat script ends. Defaults to false.

## Controlling when the dialog panel appears

The default behaviour of the dialog panel should be good enough for most games, but if your game needs finer control of it, there are a few ways to control it:

The two config options `hideDuringTransition` and `showAfterScriptEnd` allow you to control whether the dialog panel should be hidden during screen transitions, and whether it should stay on even if the narrat script ends.

You can also use the `set_dialog_panel_mode` command to manually force the dialog panel on or off:

```narrat
test_set_dialog_panel_mode:
choice:
"Which mode":
"Auto (normal default behaviour)":
set_dialog_panel_mode auto
"Force always on":
set_dialog_panel_mode on
"Force always off (will go back on after a timer for testing)":
set_dialog_panel_mode off
wait 1500
set_dialog_panel_mode auto
jump test_set_dialog_panel_mode
```
Binary file added docs/features/dialog-panel/dialog-panel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions docs/features/inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,26 @@ coverY: 0

The inventory system allow players to collect and spend items. There is also a UI for viewing the inventory.

<video controls="controls" src="./inventory/inventory.mp4" type="video/mp4" autoplay="true"></video>

## How to use the inventory

This is how you create an inventory and items in narrat:

Possible items can be defined in the `items.yaml` config file.

```yaml
categories:
- id: food
name: Food
- id: books
name: Books

items:
bread:
name: Bread
description: A bread in the game.
category: food
icon: img/items/bread.webp
onUse:
action: jump
Expand All @@ -23,6 +36,7 @@ items:
name: Ominous Book
description: An ominous book.
icon: img/items/book.webp
category: books
onUse:
action: run
label: read_book
Expand Down Expand Up @@ -51,6 +65,14 @@ main:

Items can also be used, see guide below:

## Categories

Items can be grouped into categories. Inventory categories are defined in the `categories` part of the config. Each category has an `id` and `name` property. All the categories will become tabs in the inventory ui, on top of the generic `All` category which shows all items.

Items that have no category will appear in the `All` category.

If a game has no categories defined, the inventory will have no tabs and all items will be shown directly in one place.

[items.md](../features/items.md)

![Inventory](./images/inventory.png)
Expand Down
Binary file added docs/features/inventory/inventory.mp4
Binary file not shown.
Loading

1 comment on commit ac9e567

@vercel
Copy link

@vercel vercel bot commented on ac9e567 Oct 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

narrat-editor-demo – ./packages/narrat-editor

narrat-editor-demo-git-main-nialna.vercel.app
demo.narrat.dev
narrat-editor-demo-nialna.vercel.app
narrat-editor-demo.vercel.app

Please sign in to comment.