diff --git a/content/programming.tree b/content/programming.tree
index 972d0fc..3592eca 100644
--- a/content/programming.tree
+++ b/content/programming.tree
@@ -20,7 +20,9 @@
id = "programming/opinions"
+ ### opinions
+% id = "01HPD4XQQ5GPQ20C6BPA8G670F"
- ### blog
% content.link = "programming/blog/tairu"
+ id = "01HPD4XQQ5WM0APCAX014HM43V"
+ tairu - an interactive exploration of 2D autotiling techniques
diff --git a/content/programming/blog/tairu.tree b/content/programming/blog/tairu.tree
index 0a8078e..54050c7 100644
--- a/content/programming/blog/tairu.tree
+++ b/content/programming/blog/tairu.tree
@@ -1,86 +1,131 @@
%% title = "tairu - an interactive exploration of 2D autotiling techniques"
- scripts = ["tairu/tairu.js"]
+ scripts = ["tairu/tiling-demo.js", "tairu/tairu.js"]
-+ I remember since my early days doing programming, I've been interested in how games like Terraria handle automatically tiling their terrain.
+% id = "01HPD4XQPWM8ECT2QM6AT9YRWB"
+- I remember since my early days doing programming, I've been interested in how games like Terraria handle automatically tiling their terrain.
+ % id = "01HPD4XQPWPDBH6QQAZER7A05G"
- in Terraria, you can fully modify the terrain however you want, and the tiles will connect to each other seamlessly.
+ % id = "01HPD4XQPW8HE7681P7H686X4N"
- TODO: short videos demoing this here
+% id = "01HPD4XQPWJBTJ4DWAQE3J87C9"
- once upon a time I heard of a technique called *bitwise autotiling*
- + this technique involves assigning the cardinal directions (north, south, east, west) to a bitset.
+ % id = "01HPD4XQPW6VK3FDW5QRCE6HSS"
+ + I learned about it back when I was building 2D Minecraft clones using [Construct 2](https://www.construct.net/en/construct-2/manuals/construct-2), and I wanted my terrain to look nice as it does in Terraria
+
+ % id = "01HPD4XQPWJ1CE9ZVRW98X7HE6"
+ - Construct 2 was one of my first programming experiences and the first game engine I truly actually liked :smile:
+
+ % id = "01HPD4XQPWHNFQPRHX13MYW8GT"
+ - this technique involves assigning the cardinal directions (north, south, east, west) to a bitset.
then for each tile you look at which adjacent tiles should be connected to
+ % id = "01HPD4XQPWS2JS8RJH2P5TKPAB"
- this connection condition can be whatever you want - in most cases it's just "is the adjacent tile of the same type as the current tile?"
+ % id = "01HPD4XQPWAANYFBYX681787D1"
- for example, "is the tile to the left a dirt tile?"
+ % id = "01HPD4XQPWES5K2V2AKB7H0EHK"
- and then you use this bitset to index into a lookup table of tiles
+ % id = "01HPD4XQPWD00GDZ0N5H1DRH2P"
- for example, say we have the following grid of tiles:\
TODO editable grid on javascript
for each tile, we can assign a bitset of cardinal directions like so:\
TODO grid linked with the other grid to show which adjacent tiles each tile connects to
+ % id = "01HPD4XQPWM0AAE6F162EZTFQY"
- in JavaScript it would look something like this:
```javascript
// TODO code example
```
+% id = "01HPD4XQPWT9N8X9BD9GKWD78F"
- bitwise autotiling is a really cool technique that I've used in plenty of games in the past
- - my (very messy) LÖVE-based game engine `lovejam`, powering my game jam games from 2018, had an autotiling feature in its level editor based on this
+ % id = "01HPD4XQPW5FQY8M04S6JEBDHQ"
+ - as I mentioned before, [I've known it since my Construct 2 days][branch:01HPD4XQPW6VK3FDW5QRCE6HSS], but when it comes to my released games [Planet Overgamma] would probably be the first to utilize it properly
- - TODO video of Planet Overgamma editor doing the magic after issuing the `at` command (or whatever it was called, i forgor :skull:)
+ TODO video of some Planet Overgamma gameplay showing the autotiling in action
- - every iteration of Planet Overgamma since then has been using this exact technique for procedurally generated, editable terrain
+ [Planet Overgamma]: https://liquidev.itch.io/planet-overgamma-classic
-+ but one day I found a really cool project called Tilekit (TODO link)
+ - this accursed game has been haunting me for years since; there have been many iterations.
+ he autotiling source code of the one in the video can be found [here][autotiling source code].
+ [autotiling source code]: https://github.com/liquidev/planet-overgamma/blob/classic/jam/map.lua#L209
+
+% id = "01HPD4XQPWPN6HNA6M6EH507C6"
++ but one day I found a really cool project called [Tilekit](https://rxi.itch.io/tilekit)
+
+ % id = "01HPD4XQPW11EQTBDQSGXW3S52"
+ (of course it's really cool, after all rxi made it)
+ % id = "01HPD4XQPWYHS327BV586SB085"
- for context rxi is the genius behind the Lua-powered, simple, and modular text editor `lite` that I was using for quite a while
+ % id = "01HPD4XQPWJ9QAQ5MF2J5JBB8M"
- after a while I switched to a fork - Lite XL, which had better font rendering and more features
+ % id = "01HPD4XQPWB11TZSX5VAAJ6TCD"
- I stopped using it because VS Code was just more feature packed and usable; no need to reinvent the wheel, rust-analyzer *just works.*
+ % id = "01HPD4XQPW3G7BXTBBTD05MB8V"
- the LSP plugin for Lite XL had some issues around autocompletions not filling in properly :pensive:\
it's likely a lot better now, but back then I decided this is too much for my nerves.
while tinkering with your editor is something really cool, in my experience it's only cool up to a point.
+% id = "01HPD4XQPWV1BAPA27SNDFR93B"
- the cool thing with Tilekit is that it's *more* than just your average bitwise autotiling - of course it *can* do basic autotiling, but it can also do so much more
+ % id = "01HPD4XQPWM1JSAPXVT6NBHKYY"
+ classes.branch_children = "branch-quote"
- if I had to describe it, it's basically something of a *shader langauge for tilesets.* this makes it really powerful, as you can do little programs like
+ % id = "01HPD4XQPWE7ZVR0SS67DHTGHQ"
- autotile using this base tileset
+ % id = "01HPD4XQPW2BFZYQQ920SYHM9M"
- if the tile above is empty AND with a 50% chance
+ % id = "01HPD4XQPWJB7V67TS1M3HFCYE"
- then grass
+ % id = "01HPD4XQPWF7K85Z0CEK4WDDBZ"
- if the tile above is solid AND with a 10% chance
+ % id = "01HPD4XQPW5J3N6MVT9Z2W00S9"
- then vines
+ % id = "01HPD4XQPWGCMCEAR5Z9EETSGP"
- if the tile above is vines AND with a 50% chance
+ % id = "01HPD4XQPWP847T0EAM0FJ88T4"
- then vines
- - I mean, after all - bitwise autotiling is basically a clever solution to an `if` complexity problem, so why not extend that with more logic and rules and stuff to let you build more complex maps
+ % id = "01HPD4XQPWK58Z63X6962STADR"
+ - I mean, after all - bitwise autotiling is basically a clever solution to an `if` complexity problem, so why not extend that with more logic and rules and stuff to let you build more complex maps?
+% id = "01HPD4XQPW4Y075XWJCT6AATB2"
- ever since then I've been wanting to build something just like Tilekit, but in the form of an educational, interactive blog post to demonstrate the ideas in a fun way
+ % id = "01HPD4XQPWR8J9WCNBNCTJERZS"
- and what you're reading is the result of that.
-+ so let's get going! first, we'll build a basic tile editor using JavaScript.
-
+% id = "01HPD4XQPW1EP8YHACRJVMA0GM"
+- so let's get going! first, we'll build a basic tile editor using JavaScript.
+ % id = "01HPD4XQPWPNRTVJFNFGNHJMG1"
+ not my favorite language, but we're on the Web so it's not like we have much more of a choice.
+ % id = "01HPD4XQPWGK7M4XJYC99XE4T6"
- I could use TypeScript, but this page follows a philosophy of not introducing complexity where I can deal without it.
TypeScript is totally cool, but not necessary.
+ % id = "01HPD4XQPWAE0ZH46WME6WJSVP"
- I'll be using Web Components (in particular, custom elements) combined with canvas to add stuff onto the page.
diff --git a/crates/treehouse/src/cli/generate.rs b/crates/treehouse/src/cli/generate.rs
index 16b73e8..533580b 100644
--- a/crates/treehouse/src/cli/generate.rs
+++ b/crates/treehouse/src/cli/generate.rs
@@ -203,6 +203,7 @@ impl Generator {
pub title: String,
pub thumbnail: Option,
pub scripts: Vec,
+ pub styles: Vec,
pub breadcrumbs: String,
pub tree_path: Option,
pub tree: String,
@@ -240,6 +241,7 @@ impl Generator {
alt: thumbnail.alt.clone(),
}),
scripts: roots.attributes.scripts.clone(),
+ styles: roots.attributes.styles.clone(),
breadcrumbs,
tree_path: treehouse
.tree_path(parsed_tree.file_id)
diff --git a/crates/treehouse/src/html/tree.rs b/crates/treehouse/src/html/tree.rs
index bbb50d6..d6e7c52 100644
--- a/crates/treehouse/src/html/tree.rs
+++ b/crates/treehouse/src/html/tree.rs
@@ -158,7 +158,16 @@ pub fn branch_to_html(
if has_children {
s.push_str("");
{
- s.push_str("
");
+ s.push_str("
');
let num_children = branch.children.len();
for i in 0..num_children {
let child_id = treehouse.tree.branch(branch_id).children[i];
diff --git a/crates/treehouse/src/tree/attributes.rs b/crates/treehouse/src/tree/attributes.rs
index 72424f1..4c3b169 100644
--- a/crates/treehouse/src/tree/attributes.rs
+++ b/crates/treehouse/src/tree/attributes.rs
@@ -21,6 +21,11 @@ pub struct RootAttributes {
/// These are relative to the /static/js directory.
#[serde(default)]
pub scripts: Vec,
+
+ /// Additional styles to load into to the page.
+ /// These are relative to the /static/css directory.
+ #[serde(default)]
+ pub styles: Vec,
}
/// A picture reference.
@@ -51,6 +56,10 @@ pub struct Attributes {
/// Do not persist the branch in localStorage.
#[serde(default)]
pub do_not_persist: bool,
+
+ /// Strings of extra CSS class names to include in the generated HTML.
+ #[serde(default)]
+ pub classes: Classes,
}
/// Controls for block content presentation.
@@ -76,3 +85,10 @@ pub enum Content {
/// children, an `attribute`-type error is raised.
Link(String),
}
+
+#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize)]
+pub struct Classes {
+ /// Classes to append to the branch's
element containing its children.
+ #[serde(default)]
+ pub branch_children: String,
+}
diff --git a/static/css/tairu.css b/static/css/tairu.css
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/static/css/tairu.css
@@ -0,0 +1 @@
+
diff --git a/static/css/tree.css b/static/css/tree.css
index 6a255ba..426d1a1 100644
--- a/static/css/tree.css
+++ b/static/css/tree.css
@@ -346,4 +346,12 @@ th-bb .branch-date {
background-repeat: no-repeat;
background-position: 0% 50%;
opacity: 80%;
-}
\ No newline at end of file
+}
+
+/* branch-quote class for "air quote branches"; used to separate a subtree from a parent tree
+ stylistically such that it's interpretable as a form of block quote. */
+ul.branch-quote {
+ padding: 8px;
+ border: 1px solid var(--border-1);
+ border-radius: 8px;
+}
diff --git a/static/js/tairu/framework.js b/static/js/tairu/framework.js
new file mode 100644
index 0000000..759f0d0
--- /dev/null
+++ b/static/js/tairu/framework.js
@@ -0,0 +1,13 @@
+// A frameworking class assigning some CSS classes to the canvas to make it integrate nicer with CSS.
+class Frame extends HTMLCanvasElement {
+ constructor() {
+ super();
+
+ this.style.cssText = `
+
+ `;
+ }
+
+ // Override this!
+ draw() { }
+}
diff --git a/static/js/tairu/tiling-demo.js b/static/js/tairu/tiling-demo.js
new file mode 100644
index 0000000..e69de29
diff --git a/static/js/tree.js b/static/js/tree.js
index ee51c29..b0e0199 100644
--- a/static/js/tree.js
+++ b/static/js/tree.js
@@ -109,6 +109,11 @@ class LinkedBranch extends Branch {
let linkedDocument = parser.parseFromString(text, "text/html");
let main = linkedDocument.getElementsByTagName("main")[0];
let ul = main.getElementsByTagName("ul")[0];
+ let styles = main.getElementsByTagName("link");
+ let scripts = main.getElementsByTagName("script");
+
+ this.append(...styles);
+ this.append(...scripts);
this.loadingText.remove();
this.innerUL.innerHTML = ul.innerHTML;
diff --git a/template/tree.hbs b/template/tree.hbs
index 7310c73..a442b78 100644
--- a/template/tree.hbs
+++ b/template/tree.hbs
@@ -26,6 +26,7 @@
+
@@ -33,10 +34,6 @@
-
- {{#each page.scripts}}
-
- {{/each}}
@@ -92,6 +89,18 @@
+ {{!-- Append page styles and scripts into the main content, such that they can be inlined
+ into linked branches when those are loaded in. Putting them in the page's head would make
+ extracting them way more painful than it needs to be. --}}
+
+ {{#each page.styles}}
+
+ {{/each}}
+
+ {{#each page.scripts}}
+
+ {{/each}}
+
{{{ page.tree }}}