From: xangelo Date: Wed, 9 Jun 2021 19:53:06 +0000 (-0400) Subject: update content X-Git-Url: https://git.xangelo.ca/?a=commitdiff_plain;h=7e3a9ba634ecb668ceee5be4d04ce7e0156de871;p=xangelo.ca.git update content --- diff --git a/content/.DS_Store b/content/.DS_Store new file mode 100644 index 0000000..5f42361 Binary files /dev/null and b/content/.DS_Store differ diff --git a/content/posts/.DS_Store b/content/posts/.DS_Store new file mode 100644 index 0000000..120a5b2 Binary files /dev/null and b/content/posts/.DS_Store differ diff --git a/content/posts/devlog/.DS_Store b/content/posts/devlog/.DS_Store new file mode 100644 index 0000000..962fddb Binary files /dev/null and b/content/posts/devlog/.DS_Store differ diff --git a/content/posts/devlog/blog/.DS_Store b/content/posts/devlog/blog/.DS_Store new file mode 100644 index 0000000..0f847f2 Binary files /dev/null and b/content/posts/devlog/blog/.DS_Store differ diff --git a/content/posts/devlog/blog/1.md b/content/posts/devlog/blog/1.md new file mode 100644 index 0000000..12a9c97 --- /dev/null +++ b/content/posts/devlog/blog/1.md @@ -0,0 +1,137 @@ +--- +title: "DEVLOG: Custom Theme for Hugo" +date: 2020-06-10T12:00:00-04:00 +draft: false +tags: ["devlog", "blog", "devlog-blog"] +--- + +I've started working on a custom theme for Hugo[^1] that I use on my blog. The goal here is to be as simple as possible and takes its inspiration from the IETF .txt file[^2] where possible. + +The theme itself contains a light/dark mode as well as a small variation of the main theme for mobile. I actually had some help from a good friend[^3] who helped me adjust the colors for both dark and light modes to make them a bit more legible. + +The two complicated components and 1 simple component are outlined below. + +## Features + +### Numbered Headers + +I wanted to ensure that each heading would have a number associated with it that matched the number that it was automatically assigned by Hugo during the Table of Contents generation. I didn't want to have to update numbers as I added/remove header tags and I didn't want to utilize any JavaScript on the site, so I was left with CSS only. + +I ended up utilizing counters[^4] to achieve this. + + + +```css +body {counter-reset: h2;} +h2 {counter-reset: h3;} +h3 {counter-reset: h4;} +h4 {counter-reset: h5;} +h5 {counter-reset: h6;} + +h2:before {counter-increment: h2; content: counter(h2) ". ";} +h3:before {counter-increment: h3; content: counter(h2) "."counter(h3) ". ";} +h4:before {counter-increment: h4; content: counter(h2) "."counter(h3) "."counter(h4) ". ";} +h5:before {counter-increment: h5; content: counter(h2) "."counter(h3) "."counter(h4) "."counter(h5) ". ";} +h6:before {counter-increment: h6; content: counter(h2) "."counter(h3) "."counter(h4) "."counter(h5) "."counter(h6) ". "; } +h2.nocount:before,h3.nocount:before,h4.nocount:before,h5.nocount:before,h6.nocount:before {content: ""; counter-increment: none;} +``` + + + +I only have a single `

` tag in my document which is for the title of the post, which I don't want numbered. The code above it ensures that every time we run across an `

` tag it will reset the counter for `

` tags to 0, increment the counter for `

` tags, and then display the current value of the counter. + +It repeats this for all header tags appending the counter for each subsequent tag level. + +I've also included provisions for ensuring that you can skip incrementing the counters if you add a `.nocount` class to any header. + + + +### Flexible visual line-up + +This was probably the hardest part. + +![flexible-line](/img/devlog/blog/flexible-line.png) + +That dashed line that lets you link a post with the corresponding date. Both elements are positioned at the exterior of their boxes, and the titles have a varying width. + +In order to accomplish this I ended up needing to introduce a 3rd element, the line itself. However, I can't actually use an `
` tag because I want to work towards supporting screen readers.. and those tags get interpreted as dividers between content. + +The article list is an unordered list, so the HTML code looks like this: + +```html +
  • + Post Title + + YYYY-MM-DD +
  • +``` + +I set the `
  • ` tag to utilize flex `display: flex` and tell it to align the items to the center + +I then set the `.divider` to `flex-grow: 1` [^4] and don't set the property on the `` or `.pubdate` elements. This causes the divider to grow to take up the entirety of space within the list element, subtracting the side of the title/date tags. + +```css +.article-list li { + list-style: none; + display: flex; + align-items: center; +} + +.article-list .divider { + flex-grow: 1; + border-bottom: 1px dashed black; + margin: 0.3rem; +} +``` + +### Dark/Light mode +One of the things that I ended up implementing, that I'm not 100% sold on is the auto dark/light mode. Utilizing CSS we can adjust things to account for if the user is utilizing a light or dark mode on their browser: +```css +@media (prefers-color-scheme: dark) { + /* your stuff goes here */ +} +``` +It's a very simple technique and given the minimalist nature of this site it works rather perfectly. + +Where I'm not 100% happy is on color choices. Where possible I attmpted to tweak things so that they would look the same in light or dark mode. I tweaked the original colors of links (new/visited) and also settled on a particular code-highlighting style. + +Where I'm not 100% happy, is with the default font color. In light mode it's browser defaults, but in dark mode it's a blue/grey and I think it might be a tad too dark. It's something that I'll continue tweaking in small batches until I find something that works well. + +I also faded out images just a bit so that they're not so jaring. The idea is if you hover/touch the images they'll fade in to full color, but if you're just scrolling through you won't run into any weirdness. + +### Support for Utteranc.es +This[^5] is something that I recently stumbled across - the ability to utilize GitHub issues to track comments on a site. I really love the idea - especially since I'm hosting my blog on GitHub Pages. By adding some params to your `config.toml` file you'll be able to turn on support for utterances. + +```toml +[params.utterances] +repo = "AngeloR/angelor.github.io" +issue_term="pathname" +label="comment" +theme="preferred-color-scheme" +``` + +The settings match exactly the configuration options provided by utteranc.es, so you should be able to see the mapping quite easiy. The only thing I changed was making it `issue_term` instead of `issue-term`. + +If you don't add this configuration, it'll just hide the comment block and you won't even load the utteranc.es client js. + +## Download/Install +If you're interested in this theme, you can grab it here https://github.com/AngeloR/plain-hugo-theme + +Up to date installation instructions can be found on the readme, but I've included a snapshot of what they were at this point: + +```bash +git clone https://github.com/AngeloR/plain-hugo-theme /path/to/hugo/themes/plain/ + +Edit your config.toml to add the following line: +theme = "plain" +``` + +If you do end up using it and come across any bugs, please let me know over on GitHub! + +## Footnotes + +[^1]: https://github.com/AngeloR/plain-hugo-theme +[^2]: https://tools.ietf.org/rfc/rfc7993.txt +[^3]: http://westleysz.com/ +[^4]: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-grow +[^5]: https://utteranc.es/ \ No newline at end of file diff --git a/content/posts/devlog/roguelike/dungeon-generation.md b/content/posts/devlog/roguelike/dungeon-generation.md new file mode 100644 index 0000000..aad30e7 --- /dev/null +++ b/content/posts/devlog/roguelike/dungeon-generation.md @@ -0,0 +1,183 @@ +--- +title: "Dungeon Generation in Roguelikes" +date: 2021-04-23T09:44:35-04:00 +tags: ["roguelike", "explanation"] +--- + + +## Intro +As always, I've been working on a terrible browser-based game. This time, it +will be revolving around gameplay mechanics from roguelikes(or roguelites +technically)+jrpgs. + +The thing I specifically want to look at today is the topic of Dungeon +Generation - both in and out of code. + +Roguelikes all tend to share one mechanic: Procedurally Generated Dungeons. The +idea is that every play-through is different, every floor of a dungeon is +completely unique. As a result, it requires the player to learn the mechanics of +the game over multiple runs as most roguelikes also include perma-death as a +required feature. + +Dungeon Generation in roguelikes are a very interesting topic for two reasons. +There is a definite technical component to being able to generate "good" +dungeons quickly. Dungeons that are large enough, with enough rooms/pathways to +be interesting, but that don't take forever to generate. The goal is each floor +is generated randomly when the player enters - we don't want load times +equivalent to stepping into a room in Morrowind. The second reason is one that I +think roguelikes can miss out on - dungeon generation must fit the environment. + +Most roguelikes have a generation alorithm that gets assigned to every single +floor. But that's not really that helpful. Dungeons should reflect the +environment the player is in. Having square rooms in a castle dungeon makes +sense. Having square rooms in a cave, not so much. + +A lot of dungeon generation information you find online tend to focus on the +techtechnical component: HOW do you generate a dungeon. I'm hoping to also cover +the second bit here. + +## Random +The easiest to explain algorithm is the "Random" one, but it's probably the +hardest to get right. Random dungeons are exactly what you'd think -> just +randomly place obstacles and interaction points around the dungeon. As a result +it's very easy to actually MAKE the dungeon. + +It also has the added benefit that the "random" look works really well for open +fields. Think areas that are strewn with trees or rocks or something like that. +It could also work really well for large underground caverns since you would be +peppering the inside with obstances. + +But we're not just making a dungeon - we're making a game. And truly-random +dungeons are hard to tune. How do you ensure that every chest you place is +actually reachable by the player? How about the one set of stairs? How do you +ensure that the player doesn't spawn in a box, closed off from the rest of the +dungeon. How do you ensure that they don't spawn right next to some stairs? + +Each of these questions (and many many more) result in you tuning you random +generation more and more. You'll never get it 100% right. There'll always be +edge cases reported by your places that you didn't even think about (did a +monster spawn in deep water so the player didn't even know it was there and is +now reporting that they didn't get an achievement for killing all the monsters +on a foor?). + +I started with a purly random dungeon generation system myeself. It's definitely +not a bad call to make - but you just have to be aware of the edge cases. But I +kept having to tune/adjust things and I'd still end up with play testers saying +they got spawned in a box, or couldn't reach the stairs. That's frustrating +enough to probably just stop playing. + +The nice thing about random, however, is that you don't NEED to generate the map +in its entirety. Nor do you need it to be entirely random. + + +### On-demand generation +So you have the container for your map.. and your character is spawned in a +particular point `(x,y)`. Given a field of view (`v`) really you only need to +generate a box defined by the points `(x-v, y-v)`, `(x+v, y-v)`, `(x-v, y+v)`, +and `(x+v, y+v)`. + +If the player steps in a direction, you only need to expand the generated +portion of the map by 1 tile (or whatever your fov is). In this way, your entire +dungeon is being generated as the player discovers it. You get a few benefits +like not needing to store the entirety of the map if the player doesn't visit +it. You can tune drop rates for everything just by how much of the map is +discovered vs. isn't. You can also almost guarantee that EVERY point on the map is +reachable by the player and that they'll discover the stairs exactly when you'd +like them to. + +### Pseudo-random Fabrication +Now, lets get the pedantics out of the way - nothing we're doing is random, it's +all pseudo-random. The difference is that in this generation mechanic we're +actually building the map from pre-defined map parts. + +The downside, of course, is that you have to spend a bunch of time generating +the pieces of map and you do have to have to have some guidelines. But, being +able to tune each individual section of map gives you a ton of control over the +actual gameplay. It also allows you to use non-standard map shapes (get outta +here square rooms) and generate really unique looking maps. + +You would need to rotate the location of interactables, but with enough of these +map pieces being put together in random orders it gives you a lot of variation +for your players. And if the unlikely event that they end up getting the EXACT +same map somehow (you know, cause random), the locations of all the interactable +items will be randomized. + +## Standard Dungeons (Connected Squares) +There are a million of these tutorials as this is the standard look for +dungeons. I think they work wonderfully when you're actually exploring a dungeon +in a castle or something - but otherwise they seem out of place + +The premise is pretty simplem but it involves iterating over the map numerous +times to achieve the look you want. The steps themselves are pretty +straight-foward. + +1. First go over the map and generate rooms (squares or rectangles, whatever you + want). +2. Then go over the map again and connect the rooms together via pathways. + +Normally you'll make multiple passes over the map to generate the appropriate +room density that you want. The more rooms, the easier it is to connect them +all. + +The connection part CAN be confusing, but the easiest way is to actually look at +various path-finding algorithms. Since the map doesn't actually exist, any +pathfinding algorithms will find the straightest line possible between your +rooms. + +Simply iterate over each pair of rooms and connect them using your chosen +path-finding algorithm. [A\*](https://csis.pace.edu/~benjamin/teaching/cs627/webfiles/Astar.pdf) +is always a good choice to understand the real basics of the algorithm so that +you can implement it yourself. Or at least so you understand what's happening +before using whatever package in your programming language of choice. + +The pro's of this technique is that it's a very well documented approach. You +can adjust the density of the map very easily. + +So easily, in fact, that you can ramp up the density to the point that all of +the rooms overlap. The iterate to remove random sections of obstacles (walls) +that are inside the room. That will allow you to generate LARGE rooms where +everything is accessible. + +## Drunk Walking +The Drunkards Walk is a very simple algorithm and one that I stumbled upon +without really knowing about it. The idea is simple and is based on these requirements: + +1. You want to generate organic looking maps +2. You want to ensure that all sections of the map are reachable + +The organic maps requirement is probably the most interesting one to me. The +ability to random generate maps that don't look like a bunch of pre-defined +shapes. You could, technically, achieve that same look a myriad of ways, but +this seems the easiest. + +The method is as follows: +1. Create a "walker" on your map of some size (maybe 4 tiles? maybe 9? whatever + you feel like) +2. Start them on one side of the map, with their edges being walls, and their + interiors being walkable floors. +3. Make them march to the opposite side, adding some jitter along the other + axis. + +The size of the "walker" dictates the minimum width of the space you're +generating. If you want something to feel more open, make it larger. But if +you're making caves or something, just make them smaller. + +The "drunken walk" step sounds confusing, but it's pretty straight-forward. If, +for example, we start the walker on the west side of the map, they will be +walking to the east. Every step they take to the east should be coupled with +them randomly shifting north/south by a MAX of the size of the walker. + +That's it. + +When you're done, you have a single corridor. To build a map, add more walkers +all moving along the same plane (west->east for example), and then add one or +two walkers moving from the perpendiclar plane (north->south in this case). This +ensures that all corridors will be connected, and gives you really neat looking +maps. To me, they work wonderfully for caves/pathways. + + +But, by playing with the size of the walker you can change the entire look of +the map. Really wide players give you huge open spaces! + +the only thing this DOESN'T do, is actual square looking rooms like if you were +in a real dungeon.. diff --git a/content/posts/devlog/sketchy-heroes/1.md b/content/posts/devlog/sketchy-heroes/1.md new file mode 100644 index 0000000..e7f7d9c --- /dev/null +++ b/content/posts/devlog/sketchy-heroes/1.md @@ -0,0 +1,9 @@ +--- +title: "DEVLOG: Infinite Clicker, with a story" +date: 2020-06-07T12:09:04-04:00 +draft: true +tags: ["devlog", "sketchy-heroes", "devlog-sketchy-heroes"] +--- + +## Introduction +I've been working on Sketchy Heroes for a few years now \ No newline at end of file diff --git a/content/posts/hugo-github.md b/content/posts/hugo-github.md new file mode 100644 index 0000000..4241bd9 --- /dev/null +++ b/content/posts/hugo-github.md @@ -0,0 +1,188 @@ +--- +title: "Moving to Hugo and GitHub Pages" +Description: "Moving to Hugo" +date: 2020-06-03T14:00:00-04:00 +draft: false +tags: ["general", "hugo", "github"] +--- + +## Goal + +I've been running my blog over on Ghost[^1] for a few years now. I really don't have a lot of issues with it, except for the fact that I have to manage the server itself. I've been running a small Digital Ocean VPS for a number of years where I host my blog. Ghost itself goes through a lot of updates and keeping the application up to date was starting to become a hassle. + +I was keen to move to a solution where I could + +- Write my posts in markdown +- Not have to worry about hosting/management + +After looking at a few different solutions I ended up settling on a static site that was hosted through GitHub. The benefits of this was that + +- I could have all my content stored on GitHub. +- I could utilize GitHub pages to serve the site with a custom domain name (with SSL) +- I wouldn't need to keep everything up to date +- I could re-purpose my VPS for other things + + + +Of course, not all static sites are created the same. I specifically settled on Hugo to power my static site. + +## Hugo +Unlike more traditional blogging software (WordPress, Ghost, etc.) which saves your posts in a database, Hugo[^2] generates a bunch of static files (HTML) for each post. By doing this you're still able to have the more complex features (tagging, drafts, pagination, themeing, etc.) but because Hugo pre-processes everything, you're just left with a bunch of HTML files that represent your site. Once you're happy, you can just sync the generated files with your server. In my case, I'm simply able to `git add` and `git push` my content to GitHub. + +### Dynamic Blogging Platforms +Lets look at Wordpress to contrast Hugo. WordPress is the most used blogging software in the world and has the following requirements: +- PHP +- MySQL + +The implicit requirement is also a server that supports these two. That means you are either relying on a 3rd party host that manages the server and just exposes the Wordpress interface... or you are managing that server yourself. + +Most blogging systems work this way - Some language requirement, and some database system for storing the data you create. + +However, there's lots of additional caveats that you aren't normally aware of, that tend to bite you later: +- You need to run a web server, either Apache or Nginx +- You need to keep the server itself up to date (security patches) +- You need to keep Apache|Nginx/PHP/MySQL up to date (security patches) +- You need to manage database backups (what happens if your server crashes) +- You need to keep WordPress up to date. + +That's a heck of a lot of stuff for something that's supposed to be easy. And I just picked WordPress because it's popular. Almost every blogging system is the same way. + +Except for static site generators. + +### Static Site Generators +Static Site Generators are a different way to approach blogging that merges more recent tooling with traditional delivery methods. That's just a fancy way of saying Static Site Generators give you some tooling to generate a bunch of HTML documents that represent your site. + +With Hugo, I install hugo locally.. write some markdown for my posts, and then use Hugo to generate the HTML for my site. With this, we bring our "management" layer down to: +- Hugo +- Web server (nginx/apache) +- The hosting server + +Hugo runs locally, so the surface of attack is pretty minimal. There's nothing really wrong with running an outdated version of Hugo except you won't get the most recent features/bug fixes. But there's no security implications of doing so. + +Since the output from Static Site Generators is just .. static content it can be hosted anywhere. You can use a hosting provider, a VPS, S3+CloudFront, or.. GitHub Pages! + +## GitHub Pages +GitHub pages is a feature of GitHub that is available to all accounts, regardless of subscription. GitHub pages allows you to serve static content from any repository you'd like. They have some rules around how you need to organize your code and how to configure your site (project vs. main) but it's all relatively straight forward. + +I haven't really hosted much on GitHub pages, but it's very easy - They also have a great walkthrough page[^3] that shows you how to configure the kind of Static Site you want to host. + + + +## Project Configuration + +I'm not going to go into too much detail, because both Hugo and GitHub have very good introductions, but this should be enough to get a site running. + + + +### Installing Hugo + +Installing Hugo can be done from a terminal in your chosen operating system. There are alternate installation instructions available if you don't have brew installed or if you don't have a mac[^4]. + +```bash +brew install hugo +``` + + + +### Setup Hugo + +Open up your terminal, and navigate to the place you want to store your website. Then you can run the following command: + +```bash +hugo new site mysite +``` + +This creates a new folder called `mysite` that contains the raw files for your static site. At this point you don't have anything generated just the files that will eventually be compiled into your static site. + +You can install a theme by doing the following: + +```bash +git init +git submodule add https://github.com/budparr/gohugo-theme-ananke.git themes/ananke +``` + +You can actually choose whatever theme you would like from https://themes.gohugo.io/ [^5]and just replace the `git submodule` line with the instructions from your theme. + + + +Line 1 creates a git repository in the `mysite` directory. We want this because themes in Hugo are installed via `git submodule` which clones a particular repository into the current one. It also allows you to save the raw site (before static generation) to git! + + + +Now it's time to head over to your `config.toml` file and set up the defaults for your website. My config file looks like this. You only really need the configurations on the first 9 lines. The rest are just further configurations[^6] that I've made. + +```toml +baseURL = "https://xangelo.ca" +theme = "plain" +title = "Xangelo.ca" +author = "Angelo R" +copyright = "Copyright © 2011 - 2020" +paginate = 15 +languageCode = "en-us" +enableInlineShortcodes = true +footnoteReturnLinkContents = "^" + +[params] +subtitle = "Technical musings and other tidbits" + +[markup] +[markup.highlight] +lineNos = true +lineNumbersInTable = true +style = "vs" +tabWidth = 2 +[markup.tableOfContents] +endLevel = 3 +ordered = true +startLevel = 2 +``` + + + + + +### Create and test! + +Hugo ships with a built in server that allows you to preview what your site will end up looking like, you can start it up with: + +```bash +hugo server -w +``` + +This creates the server and the `-w` flag sets it to "watch". Any changes that are made will automatically reload the server and also reload the site. You can visit this site by navigating to `https://localhost:1313` in your browser. + +You can create a new post by using `hugo new posts/welcome.md`. This creates a new Markdown file in the `posts/` directory. + +You can go ahead and edit that file - saving it will cause Hugo to live reload the website. + + + +### Publish your site! + +Once you're happy with your stuff, you can turn off the live-reloading server and run the `hugo` command. This parses all your information and generates the static files for your website. It will then put all this content in the `public/` directory. If you followed the instructions from earlier around setting up GitHub Pages, you can `cd` into the `public/` directory and set it up as another git repository. + +then running `git push `will publish your static files to whatever GitHub repository you configured to host the site. + + + +## Wrapping Up + +I haven't really dug too much into setting up GitHub pages because it's mostly clicking around the interface and the instructions for that are kept up to date [^3]. I highly recommend GitHub pages because of the ease of setting up + +- Custom domain names (if you have your own domain it's trivial to point it to your GitHub pages site) +- Custom domain name SSL certificafte. Most places only allow you custom SSL certs if you use a subdomain, but GitHub lets you use a custom domain name. + + + +I also highly suggest you spend some time going through the themes[^5] on Hugo to find one that you really like. There are so many and it's so easy to make new themes that you'll definitely find one you like. + + + +## Footnotes + +[^1]: Ghost, a node.js based blogging engine: https://ghost.org/ +[^2]: Hugo, static site generatror: https://gohugo.io +[^3]: GitHub Pages setup: https://pages.github.com/ +[^4]: Hugo installation: https://gohugo.io/getting-started/installing +[^5]: Hugo themes: https://themes.gohugo.io/ +[^6]: Hugo configuration options: https://gohugo.io/getting-started/configuration-markup \ No newline at end of file