diff --git a/_includes/layouts/home.njk b/_includes/layouts/home.njk index e83483d..4a3a107 100644 --- a/_includes/layouts/home.njk +++ b/_includes/layouts/home.njk @@ -10,9 +10,9 @@ title: runtimefee.lol - Homepage {{ title }} - + {% include "_header.njk" %} -
{{ content | safe }}
+
{{ content | safe }}
{% include "_footer.njk" %} diff --git a/_includes/layouts/post.njk b/_includes/layouts/post.njk index c1a4fa2..55c2678 100644 --- a/_includes/layouts/post.njk +++ b/_includes/layouts/post.njk @@ -10,12 +10,18 @@ title: runtimefee.lol runtimefee.lol - {{ title }} - + {% include "_header.njk" %} - - -

{{ title }}

-
{{ content | safe }}
+
+ +

{{ title }}

+ {{ page.date + | date }} + +
+
{{ content | safe }}
{% include "_footer.njk" %} diff --git a/content/blog/blog.11tydata.js b/content/blog/blog.11tydata.js index a7128c9..806a9e5 100644 --- a/content/blog/blog.11tydata.js +++ b/content/blog/blog.11tydata.js @@ -1,5 +1,5 @@ export default { - tags: ["posts"], + tags: ["Posts"], type: "recommendation", title: "UNTITLED", layout: "layouts/post.njk", diff --git a/content/blog/recommended-godot-editor-settings.md b/content/blog/recommended-godot-editor-settings.md index 2341de3..447e8e0 100644 --- a/content/blog/recommended-godot-editor-settings.md +++ b/content/blog/recommended-godot-editor-settings.md @@ -3,14 +3,12 @@ title: Recommended Godot Editor Settings tags: ["Godot", "IDE", "Game Engine"] --- -The Editor defaults are good, but it can be better. - - - The default Godot Editor has sensible defaults, but it isn't quite optimized for me. Over the years working with the engine, I found various editor tweaks that make using the engine a little bit easier. I will go through most of the editor settings and explain which settings I changed, what they are doing and how it makes working with Godot a bit easier. + + ## Accessing the Editor Settings Let's start by changing the editor settings for the Engine. This will affect all projects opened with the Engine, which can or can not be what you want. So keep that in mind when changing a settings here. diff --git a/content/index.njk b/content/index.njk index e60b803..dd21e5d 100644 --- a/content/index.njk +++ b/content/index.njk @@ -3,7 +3,7 @@ layout: layouts/home.njk permalink: /index.html --- -
+

Welcome!

This blog is dedicated to game development. You can find hints, tutorials diff --git a/eleventy.config.js b/eleventy.config.js index 4fde384..9b91bbf 100644 --- a/eleventy.config.js +++ b/eleventy.config.js @@ -1,9 +1,4 @@ -import { createNoise2D } from "simplex-noise"; -import { createCanvas, ImageData } from "canvas"; -import alea from "alea"; - -const SEED = "runtimefee.lol"; -var log_once = false; +import { generateThumbnail } from "./scripts/thumbnails.js"; /** @param {import("@11ty/eleventy").UserConfig} eleventyConfig */ export default function (eleventyConfig) { @@ -28,135 +23,27 @@ export default function (eleventyConfig) { }).format(dateObj); }); + eleventyConfig.addFilter("listTags", (tagsList) => { + let listHTML = ""; + for (let i in tagsList) { + listHTML += `${tagsList[i]}`; + } + return listHTML; + }); + eleventyConfig.addFilter("capitalize", function (value) { return value.toUpperCase(); }); // generate a nice preview image for articles that don't have one eleventyConfig.addShortcode("generateThumbnail", function (hash) { - return getThumbnailImage(hash); + return generateThumbnail(hash); }); // Collections eleventyConfig.addCollection("posts", (collectionApi) => { - return collectionApi.getFilteredByTag("posts"); + return collectionApi.getFilteredByTag("Posts"); }); eleventyConfig.addPassthroughCopy({ "public/": "/" }); } - -function getRandomFloat(min, max) { - return parseFloat((Math.random() * (max - min) + min).toFixed(2)); -} - -function getRandomPaletteValues() { - // Generate random arrays for a, b, c, and d - const a = [ - getRandomFloat(0.5, 1.0), - getRandomFloat(0.5, 1.0), - getRandomFloat(0.5, 1.0), - ]; - const b = [ - getRandomFloat(0.2, 0.8), - getRandomFloat(0.2, 0.8), - getRandomFloat(0.2, 0.8), - ]; - const c = [ - getRandomFloat(0.0, 2.0), - getRandomFloat(0.0, 2.0), - getRandomFloat(0.0, 2.0), - ]; - const d = [ - getRandomFloat(0.0, 1.0), - getRandomFloat(0.0, 1.0), - getRandomFloat(0.0, 1.0), - ]; - - if (log_once == false) { - log_once = true; - //console.log({ a, b, c, d }); - } - - return { a, b, c, d }; -} - -function getPalette(t, a, b, c, d) { - const result = []; - - for (let i = 0; i < 3; i++) { - // Apply the formula element-wise to each component of the vectors - result[i] = - 255 * (a[i] + b[i] * Math.cos(2.0 * Math.PI * (c[i] * t + d[i]))); - } - - if (log_once == false) { - log_once = true; - //console.log(result); - } - - return result; -} - -function getThumbnailImage(hash) { - var width = 800; - var height = 300; - var rng = alea(SEED + hash); - - var noise2D = createNoise2D(rng); - - const canvas = createCanvas(width, height); - const ctx = canvas.getContext("2d"); - const imageData = ctx.createImageData(width, height); - const paletteSettings = getRandomPaletteValues(); - - var dist = 0; - for (let x = 0; x < width; x++) { - for (let y = 0; y < height; y++) { - const value = noise2D(x / 50, y / 50); - var threshold = Math.floor((value + 1) * 128); - threshold = value > 0.2 ? 128 : 0; - - const index = (x + y * width) * 4; - - const dx = x - width / 2; - const dy = y - height / 2; - const distance = Math.sqrt(dx * dx + dy * dy); // Euclidean distance - - // Normalize the distance to be between 0 and 1 (for a radial gradient effect) - const maxDistance = Math.sqrt( - ((width / 2) * width) / 2 + ((height / 2) * height) / 2 - ); - - const t = (distance / maxDistance) * 3.0 * Math.sin(dist); - dist += 0.00001; - - const a = [0.5, 0.5, 0.5]; - const b = [0.5, 0.5, 0.5]; - const c = [1.0, 1.0, 1.0]; - const d = [0.0, 0.1, 0.2]; - - const palette = getPalette( - t, - paletteSettings.a, - paletteSettings.b, - paletteSettings.c, - paletteSettings.d - ); - - if (threshold == 0) { - imageData.data[index] = palette[0] * 0.05; // Red - imageData.data[index + 1] = palette[1] * 0.09; // Green - imageData.data[index + 2] = palette[2] * 0.3; // Blue - imageData.data[index + 3] = 255; // Alpha - } else { - imageData.data[index] = palette[0]; // Red - imageData.data[index + 1] = palette[1]; // Green - imageData.data[index + 2] = palette[2]; // Blue - imageData.data[index + 3] = 255; // Alpha - } - } - } - - ctx.putImageData(imageData, 0, 0); - return canvas.toDataURL("image/jpeg"); -} diff --git a/public/css/bundle.css b/public/css/bundle.css index 095f804..3e5799c 100644 --- a/public/css/bundle.css +++ b/public/css/bundle.css @@ -1,30 +1,30 @@ /* See https://codeberg.org/lucajunge/css-reset for details */ @import url(./reset.css); -/* Custom fonts */ @import url(./fonts.css); -@import url(./margins.css); - @import url(./icons.css); +@import url(./util.css); + +@import url(./post.css); + :root { --font-family: "Source Sans 3", -apple-system, system-ui, sans-serif; --font-family-monospace: Consolas, Menlo, Monaco, Andale Mono WT, Andale Mono, Lucida Console, Lucida Sans Typewriter, DejaVu Sans Mono, Bitstream Vera Sans Mono, Liberation Mono, Nimbus Mono L, Courier New, Courier, monospace; -} - -:root { - --background-color: #121212; - --background-color-dark: #080808; + --background-color: #242424; + --background-color-strong: #080808; + --text-color: #f3f3f3; --accent-color: #daa520; } html, body { font-family: var(--font-family); + color: var(--text-color); background-color: var(--background-color); } @@ -40,6 +40,18 @@ h6 { color: var(--accent-color); } +h1 { + font-size: 1.6em; +} + +h2, +h3, +h4, +h5, +h6 { + margin-block: 0.5em 0.7em; +} + .header { padding: 1rem; display: flex; @@ -61,9 +73,18 @@ h6 { } .footer div { - background-color: #080808; + background-color: var(--background-color-strong); border-radius: 4px; - padding: 2px 4px 1px 2px; + padding: 2px 4px 1px 4px; +} + +.tag { + padding: 3px 6px; + background-color: var(--background-color-strong); + margin-left: 4px; + display: inline-block; + border-radius: 4px; + font-size: 0.8em; } .recent-posts-container { @@ -120,5 +141,24 @@ h6 { font-weight: bold; border-radius: 4px; padding: 2px 7px 5px 7px; - background-color: var(--background-color-dark); + background-color: var(--background-color-strong); +} + +/* Light theme */ +@media (prefers-color-scheme: light) { + :root { + --text-color: #242424; + --background-color: #f3f3f3; + --background-color-strong: #ababab; + } +} + +.home main { + display: flex; + flex-direction: column; + max-width: 786px; +} + +.home main * { + max-width: 786px; } diff --git a/public/css/icons.css b/public/css/icons.css index 438a6ba..d435ef5 100644 --- a/public/css/icons.css +++ b/public/css/icons.css @@ -5,6 +5,15 @@ font-size: 24px; } +.ti-font-size { + font-size: 1em; +} + +.ti-xsmall, +.ti-xtra-small { + font-size: 14px; +} + .ti.small { font-size: 16px; } diff --git a/public/css/margins.css b/public/css/margins.css deleted file mode 100644 index f27ae96..0000000 --- a/public/css/margins.css +++ /dev/null @@ -1,3 +0,0 @@ -.margin-small { - margin: 12px; -} diff --git a/public/css/post.css b/public/css/post.css new file mode 100644 index 0000000..7edb1c1 --- /dev/null +++ b/public/css/post.css @@ -0,0 +1,41 @@ +.post main { + display: flex; + flex-direction: column; + max-width: 786px; +} + +.post main * { + max-width: 786px; +} + +.post nav a { + background-color: var(--background-color-strong); + border-radius: 8px; + padding: 8px 12px; + display: inline-block; + text-decoration: none; + color: inherit; + font-weight: bold; + margin-block: 0px 8px; +} + +.post #post-info { + display: flex; + max-width: 786px; + flex-direction: column; + justify-content: center; + padding-block-end: 0px; +} + +.post h2 { + font-size: 1.6em; + font-weight: bold; +} + +.post p ~ h2 { + margin-block: 2em 0.5em; +} + +.post p ~ h3 { + margin-block: 1.5em 0.5em; +} diff --git a/public/css/util.css b/public/css/util.css new file mode 100644 index 0000000..8236ed1 --- /dev/null +++ b/public/css/util.css @@ -0,0 +1,23 @@ +.center { + justify-self: center; +} + +.margin-small { + margin: 12px; +} + +.margin-right-small { + margin-right: 4px; +} + +.margin-left-small { + margin-left: 4px; +} + +.padding-small { + padding: 12px; +} + +.margin-auto { + margin: 0 auto; +} diff --git a/scripts/thumbnails.js b/scripts/thumbnails.js new file mode 100644 index 0000000..700c452 --- /dev/null +++ b/scripts/thumbnails.js @@ -0,0 +1,111 @@ +import { createNoise2D } from "simplex-noise"; +import { createCanvas, ImageData } from "canvas"; +import alea from "alea"; + +// The hash is the name of the article e.g. "Recommended Godot Editor Settings" +export function generateThumbnail(hash) { + var rng = alea(hash); + console.log(`Generating thumbnail for \"${hash}\" with ${rng()}`); + var width = 800; + var height = 300; + + var noise2D = createNoise2D(rng); + + const canvas = createCanvas(width, height); + const ctx = canvas.getContext("2d"); + const imageData = ctx.createImageData(width, height); + const paletteSettings = getRandomPaletteValues(rng()); + + var dist = 0; + for (let x = 0; x < width; x++) { + for (let y = 0; y < height; y++) { + const value = noise2D(x / 50, y / 50); + var threshold = Math.floor((value + 1) * 128); + threshold = value > 0.2 ? 128 : 0; + + const index = (x + y * width) * 4; + + const dx = x - width / 2; + const dy = y - height / 2; + const distance = Math.sqrt(dx * dx + dy * dy); // Euclidean distance + + // Normalize the distance to be between 0 and 1 (for a radial gradient effect) + const maxDistance = Math.sqrt( + ((width / 2) * width) / 2 + ((height / 2) * height) / 2 + ); + + const t = (distance / maxDistance) * 3.0 * Math.sin(dist); + dist += 0.00001; + + const a = [0.5, 0.5, 0.5]; + const b = [0.5, 0.5, 0.5]; + const c = [1.0, 1.0, 1.0]; + const d = [0.0, 0.1, 0.2]; + + const palette = getPalette( + t, + paletteSettings.a, + paletteSettings.b, + paletteSettings.c, + paletteSettings.d + ); + + if (threshold == 0) { + imageData.data[index] = palette[0] * 0.05; // Red + imageData.data[index + 1] = palette[1] * 0.09; // Green + imageData.data[index + 2] = palette[2] * 0.3; // Blue + imageData.data[index + 3] = 255; // Alpha + } else { + imageData.data[index] = palette[0]; // Red + imageData.data[index + 1] = palette[1]; // Green + imageData.data[index + 2] = palette[2]; // Blue + imageData.data[index + 3] = 255; // Alpha + } + } + } + + ctx.putImageData(imageData, 0, 0); + return canvas.toDataURL("image/jpeg"); +} + +function getRandomFloat(seed, min, max) { + return parseFloat((seed * (max - min) + min).toFixed(2)); +} + +function getRandomPaletteValues(seed) { + // Generate random arrays for a, b, c, and d + const a = [ + getRandomFloat(seed, 0.5, 1.0), + getRandomFloat(seed, 0.5, 1.0), + getRandomFloat(seed, 0.5, 1.0), + ]; + const b = [ + getRandomFloat(seed, 0.2, 0.8), + getRandomFloat(seed, 0.2, 0.8), + getRandomFloat(seed, 0.2, 0.8), + ]; + const c = [ + getRandomFloat(seed, 0.0, 2.0), + getRandomFloat(seed, 0.0, 2.0), + getRandomFloat(seed, 0.0, 2.0), + ]; + const d = [ + getRandomFloat(seed, 0.0, 1.0), + getRandomFloat(seed, 0.0, 1.0), + getRandomFloat(seed, 0.0, 1.0), + ]; + + return { a, b, c, d }; +} + +function getPalette(t, a, b, c, d) { + const result = []; + + for (let i = 0; i < 3; i++) { + // Apply the formula element-wise to each component of the vectors + result[i] = + 255 * (a[i] + b[i] * Math.cos(2.0 * Math.PI * (c[i] * t + d[i]))); + } + + return result; +}