"it's just Words On A Screen."
a domain-specific language used to make text-based games that outputs entirely in HTML5.
- uhh what did you even make?
- ts kinda useless, why did you build it?
- demo game
- installation
- quick start
- controls
- syntax guide
- ai declaration
- contributing
i built:
- woas language syntax: a semi-easy-to-use language to write text-based games in
- woas compiler: a python script that turns
.woasfiles into completely standalone HTML5 files - woas runtime engine: the javascript game loop inside every woas html file, that turns woas commands into DOM generation, audio playback, and complex storyline managemment
i made it cause i needed hours for horizons polaris wanted an easy to use engine to make story games/slideshows that are a bit more barebones than what renpy has to offer. i wanted to create a story-based game but the idea of having to use renpy and deal with all of the stuff to make it look nice (UI, character sprites, animations) and not like the default template overwhelmed me. woas is much more barebones and lets your story stand on its own two legs rather than bombarding you with tons of features you might not need that end up looking generic in the end.
i made a small demo game to show off the capabilities of the engine! play the demo here: https://purestellenium.github.io/my-barista-girl/ and view the source code here: https://github.com/purestellenium/woas/blob/main/demo.woas
if you have python installed, you can just download the compile.py script and run it to compile your .woas files.
however, you can also use one of our prebuilt executables... because it's a unified db requirement.
download the .exe file from the latest release and run it.
download the .zip file labeled "macos" from the latest release.
there is a chance that macos will "quarantine" this executable, and not allow you to run it. in this case, follow these instructions to un-quarantine it:
- open terminal
- paste in
sudo xattr -rd com.apple.quarantine<- the trailing space is important - drag and drop the unix executable file into the terminal (should cause a long file path to show up)
- run the command
- voila, now your executable is no longer quarantined!
then, just run the executable.
download the .zip file labeled "linux" from the latest release and run it.
- create a plaintext file with the
.woasfile extension - write your game in woas using the syntax guide below
- run/open the compiler
- pass the path to your .woas file
players advance text by pressing space, clicking, or tapping anywhere on the game screen. choices are picked by clicking/tapping the option itself.
woas is read line-by-line, meaning each line is one command.
woas completely ignores all newlines, so they are optional but usable if you want to make your .woas code more readable.
here are the commands you can use:
sets the name of the tab in the web browser.
note: you can only set one game title - the title command written last will be the one used.
title "My Awesome Game"
by default, only one piece of text is shown on the screen at a time (not counting choice screens) - each new text command replaces the last. you can make a piece of text persist instead, which stacks it on screen alongside whatever comes after it, rather than clearing it away.
text must be wrapped in double quotes (escaped quotes like \" inside these quotes are supported). you can optionally add css classes to style this text, and specify a custom color, font, and whether it persists, after the / separator.
- format: "Text" classes / color font persist
- use
nullin the color slot to use the default color while still defining a font. persististrueorfalse(defaults tofalse, clearing the screen like normal). to set it without changing the font, usenullin the font slot -persistis only read when a font (ornull) comes before it.- text supports inline html tags (like
<i>or<b>) - they'll actually render, not just show up as plain text. if you want to display a literal<or>instead, escape it as<or>.
"You wake up in a dark room." s center vcenter
"A loud noise startles you!" xl center / red
"A ghostly whisper..." m right / null "Times New Roman"
"This stays on screen..." m left / null null true
"...while this appears alongside it." m right / null null true
"\"This dialogue has <i>italic</i> and <strong>bold</strong> formatting!\"" / pink
available classes:
- size:
smlxlxxl - vertical position:
vcenterbottom(default is top-aligned) - horizontal position:
leftcenterright - text alignment (for text that wraps to multiple lines):
centeralignrightalign(default is left-aligned)
ask a question and display choices for the user. when the player clicks a choice linked to a jump marked by an id, the engine will skip to the next "jump [id]" command. the engine avoids hitting the other branches by skipping over jumps (by going to their end command) that aren't triggered specifically by a user-made choice.
after the last option, a choice can also take / color font persist - same rules as displaying text: null for defaults, and persist needs an explicit font (or null) before it to be read.
warning: unlike persisted text, a persisted choice's buttons stay in the DOM and stay clickable even after the player has moved past them - their click handlers don't get removed, so clicking an old option can still trigger its jump. use persist on choices carefully.
format:
- a jump command declaring the jump and its id (which cannot have spaces)
- any commands that should (and will) only be executed if a choice is picked that points to this jump
- an end command declaring the end of the jump, with its id (to clarify which jump is being ended)
engine logic is as follows:
- get to jump -> skip to end command
- if user triggers a choice, skip to the corresponding jump command and execute the commands inside of it
note: choices in a choice command can only jump to jumps declared after the choice command itself.
choice "Which path do you take?" / "Go left" path_left "Go right" path_right / royalblue
jump path_left
"You went left and found a treasure!" m center vcenter / gold
choice "What do you do with your treasure?" / "Sell it" sell "Go back and go right" path_right / gold
jump sell
"You sold it for a lot of money, and now you're rich." m center vcenter
end sell
end path_left
jump path_right
"You went right and fell in a pit." m center vcenter / brown
end path_right
jump straight to a jump command elsewhere in the file, without needing a choice to trigger it - useful for allowing users to access jumps outside of choices, merging branching paths, or simply just jumping to another place in the script.
format: skip id
note: like choices, a skip can only target a jump declared after itself.
choice "What do you do first?" / "Rest by the fire" rest "Explore the cave" explore / royalblue
jump rest
"You rest by the fire, but you're too curious to sleep." m center vcenter
skip explore
end rest
jump explore
"You explore the cave and find a hidden passage." m center vcenter
end explore
"Eventually, you press onward." m center vcenter
commands below run without stopping the queue, meaning they don't need an input to go to the next command.
change the background to a color or image. works similarly to the css shorthand property "background".
bg black
bg #a58dca
bg rgb(255, 255, 255)
bg my_image.png
set the default font and colors, so you don't have to define them for every single text command. note: these aren't one time for the entire project; you can change these as you go. a usecase for this may be: you enter a new environment that will have a new default font color and font.
color white
font "Courier New"
import a custom font file so you can use it anywhere a font is accepted (the font command, or a text line's font slot). give the font a name to import it under - this name is just a label, it doesn't need to match the file name.
note: like background images and music, font files must be in the same folder as your compiled .html file, or linked by url.
import "Handwriting" my_font.woff2
font "Handwriting"
"This is written in my custom font." m vcenter / null "Handwriting"
"So is this, since my font is now the default." m vcenter
"But this text overrides it for just one line." m vcenter / null monospace
you can also paste a google fonts stylesheet link directly - the compiler notices it isn't a font file and links it in the page's head instead, letting the browser handle the loading. since the stylesheet already defines its own font names, you don't (and can't) give it one here - just make sure the name you use afterwards matches the family name from the link exactly.
import https://fonts.googleapis.com/css2?family=Roboto&display=swap
font "Roboto"
play/resume, pause, or stop a single looping audio track. this feature is designed for background music, so only one track can play at a time, and it will loop infinitely.
note: audio files must be in the same folder as your compiled .html file, or linked by url.
note: due to how web browsers process sound, you cannot have a music command before the first input from the user (click or keypress). you can get around this limitation by adding a "click to start game" text.
"press space to start" l center vcenter centeralign / white monospace
music play scary_ambience.mp3
music pause
music stop
you can add comment lines to your woas code, and the compiler will ignore it. use this feature to make notes to yourself, section things off, etc!
note:
"Woas. This is valid a woas text command." m center
# This is a comment that the compiler will ignore!
"Woas. This is also valid." xl right bottom rightalign / royalblue
throughout the process of making this project, i used LLM models such as gemini and claude for very small bug fixes and the implementation of a few non-core features (for example the script that automatically compiles your .woas files upon saving them).
most of the code for both the engine and the compiler were written by me, completely by hand.
pull requests open! if you have questions about contributing, you can message me on the Hack Club Slack @stellenium, and you can reach me at the email listed on my GitHub README.