# A walk through the forest

**URL:** <https://narrat.discourse.group/t/a-walk-through-the-forest/77>\
**Category:** Projects\
**Created:** [15 July 2023 22:52 UTC](https://narrat.discourse.group/t/a-walk-through-the-forest/77 "2023-07-15T22:52:37Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Narrat-Admin](https://yyz2.discourse-cdn.com/free1/user_avatar/narrat.discourse.group/narrat-admin/32/429_2.png) [@Narrat-Admin](https://narrat.discourse.group/u/Narrat-Admin)\
**Post date:** [15 July 2023 22:52 UTC](https://narrat.discourse.group/t/a-walk-through-the-forest/77/1 "2023-07-15T22:52:37Z")

</div>

# A walk through the forest

(Or whatever this game will end up being called)  
I’ve started a Narrat Jam game. It’s an interactive forest walk with branching and pictures to click on.

I’m thinking of having pictures of plants and info about them. maybe a fun mode where there’s also a test where you have to identify plants I don’t know.

Video of the basic system working (I can’t upload video here so here’s a link to a mastodon post):

[https://tech.lgbt/@bubbline/110720588590283465](https://tech.lgbt/@bubbline/110720588590283465)

## How it works

I’ve made a system to read a yaml data file and use that as the base to dynamically do everything. So in this case, the file defining all the paths etc looks like this:

 ![image](https://global.discourse-cdn.com/free1/uploads/narrat/original/1X/38b8899c4b08810fce1a60395a57fa3e135faad5.png)

## Source code

I will probably add a basic setup for making this type of point and click game to the narrat examples repo at some point, but for now here’s the important source code (as of today) if anyone wants to use it as a base for something:

> **Code Details**
>
> ## Utilities
> 
> `utilities.narrat` which contains general useful functions:
> 
> ```auto
> add_paths content:
> if $content.paths:
> log "adding paths"
> for_of $content.paths add_path
> elseif (< $current.index (- $current.path.contents.length 1)):
> log "Adding default forward path"
> var path (new Object)
> set path.id "next"
> set path.x 960
> set path.y 540
> set path.arrow "forward"
> run add_path $path
> if (!= $content.backAllowed false):
> var backPath (new Object)
> set backPath.direction "back"
> set backPath.id "previous"
> if $content.back:
> set backPath.id $content.back
> set backPath.x 960
> set backPath.y 900
> set backPath.arrow "back"
> run add_path $backPath
> 
> add_path path:
> var arrowType $path.arrow
> log "adding path " $path.id " with arrow " $arrowType
> var arrowConfig $data.SPRITES[$arrowType]
> var spriteData (new Object)
> set spriteData.background $arrowConfig.background
> set spriteData.x $path.x
> set spriteData.y $path.y
> set spriteData.width $arrowConfig.width
> set spriteData.height $arrowConfig.height
> set spriteData.anchor.x $arrowConfig.anchor.x
> set spriteData.anchor.y $arrowConfig.anchor.y
> var pathCallback (concat "load_path " $path.id )
> if (== $path.direction "back"):
> set pathCallback (concat "go_back " $path.id)
> set spriteData.onClick $pathCallback
> run load_sprite $spriteData
> 
> load_sprite spriteData:
> var sprite (create_sprite $spriteData.background $spriteData.x $spriteData.y)
> run setup_sprite $spriteData $sprite
> return $sprite
> 
> load_object spriteData:
> var object (create_object $spriteData.x $spriteData.y)
> run setup_sprite $spriteData $object
> return $object
> 
> setup_sprite spriteData sprite:
> if $spriteData.anchor:
> set sprite.anchor.x $spriteData.anchor.x
> set sprite.anchor.y $spriteData.anchor.y
> if $spriteData.width:
> set sprite.width $spriteData.width
> if $spriteData.height:
> set sprite.height $spriteData.height
> if $spriteData.onClick:
> set sprite.onClick $spriteData.onClick
> if $spriteData.layer:
> set sprite.layer $spriteData.layer
> if $spriteData.cssClass:
> set sprite.cssClass $spriteData.cssClass
> return $sprite
> 
> load_path pathId:
> log "Moving to path %{$pathId}"
> var previousId $previousPathId
> var previous $PATHS[$previousId]
> set current.lastIndex $current.index
> set previousPathId $current.id
> if (== $pathId "next"):
> set current.index (+ $current.index 1)
> else:
> set current.id $pathId
> set current.path $PATHS[$pathId]
> set current.index 0
> run process_current_path
> 
> go_back backId:
> if (!= $backId "previous"):
> set current.id $backId
> set current.path $PATHS[$backId]
> set current.index (- $current.path.contents.length 1)
> else:
> set current.index (- $current.index 1)
> if (>= $current.index 0):
> run process_current_path
> 
> process_current_path:
> empty_sprites
> set current.content $current.path.contents[$current.index]
> if $current.content.bg:
> log "Setting background to %{$current.content.bg}"
> set_screen $current.content.bg 0 fade 1000 0
> run add_paths $current.content
> run add_pics $current.content
> 
> ```
> 
> ### Pics display
> 
> `pics.narrat` which takes care of reading the info about pics and adding them to the screens so they appear and are clickable:
> 
> ```auto
> add_pics content:
> if $content.pics:
> log "adding pics"
> for_of $content.pics add_pic
> 
> add_pic pic:
> var imagePath (concat "img/pics/" $pic.img)
> var width 160
> var height 90
> var spriteData (new Object)
> set spriteData.background $imagePath
> set spriteData.cssClass pic-preview
> set spriteData.x $pic.x
> set spriteData.y $pic.y
> set spriteData.width $width
> set spriteData.height $height
> set spriteData.onClick (concat "show_pic " $pic.label " " $imagePath)
> run load_sprite $spriteData
> 
> show_pic label img:
> log "Show pic %{$label} %{$img}"
> set data.overlay (run load_object $data.SPRITES.big_overlay)
> var width 1760
> var height 990
> var spriteData (new Object)
> set spriteData.background $img
> set spriteData.x 20
> set spriteData.y 20
> set spriteData.anchor.x 0
> set spriteData.anchor.y 0
> set spriteData.width $width
> set spriteData.height $height
> set spriteData.cssClass "full-pic"
> set spriteData.onClick "close_pic"
> set spriteData.layer 2
> set data.currentPic (run load_sprite $spriteData)
> if $label:
> run $label
> 
> close_pic:
> log "Closing pic"
> delete_sprite $data.currentPic
> delete_sprite $data.overlay
> 
> ```
> 
> ## Main game script
> 
> Basic `game.narrat` which mostly uses the above:
> 
> ```auto
> main:
> set data.PATHS (load_data data/forest.yaml)
> set data.SPRITES (load_data data/common_sprites.yaml)
> set data.previousPathId forest
> set current (new Object)
> set current.id forest
> set current.path $PATHS.forest
> set current.index 0
> set_screen @empty 1
> set_screen @empty 2
> run load_path $current.id
> 
> dr_pepper:
> clear_dialog
> "A can of Dr. Pepper."
> "I didn't know they grew in forests."
> 
> ```
> 
> ## Yaml file for paths
> 
> `forest.yaml`, which contains the actual data for all the paths
> 
> ```yaml
> forest:
> id: Forest Entrance
> contents:
> - bg: entrance1
> backAllowed: false
> - bg: entrance2
> - bg: entrance3
> pics:
> - img: dr_pepper.jpeg
> x: 100
> y: 800
> label: dr_pepper
> ratio: 16/9
> paths:
> - id: entrance-fork-1
> x: 200
> y: 500
> arrow: left
> - id: step-2
> x: 1500
> y: 300
> arrow: forward
> entrance-fork-1:
> id: Entrance Fork 1
> contents:
> - bg: entrance-fork-1
> back: forest
> 
> step-2:
> id: Step 2
> contents:
> - bg: step-2-1
> back: forest
> - bg: step-2-2
> 
> ```
> 
> ### Sprites data
> 
> `common_sprites.yaml`, which contains a list of sprites info for easily adding commonly needed sprites:
> 
> ```yaml
> left:
> background: img/ui/left.webp
> x: 100
> y: 250
> width: 200
> height: 200
> anchor:
> x: 0.5
> y: 0.5
> onClick: choose_left
> right:
> background: img/ui/right.webp
> x: 770
> y: 250
> width: 200
> height: 200
> anchor:
> x: 0.5
> y: 0.5
> onClick: choose_right
> forward:
> background: img/ui/front.webp
> x: 440
> y: 120
> width: 200
> height: 200
> anchor:
> x: 0.5
> y: 0.5
> onClick: choose_front
> back:
> background: img/ui/back.png
> x: 440
> y: 380
> width: 200
> height: 200
> anchor:
> x: 0.5
> y: 0.5
> onClick: choose_back
> big_overlay:
> cssClass: big-overlay
> layer: 1
> x: 0
> y: 0
> width: 1920
> height: 1080
> anchor:
> x: 0
> y: 0
> onClick: close_pic
> 
> ```
> 
> ### CSS file
> 
> And the `main.css` file:
> 
> ```css
> /* See https://docs.narrat.dev/guides/theming-the-game-and-ui for info on how to customise your game with CSS. */
> 
> html {
> font-size: 20px;
> }
> #app {
> /* Customise CSS variables here. They will override the existing narrat ones. You can also add your own variables */
> --bg-color: #131720;
> --text-color: #d9e1f2;
> --primary: hsl(255, 30%, 55%);
> --focus: hsl(210, 90%, 50%);
> --secondary: #42b983;
> }
> 
> /* Add any other CSS you want here */
> 
> .big-overlay {
> background: rgba(0, 0, 0, 0.5);
> }
> 
> .pic-preview {
> background-color: white;
> /* Polaroid style image */
> border-radius: 10px;
> border-top: 6px solid white;
> border-left: 6px solid white;
> border-right: 6px solid white;
> border-bottom: 6px solid white;
> box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.8), 0 6px 20px 0 rgba(0, 0, 0, 0.8);
> }
> 
> .full-pic {
> border-top: 30px solid white;
> border-left: 10px solid white;
> border-right: 10px solid white;
> border-bottom: 10px solid white;
> box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.8), 0 6px 20px 0 rgba(0, 0, 0, 0.8);
> }
> 
> .dialog.override {
> border-radius: 20px;
> }
> 
> ```

---

<div class="post-metadata">

**Author:** ![dh\_croasdill](https://yyz2.discourse-cdn.com/free1/user_avatar/narrat.discourse.group/dh_croasdill/32/106_2.png) [@dh\_croasdill](https://narrat.discourse.group/u/dh_croasdill)\
**Post date:** [15 July 2023 23:24 UTC](https://narrat.discourse.group/t/a-walk-through-the-forest/77/2 "2023-07-15T23:24:10Z")

</div>

this is neat as hell! i’d been wondering about doing something like this. it’s very [dumpling.love](https://dumpling.love)

---

<div class="post-metadata">

**Author:** ![Binary](https://yyz2.discourse-cdn.com/free1/user_avatar/narrat.discourse.group/binary/32/39_2.png) [@Binary](https://narrat.discourse.group/u/Binary)\
**Post date:** [16 July 2023 02:15 UTC](https://narrat.discourse.group/t/a-walk-through-the-forest/77/3 "2023-07-16T02:15:33Z")

</div>

Oh, this is really cool! Makes perfect sense that this would work but I never thought about it.

---

<div class="post-metadata">

**Author:** ![Narrat-Admin](https://yyz2.discourse-cdn.com/free1/user_avatar/narrat.discourse.group/narrat-admin/32/429_2.png) [@Narrat-Admin](https://narrat.discourse.group/u/Narrat-Admin)\
**Post date:** [16 July 2023 12:08 UTC](https://narrat.discourse.group/t/a-walk-through-the-forest/77/4 "2023-07-16T12:08:44Z")

</div>

Another update, I added a little plants widget system to show plant identification and info on some pictures

[https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExb29sZHEyNjc1MXpmeWpseGQyaDVsZWswem54ajZqbGw1aWN0bm96ZyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/ho7umxa3lK0C6o4hkk/giphy-downsized-large.gif(image larger than 4 MB)](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExb29sZHEyNjc1MXpmeWpseGQyaDVsZWswem54ajZqbGw1aWN0bm96ZyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/ho7umxa3lK0C6o4hkk/giphy-downsized-large.gif)

 ![image](https://global.discourse-cdn.com/free1/uploads/narrat/original/1X/53cb538b30a4c8f4d1d7a127b570778a9cc3fffd.jpeg)

---

<div class="post-metadata">

**Author:** ![Narrat-Admin](https://yyz2.discourse-cdn.com/free1/user_avatar/narrat.discourse.group/narrat-admin/32/429_2.png) [@Narrat-Admin](https://narrat.discourse.group/u/Narrat-Admin)\
**Post date:** [22 July 2023 23:21 UTC](https://narrat.discourse.group/t/a-walk-through-the-forest/77/5 "2023-07-22T23:21:15Z")

</div>

I’ve just finished setting up the entire path and wrote all the main story 👀

Now I just need to place all the pictures in the screens and write their descriptions 💤
