Compare commits

...

32 Commits

Author SHA1 Message Date
3wc
2ad54aa613 WIP: Switch to domkit for dialogue 2024-02-18 12:25:03 -03:00
3wc
ed8bc13402 Moar TODO 2024-02-16 23:57:42 -03:00
3wc
d6b042f2a4 Drop useless Main file 2024-02-16 23:57:17 -03:00
3wc
c768073503 Uncomment quarters dialogue 2024-02-16 23:38:39 -03:00
3wc
32885707de Moar TODO 2024-02-16 23:38:29 -03:00
3wc
bb7690e606 Add TODO 2024-02-16 21:53:53 -03:00
3wc
4b00d713a9 Twiddle text a bit 2024-02-16 03:55:49 -03:00
3wc
8be7c18d4f 4matting 2024-02-16 03:52:16 -03:00
3wc
fd6b9ee8dd Split yarn, handle inactive options 2024-02-16 03:51:57 -03:00
3wc
808958f7cc Tidy up some temp files 2024-02-16 03:51:49 -03:00
3wc
b16b27e03d Test out some YarnSpinner format stuff 2024-02-16 02:54:58 -03:00
3wc
e0d3ca8021 Add RoomOpen command / event 2024-02-16 02:38:52 -03:00
3wc
c1b102860e Clickable rooms with per-room dialogue 2024-02-16 01:53:38 -03:00
3wc
bb9db51560 Tidy up debugging, remove 12px padding 2024-02-15 02:08:08 -03:00
3wc
867b33aef5 Specify git version of heaps 2024-02-15 02:06:16 -03:00
3wc
05fc9156b0 Working debug console, fix dialogue bugs 2024-02-15 01:54:01 -03:00
3wc
8921f231bd Fix crash when jumping straight to WorldMapScene 2024-02-14 14:25:04 -03:00
3wc
010aa5323d Only launch dialogue when world map shown 2024-02-14 12:33:05 -03:00
3wc
dd9fc47787 README and makefile improvements 2024-02-14 12:32:45 -03:00
3wc
021aac9914 Make dialogue system work (hackily) with domkit 2024-02-14 12:13:29 -03:00
3wc
477b57e2a7 Build in debug mode 2024-02-14 00:21:23 -03:00
3wc
87302a3713 Add EventBus and GameScene from ecs 2024-02-14 00:21:02 -03:00
3wc
cd8be645a3 Hide Quit button on web 2024-02-13 13:47:41 -03:00
3wc
17ba4ada30 Break out title screen into separate file 2024-02-13 13:47:24 -03:00
3wc
aaddce255a Ensure make looks at all dependent files 2024-02-13 13:46:43 -03:00
3wc
4b6cd309ac Add index.html for HTML rendering 2024-02-13 03:27:22 -03:00
3wc
da1f1f1e2a Working dialogue actions handling 2024-02-13 03:27:07 -03:00
3wc
1d8222a395 Make HTML5 work again 2024-02-13 00:04:25 -03:00
3wc
51d10f430f omg working yarnspinner dialogue 😍 2024-02-12 21:58:44 -03:00
3wc
96c430c3c1 Re4mat 2024-02-12 18:30:13 -03:00
3wc
ea32d0356d Basic dialogue box support 2024-02-12 18:03:43 -03:00
3wc
f39ece171e Add make clean 2024-02-12 16:47:53 -03:00
46 changed files with 3586 additions and 165 deletions

4
.gitignore vendored
View File

@ -1 +1,3 @@
**/*.hl /bin/*
/res/.tmp/
/res/rewild.tiled-*

View File

@ -2,10 +2,31 @@
## Development ## Development
### Requirements
* `haxe`
* `haxelib`
* Haxelib dependencies; run `haxelib install compile-hl.hxml`
* `automake`
### Compiling ### Compiling
`haxe compile.hxml` `make debug`
You can alternatively run `make watch` to automatically rebuild on changes to
`.hx` files.
### Running ### Running
`hl rewild.hl` `make run`
### Making a release
**TODO**: Making a redistributable `hl` version
#### Web
```
make bin/rewild.js
abra app cp <domain> bin/rewild.js app:/usr/share/nginx/html/bin/
```

27
TODO.md Normal file
View File

@ -0,0 +1,27 @@
# TODO
## Features
- Saving and loading games
- Character select
- Stats
- Better open / closed state graphics for rooms
- Displaying sprites (characters, objects)
- Inventory
- Room labels
- Background music
- Sound effects
## Bugs
- Fix console rendering issues
### Dialogue
- Text formatting
- Character profiles / speaker ID
## Code architecture
- Move dialogue- and option-drawing out of `Game.hx`
- Use domkit for dialogue

7
compile-common.hxml Normal file
View File

@ -0,0 +1,7 @@
-cp src
--macro Init.setup()
-lib heaps:git:https://github.com/HeapsIO/heaps.git
-lib tiledhx
-lib hxyarn
-main Game
-lib domkit

5
compile-hl.hxml Normal file
View File

@ -0,0 +1,5 @@
compile-common.hxml
-D windowTitle=StoneInAGlasshouse
-lib hlsdl
-hl bin/rewild.hl

3
compile-js.hxml Normal file
View File

@ -0,0 +1,3 @@
compile-common.hxml
-js bin/rewild.js

View File

@ -1,7 +0,0 @@
-cp src
--macro Init.setup()
-lib heaps
-lib hlsdl
-hl rewild.hl
-main Main
-lib domkit

32
index.html Normal file
View File

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Stone In a Glasshouse</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui"
/>
<meta name="format-detection" content="telephone=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<style>
body {
margin: 0;
padding: 0;
background-color: black;
width: 100%;
height: 100%;
text-align: center;
}
canvas#webgl {
width: 900px;
margin: 0 auto;
}
</style>
</head>
<body>
<canvas id="webgl"></canvas>
<script type="text/javascript" src="bin/rewild.js"></script>
</body>
</html>

View File

@ -1,7 +1,23 @@
.PHONY: watch .PHONY: watch run
rewild.hl: **/*.hx default: bin/rewild.hl
haxe compile.hxml
SOURCES := $(shell find . -name \*.hx -print)
bin/rewild.hl: $(SOURCES)
haxe compile-hl.hxml
bin/rewild.js: $(SOURCES)
haxe compile-js.hxml
debug: $(SOURCES)
haxe --debug compile-hl.hxml
clean:
rm -f bin/rewild.hl bin/rewild.js
watch: watch:
@inotifywait --recursive --monitor --event modify,move,create,delete --include '.*.hx$$' ./ | while read changed; do echo $$changed; make; done @inotifywait --recursive --monitor --event modify,move,create,delete --include '.*.hx$$' ./ | while read changed; do echo $$changed; make debug; done
run:
hl bin/rewild.hl

View File

@ -0,0 +1,195 @@
<?xml version="1.0" encoding="utf-8"?>
<Font size="6" family="Minecraftia" height="11" style="Regular">
<Char width="2" offset="0 14" rect="1 13 0 0" code=" "/>
<Char width="2" offset="0 2" rect="2 1 1 7" code="!"/>
<Char width="4" offset="0 2" rect="4 1 3 2" code="&quot;"/>
<Char width="6" offset="0 2" rect="8 1 5 7" code="#"/>
<Char width="6" offset="0 2" rect="14 1 5 7" code="$"/>
<Char width="6" offset="0 2" rect="20 1 5 7" code="%"/>
<Char width="6" offset="0 2" rect="26 1 5 7" code="&amp;"/>
<Char width="2" offset="0 2" rect="32 1 1 2" code="'"/>
<Char width="5" offset="0 2" rect="34 1 4 7" code="("/>
<Char width="5" offset="0 2" rect="39 1 4 7" code=")"/>
<Char width="5" offset="0 2" rect="44 1 4 3" code="*"/>
<Char width="6" offset="0 4" rect="49 3 5 5" code="+"/>
<Char width="2" offset="0 7" rect="55 6 1 3" code=","/>
<Char width="6" offset="0 6" rect="57 5 5 1" code="-"/>
<Char width="2" offset="0 7" rect="63 6 1 2" code="."/>
<Char width="6" offset="0 2" rect="65 1 5 7" code="/"/>
<Char width="6" offset="0 2" rect="71 1 5 7" code="0"/>
<Char width="6" offset="0 2" rect="77 1 5 7" code="1"/>
<Char width="6" offset="0 2" rect="83 1 5 7" code="2"/>
<Char width="6" offset="0 2" rect="89 1 5 7" code="3"/>
<Char width="6" offset="0 2" rect="95 1 5 7" code="4"/>
<Char width="6" offset="0 2" rect="101 1 5 7" code="5"/>
<Char width="6" offset="0 2" rect="1 14 5 7" code="6"/>
<Char width="6" offset="0 2" rect="7 14 5 7" code="7"/>
<Char width="6" offset="0 2" rect="13 14 5 7" code="8"/>
<Char width="6" offset="0 2" rect="19 14 5 7" code="9"/>
<Char width="2" offset="0 3" rect="25 15 1 6" code=":"/>
<Char width="2" offset="0 3" rect="27 15 1 7" code=";"/>
<Char width="5" offset="0 2" rect="29 14 4 7" code="&lt;"/>
<Char width="6" offset="0 4" rect="34 16 5 4" code="="/>
<Char width="5" offset="0 2" rect="40 14 4 7" code=">"/>
<Char width="6" offset="0 2" rect="45 14 5 7" code="?"/>
<Char width="7" offset="0 2" rect="51 14 6 7" code="@"/>
<Char width="6" offset="0 2" rect="58 14 5 7" code="A"/>
<Char width="6" offset="0 2" rect="64 14 5 7" code="B"/>
<Char width="6" offset="0 2" rect="70 14 5 7" code="C"/>
<Char width="6" offset="0 2" rect="76 14 5 7" code="D"/>
<Char width="6" offset="0 2" rect="82 14 5 7" code="E"/>
<Char width="6" offset="0 2" rect="88 14 5 7" code="F"/>
<Char width="6" offset="0 2" rect="94 14 5 7" code="G"/>
<Char width="6" offset="0 2" rect="100 14 5 7" code="H"/>
<Char width="4" offset="0 2" rect="1 23 3 7" code="I"/>
<Char width="6" offset="0 2" rect="5 23 5 7" code="J"/>
<Char width="6" offset="0 2" rect="11 23 5 7" code="K"/>
<Char width="6" offset="0 2" rect="17 23 5 7" code="L"/>
<Char width="6" offset="0 2" rect="23 23 5 7" code="M"/>
<Char width="6" offset="0 2" rect="29 23 5 7" code="N"/>
<Char width="6" offset="0 2" rect="35 23 5 7" code="O"/>
<Char width="6" offset="0 2" rect="41 23 5 7" code="P"/>
<Char width="6" offset="0 2" rect="47 23 5 7" code="Q"/>
<Char width="6" offset="0 2" rect="53 23 5 7" code="R"/>
<Char width="6" offset="0 2" rect="59 23 5 7" code="S"/>
<Char width="6" offset="0 2" rect="65 23 5 7" code="T"/>
<Char width="6" offset="0 2" rect="71 23 5 7" code="U"/>
<Char width="6" offset="0 2" rect="77 23 5 7" code="V"/>
<Char width="6" offset="0 2" rect="83 23 5 7" code="W"/>
<Char width="6" offset="0 2" rect="89 23 5 7" code="X"/>
<Char width="6" offset="0 2" rect="95 23 5 7" code="Y"/>
<Char width="6" offset="0 2" rect="101 23 5 7" code="Z"/>
<Char width="4" offset="0 2" rect="1 32 3 7" code="["/>
<Char width="6" offset="0 2" rect="5 32 5 7" code="\"/>
<Char width="4" offset="0 2" rect="11 32 3 7" code="]"/>
<Char width="6" offset="0 2" rect="15 32 5 3" code="^"/>
<Char width="6" offset="0 9" rect="21 39 5 1" code="_"/>
<Char width="3" offset="0 1" rect="27 31 2 2" code="`"/>
<Char width="6" offset="0 4" rect="30 34 5 5" code="a"/>
<Char width="6" offset="0 2" rect="36 32 5 7" code="b"/>
<Char width="6" offset="0 4" rect="42 34 5 5" code="c"/>
<Char width="6" offset="0 2" rect="48 32 5 7" code="d"/>
<Char width="6" offset="0 4" rect="54 34 5 5" code="e"/>
<Char width="5" offset="0 2" rect="60 32 4 7" code="f"/>
<Char width="6" offset="0 4" rect="65 34 5 6" code="g"/>
<Char width="6" offset="0 2" rect="71 32 5 7" code="h"/>
<Char width="2" offset="0 2" rect="77 32 1 7" code="i"/>
<Char width="6" offset="0 2" rect="79 32 5 8" code="j"/>
<Char width="5" offset="0 2" rect="85 32 4 7" code="k"/>
<Char width="3" offset="0 2" rect="90 32 2 7" code="l"/>
<Char width="6" offset="0 4" rect="93 34 5 5" code="m"/>
<Char width="6" offset="0 4" rect="99 34 5 5" code="n"/>
<Char width="6" offset="0 4" rect="1 43 5 5" code="o"/>
<Char width="6" offset="0 4" rect="7 43 5 6" code="p"/>
<Char width="6" offset="0 4" rect="13 43 5 6" code="q"/>
<Char width="6" offset="0 4" rect="19 43 5 5" code="r"/>
<Char width="6" offset="0 4" rect="25 43 5 5" code="s"/>
<Char width="4" offset="0 2" rect="31 41 3 7" code="t"/>
<Char width="6" offset="0 4" rect="35 43 5 5" code="u"/>
<Char width="6" offset="0 4" rect="41 43 5 5" code="v"/>
<Char width="6" offset="0 4" rect="47 43 5 5" code="w"/>
<Char width="6" offset="0 4" rect="53 43 5 5" code="x"/>
<Char width="6" offset="0 4" rect="59 43 5 6" code="y"/>
<Char width="6" offset="0 4" rect="65 43 5 5" code="z"/>
<Char width="5" offset="0 2" rect="71 41 4 7" code="{"/>
<Char width="2" offset="0 2" rect="76 41 1 8" code="|"/>
<Char width="5" offset="0 2" rect="78 41 4 7" code="}"/>
<Char width="7" offset="0 2" rect="83 41 6 2" code="~"/>
<Char width="2" offset="0 2" rect="90 41 1 7" code="¡"/>
<Char width="5" offset="0 4" rect="92 43 4 5" code="¢"/>
<Char width="6" offset="0 2" rect="97 41 5 7" code="£"/>
<Char width="6" offset="0 3" rect="103 42 5 5" code="¤"/>
<Char width="6" offset="0 2" rect="1 51 5 7" code="¥"/>
<Char width="2" offset="0 2" rect="7 51 1 7" code="¦"/>
<Char width="6" offset="0 2" rect="9 51 5 7" code="§"/>
<Char width="5" offset="1 2" rect="15 51 3 1" code="¨"/>
<Char width="8" offset="0 2" rect="19 51 7 7" code="©"/>
<Char width="4" offset="0 2" rect="27 51 3 6" code="ª"/>
<Char width="5" offset="0 5" rect="31 54 4 4" code="«"/>
<Char width="5" offset="0 4" rect="36 53 4 3" code="¬"/>
<Char width="8" offset="0 2" rect="41 51 7 7" code="®"/>
<Char width="6" offset="0 2" rect="49 51 5 1" code="¯"/>
<Char width="4" offset="0 2" rect="55 51 3 3" code="°"/>
<Char width="6" offset="0 2" rect="59 51 5 7" code="±"/>
<Char width="4" offset="0 2" rect="65 51 3 4" code="²"/>
<Char width="4" offset="0 2" rect="69 51 3 4" code="³"/>
<Char width="3" offset="0 1" rect="73 50 2 2" code="´"/>
<Char width="6" offset="0 4" rect="76 53 5 6" code="µ"/>
<Char width="6" offset="0 2" rect="82 51 5 7" code="¶"/>
<Char width="2" offset="0 6" rect="88 55 1 1" code="·"/>
<Char width="4" offset="1 9" rect="90 58 2 2" code="¸"/>
<Char width="4" offset="0 2" rect="93 51 3 4" code="¹"/>
<Char width="4" offset="0 2" rect="97 51 3 6" code="º"/>
<Char width="5" offset="0 5" rect="101 54 4 4" code="»"/>
<Char width="9" offset="0 2" rect="1 63 8 7" code="¼"/>
<Char width="9" offset="0 2" rect="10 63 8 7" code="½"/>
<Char width="9" offset="0 2" rect="19 63 8 7" code="¾"/>
<Char width="6" offset="0 2" rect="28 63 5 7" code="¿"/>
<Char width="6" offset="0 0" rect="34 61 5 9" code="À"/>
<Char width="6" offset="0 0" rect="40 61 5 9" code="Á"/>
<Char width="6" offset="0 0" rect="46 61 5 9" code="Â"/>
<Char width="6" offset="0 0" rect="52 61 5 9" code="Ã"/>
<Char width="6" offset="0 0" rect="58 61 5 9" code="Ä"/>
<Char width="6" offset="0 0" rect="64 61 5 9" code="Å"/>
<Char width="10" offset="0 2" rect="70 63 9 7" code="Æ"/>
<Char width="6" offset="0 2" rect="80 63 5 9" code="Ç"/>
<Char width="6" offset="0 0" rect="86 61 5 9" code="È"/>
<Char width="6" offset="0 0" rect="92 61 5 9" code="É"/>
<Char width="6" offset="0 0" rect="98 61 5 9" code="Ê"/>
<Char width="6" offset="0 0" rect="1 73 5 9" code="Ë"/>
<Char width="4" offset="0 0" rect="7 73 3 9" code="Ì"/>
<Char width="4" offset="0 0" rect="11 73 3 9" code="Í"/>
<Char width="4" offset="0 0" rect="15 73 3 9" code="Î"/>
<Char width="4" offset="0 0" rect="19 73 3 9" code="Ï"/>
<Char width="7" offset="0 2" rect="23 75 6 7" code="Ð"/>
<Char width="6" offset="0 0" rect="30 73 5 9" code="Ñ"/>
<Char width="6" offset="0 0" rect="36 73 5 9" code="Ò"/>
<Char width="6" offset="0 0" rect="42 73 5 9" code="Ó"/>
<Char width="6" offset="0 0" rect="48 73 5 9" code="Ô"/>
<Char width="6" offset="0 0" rect="54 73 5 9" code="Õ"/>
<Char width="6" offset="0 0" rect="60 73 5 9" code="Ö"/>
<Char width="5" offset="0 5" rect="66 78 4 4" code="×"/>
<Char width="6" offset="0 2" rect="71 75 5 7" code="Ø"/>
<Char width="6" offset="0 0" rect="77 73 5 9" code="Ù"/>
<Char width="6" offset="0 0" rect="83 73 5 9" code="Ú"/>
<Char width="6" offset="0 0" rect="89 73 5 9" code="Û"/>
<Char width="6" offset="0 0" rect="95 73 5 9" code="Ü"/>
<Char width="6" offset="0 0" rect="101 73 5 9" code="Ý"/>
<Char width="6" offset="0 2" rect="1 85 5 7" code="Þ"/>
<Char width="6" offset="0 2" rect="7 85 5 7" code="ß"/>
<Char width="6" offset="0 1" rect="13 84 5 8" code="à"/>
<Char width="6" offset="0 1" rect="19 84 5 8" code="á"/>
<Char width="6" offset="0 1" rect="25 84 5 8" code="â"/>
<Char width="6" offset="0 1" rect="31 84 5 8" code="ã"/>
<Char width="6" offset="0 2" rect="37 85 5 7" code="ä"/>
<Char width="6" offset="0 0" rect="43 83 5 9" code="å"/>
<Char width="10" offset="0 4" rect="49 87 9 5" code="æ"/>
<Char width="6" offset="0 4" rect="59 87 5 7" code="ç"/>
<Char width="6" offset="0 1" rect="65 84 5 8" code="è"/>
<Char width="6" offset="0 1" rect="71 84 5 8" code="é"/>
<Char width="6" offset="0 1" rect="77 84 5 8" code="ê"/>
<Char width="6" offset="0 2" rect="83 85 5 7" code="ë"/>
<Char width="2" offset="-1 1" rect="89 84 2 8" code="ì"/>
<Char width="3" offset="0 1" rect="92 84 2 8" code="í"/>
<Char width="3" offset="-1 1" rect="95 84 3 8" code="î"/>
<Char width="3" offset="-1 2" rect="99 85 3 7" code="ï"/>
<Char width="6" offset="0 2" rect="103 85 5 7" code="ð"/>
<Char width="6" offset="0 1" rect="1 95 5 8" code="ñ"/>
<Char width="6" offset="0 1" rect="7 95 5 8" code="ò"/>
<Char width="6" offset="0 1" rect="13 95 5 8" code="ó"/>
<Char width="6" offset="0 1" rect="19 95 5 8" code="ô"/>
<Char width="6" offset="0 1" rect="25 95 5 8" code="õ"/>
<Char width="6" offset="0 2" rect="31 96 5 7" code="ö"/>
<Char width="6" offset="0 4" rect="37 98 5 5" code="÷"/>
<Char width="6" offset="0 4" rect="43 98 5 5" code="ø"/>
<Char width="6" offset="0 1" rect="49 95 5 8" code="ù"/>
<Char width="6" offset="0 1" rect="55 95 5 8" code="ú"/>
<Char width="6" offset="0 1" rect="61 95 5 8" code="û"/>
<Char width="6" offset="0 2" rect="67 96 5 7" code="ü"/>
<Char width="6" offset="0 1" rect="73 95 5 9" code="ý"/>
<Char width="6" offset="0 2" rect="79 96 5 8" code="þ"/>
<Char width="6" offset="0 4" rect="85 98 5 6" code="ÿ"/>
<Char width="10" offset="0 2" rect="91 96 9 7" code="Œ"/>
<Char width="10" offset="0 4" rect="1 107 9 5" code="œ"/>
<Char width="6" offset="0 2" rect="11 105 5 7" code="€"/>
</Font>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -0,0 +1,4 @@
The FontStruction “Pixel UniCode”
(http://fontstruct.com/fontstructions/show/908795) by “ivancr72” is licensed
under a Creative Commons Attribution license
(http://creativecommons.org/licenses/by/3.0/).

View File

@ -0,0 +1,26 @@
The font file in this archive was created using Fontstruct the free, online
font-building tool.
This font was created by “ivancr72”.
This font has a homepage where this archive and other versions may be found:
http://fontstruct.com/fontstructions/show/908795
Try Fontstruct at http://fontstruct.com
Its easy and its fun.
NOTE FOR FLASH USERS: Fontstruct fonts (fontstructions) are optimized for Flash.
If the font in this archive is a pixel font, it is best displayed at a font-size
of 16.
Fontstruct is sponsored by FontShop.
Visit them at http://fontshop.com
FontShop is the original independent font retailer. Weve been around since
the dawn of digital type. Whether you need the right font or need to create the
right font from scratch, let our 23 years of experience work for you.
Fontstruct is copyright ©2013-2014 Rob Meek
LEGAL NOTICE:
In using this font you must comply with the licensing terms described in the
file “license.txt” included with this archive.
If you redistribute the font file in this archive, it must be accompanied by all
the other files from this archive, including this one.

View File

@ -21,6 +21,6 @@
<object id="7" name="medical" x="96" y="96" width="224" height="128"/> <object id="7" name="medical" x="96" y="96" width="224" height="128"/>
<object id="8" name="generator" x="96" y="416" width="192" height="128"/> <object id="8" name="generator" x="96" y="416" width="192" height="128"/>
<object id="9" name="quarters" x="320" y="416" width="288" height="128"/> <object id="9" name="quarters" x="320" y="416" width="288" height="128"/>
<object id="10" name="hangar" x="640" y="128" width="224" height="416"/> <object id="10" name="hangar" x="640" y="96" width="224" height="448"/>
</objectgroup> </objectgroup>
</map> </map>

View File

@ -1,13 +1,21 @@
text {
font : url("res/font/minecraftia_regular_6.fnt")
}
game-container {
background: blue;
}
.mybox { .mybox {
background: #080; background: #080;
padding: -10; padding: -10;
} }
view.mybox { heading.mybox {
padding: 10; padding: 10;
} }
container { title-scene {
max-width: 300; max-width: 300;
layout: vertical; layout: vertical;
} }
@ -44,3 +52,22 @@ menubutton:hover text {
menubutton:active { menubutton:active {
background: #666; background: #666;
} }
flow.dialogue-container {
fill-width: true;
height: 20;
debug: true;
}
dialogue-box {
fill-width: true;
height: 20;
}
scale-grid#dialogueBackground {
/* fill-width: true; */
}
/* text#dialogueText { */
/* font : url("res/font/minecraftia_regular_6.fnt"); */
/* } */

12
res/text/intro.yarn Normal file
View File

@ -0,0 +1,12 @@
title: Intro
---
You: It's been 3 earth-days since I woke up from cryostasis, and I still don't know what's going on.
You: Why is nobody else awake?
You: What happened to the updates from mission control?
-> Maybe I'm still asleep?
You: Surely the scriptwriting isn't *that* cliché...
-> Is this even still the same ship?
You: Best not get too philsophical just yet
You: Let's have another look around...
<<room quarters>>
===

37
res/text/rooms.yarn Normal file
View File

@ -0,0 +1,37 @@
title: Room:quarters
---
<<declare $roll = 0>>
<<declare $hangarKeyFound = false>>
<<declare $sleepingMatSetUp = false>>
You: It's the crew quarters.
You: Well, it will be. Set-up hasn't started yet.
You: That was meant to be one of my first jobs after defrost...
You: ...but it doesn't exactly seem like a priority now.
You: Maybe there's something useful here?
-> Search the lockers (perception) <<if not $hangarKeyFound>>
<<set $roll to dice(6)>>
<<if $roll > 2>>
You: Aha! A small piece of paper with the **hangar access code**.
<<room hangar>>
<<set $hangarKeyFound to true>>
<<else>>
You: Just some dust bunnies. Guess they stowed away from Earth.
<<endif>>
-> Set up a sleeping mat (ingenuity) <<if not $sleepingMatSetUp>>
<<set $roll to dice(6)>>
<<if $roll > 2>>
You: Nice, at least I have somewhere to crash now.
<<set $sleepingMatSetUp to true>>
<<else>>
You: Hmm, I was never good at this camping stuff. Maybe I can find somewhere else to rest.
<<endif>>
-> Leave
===
title: Room:hangar
---
You: The **hangar** seems eerily deserted.
===
title: Room not open
---
You: Hmm, that part of the ship is still inaccessible. I wonder how to get in?
===

BIN
res/ui.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

View File

@ -1,6 +1,4 @@
class Const { class Const {
public static inline var W = 960; public static inline var W = 960;
public static inline var H = 640; public static inline var H = 640;
} }

View File

@ -1,17 +1,131 @@
import h2d.Layers;
import h2d.Console;
import h3d.Vector4;
import scene.TitleScene;
import scene.WorldMapScene;
import scene.GameScene;
import event.EventBus;
import event.ChangeSceneEvent;
import Const; import Const;
import listeners.DialogueBoxController;
import dialogue.DialogueManager;
import dialogue.command.OpenRoomCommand;
@:uiComp("game-container")
class GameContainer extends h2d.Flow implements h2d.domkit.Object {
static var SRC = <game-container>
${scene}
</game-container>;
public var scene:GameScene;
public function new(?parent) {
super(parent);
initComponent();
}
}
@:publicFields
class Game extends hxd.App { class Game extends hxd.App {
public var scene : h2d.Scene; public static var loader = new tiled.Tiled();
public var font : h2d.Font; public static var current:Game; // Current Game (singleton)
public var world : World;
public var font:h2d.Font;
public var options:Array<h2d.ScaleGrid> = [];
public var dialogueManager:DialogueManager;
public var root:GameContainer;
public var console:Console;
public var globalEventBus:EventBus;
var dialogueBoxController:DialogueBoxController;
var layer:Layers;
var style = null;
override function init() { override function init() {
scene = s2d; s2d.scaleMode = Stretch(Const.W, Const.H);
s2d.setFixedSize(Const.W, Const.H + 12); layer = new Layers(s2d);
world = new World(Res.map, Res.tiles);
s2d.add(world.root, 0); #if hl
hxd.res.Resource.LIVE_UPDATE = true;
hxd.Res.initLocal();
#else
hxd.Res.initEmbed();
#end
root = new GameContainer();
root.horizontalAlign = root.verticalAlign = Middle;
layer.addChildAt(root, 1);
onResize();
style = new h2d.domkit.Style();
style.load(hxd.Res.style);
style.allowInspect = true;
style.addObject(root);
font = Res.font.minecraftia_regular_6.toFont();
font.resizeTo(18);
#if debug
console = new Console(font);
layer.addChildAt(console, 4);
#end
globalEventBus = new EventBus(console);
globalEventBus.subscribe(ChangeSceneEvent, onChangeScene);
dialogueManager = new DialogueManager(globalEventBus);
var yarnText = [hxd.Res.text.intro.entry.getText(), hxd.Res.text.rooms.entry.getText(),];
var yarnFileNames = [hxd.Res.text.intro.entry.name, hxd.Res.text.rooms.entry.name,];
dialogueManager.load(yarnText, yarnFileNames);
dialogueManager.addCommandHandler(new OpenRoomCommand(globalEventBus));
var dialogueParent = new h2d.Flow();
dialogueParent.dom = domkit.Properties.create("flow", dialogueParent);
dialogueParent.dom.addClass('dialogue-container');
style.addObject(dialogueParent);
layer.addChildAt(dialogueParent, 2);
dialogueBoxController = new DialogueBoxController(globalEventBus, dialogueParent, style);
#if debug
setGameScene(new WorldMapScene(root));
#else
setGameScene(new TitleScene(root));
#end
} }
public static var inst : Game; public function new() {
super();
current = this;
}
override function onResize() {
root.minWidth = root.maxWidth = s2d.width;
root.minHeight = root.maxHeight = s2d.height;
}
override function update(dt:Float) {
style.sync();
}
public function onChangeScene(event:ChangeSceneEvent) {
setGameScene(event.newScene);
}
public function setGameScene(gs:GameScene) {
#if debug
console.resetCommands();
#end
if (root.scene != null) {
root.scene.getH2dObject().remove();
}
root.scene = gs;
style.addObject(gs.getH2dObject());
}
static function main() {
new Game();
}
} }

View File

@ -1,5 +1,5 @@
class Init { class Init {
public static function setup() { public static function setup() {
domkit.Macros.registerComponentsPath("components.$Component"); domkit.Macros.registerComponentsPath("components.$Component");
} }
} }

View File

@ -1,78 +0,0 @@
import components.MenubuttonComponent;
@:uiComp("view")
class ViewComp extends h2d.Flow implements h2d.domkit.Object {
static var SRC = <view class="mybox" min-width="200" content-halign={align}>
<text text={"Rewild"}/>
for( i in icons )
<bitmap src={i} id="icons[]"/>
</view>;
public function new(align:h2d.Flow.FlowAlign, icons:Array<h2d.Tile>, ?parent) {
super(parent);
initComponent();
}
}
@:uiComp("container")
class ContainerComp extends h2d.Flow implements h2d.domkit.Object {
static var SRC = <container>
<view(align,[]) id="view"/>
<menubutton("New game") public id="btnNewGame"/>
<menubutton("Continue game") public id="btnContinueGame"/>
<menubutton("Credits") public id="btnCredits"/>
<menubutton("Quit") public id="btnQuit"/>
</container>;
public function new(align:h2d.Flow.FlowAlign, ?parent) {
super(parent);
initComponent();
}
}
// PARAM=-lib domkit
class Main extends hxd.App {
var center:h2d.Flow;
var style = null;
override function init() {
center = new h2d.Flow(s2d);
center.horizontalAlign = center.verticalAlign = Middle;
onResize();
var root = new ContainerComp(Right, center);
root.btnNewGame.onClick = function() {
Game.inst = new Game();
}
root.btnContinueGame.onClick = function() {
root.btnContinueGame.dom.addClass("highlight");
}
root.btnQuit.onClick = function() {
Sys.exit(0);
}
style = new h2d.domkit.Style();
style.load(hxd.Res.style);
style.allowInspect = true;
style.addObject(root);
}
override function onResize() {
center.minWidth = center.maxWidth = s2d.width;
center.minHeight = center.maxHeight = s2d.height;
}
override function update(dt:Float) {
style.sync();
}
static function main() {
#if hl
hxd.res.Resource.LIVE_UPDATE = true;
hxd.Res.initLocal();
#else
hxd.Res.initEmbed();
#end
new Main();
}
}

229
src/TilemapLayer.hx Normal file
View File

@ -0,0 +1,229 @@
import h2d.col.Point;
import h2d.Object;
import h2d.SpriteBatch;
import tiled.types.TmxLayer;
import tiled.types.TmxMap;
using tiled.TiledTools;
class TilemapLayer extends h2d.TileGroup {
public var map:TmxMap;
public var layer:TmxLayer;
public function new(map:TmxMap, layer:TmxLayer, ?parent:Object) {
this.map = map;
this.layer = layer;
super(parent);
for (c in layer.tileChunks) {
addChunk(c);
}
// TODO: Animations
}
// public function gidAt(x:Int, y:Int):Int {
// if (x < 0 || x >= layer.width || y < 0 || y >= layer.height) return 0;
// return layer.data.tiles[y * layer.width + x].gid;
// }
public function addChunk(chunk:TileChunk) {
var tw = map.tileWidth;
var th = map.tileHeight;
var ix = 0, iy = 0;
var tiles = chunk.tiles, i = 0;
var tsets = map.tilesets;
switch (map.orientation) {
case Orthogonal:
var cx = chunk.x * tw + layer.offsetX;
var cy = chunk.y * th + layer.offsetY;
while (i < tiles.length) {
var gid = tiles[i++];
if (gid != 0) {
var t = tsets.getImage(gid);
var x = cx + ix * tw;
var y = cy + iy * th + th - t.height;
if (gid.flippedHorizontally)
addTransform(x + t.width, y, -1, 1, 0, t);
else if (gid.flippedVertically)
addTransform(x, y + t.height, 1, -1, 0, t);
else if (gid.flippedDiagonally)
addTransform(x + t.width, y + t.height, -1, -1, 0, t);
else
add(x, y, t);
}
if (++ix == chunk.width) {
iy++;
ix = 0;
}
}
case Isometric:
var isoW = tw >> 1;
var isoH = th >> 1;
var cx = (chunk.x - chunk.y) * isoW + layer.offsetX;
var cy = (chunk.x + chunk.y) * isoH + layer.offsetY;
while (i < tiles.length) {
var gid = tiles[i++];
if (gid != 0) {
var t = tsets.getImage(gid);
var x = cx + (ix - iy) * isoW;
var y = cy + (ix + iy) * isoH + th - t.height;
if (gid.flippedHorizontally)
addTransform(x + t.width, y, -1, 1, 0, t);
else if (gid.flippedVertically)
addTransform(x, y + t.height, 1, -1, 0, t);
else if (gid.flippedDiagonally)
addTransform(x + t.width, y + t.height, -1, -1, 0, t);
else
add(x, y, t);
}
if (++ix == chunk.width) {
iy++;
ix = 0;
}
}
case Staggered(staggerYAxis, staggerIndexOdd):
var staggerX = 0,
staggerY = 0,
stepX = tw >> 1,
stepY = th >> 1;
var cx = chunk.x * stepX + layer.offsetX;
var cy = chunk.y * stepY + layer.offsetY;
if (staggerYAxis) {
if (staggerIndexOdd) {
staggerX = tw >> 1;
} else {
staggerX = -(tw >> 1);
cx -= staggerX;
}
} else {
if (staggerIndexOdd) {
staggerY = th >> 1;
} else {
staggerY = -(tw >> 1);
cy -= staggerY;
}
}
cx += (chunk.x % 2) * staggerX;
cy += (chunk.y % 2) * staggerY;
while (i < tiles.length) {
var gid = tiles[i++];
if (gid != 0) {
var t = tsets.getImage(gid);
var x = cx + ix * stepX + staggerX * (ix % 1);
var y = cy + iy * stepY + th - t.height;
if (gid.flippedHorizontally)
addTransform(x + t.width, y, -1, 1, 0, t);
else if (gid.flippedVertically)
addTransform(x, y + t.height, 1, -1, 0, t);
else if (gid.flippedDiagonally)
addTransform(x + t.width, y + t.height, -1, -1, 0, t);
else
add(x, y, t);
}
if (++ix == chunk.width) {
iy++;
ix = 0;
}
}
case Hexagonal(sideLength, staggerYAxis, staggerIndexOdd):
// TODO: Fix
var staggerX = 0, staggerY = 0, stepX, stepY;
var cx, cy;
if (staggerYAxis) {
stepX = tw;
stepY = (th + sideLength) >> 1;
cx = chunk.x * stepX + layer.offsetX;
cy = chunk.y * stepY + layer.offsetY;
if (staggerIndexOdd) {
staggerX = tw >> 1;
} else {
staggerX = -(tw >> 1);
cx -= staggerX;
}
} else {
stepX = (tw + sideLength) >> 1;
stepY = th;
cx = chunk.x * stepX + layer.offsetX;
cy = chunk.y * stepY + layer.offsetY;
if (staggerIndexOdd) {
staggerY = th >> 1;
} else {
staggerY = -(tw >> 1);
cy -= staggerY;
}
}
while (i < tiles.length) {
var gid = tiles[i++];
if (gid != 0) {
var t = tsets.getImage(gid);
var x = cx + ix * stepX;
var y = cy + iy * stepY + th - t.height;
if (gid.flippedHorizontally)
addTransform(x + t.width, y, -1, 1, 0, t);
else if (gid.flippedVertically)
addTransform(x, y + t.height, 1, -1, 0, t);
else if (gid.flippedDiagonally)
addTransform(x + t.width, y + t.height, -1, -1, 0, t);
else
add(x, y, t);
}
if (++ix == chunk.width) {
iy++;
ix = 0;
}
}
}
}
public function addTile(tx:Int, ty:Int, ox:Float, oy:Float, gid:TmxTileIndex) {
if (gid == 0)
return;
var t = map.tilesets.getImage(gid);
if (t != null) {
var x, y;
switch (map.orientation) {
case Orthogonal:
x = tx * map.tileWidth + ox;
y = ty * map.tileHeight + oy;
case Isometric:
x = (tx - ty) * (map.tileWidth >> 1) + ox;
y = (tx + ty) * (map.tileHeight >> 1) + oy;
case Staggered(staggerYAxis, staggerIndexOdd):
if (staggerYAxis) {
y = ty * (map.tileHeight >> 1);
if (staggerIndexOdd)
x = tx * map.tileWidth + (tx % 2) * (map.tileWidth >> 1);
else
x = tx * map.tileWidth + ((tx + 1) % 2) * (map.tileWidth >> 1);
} else {
x = tx * (map.tileWidth >> 1);
if (staggerIndexOdd)
y = ty * map.tileHeight + (tx % 2) * (map.tileHeight >> 1);
else
y = ty * map.tileHeight + ((tx + 1) % 2) * (map.tileHeight >> 1);
}
case Hexagonal(sideLength, staggerYAxis, staggerIndexOdd):
if (staggerYAxis) {
y = ty * ((map.tileHeight + sideLength) >> 1);
if (staggerIndexOdd)
x = tx * map.tileWidth + (tx % 2) * (map.tileWidth >> 1);
else
x = tx * map.tileWidth + ((tx + 1) % 2) * (map.tileWidth >> 1);
} else {
x = tx * ((map.tileWidth + sideLength) >> 1);
if (staggerIndexOdd)
y = ty * map.tileHeight + (tx % 2) * (map.tileHeight >> 1);
else
y = ty * map.tileHeight + ((tx + 1) % 2) * (map.tileHeight >> 1);
}
}
if (gid.flippedHorizontally)
addTransform(x + t.width, y, -1, 1, 0, t);
else if (gid.flippedVertically)
addTransform(x, y + t.height, 1, -1, 0, t);
else if (gid.flippedDiagonally)
addTransform(x + t.width, y + t.height, -1, -1, 0, t);
else
add(x, y, t);
}
}
}

View File

@ -1,54 +0,0 @@
class World {
var game : Game;
var map : hxd.res.TiledMap.TiledMapData;
public var root : h2d.Object;
var layers : Map < String, { name : String, data : Array<Int>, g : h2d.TileGroup, alpha : Float } > ;
var tiles : Array<h2d.Tile>;
public var width : Int;
public var height : Int;
public function new( r : hxd.res.TiledMap, tiles : hxd.res.Image ) {
game = Game.inst;
root = new h2d.Object();
map = r.toMap();
root = new h2d.Object();
width = map.width;
height = map.height;
var t = tiles.toTile();
layers = new Map();
var font : h2d.Font = hxd.res.DefaultFont.get();
this.tiles = [for( y in 0...Std.int(t.height) >> 5 ) for( x in 0...Std.int(t.width) >> 5 ) t.sub(x * 32, y * 32, 32, 32)];
for( ld in map.layers ) {
if( ld.name == "hotspots") continue;
var l = {
name : ld.name,
data : ld.data,
g : new h2d.TileGroup(t, root),
alpha : ld.opacity,
}
// l.g.colorKey = 0x1D8700;
l.g.alpha = ld.opacity;
layers.set(ld.name, l);
rebuildLayer(ld.name);
}
}
function rebuildLayer( name : String ) {
var l = layers.get(name);
if( l == null ) return;
var pos = 0;
var g = l.g;
g.clear();
while( g.numChildren > 0 )
g.getChildAt(0).remove();
for( y in 0...height )
for( x in 0...width ) {
var t = l.data[pos++] - 1;
if( t < 0 ) continue;
g.add(x * 32, y * 32, tiles[t]);
}
}
}

View File

@ -0,0 +1,135 @@
package components;
import dialogue.event.NextLine;
@:uiComp("dialogue-option")
class DialogueOptionComponent extends h2d.Flow implements h2d.domkit.Object {
static var SRC = <dialogue-option>
<text text={label} public font={Game.current.font} id="labelTxt" />
</dialogue-option>;
public var label(get, set):String;
function get_label()
return labelTxt.text;
function set_label(s) {
labelTxt.text = s;
return s;
}
public function new(label:String, ?parent) {
super(parent);
initComponent();
enableInteractive = true;
interactive.onClick = function(_) onClick();
interactive.onOver = function(_) {
dom.hover = true;
};
interactive.onPush = function(_) {
dom.active = true;
};
interactive.onRelease = function(_) {
dom.active = false;
};
interactive.onOut = function(_) {
dom.hover = false;
};
}
public dynamic function onClick() {}
}
@:uiComp("dialogue-options")
class DialogueOptionsComponent extends h2d.Flow implements h2d.domkit.Object {
static var SRC = <dialogue-options>
${options}
</dialogue-options>;
public var options:Array<DialogueOptionComponent>;
}
@:uiComp("dialogue-box")
class DialogueBoxComponent extends h2d.Flow implements h2d.domkit.Object {
var timer:haxe.Timer;
var chan:hxd.snd.Channel;
var textPos:Int = 0;
var game:Game;
static var SRC = <dialogue-box>
<scale-grid id="dialogueBackground">
<text text={displayedText} public font={Game.current.font} id="dialogueText" />
</scale-grid>
</dialogue-box>
public var displayedText(get, set):String;
function get_displayedText()
return dialogueText.text;
function set_displayedText(s) {
dialogueText.text = s;
return s;
}
public var internalText(default, set):String;
function set_internalText(t) {
internalText = t;
timer = new haxe.Timer(30);
timer.run = updateText;
displayedText = "";
textPos = 0;
return t;
}
public function new(text:String, ?parent) {
this.game = Game.current;
super(parent);
initComponent();
internalText = text;
this.dialogueBackground.tile = Res.ui.toTile();
this.dialogueBackground.borderWidth = 5;
this.dialogueBackground.borderHeight = 5;
this.dialogueBackground.colorKey = 0xFF00FF;
this.dialogueBackground.width = this.innerWidth;
this.dialogueBackground.height = this.innerHeight;
// trace(this.dialogueBackground.width);
enableInteractive = true;
interactive.onClick = function(_) onClick();
}
function updateText() {
if (textPos == internalText.length) {
timer.stop();
// onReady();
// if (chan != null)
// chan.stop();
return;
}
// if (chan != null) {
// switch (text.charCodeAt(textPos)) {
// case " ".code, "\n".code:
// chan.volume = 0;
// default:
// if (chan.volume == 0)
// chan.volume = 1
// else
// chan.volume *= 0.9;
// }
// }
textPos++;
displayedText = internalText.substr(0, textPos);
}
public dynamic function onClick() {
if (textPos == internalText.length)
Game.current.globalEventBus.publishEvent(new NextLine());
else if (textPos < internalText.length) {
textPos = internalText.length;
displayedText = internalText;
updateText();
};
}
}

View File

@ -37,4 +37,3 @@ class MenubuttonComponent extends h2d.Flow implements h2d.domkit.Object {
public dynamic function onClick() {} public dynamic function onClick() {}
} }

View File

@ -0,0 +1,164 @@
package dialogue;
import hxyarn.dialogue.Dialogue;
import hxyarn.dialogue.VariableStorage.MemoryVariableStore;
import hxyarn.dialogue.StringInfo;
import hxyarn.dialogue.Line;
import hxyarn.dialogue.Command;
import hxyarn.dialogue.Option;
import hxyarn.dialogue.OptionSet;
import hxyarn.dialogue.markup.MarkupParseResult;
import hxyarn.compiler.Compiler;
import hxyarn.compiler.CompilationJob;
import event.EventBus;
import dialogue.command.ICommandHandler;
import dialogue.event.LineShown;
import dialogue.event.OptionsShown;
import dialogue.event.OptionsShown.OptionChoice;
import dialogue.event.OptionSelected;
import dialogue.event.NextLine;
import dialogue.event.StartDialogueNode;
import dialogue.event.DialogueComplete;
class DialogueManager {
public var eventBus:EventBus;
var storage = new MemoryVariableStore();
var dialogue:Dialogue;
var stringTable:Map<String, StringInfo>;
var commandHandlers = new Map<String, ICommandHandler>();
public var waitingForOption:Bool = false;
public function new(eventBus:EventBus) {
this.eventBus = eventBus;
dialogue = new Dialogue(new MemoryVariableStore());
dialogue.logDebugMessage = this.logDebugMessage;
dialogue.logErrorMessage = this.logErrorMessage;
dialogue.lineHandler = this.lineHandler;
dialogue.optionsHandler = this.optionsHandler;
dialogue.commandHandler = this.commandHandler;
dialogue.nodeCompleteHandler = this.nodeCompleteHandler;
dialogue.nodeStartHandler = this.nodeStartHandler;
dialogue.dialogueCompleteHandler = this.dialogueCompleteHandler;
eventBus.subscribe(NextLine, this.nextLine);
eventBus.subscribe(OptionSelected, this.optionSelected);
eventBus.subscribe(StartDialogueNode, function(event) {
this.runNode(event.node);
});
}
public function load(text:Array<String>, fileNames:Array<String>) {
var job = CompilationJob.createFromStrings(text, fileNames, dialogue.library);
var compiler = Compiler.compile(job);
stringTable = compiler.stringTable;
dialogue.addProgram(compiler.program);
}
public function runNode(nodeName:String) {
dialogue.setNode(nodeName);
dialogue.resume();
}
public function unload() {
dialogue.unloadAll();
}
public function resume() {
dialogue.resume();
}
public function logDebugMessage(message:String):Void {}
public function logErrorMessage(message:String):Void {}
public function nextLine(event:NextLine) {
if ((dialogue.isActive()) && (!waitingForOption))
dialogue.resume();
}
public function lineHandler(line:Line):Void {
var text = getComposedTextForLine(line);
eventBus.publishEvent(new LineShown(text));
}
public function optionSelected(event:OptionSelected) {
dialogue.setSelectedOption(event.index);
dialogue.resume();
waitingForOption = false;
}
public function optionsHandler(options:OptionSet) {
var optionCount = options.options.length;
var optionChoices = new Array<OptionChoice>();
for (i => option in options.options) {
var markup = getComposedTextForLine(option.line);
optionChoices.push({
text: markup.text,
index: i,
enabled: option.enabled,
markup: markup
});
}
eventBus.publishEvent(new OptionsShown(optionChoices));
waitingForOption = true;
}
public function getComposedTextForLine(line:Line):MarkupParseResult {
var substitutedText = Dialogue.expandSubstitutions(stringTable[line.id].text, line.substitutions);
return dialogue.parseMarkup(substitutedText);
}
public function commandHandler(command:Command) {
var parts = command.text.split(' ');
var key = parts.shift();
if (commandHandlers.exists(key)) {
if (commandHandlers.get(key).handleCommand(parts)) {
resume();
return;
}
}
resume();
}
public function addCommandHandler(handler:ICommandHandler) {
if (handler.commandName == null || handler.commandName == "") {
trace("Command handler has no command name");
return;
}
commandHandlers.set(handler.commandName, handler);
}
public function nodeCompleteHandler(nodeName:String) {}
public function nodeStartHandler(nodeName:String) {}
public function dialogueCompleteHandler() {
eventBus.publishEvent(new DialogueComplete(""));
}
public function getNodeNames(?includesTag = "") {
var nodeNames = [];
for (nodeName in dialogue.allNodes) {
if (includesTag == "") {
nodeNames.push(nodeName);
continue;
}
var tags = dialogue.getTagsForNode(nodeName);
if (tags.contains(includesTag)) {
nodeNames.push(nodeName);
}
}
return nodeNames;
}
}

View File

@ -0,0 +1,6 @@
package dialogue.command;
interface ICommandHandler {
var commandName:String;
function handleCommand(args:Array<String>):Bool;
}

View File

@ -0,0 +1,19 @@
package dialogue.command;
import event.EventBus;
import event.OpenRoomEvent;
class OpenRoomCommand implements ICommandHandler {
public var commandName:String = "room";
var eventBus:EventBus;
public function new(eventBus:EventBus) {
this.eventBus = eventBus;
}
public function handleCommand(args:Array<String>):Bool {
eventBus.publishEvent(new OpenRoomEvent(args[0]));
return true;
}
}

View File

@ -0,0 +1,11 @@
package dialogue.event;
import event.IEvent;
class DialogueComplete implements IEvent {
public var nodeName:String;
public function new(nodeName:String) {
this.nodeName = nodeName;
}
}

View File

@ -0,0 +1,36 @@
package dialogue.event;
import hxyarn.dialogue.markup.MarkupAttribute;
import hxyarn.dialogue.markup.MarkupParseResult;
import event.IEvent;
class LineShown implements IEvent {
public var markUpResults:MarkupParseResult;
public function new(markupParseResults:MarkupParseResult) {
this.markUpResults = markupParseResults;
}
public function line():String {
var text = markUpResults.text;
var characterAttribute = characterNameAttribute();
if (characterAttribute != null)
text = text.substr(characterAttribute.position + characterAttribute.length);
return text;
}
public function characterName():String {
var attribute = characterNameAttribute();
if (attribute != null)
return attribute.properties[0].value.stringValue;
return "";
}
function characterNameAttribute():MarkupAttribute {
return markUpResults.tryGetAttributeWithName("character");
}
}

View File

@ -0,0 +1,7 @@
package dialogue.event;
import event.IEvent;
class NextLine implements IEvent {
public function new() {}
}

View File

@ -0,0 +1,11 @@
package dialogue.event;
import event.IEvent;
class OptionSelected implements IEvent {
public var index:Int;
public function new(index:Int) {
this.index = index;
}
}

View File

@ -0,0 +1,19 @@
package dialogue.event;
import hxyarn.dialogue.markup.MarkupParseResult;
import event.IEvent;
typedef OptionChoice = {
text:String,
index:Int,
enabled:Bool,
markup:MarkupParseResult
}
class OptionsShown implements IEvent {
public var options:Array<OptionChoice>;
public function new(options:Array<OptionChoice>) {
this.options = options;
}
}

View File

@ -0,0 +1,11 @@
package dialogue.event;
import event.IEvent;
class StartDialogueNode implements IEvent {
public var node:String;
public function new(node:String) {
this.node = node;
}
}

View File

@ -0,0 +1,11 @@
package event;
import scene.GameScene;
class ChangeSceneEvent implements IEvent {
public var newScene:GameScene;
public function new(gs:GameScene) {
this.newScene = gs;
}
}

48
src/event/EventBus.hx Normal file
View File

@ -0,0 +1,48 @@
package event;
import h2d.Console;
class EventBus {
var listeners = new Map<String, Array<Dynamic>>();
var console:Console;
public function new(console:Console) {
this.console = console;
}
public function subscribe<T:IEvent>(event:Class<T>, callback:(T) -> Void) {
var type = Type.getClassName(event);
if (!listeners.exists(type))
listeners.set(type, new Array<T>());
listeners.get(type).push(callback);
}
public function unsubscribe<T:IEvent>(event:Class<T>, callback:(T) -> Void) {
var type = Type.getClassName(event);
if (!listeners.exists(type))
return;
var callbacks = listeners.get(type);
for (c in callbacks) {
if (Reflect.compareMethods(c, callback)) {
callbacks.remove(c);
return;
}
}
}
public function publishEvent<T:IEvent>(event:T) {
var type = Type.getClassName(Type.getClass(event));
if (!listeners.exists(type)) {
#if debug
console.log('Publishing event with no listeners: $type');
#end
return;
}
trace('Publishing event $type');
for (func in listeners.get(type))
func(event);
}
}

3
src/event/IEvent.hx Normal file
View File

@ -0,0 +1,3 @@
package event;
interface IEvent {}

View File

@ -0,0 +1,9 @@
package event;
class OpenRoomEvent implements IEvent {
public var roomName:String;
public function new(rn:String) {
this.roomName = rn;
}
}

View File

@ -0,0 +1,125 @@
package listeners;
import Game;
import event.EventBus;
import dialogue.DialogueManager;
import dialogue.event.LineShown;
import dialogue.event.OptionsShown;
import dialogue.event.OptionSelected;
import dialogue.event.DialogueComplete;
import dialogue.event.NextLine;
import components.DialogueBoxComponent;
class DialogueBoxController {
public var curDialogue:DialogueBoxComponent;
var game:Game;
var bg:h2d.ScaleGrid;
var tf:h2d.Text;
var int:h2d.Interactive;
var eventBus:EventBus;
var parent:h2d.Object;
var style:h2d.domkit.Style;
public function new(eventBus:EventBus, parent:h2d.Object, style:h2d.domkit.Style) {
this.parent = parent;
this.style = style;
// game = Game.current;
// parent.getScene().add(this, 1);
// bg = new h2d.ScaleGrid(Res.ui.toTile(), 5, 5, this);
// bg.colorKey = 0xFF00FF;
// tf = new h2d.Text(game.font, this);
// tf.y = 5;
// tf.x = 7;
// tf.dropShadow = {
// dx: 0,
// dy: 1,
// color: 0,
// alpha: 0.3
// };
// int = new h2d.Interactive(0, 0, this);
// int.onClick = function(_) click();
eventBus.subscribe(LineShown, dialogue);
// eventBus.subscribe(OptionsShown, renderOptions);
// eventBus.subscribe(OptionSelected, onOptionSelected);
eventBus.subscribe(DialogueComplete, onDialogueComplete);
}
// override function onRemove() {
// super.onRemove();
// // if (chan != null)
// // chan.stop();
// // timer.stop();
// }
public dynamic function onClick() {}
public dynamic function onReady() {}
function dialogue(event:LineShown) {
if (curDialogue != null) {
curDialogue.remove();
}
var d = new DialogueBoxComponent(event.line(), this.parent);
style.addObject(d);
curDialogue = d;
}
// function renderOptions(event:OptionsShown) {
// for (option in event.options) {
// addOption(option.text, option.enabled, function() {
// if (option.enabled) {
// globalEventBus.publishEvent(new OptionSelected(option.index));
// }
// });
// }
// }
//
// function newPanel(w, h) {
// var g = new h2d.ScaleGrid(Res.ui.toTile(), 5, 5);
// g.width = w;
// g.height = h;
// g.colorKey = 0xFF00FF;
// root.scene.getH2dObject().getScene().add(g, 1);
// return g;
// }
//
// function addOption(o:String, enabled:Bool, callback:() -> Void) {
// var spr = newPanel(Const.W, 60);
// curDialogue.addChild(spr);
// var tf = new h2d.Text(font, spr);
// if (!enabled) {
// tf.color = new Vector4(0.5, 0.5, 0.5, 1);
// }
// tf.text = o;
// tf.x = 10;
// tf.y = 10;
// spr.x = 0;
// spr.y = 100 + options.length * 60;
// var int = new h2d.Interactive(spr.width, spr.height, spr);
// int.onClick = function(_) {
// callback();
// }
// int.cursor = Button;
// options.push(spr);
// return spr;
// }
//
// function onOptionSelected(event:OptionSelected) {
// for (o in options) {
// o.remove();
// }
// options.splice(0, options.length);
// }
function onDialogueComplete(event:DialogueComplete) {
curDialogue.remove();
}
}

5
src/scene/GameScene.hx Normal file
View File

@ -0,0 +1,5 @@
package scene;
interface GameScene {
function getH2dObject():h2d.Object;
}

52
src/scene/TitleScene.hx Normal file
View File

@ -0,0 +1,52 @@
package scene;
import scene.WorldMapScene;
import event.ChangeSceneEvent;
import components.MenubuttonComponent;
@:uiComp("heading")
class HeadingComp extends h2d.Flow implements h2d.domkit.Object {
static var SRC = <heading class="mybox" min-width="200">
<text text={"Glass House"}/>
for( i in icons )
<bitmap src={i} id="icons[]"/>
</heading>;
public function new(icons:Array<h2d.Tile>, ?parent) {
super(parent);
initComponent();
}
}
@:uiComp("title-scene")
class TitleScene extends h2d.Flow implements GameScene implements h2d.domkit.Object {
static var SRC = <title-scene>
<heading([]) id="view"/>
<menubutton("New game") public id="btnNewGame"/>
<menubutton("Continue game") public id="btnContinueGame"/>
<menubutton("Credits") public id="btnCredits"/>
<menubutton("Quit") public id="btnQuit"/>
</title-scene>;
public function new(?parent) {
super(parent);
initComponent();
btnNewGame.onClick = function() {
Game.current.globalEventBus.publishEvent(new ChangeSceneEvent(new WorldMapScene(Game.current.root)));
}
btnContinueGame.onClick = function() {
btnContinueGame.dom.addClass("highlight");
}
#if hl
btnQuit.onClick = function() {
Sys.exit(0);
}
#else
btnQuit.remove();
#end
}
public function getH2dObject() {
return this;
}
}

View File

@ -0,0 +1,76 @@
package scene;
import dialogue.event.StartDialogueNode;
import event.OpenRoomEvent;
import TilemapLayer;
typedef Room = {
rect:h2d.Graphics,
area:h2d.Interactive,
isOpen:Bool
}
@:uiComp("world-map-scene")
class WorldMapScene extends h2d.Flow implements GameScene implements h2d.domkit.Object {
public var width:Int;
public var height:Int;
var rooms:Map<String, Room> = new Map<String, Room>();
public function new(?parent) {
super(parent);
initComponent();
var root = new h2d.Object(this);
var map = Game.loader.loadTMX("map.tmx");
Game.current.globalEventBus.subscribe(OpenRoomEvent, openRoom);
for (layer in (map.layers)) {
switch (layer.kind) {
case TTileLayer:
var l = new TilemapLayer(map, layer, root);
case TObjectGroup:
for (obj in layer.objects) {
var rect = new h2d.Graphics(root);
rect.beginFill(0x333333);
rect.alpha = 0.8;
rect.drawRect(obj.x, obj.y, obj.width, obj.height);
rect.endFill();
var area = new h2d.Interactive(obj.width, obj.height, root);
area.x = obj.x;
area.y = obj.y;
area.onClick = function(_) {
var room = rooms.get(obj.name);
if (room.isOpen) {
Game.current.globalEventBus.publishEvent(new StartDialogueNode("Room:" + obj.name));
} else {
Game.current.globalEventBus.publishEvent(new StartDialogueNode("Room not open"));
}
};
rooms.set(obj.name, {rect: rect, area: area, isOpen: false});
}
case TImageLayer:
case TGroup:
}
}
#if debug
trace('skipping intro dialogue');
Game.current.globalEventBus.publishEvent(new OpenRoomEvent("quarters"));
#else
Game.current.globalEventBus.publishEvent(new StartDialogueNode("Intro"));
#end
}
public function openRoom(event:OpenRoomEvent) {
var room = rooms.get(event.roomName);
room.isOpen = true;
room.rect.alpha = 0;
}
public function getH2dObject() {
return this;
}
}