Initial Guidebook code
This commit is contained in:
parent
b4922edf5d
commit
7142c76b86
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -3,6 +3,8 @@ fonts/
|
|||
maps/
|
||||
bin/
|
||||
dist/
|
||||
dev-assets/guidebook/venv
|
||||
dev-assets/guidebook/compiled/pages
|
||||
wasm/assets/
|
||||
*.wasm
|
||||
*.doodad
|
||||
|
|
BIN
dev-assets/doodads/doors/electric.gif
Normal file
BIN
dev-assets/doodads/doors/electric.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
dev-assets/doodads/trapdoors/down.gif
Normal file
BIN
dev-assets/doodads/trapdoors/down.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
73
dev-assets/guidebook/build.py
Normal file
73
dev-assets/guidebook/build.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import codecs
|
||||
import glob
|
||||
import os
|
||||
import markdown
|
||||
import jinja2
|
||||
import re
|
||||
|
||||
def main():
|
||||
if not os.path.isdir("./compiled"):
|
||||
print("Make output directory: ./compiled")
|
||||
os.mkdir("./compiled")
|
||||
os.mkdir("./compiled/pages")
|
||||
|
||||
# Render the main index.html template.
|
||||
with codecs.open("./pages/index.html", "r", "utf-8") as fh:
|
||||
html = fh.read()
|
||||
html = render_template(html)
|
||||
with open("./compiled/index.html", "w") as outfh:
|
||||
outfh.write(html)
|
||||
|
||||
# Load the Markdown wrapper HTML template.
|
||||
html_wrapper = "$CONTENT"
|
||||
with codecs.open("./pages/markdown.html", "r", "utf-8") as fh:
|
||||
html_wrapper = fh.read()
|
||||
|
||||
for md in glob.glob("./pages/*.md"):
|
||||
filename = md.split(os.path.sep)[-1]
|
||||
htmlname = filename.replace(".md", ".html")
|
||||
print("Compile Markdown: {} -> {}".format(filename, htmlname))
|
||||
|
||||
with codecs.open(md, 'r', 'utf-8') as fh:
|
||||
data = fh.read()
|
||||
rendered = markdown.markdown(data,
|
||||
extensions=["codehilite", "fenced_code"],
|
||||
)
|
||||
html = html_wrapper.replace("$CONTENT", rendered)
|
||||
html = render_template(html,
|
||||
title=title_from_markdown(data),
|
||||
)
|
||||
|
||||
with open(os.path.join("compiled", "pages", htmlname), "w") as outfh:
|
||||
outfh.write(html)
|
||||
|
||||
jinja_env = jinja2.Environment()
|
||||
|
||||
def render_template(input, *args, **kwargs):
|
||||
templ = jinja_env.from_string(input)
|
||||
return templ.render(
|
||||
app_name="Project: Doodle",
|
||||
app_version=get_app_version(),
|
||||
*args, **kwargs
|
||||
)
|
||||
|
||||
def title_from_markdown(text):
|
||||
"""Retrieve the title from the first Markdown header."""
|
||||
for line in text.split("\n"):
|
||||
if line.startswith("# "):
|
||||
return line[2:]
|
||||
|
||||
def get_app_version():
|
||||
"""Get the app version from pkg/branding/branding.go in Doodle"""
|
||||
ver = re.compile(r'Version\s*=\s*"(.+?)"')
|
||||
with codecs.open("../../pkg/branding/branding.go", "r", "utf-8") as fh:
|
||||
text = fh.read()
|
||||
for line in text.split("\n"):
|
||||
m = ver.search(line)
|
||||
if m:
|
||||
return m[1]
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
16
dev-assets/guidebook/build.sh
Executable file
16
dev-assets/guidebook/build.sh
Executable file
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [[ ! -d "./venv" ]]; then
|
||||
echo Creating Python virtualenv...
|
||||
python3 -m venv ./venv
|
||||
source ./venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
else
|
||||
source ./venv/bin/activate
|
||||
fi
|
||||
|
||||
python build.py
|
||||
|
||||
# Copy static files in.
|
||||
mkdir -p compiled/pages/res
|
||||
cp -r pages/res/*.* compiled/pages/res/
|
28
dev-assets/guidebook/compiled/index.html
Normal file
28
dev-assets/guidebook/compiled/index.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Project: Doodle Guidebook</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="pages/res/main.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="sidebar">
|
||||
<nav>
|
||||
<h3>Navigation</h3>
|
||||
|
||||
<ul>
|
||||
<li><a href="pages/Home.html" target="frame">Home</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<div>
|
||||
<iframe name="frame" src="pages/Home.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
130
dev-assets/guidebook/pages/DoodadScripts.md
Normal file
130
dev-assets/guidebook/pages/DoodadScripts.md
Normal file
|
@ -0,0 +1,130 @@
|
|||
# Doodad Scripts
|
||||
|
||||
Doodads are programmed using JavaScript which gives them their behavior
|
||||
and ability to interact with the player and other doodads.
|
||||
|
||||
An example Doodad script looks like the following:
|
||||
|
||||
```javascript
|
||||
// The main function is called when the doodad is initialized in Play Mode
|
||||
// at the start of the level.
|
||||
function main() {
|
||||
// Important global variables:
|
||||
// - Self: information about the current Doodad running this script.
|
||||
// - Events: handle events raised during gameplay.
|
||||
// - Message: publish or subscribe to named messages to interact with
|
||||
// other doodads.
|
||||
|
||||
// Logs go to the game's log file (standard output on Linux/Mac).
|
||||
console.log("%s initialized!", Self.Doodad.Title);
|
||||
|
||||
// If our doodad has 'solid' parts that should prohibit movement,
|
||||
// define the hitbox here. Coordinates are relative so 0,0 is the
|
||||
// top-left pixel of the doodad's sprite.
|
||||
Self.SetHitbox(0, 0, 64, 12);
|
||||
|
||||
// Handle a collision when another doodad (or player) has entered
|
||||
// the space of our doodad.
|
||||
Events.OnCollide(function(e) {
|
||||
// The `e` object holds information about the event.
|
||||
console.log("Actor %s has entered our hitbox!", e.Actor.ID());
|
||||
|
||||
// InHitbox is `true` if we defined a hitbox for ourselves, and
|
||||
// the colliding actor is inside of the hitbox we defined.
|
||||
if (e.InHitbox) {
|
||||
// To prohibit movement, return false from the OnCollide handler.
|
||||
// If you don't return false, the actor is allowed to keep on
|
||||
// moving through.
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// OnLeave is called when an actor, who was previously colliding with
|
||||
// us, is no longer doing so.
|
||||
Events.OnLeave(function(e) {
|
||||
console.log("Actor %s has stopped colliding!", e.Actor.ID());
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
# JavaScript API
|
||||
|
||||
## Global Variables
|
||||
|
||||
The following global variables are available to all Doodad scripts.
|
||||
|
||||
### Self
|
||||
|
||||
Self holds information about the current doodad. The full surface area of
|
||||
the Self object is subject to change, but some useful things you can access
|
||||
from it include:
|
||||
|
||||
* Self.Doodad: a pointer to the doodad's file data.
|
||||
* Self.Doodad.Title: get the title of the doodad file.
|
||||
* Self.Doodad.Author: the name of the author who wrote the doodad.
|
||||
* Self.Doodad.Script: the doodad's JavaScript source code. Note that
|
||||
modifying this won't have any effect in-game, as the script had already
|
||||
been loaded into the interpreter.
|
||||
* Self.Doodad.GameVersion: the version of {{ app_name }} that was used
|
||||
when the doodad was created.
|
||||
|
||||
### Events
|
||||
|
||||
### Message
|
||||
|
||||
## Global Functions
|
||||
|
||||
The following useful functions are also available globally:
|
||||
|
||||
### Timers and Intervals
|
||||
|
||||
Doodad scripts implement setTimeout() and setInterval() functions similar
|
||||
to those found in web browsers.
|
||||
|
||||
```javascript
|
||||
// Call a function after 5 seconds.
|
||||
setTimeout(function() {
|
||||
console.log("I've been called!");
|
||||
}, 5000);
|
||||
```
|
||||
|
||||
setTimeout() and setInterval() return an ID number for the timer created.
|
||||
If you wish to cancel a timer before it has finished, or to stop an interval
|
||||
from running, you need to pass its ID number into `clearTimeout()` or
|
||||
`clearInterval()`, respectively.
|
||||
|
||||
```javascript
|
||||
// Start a 1-second interval
|
||||
var id = setInterval(function() {
|
||||
console.log("Tick...");
|
||||
}, 1000);
|
||||
|
||||
// Cancel it after 30 seconds.
|
||||
setTimeout(function() {
|
||||
clearInterval(id);
|
||||
}, 30000);
|
||||
```
|
||||
|
||||
### Console Logging
|
||||
|
||||
Doodad scripts also implement the `console.log()` and similar functions as
|
||||
found in web browser APIs. They support "printf" style variable placeholders.
|
||||
|
||||
```javascript
|
||||
console.log("Hello world!");
|
||||
console.error("The answer is %d!", 42);
|
||||
console.warn("Actor '%s' has collided with us!", e.Actor.ID());
|
||||
console.debug("This only logs when the game is in debug mode!");
|
||||
```
|
||||
|
||||
### RGBA(red, green, blue, alpha uint8)
|
||||
|
||||
RGBA initializes a Color variable using the game's native Color type. May
|
||||
be useful for certain game APIs that take color values.
|
||||
|
||||
Example: RGBA(255, 0, 255, 255) creates an opaque magenta color.
|
||||
|
||||
### Point(x, y int)
|
||||
|
||||
Returns a Point object which refers to a location in the game world. This
|
||||
type is required for certain game APIs.
|
9
dev-assets/guidebook/pages/Home.md
Normal file
9
dev-assets/guidebook/pages/Home.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Guidebook to {{ app_name }}
|
||||
|
||||
This is the users manual to {{ app_name }}, a drawing-based maze game.
|
||||
|
||||
## Creating Custom Content
|
||||
|
||||
* [Doodad Scripts](DoodadScripts.html)
|
||||
|
||||
v{{ app_version }}
|
28
dev-assets/guidebook/pages/index.html
Normal file
28
dev-assets/guidebook/pages/index.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ app_name }} Guidebook</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="pages/res/main.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="sidebar">
|
||||
<nav>
|
||||
<h3>Navigation</h3>
|
||||
|
||||
<ul>
|
||||
<li><a href="pages/Home.html" target="frame">Home</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<div>
|
||||
<iframe name="frame" src="pages/Home.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
15
dev-assets/guidebook/pages/markdown.html
Normal file
15
dev-assets/guidebook/pages/markdown.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ title }}</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="res/markdown.css">
|
||||
<link rel="stylesheet" type="text/css" href="res/syntax.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
$CONTENT
|
||||
|
||||
</body>
|
||||
</html>
|
66
dev-assets/guidebook/pages/res/main.css
Normal file
66
dev-assets/guidebook/pages/res/main.css
Normal file
|
@ -0,0 +1,66 @@
|
|||
body,html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
body {
|
||||
background-color: #EEE;
|
||||
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
color: #000;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
div#sidebar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 220px;
|
||||
background-color: #000066;
|
||||
color: #EEE;
|
||||
}
|
||||
|
||||
nav {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
nav ul li {
|
||||
display: block;
|
||||
}
|
||||
nav a:link, nav a:visited {
|
||||
color: #EEE;
|
||||
text-decoration: none;
|
||||
}
|
||||
nav a:hover, nav a:active {
|
||||
color: #F9F;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div#content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 220px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
div#content div {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
div#content iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
overflow: auto;
|
||||
}
|
25
dev-assets/guidebook/pages/res/markdown.css
Normal file
25
dev-assets/guidebook/pages/res/markdown.css
Normal file
|
@ -0,0 +1,25 @@
|
|||
body {
|
||||
background-color: #EEE;
|
||||
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
color: #000;
|
||||
line-height: 1.4em;
|
||||
margin: 2rem;
|
||||
}
|
||||
|
||||
a:link, a:visited {
|
||||
color: #006699;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover, a:active {
|
||||
color: #996600;
|
||||
}
|
||||
|
||||
.codehilite {
|
||||
border: 1px solid #222;
|
||||
}
|
||||
pre {
|
||||
font-family: "Lucida Console", "DejaVu LGC Sans Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Ubuntu Mono", monospace;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
}
|
69
dev-assets/guidebook/pages/res/syntax.css
Normal file
69
dev-assets/guidebook/pages/res/syntax.css
Normal file
|
@ -0,0 +1,69 @@
|
|||
.codehilite .hll { background-color: #ffffcc }
|
||||
.codehilite { background: #f8f8f8; }
|
||||
.codehilite .c { color: #408080; font-style: italic } /* Comment */
|
||||
.codehilite .err { border: 1px solid #FF0000 } /* Error */
|
||||
.codehilite .k { color: #008000; font-weight: bold } /* Keyword */
|
||||
.codehilite .o { color: #666666 } /* Operator */
|
||||
.codehilite .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
|
||||
.codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */
|
||||
.codehilite .cp { color: #BC7A00 } /* Comment.Preproc */
|
||||
.codehilite .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
|
||||
.codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */
|
||||
.codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */
|
||||
.codehilite .gd { color: #A00000 } /* Generic.Deleted */
|
||||
.codehilite .ge { font-style: italic } /* Generic.Emph */
|
||||
.codehilite .gr { color: #FF0000 } /* Generic.Error */
|
||||
.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.codehilite .gi { color: #00A000 } /* Generic.Inserted */
|
||||
.codehilite .go { color: #888888 } /* Generic.Output */
|
||||
.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||
.codehilite .gs { font-weight: bold } /* Generic.Strong */
|
||||
.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
.codehilite .gt { color: #0044DD } /* Generic.Traceback */
|
||||
.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
|
||||
.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
|
||||
.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
|
||||
.codehilite .kp { color: #008000 } /* Keyword.Pseudo */
|
||||
.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
|
||||
.codehilite .kt { color: #B00040 } /* Keyword.Type */
|
||||
.codehilite .m { color: #666666 } /* Literal.Number */
|
||||
.codehilite .s { color: #BA2121 } /* Literal.String */
|
||||
.codehilite .na { color: #7D9029 } /* Name.Attribute */
|
||||
.codehilite .nb { color: #008000 } /* Name.Builtin */
|
||||
.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
||||
.codehilite .no { color: #880000 } /* Name.Constant */
|
||||
.codehilite .nd { color: #AA22FF } /* Name.Decorator */
|
||||
.codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
||||
.codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
|
||||
.codehilite .nf { color: #0000FF } /* Name.Function */
|
||||
.codehilite .nl { color: #A0A000 } /* Name.Label */
|
||||
.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
||||
.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */
|
||||
.codehilite .nv { color: #19177C } /* Name.Variable */
|
||||
.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
||||
.codehilite .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.codehilite .mb { color: #666666 } /* Literal.Number.Bin */
|
||||
.codehilite .mf { color: #666666 } /* Literal.Number.Float */
|
||||
.codehilite .mh { color: #666666 } /* Literal.Number.Hex */
|
||||
.codehilite .mi { color: #666666 } /* Literal.Number.Integer */
|
||||
.codehilite .mo { color: #666666 } /* Literal.Number.Oct */
|
||||
.codehilite .sa { color: #BA2121 } /* Literal.String.Affix */
|
||||
.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */
|
||||
.codehilite .sc { color: #BA2121 } /* Literal.String.Char */
|
||||
.codehilite .dl { color: #BA2121 } /* Literal.String.Delimiter */
|
||||
.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
|
||||
.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */
|
||||
.codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
|
||||
.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */
|
||||
.codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
|
||||
.codehilite .sx { color: #008000 } /* Literal.String.Other */
|
||||
.codehilite .sr { color: #BB6688 } /* Literal.String.Regex */
|
||||
.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */
|
||||
.codehilite .ss { color: #19177C } /* Literal.String.Symbol */
|
||||
.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */
|
||||
.codehilite .fm { color: #0000FF } /* Name.Function.Magic */
|
||||
.codehilite .vc { color: #19177C } /* Name.Variable.Class */
|
||||
.codehilite .vg { color: #19177C } /* Name.Variable.Global */
|
||||
.codehilite .vi { color: #19177C } /* Name.Variable.Instance */
|
||||
.codehilite .vm { color: #19177C } /* Name.Variable.Magic */
|
||||
.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */
|
2
dev-assets/guidebook/requirements.txt
Normal file
2
dev-assets/guidebook/requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
markdown
|
||||
jinja2
|
Loading…
Reference in New Issue
Block a user