fixed layout
This commit is contained in:
parent
1302098199
commit
88ded772fd
12 changed files with 263 additions and 151 deletions
|
|
@ -10,9 +10,9 @@ title: runtimefee.lol - Homepage
|
|||
<link rel="stylesheet" href="/css/bundle.css" />
|
||||
<title>{{ title }}</title>
|
||||
</head>
|
||||
<body>
|
||||
<body class="home">
|
||||
{% include "_header.njk" %}
|
||||
<main>{{ content | safe }}</main>
|
||||
<main class="margin-auto padding-small">{{ content | safe }}</main>
|
||||
{% include "_footer.njk" %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -10,12 +10,18 @@ title: runtimefee.lol
|
|||
<link rel="stylesheet" href="/css/bundle.css" />
|
||||
<title>runtimefee.lol - {{ title }}</title>
|
||||
</head>
|
||||
<body>
|
||||
<body class="post">
|
||||
{% include "_header.njk" %}
|
||||
<div id="post-info" class="padding-small margin-auto">
|
||||
<nav><a href="/">back</a></nav>
|
||||
<aside>Tags: {{ tags }}</aside>
|
||||
<h1>{{ title }}</h1>
|
||||
<main>{{ content | safe }}</main>
|
||||
<span
|
||||
><i class="ti ti-clock ti-font-size margin-right-small"></i>{{ page.date
|
||||
| date }}</span
|
||||
>
|
||||
<aside>Tags:{{ tags | listTags | safe }}</aside>
|
||||
</div>
|
||||
<main class="padding-small margin-auto">{{ content | safe }}</main>
|
||||
{% include "_footer.njk" %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
export default {
|
||||
tags: ["posts"],
|
||||
tags: ["Posts"],
|
||||
type: "recommendation",
|
||||
title: "UNTITLED",
|
||||
layout: "layouts/post.njk",
|
||||
|
|
|
|||
|
|
@ -3,14 +3,12 @@ title: Recommended Godot Editor Settings
|
|||
tags: ["Godot", "IDE", "Game Engine"]
|
||||
---
|
||||
|
||||
The Editor defaults are good, but it can be better.
|
||||
|
||||
<!-- excerpt -->
|
||||
|
||||
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.
|
||||
|
||||
<!-- excerpt -->
|
||||
|
||||
## 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.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ layout: layouts/home.njk
|
|||
permalink: /index.html
|
||||
---
|
||||
|
||||
<div class="margin-small">
|
||||
<div>
|
||||
<h1>Welcome!</h1>
|
||||
<p>
|
||||
This blog is dedicated to game development. You can find hints, tutorials
|
||||
|
|
|
|||
|
|
@ -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 += `<span class='tag'>${tagsList[i]}</span>`;
|
||||
}
|
||||
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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
.margin-small {
|
||||
margin: 12px;
|
||||
}
|
||||
41
public/css/post.css
Normal file
41
public/css/post.css
Normal file
|
|
@ -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;
|
||||
}
|
||||
23
public/css/util.css
Normal file
23
public/css/util.css
Normal file
|
|
@ -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;
|
||||
}
|
||||
111
scripts/thumbnails.js
Normal file
111
scripts/thumbnails.js
Normal file
|
|
@ -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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue