add Code section
add only journal post for 2025 update copyrights to 2026 add licenses to BPS remove unused files update to 0.14.2
This commit is contained in:
8
.editorconfig
Normal file
8
.editorconfig
Normal file
@@ -0,0 +1,8 @@
|
||||
# EditorConfig is awesome: https://editorconfig.org
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -17,4 +17,4 @@ TODO.md
|
||||
|
||||
# old directories kept locally
|
||||
stash/
|
||||
trash/
|
||||
trash/
|
||||
|
||||
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"[json5]": {
|
||||
"editor.insertSpaces": true,
|
||||
"editor.tabSize": 4
|
||||
}
|
||||
}
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "iew-site",
|
||||
"version": "0.14.0",
|
||||
"version": "0.14.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "iew-site",
|
||||
"version": "0.14.0",
|
||||
"version": "0.14.2",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"web-weevr": "git+ssh://git@git.itsericwoodward.com:eric/web-weevr.git"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "iew-site",
|
||||
"version": "0.14.1",
|
||||
"version": "0.14.2",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {},
|
||||
|
||||
@@ -1,60 +1,59 @@
|
||||
{
|
||||
site: {
|
||||
title: "It's Eric Woodward (dotcom)",
|
||||
author: {
|
||||
name: "Eric Woodward",
|
||||
email: "hey@itsericwoodward.com", // not used
|
||||
photo: "/images/eric-8bit.gif",
|
||||
site: "https://itsericwoodward.com",
|
||||
geo: {
|
||||
position: "35.4, -80.5",
|
||||
placename: "Concord",
|
||||
region: "US-NC",
|
||||
},
|
||||
},
|
||||
site: {
|
||||
title: "It's Eric Woodward (dotcom)",
|
||||
author: {
|
||||
name: "Eric Woodward",
|
||||
email: "hey@itsericwoodward.com", // not used
|
||||
photo: "/images/eric-8bit.gif",
|
||||
site: "https://itsericwoodward.com",
|
||||
geo: {
|
||||
position: "35.4, -80.5",
|
||||
placename: "Concord",
|
||||
region: "US-NC",
|
||||
},
|
||||
},
|
||||
|
||||
base_uri: "",
|
||||
// csp: "default-src 'self' data: https://v8.js-dos.com 'unsafe-inline'; img-src 'self' https://*; media-src 'self' https://* data:; script-src 'self' https://v8.js-dos.com 'wasm-eval' 'unsafe-eval' 'unsafe-inline'; style-src 'self' https://v8.js-dos.com 'unsafe-inline'; worker-src 'self' blob:;",
|
||||
csp: "default-src 'self' data: ; img-src 'self' https://*; media-src 'self' https://* data:;",
|
||||
robots: "index,follow",
|
||||
language: "en-us",
|
||||
copyright: "Copyright 2014-2025 Eric Woodward, licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.",
|
||||
basePath: "",
|
||||
uri: "https://www.itsericwoodward.com",
|
||||
comment_insert: "\n\
|
||||
___________________________.\n\
|
||||
|;;| |;;||\n\
|
||||
|[]|---------------------|[]||\n\
|
||||
|;;| |;;||\n\
|
||||
|;;| |;;||\n\
|
||||
|;;| ItsEricWoodward.com |;;||\n\
|
||||
|;;| |;;||\n\
|
||||
|;;| |;;||\n\
|
||||
|;;| |;;||\n\
|
||||
|;;|_____________________|;;||\n\
|
||||
|;;;;;;;;;;;;;;;;;;;;;;;;;;;||\n\
|
||||
|;;;;;;_______________ ;;;;;||\n\
|
||||
|;;;;;| ___ |;;;;;||\n\
|
||||
|;;;;;| |;;;| |;;;;;||\n\
|
||||
|;;;;;| |;;;| |;;;;;||\n\
|
||||
|;;;;;| |;;;| |;;;;;||\n\
|
||||
|;;;;;| |;;;| |;;;;;||\n\
|
||||
|;;;;;| |___| |;;;;;||\n\
|
||||
\\_____|_______________|_____||\n\
|
||||
~~~~~^^^^^^^^^^^^^^^^^~~~~~~\n\
|
||||
",
|
||||
},
|
||||
build: {
|
||||
journalsPerPage: 5,
|
||||
srcPath: "src",
|
||||
outputPath: "out",
|
||||
publishPath: "public",
|
||||
},
|
||||
serve: {
|
||||
authTypeUI: "basic",
|
||||
handleStatic: true,
|
||||
port: 4997,
|
||||
shortCodeLink: "/q/",
|
||||
static404: "./public/errors/404.html",
|
||||
},
|
||||
base_uri: "",
|
||||
csp: "default-src 'self' data: ; img-src 'self' https://*; media-src 'self' https://* data:; worker-src 'self' blob:;",
|
||||
robots: "index,follow",
|
||||
language: "en-us",
|
||||
copyright: "Copyright 2014-2026 Eric Woodward, licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.",
|
||||
basePath: "",
|
||||
uri: "https://www.itsericwoodward.com",
|
||||
comment_insert: "\n\
|
||||
___________________________.\n\
|
||||
|;;| |;;||\n\
|
||||
|[]|---------------------|[]||\n\
|
||||
|;;| |;;||\n\
|
||||
|;;| |;;||\n\
|
||||
|;;| ItsEricWoodward.com |;;||\n\
|
||||
|;;| |;;||\n\
|
||||
|;;| |;;||\n\
|
||||
|;;| |;;||\n\
|
||||
|;;|_____________________|;;||\n\
|
||||
|;;;;;;;;;;;;;;;;;;;;;;;;;;;||\n\
|
||||
|;;;;;;_______________ ;;;;;||\n\
|
||||
|;;;;;| ___ |;;;;;||\n\
|
||||
|;;;;;| |;;;| |;;;;;||\n\
|
||||
|;;;;;| |;;;| |;;;;;||\n\
|
||||
|;;;;;| |;;;| |;;;;;||\n\
|
||||
|;;;;;| |;;;| |;;;;;||\n\
|
||||
|;;;;;| |___| |;;;;;||\n\
|
||||
\\_____|_______________|_____||\n\
|
||||
~~~~~^^^^^^^^^^^^^^^^^~~~~~~\n\
|
||||
",
|
||||
},
|
||||
build: {
|
||||
journalsPerPage: 5,
|
||||
srcPath: "src",
|
||||
outputPath: "out",
|
||||
publishPath: "public",
|
||||
},
|
||||
serve: {
|
||||
authTypeUI: "basic",
|
||||
handleStatic: true,
|
||||
port: 4997,
|
||||
shortCodeLink: "/q/",
|
||||
static404: "./public/errors/404.html",
|
||||
},
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,45 +1,55 @@
|
||||
// @license magnet:?xt=urn:btih:90dc5c0be029de84e523b9b3922520e79e0e6f08&dn=cc0.txt CC0-1.0
|
||||
/****************************************************************************
|
||||
* Byte Beasties Escape!
|
||||
*
|
||||
* Copyright 2023-2026 Eric Woodward
|
||||
* Source released under CC0 Public Domain License v1.0
|
||||
* https://www.planarvagabond.com/licenses/cc0/
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
****************************************************************************/
|
||||
export const createLightning = (canvas, enemy) => {
|
||||
const { y: size } = enemy;
|
||||
var center = { x: canvas.width / 2, y: canvas.height };
|
||||
var minSegmentHeight = 5;
|
||||
var roughness = 2;
|
||||
var maxDifference = size / 5;
|
||||
const { y: size } = enemy;
|
||||
var center = { x: canvas.width / 2, y: canvas.height };
|
||||
var minSegmentHeight = 5;
|
||||
var roughness = 2;
|
||||
var maxDifference = size / 5;
|
||||
|
||||
let lightning = [];
|
||||
let segmentHeight = size / 3;
|
||||
lightning.push({
|
||||
x: center.x,
|
||||
y: center.y + 200,
|
||||
});
|
||||
lightning.push({
|
||||
x: Math.random() * (canvas.width - 100) + 50,
|
||||
y: Math.abs((Math.random() - 0.9) * 100),
|
||||
});
|
||||
let currDiff = maxDifference;
|
||||
while (segmentHeight > minSegmentHeight) {
|
||||
const newSegments = [];
|
||||
for (var i = 0; i < lightning.length - 1; i++) {
|
||||
const start = lightning[i],
|
||||
end = lightning[i + 1],
|
||||
midX = (start.x + end.x) / 2,
|
||||
newX = midX + (Math.random() * 2 - 1) * currDiff;
|
||||
newSegments.push(start, { x: newX, y: (start.y + end.y) / 2 });
|
||||
}
|
||||
let lightning = [];
|
||||
let segmentHeight = size / 3;
|
||||
lightning.push({
|
||||
x: center.x,
|
||||
y: center.y + 200,
|
||||
});
|
||||
lightning.push({
|
||||
x: Math.random() * (canvas.width - 100) + 50,
|
||||
y: Math.abs((Math.random() - 0.9) * 100),
|
||||
});
|
||||
let currDiff = maxDifference;
|
||||
while (segmentHeight > minSegmentHeight) {
|
||||
const newSegments = [];
|
||||
for (var i = 0; i < lightning.length - 1; i++) {
|
||||
const start = lightning[i],
|
||||
end = lightning[i + 1],
|
||||
midX = (start.x + end.x) / 2,
|
||||
newX = midX + (Math.random() * 2 - 1) * currDiff;
|
||||
newSegments.push(start, { x: newX, y: (start.y + end.y) / 2 });
|
||||
}
|
||||
|
||||
newSegments.push(lightning.pop());
|
||||
lightning = newSegments;
|
||||
newSegments.push(lightning.pop());
|
||||
lightning = newSegments;
|
||||
|
||||
currDiff /= roughness;
|
||||
segmentHeight /= 2;
|
||||
}
|
||||
return lightning;
|
||||
currDiff /= roughness;
|
||||
segmentHeight /= 2;
|
||||
}
|
||||
return lightning;
|
||||
};
|
||||
|
||||
// Get the position of the mouse relative to the canvas
|
||||
export const getMousePos = (canvasDom, mouseEvent) => {
|
||||
var rect = canvasDom.getBoundingClientRect();
|
||||
return {
|
||||
x: mouseEvent.clientX - rect.left,
|
||||
y: mouseEvent.clientY - rect.top,
|
||||
};
|
||||
var rect = canvasDom.getBoundingClientRect();
|
||||
return {
|
||||
x: mouseEvent.clientX - rect.left,
|
||||
y: mouseEvent.clientY - rect.top,
|
||||
};
|
||||
};
|
||||
// @license-end
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// @license magnet:?xt=urn:btih:90dc5c0be029de84e523b9b3922520e79e0e6f08&dn=cc0.txt CC0-1.0
|
||||
/****************************************************************************
|
||||
* Planar Vagabond's Guide to the Multiverse (planarvagabond.com)
|
||||
* Byte Beasties Escape!
|
||||
*
|
||||
* Copyright 2023-2024 Eric Woodward
|
||||
* Copyright 2023-2026 Eric Woodward
|
||||
* Source released under CC0 Public Domain License v1.0
|
||||
* https://www.planarvagabond.com/licenses/cc0/
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
@@ -11,22 +11,22 @@
|
||||
import { startGame } from "./bbe.js";
|
||||
|
||||
export default (() => {
|
||||
// we load this library as a module to guarantee baseline ES6 functionality
|
||||
// we load this library as a module to guarantee baseline ES6 functionality
|
||||
|
||||
// Indicate JS is loaded
|
||||
document.documentElement.className =
|
||||
document.documentElement.className.replace("no-js", "js");
|
||||
// Indicate JS is loaded
|
||||
document.documentElement.className =
|
||||
document.documentElement.className.replace("no-js", "js");
|
||||
|
||||
setTimeout(() => {
|
||||
const canvas = document.createElement("canvas"),
|
||||
contentDiv = document.getElementById("game");
|
||||
setTimeout(() => {
|
||||
const canvas = document.createElement("canvas"),
|
||||
contentDiv = document.getElementById("game");
|
||||
|
||||
canvas.setAttribute("width", "375");
|
||||
canvas.setAttribute("height", "667");
|
||||
canvas.setAttribute("id", "game");
|
||||
contentDiv.appendChild(canvas);
|
||||
canvas.setAttribute("width", "375");
|
||||
canvas.setAttribute("height", "667");
|
||||
canvas.setAttribute("id", "game");
|
||||
contentDiv.appendChild(canvas);
|
||||
|
||||
startGame(canvas);
|
||||
}, 1);
|
||||
startGame(canvas);
|
||||
}, 1);
|
||||
})();
|
||||
// @license-end
|
||||
|
||||
@@ -1,150 +1,168 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!--
|
||||
<!--
|
||||
/****************************************************************************
|
||||
* BPS (Bill Paxton Soundboard)
|
||||
*
|
||||
* Copyright 2024 Eric Woodward
|
||||
* Copyright 2024-2026 Eric Woodward
|
||||
* Source released under CC0 Public Domain License v1.0
|
||||
* https://www.itsericwoodward.com/licenses/cc0/
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
****************************************************************************/
|
||||
-->
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>BPS (Bill Paxton Soundboard)</title>
|
||||
<link rel="stylesheet" href="styles/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="output"></div>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<title>BPS (Bill Paxton Soundboard)</title>
|
||||
<link rel="stylesheet" href="styles/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="output"></div>
|
||||
|
||||
<!--
|
||||
<!--
|
||||
`cat main.js | openssl dgst -sha256 -binary | openssl base64 -A`, then repeat for 384 and 512
|
||||
-->
|
||||
<script crossorigin="anonymous" integrity="sha256-YvGi/WY2dKJwaU3cCMLSkiJCnE2hFCiiUdRwqWTGvEE=
|
||||
<script
|
||||
crossorigin="anonymous"
|
||||
integrity="sha256-YvGi/WY2dKJwaU3cCMLSkiJCnE2hFCiiUdRwqWTGvEE=
|
||||
sha384-mtemuzaWEW/0HsyxJyDCaqMquUejVMwzs5VSj5KOr0jrg0+bG/aV2JGsvn/5AbRP
|
||||
sha512-z5iEy8ijJzKBzzzBZSdt1DFqwsHLRAV2fvGk4N7P0VikiXtRla258zX7YiSvSIwYskOnnPySzFLaDAdXWUkgNQ=="
|
||||
src="scripts/main.js" type="module" ></script>
|
||||
src="scripts/main.js"
|
||||
type="module"
|
||||
></script>
|
||||
|
||||
<noscript>
|
||||
<p>Sorry, but the Bill Paxton Soundboard requires JavaScript to work.</p>
|
||||
<p>Please enable it or try using a different browser.</p>
|
||||
</noscript>
|
||||
<noscript>
|
||||
<p>
|
||||
Sorry, but the Bill Paxton Soundboard requires JavaScript to
|
||||
work.
|
||||
</p>
|
||||
<p>Please enable it or try using a different browser.</p>
|
||||
</noscript>
|
||||
|
||||
<p class="center">
|
||||
<a class="downloadButton" href="bps.zip">Download ZIP</a>
|
||||
<a class="downloadButton" href="bps.tar.gz">Download TAR</a>
|
||||
</p>
|
||||
<p class="center">
|
||||
<a class="downloadButton" href="bps.zip">Download ZIP</a>
|
||||
<a class="downloadButton" href="bps.tar.gz">Download TAR</a>
|
||||
</p>
|
||||
|
||||
<hr />
|
||||
<hr />
|
||||
|
||||
<h2>What is This?</h2>
|
||||
<h2>What is This?</h2>
|
||||
|
||||
<p>
|
||||
This is the BPS (Bill Paxton Soundboard), my entry into the UI Developers Guild Coding Challenge for
|
||||
February 2024 at the company I work for.
|
||||
</p>
|
||||
<p>
|
||||
This is the BPS (Bill Paxton Soundboard), my entry into the UI
|
||||
Developers Guild Coding Challenge for February 2024 at the company I
|
||||
work for.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you want to know a bit more about how (and why) it was made, be sure to check
|
||||
out <a href="/journal/2024/02-10-webtoys-bps">the blog post I wrote about it</a> when it was released
|
||||
on 2024-02-10.
|
||||
</p>
|
||||
<p>
|
||||
If you want to know a bit more about how (and why) it was made, be
|
||||
sure to check out
|
||||
<a href="/journal/2024/02-10-webtoys-bps"
|
||||
>the blog post I wrote about it</a
|
||||
>
|
||||
when it was released on 2024-02-10.
|
||||
</p>
|
||||
|
||||
<h3>The Rules</h3>
|
||||
<h3>The Rules</h3>
|
||||
|
||||
<p>
|
||||
This particular challenge had 3 simple rules (copied verbatim below):
|
||||
</p>
|
||||
<p>
|
||||
This particular challenge had 3 simple rules (copied verbatim
|
||||
below):
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li><em>Play some kind of music / sound</em></li>
|
||||
<li><em>Be viewable</em></li>
|
||||
<li><em>Don't work over 4hrs!!!!</em></li>
|
||||
</ol>
|
||||
<ol>
|
||||
<li><em>Play some kind of music / sound</em></li>
|
||||
<li><em>Be viewable</em></li>
|
||||
<li><em>Don't work over 4hrs!!!!</em></li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
The BPS satisfies all 3 of the rules: it's an HTML5 / CSS / JS application that creates
|
||||
a series of virtual <code>audio</code> tags, and then loads a WAV or MP3 into each one before
|
||||
inserting them into the document. It then renders a series of clickable image-buttons
|
||||
(each one being an <code>img</code> tag, surrounded by a <code>figure</code> tag, and
|
||||
augmented by the text of a <code>figcaption</code> tag) and attaches a <code>play()</code>
|
||||
function to the click handlers for those <code>figure</code>s. Plus, I wrote it all in under 4 hours:
|
||||
</p>
|
||||
<p>
|
||||
The BPS satisfies all 3 of the rules: it's an HTML5 / CSS / JS
|
||||
application that creates a series of virtual
|
||||
<code>audio</code> tags, and then loads a WAV or MP3 into each one
|
||||
before inserting them into the document. It then renders a series of
|
||||
clickable image-buttons (each one being an <code>img</code> tag,
|
||||
surrounded by a <code>figure</code> tag, and augmented by the text
|
||||
of a <code>figcaption</code> tag) and attaches a
|
||||
<code>play()</code> function to the click handlers for those
|
||||
<code>figure</code>s. Plus, I wrote it all in under 4 hours:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
One hour thinking through the concept and writing the rough draft
|
||||
<a href="scripts/player.js"><code>player.js</code></a> and
|
||||
<a href="scripts/main.js"><code>main.js</code></a> modules;
|
||||
</li>
|
||||
<li>
|
||||
One hour to turn draft into an MVP, addressing
|
||||
<a href="styles/styles.css">layout</a> and audio issues;
|
||||
</li>
|
||||
<li>
|
||||
One hour to add images and expand the audio selection; and
|
||||
</li>
|
||||
<li>
|
||||
One final hour to add mobile support and some light documentation.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>How to Install Locally</h3>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
Download either the <a href="bps.zip">ZIP'd</a>
|
||||
or <a href="bps.tar.gz">TAR-balled</a> version.
|
||||
</li>
|
||||
<li>
|
||||
Decompress it:
|
||||
<ul>
|
||||
<li>For the ZIP: <code>unzip bps.zip</code></li>
|
||||
<li>For the TAR-ball: <code>tar -xvzf bps.tar.gz</code></li>
|
||||
<li>
|
||||
One hour thinking through the concept and writing the rough
|
||||
draft
|
||||
<a href="scripts/player.js"><code>player.js</code></a> and
|
||||
<a href="scripts/main.js"><code>main.js</code></a> modules;
|
||||
</li>
|
||||
<li>
|
||||
One hour to turn draft into an MVP, addressing
|
||||
<a href="styles/styles.css">layout</a> and audio issues;
|
||||
</li>
|
||||
<li>One hour to add images and expand the audio selection; and</li>
|
||||
<li>
|
||||
One final hour to add mobile support and some light
|
||||
documentation.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
Change to the new directory: <code>cd bps</code>
|
||||
</li>
|
||||
<li>
|
||||
Start an HTTP server: <code>npx http-server</code>
|
||||
</li>
|
||||
<li>
|
||||
Point your web browser to
|
||||
<a href="http://127.0.0.1:8080/">http://127.0.0.1:8080/</a>.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<h3>Copyright</h3>
|
||||
<h3>How to Install Locally</h3>
|
||||
|
||||
<ul>
|
||||
<li><em>True Lies</em> is copyright 1994 20th Century Fox.</li>
|
||||
<li><em>Aliens</em> is copyright 1986 Twentieth Century Fox.</li>
|
||||
<li><em>Weird Science</em> is copyright 1985 Universal Pictures (I think).</li>
|
||||
</ul>
|
||||
<ol>
|
||||
<li>
|
||||
Download either the <a href="bps.zip">ZIP'd</a> or
|
||||
<a href="bps.tar.gz">TAR-balled</a> version.
|
||||
</li>
|
||||
<li>
|
||||
Decompress it:
|
||||
<ul>
|
||||
<li>For the ZIP: <code>unzip bps.zip</code></li>
|
||||
<li>For the TAR-ball: <code>tar -xvzf bps.tar.gz</code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Change to the new directory: <code>cd bps</code></li>
|
||||
<li>Start an HTTP server: <code>npx http-server</code></li>
|
||||
<li>
|
||||
Point your web browser to
|
||||
<a href="http://127.0.0.1:8080/">http://127.0.0.1:8080/</a>.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
The images and sound clips used for the Bill Paxton Soundboard are copyright their
|
||||
respective owners, and used under the
|
||||
<a href="https://fairuse.stanford.edu/overview/fair-use/">fair use provision</a>
|
||||
of the <a href="https://constitution.congress.gov/constitution/">Constitution of the United
|
||||
States of America</a>.
|
||||
</p>
|
||||
<h3>Copyright</h3>
|
||||
|
||||
<p>
|
||||
All other content on this page (including scripts and text content) is released under a
|
||||
<a href="/licenses/cc0/">Creative Commons CC0 1.0 Universal</a>
|
||||
license.
|
||||
</p>
|
||||
<ul>
|
||||
<li><em>True Lies</em> is copyright 1994 20th Century Fox.</li>
|
||||
<li><em>Aliens</em> is copyright 1986 Twentieth Century Fox.</li>
|
||||
<li>
|
||||
<em>Weird Science</em> is copyright 1985 Universal Pictures (I
|
||||
think).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Share and enjoy!</p>
|
||||
<p>
|
||||
The images and sound clips used for the Bill Paxton Soundboard are
|
||||
copyright their respective owners, and used under the
|
||||
<a href="https://fairuse.stanford.edu/overview/fair-use/"
|
||||
>fair use provision</a
|
||||
>
|
||||
of the
|
||||
<a href="https://constitution.congress.gov/constitution/"
|
||||
>Constitution of the United States of America</a
|
||||
>.
|
||||
</p>
|
||||
|
||||
<p class="center">
|
||||
<a href="/web.html">More of Eric's Web Stuff</a>
|
||||
</p>
|
||||
<p>
|
||||
All other content on this page (including scripts and text content)
|
||||
is released under a
|
||||
<a href="/licenses/cc0/">Creative Commons CC0 1.0 Universal</a>
|
||||
license.
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<p>Share and enjoy!</p>
|
||||
|
||||
<p class="center">
|
||||
<a href="/web.html">More of Eric's Web Stuff</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/****************************************************************************
|
||||
* BPS (Bill Paxton Soundboard)
|
||||
*
|
||||
* Copyright 2024 Eric Woodward
|
||||
* Copyright 2024-2026 Eric Woodward
|
||||
* Source released under CC0 Public Domain License v1.0
|
||||
* https://www.itsericwoodward.com/licenses/cc0/
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
@@ -12,127 +12,127 @@ import { load, play } from "./player.js";
|
||||
import rootdir from "./rootdir.js";
|
||||
|
||||
export default (() => {
|
||||
// adapted from: https://cheatcode.co/tutorials/how-to-build-a-soundboard-with-javascript
|
||||
// adapted from: https://cheatcode.co/tutorials/how-to-build-a-soundboard-with-javascript
|
||||
|
||||
const sounds = [
|
||||
{
|
||||
name: "true_lies_navel_lint",
|
||||
fmt: "wav",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Navel Lint",
|
||||
},
|
||||
{
|
||||
name: "true_lies_pathetic",
|
||||
fmt: "mp3",
|
||||
image: "aliens_17_days.png",
|
||||
text: "It's Pathetic!",
|
||||
},
|
||||
const sounds = [
|
||||
{
|
||||
name: "true_lies_navel_lint",
|
||||
fmt: "wav",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Navel Lint",
|
||||
},
|
||||
{
|
||||
name: "true_lies_pathetic",
|
||||
fmt: "mp3",
|
||||
image: "aliens_17_days.png",
|
||||
text: "It's Pathetic!",
|
||||
},
|
||||
|
||||
{
|
||||
name: "aliens_game_over",
|
||||
fmt: "wav",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Game Over!",
|
||||
},
|
||||
{
|
||||
name: "aliens_current_affairs",
|
||||
fmt: "wav",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Current Affairs",
|
||||
},
|
||||
{
|
||||
name: "aliens_17_days",
|
||||
fmt: "wav",
|
||||
image: "aliens_17_days.png",
|
||||
text: "17 Days?",
|
||||
},
|
||||
{
|
||||
name: "aliens_express_elevator",
|
||||
fmt: "wav",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Express Elevator",
|
||||
},
|
||||
{
|
||||
name: "aliens_game_over",
|
||||
fmt: "wav",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Game Over!",
|
||||
},
|
||||
{
|
||||
name: "aliens_current_affairs",
|
||||
fmt: "wav",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Current Affairs",
|
||||
},
|
||||
{
|
||||
name: "aliens_17_days",
|
||||
fmt: "wav",
|
||||
image: "aliens_17_days.png",
|
||||
text: "17 Days?",
|
||||
},
|
||||
{
|
||||
name: "aliens_express_elevator",
|
||||
fmt: "wav",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Express Elevator",
|
||||
},
|
||||
|
||||
{
|
||||
name: "weird_science_booze",
|
||||
fmt: "mp3",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Boozehounds Return",
|
||||
},
|
||||
{
|
||||
name: "weird_science_dead_meat",
|
||||
fmt: "mp3",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Dead Meat",
|
||||
},
|
||||
{
|
||||
name: "weird_science_sandwich",
|
||||
fmt: "mp3",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Pork Sandwich",
|
||||
},
|
||||
{
|
||||
name: "weird_science_stewwed",
|
||||
fmt: "mp3",
|
||||
image: "aliens_17_days.png",
|
||||
text: "You're Stewwed",
|
||||
},
|
||||
{
|
||||
name: "weird_science_turd_brain",
|
||||
fmt: "mp3",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Turd Brain",
|
||||
},
|
||||
];
|
||||
{
|
||||
name: "weird_science_booze",
|
||||
fmt: "mp3",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Boozehounds Return",
|
||||
},
|
||||
{
|
||||
name: "weird_science_dead_meat",
|
||||
fmt: "mp3",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Dead Meat",
|
||||
},
|
||||
{
|
||||
name: "weird_science_sandwich",
|
||||
fmt: "mp3",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Pork Sandwich",
|
||||
},
|
||||
{
|
||||
name: "weird_science_stewwed",
|
||||
fmt: "mp3",
|
||||
image: "aliens_17_days.png",
|
||||
text: "You're Stewwed",
|
||||
},
|
||||
{
|
||||
name: "weird_science_turd_brain",
|
||||
fmt: "mp3",
|
||||
image: "aliens_17_days.png",
|
||||
text: "Turd Brain",
|
||||
},
|
||||
];
|
||||
|
||||
sounds.forEach(({ name, fmt }) => {
|
||||
load(name, `${rootdir}/sounds/${name}.${fmt}`);
|
||||
});
|
||||
sounds.forEach(({ name, fmt }) => {
|
||||
load(name, `${rootdir}/sounds/${name}.${fmt}`);
|
||||
});
|
||||
|
||||
// adapted from https://stackoverflow.com/questions/12813573/position-icons-into-circle
|
||||
// adapted from https://stackoverflow.com/questions/12813573/position-icons-into-circle
|
||||
|
||||
let m = sounds.length; /* how many are ON the circle */
|
||||
let tan = Math.tan(Math.PI / m); /* tangent of half the base angle */
|
||||
let m = sounds.length; /* how many are ON the circle */
|
||||
let tan = Math.tan(Math.PI / m); /* tangent of half the base angle */
|
||||
|
||||
const build = () => {
|
||||
const figureButtons = sounds.map(({ name, text }, idx) => {
|
||||
const caption = document.createElement("figcaption"),
|
||||
figure = document.createElement("figure"),
|
||||
img = document.createElement("img");
|
||||
caption.textContent = text;
|
||||
img.alt = text;
|
||||
img.src = `${rootdir}/images/${name}.png`;
|
||||
figure.className = "figureButton";
|
||||
figure.onclick = () => play(name);
|
||||
figure.style = `--i: ${idx}`;
|
||||
figure.append(...[img, caption]);
|
||||
return figure;
|
||||
});
|
||||
const build = () => {
|
||||
const figureButtons = sounds.map(({ name, text }, idx) => {
|
||||
const caption = document.createElement("figcaption"),
|
||||
figure = document.createElement("figure"),
|
||||
img = document.createElement("img");
|
||||
caption.textContent = text;
|
||||
img.alt = text;
|
||||
img.src = `${rootdir}/images/${name}.png`;
|
||||
figure.className = "figureButton";
|
||||
figure.onclick = () => play(name);
|
||||
figure.style = `--i: ${idx}`;
|
||||
figure.append(...[img, caption]);
|
||||
return figure;
|
||||
});
|
||||
|
||||
const randomFigure = document.createElement("figure"),
|
||||
randomCaption = document.createElement("figcaption"),
|
||||
randomImg = document.createElement("img");
|
||||
randomCaption.textContent = "Random";
|
||||
randomImg.alt = "Random";
|
||||
randomImg.src = `${rootdir}/images/random.png`;
|
||||
randomFigure.className = "figureButton";
|
||||
randomFigure.onclick = () =>
|
||||
play(sounds[~~(sounds.length * Math.random())].name);
|
||||
randomFigure.append(...[randomImg, randomCaption]);
|
||||
const randomFigure = document.createElement("figure"),
|
||||
randomCaption = document.createElement("figcaption"),
|
||||
randomImg = document.createElement("img");
|
||||
randomCaption.textContent = "Random";
|
||||
randomImg.alt = "Random";
|
||||
randomImg.src = `${rootdir}/images/random.png`;
|
||||
randomFigure.className = "figureButton";
|
||||
randomFigure.onclick = () =>
|
||||
play(sounds[~~(sounds.length * Math.random())].name);
|
||||
randomFigure.append(...[randomImg, randomCaption]);
|
||||
|
||||
const div = document.createElement("div");
|
||||
div.className = "circleWrapper";
|
||||
div.style = `--m: ${m}; --tan: ${+tan.toFixed(2)}`;
|
||||
div.append(...[randomFigure, ...figureButtons]);
|
||||
document.getElementById("output").replaceWith(div);
|
||||
};
|
||||
const div = document.createElement("div");
|
||||
div.className = "circleWrapper";
|
||||
div.style = `--m: ${m}; --tan: ${+tan.toFixed(2)}`;
|
||||
div.append(...[randomFigure, ...figureButtons]);
|
||||
document.getElementById("output").replaceWith(div);
|
||||
};
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
setTimeout(() => {
|
||||
build();
|
||||
}, 1);
|
||||
});
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
setTimeout(() => {
|
||||
build();
|
||||
}, 1);
|
||||
});
|
||||
|
||||
return { play, build };
|
||||
return { play, build };
|
||||
})();
|
||||
// @license-end
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/****************************************************************************
|
||||
* BPS (Bill Paxton Soundboard)
|
||||
*
|
||||
* Copyright 2024 Eric Woodward
|
||||
* Copyright 2024-2026 Eric Woodward
|
||||
* Source released under CC0 Public Domain License v1.0
|
||||
* https://www.itsericwoodward.com/licenses/cc0/
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
@@ -13,25 +13,25 @@
|
||||
let sounds = [];
|
||||
|
||||
const injectPlayerIntoPage = (name, path) => {
|
||||
const player = document.createElement("audio");
|
||||
player.id = name;
|
||||
player.src = path;
|
||||
player.volume = 0.5;
|
||||
player.type = "audio/mpeg";
|
||||
document.body.appendChild(player);
|
||||
},
|
||||
load = (name, path) => {
|
||||
sounds = [...sounds, { name, path }];
|
||||
injectPlayerIntoPage(name, path);
|
||||
},
|
||||
play = (name) => {
|
||||
const player = document.getElementById(name);
|
||||
if (player) {
|
||||
player.pause();
|
||||
player.currentTime = 0;
|
||||
player.play();
|
||||
}
|
||||
};
|
||||
const player = document.createElement("audio");
|
||||
player.id = name;
|
||||
player.src = path;
|
||||
player.volume = 0.5;
|
||||
player.type = "audio/mpeg";
|
||||
document.body.appendChild(player);
|
||||
},
|
||||
load = (name, path) => {
|
||||
sounds = [...sounds, { name, path }];
|
||||
injectPlayerIntoPage(name, path);
|
||||
},
|
||||
play = (name) => {
|
||||
const player = document.getElementById(name);
|
||||
if (player) {
|
||||
player.pause();
|
||||
player.currentTime = 0;
|
||||
player.play();
|
||||
}
|
||||
};
|
||||
|
||||
export { load, play };
|
||||
// @license-end
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/****************************************************************************
|
||||
* BPS (Bill Paxton Soundboard)
|
||||
*
|
||||
* Copyright 2024 Eric Woodward
|
||||
* Copyright 2024-2026 Eric Woodward
|
||||
* Source released under CC0 Public Domain License v1.0
|
||||
* https://www.itsericwoodward.com/licenses/cc0/
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright © 2023-2024 [Eric Woodward](https://www.itsericwoodward.com/)
|
||||
Copyright © 2023-2026 [Eric Woodward](https://www.itsericwoodward.com/)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
BIN
src/assets/images/eric-8bit.png
Normal file
BIN
src/assets/images/eric-8bit.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
@@ -2,7 +2,7 @@
|
||||
/****************************************************************************
|
||||
* It's Eric Woodward's Site
|
||||
*
|
||||
* Copyright 2014-2025 Eric Woodward
|
||||
* Copyright 2014-2026 Eric Woodward
|
||||
* Source released under CC0 Public Domain License v1.0
|
||||
* https://www.itsericwoodward.com/licenses/cc0/
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
@@ -43,29 +43,21 @@ export default (actionBox) => {
|
||||
actionBox.classList.add("js-actionBox");
|
||||
|
||||
const actionBoxTitle = document.createElement("summary");
|
||||
actionBoxTitle.innerHTML =
|
||||
"<h3 class='actionBox-title'>Settings</h3>";
|
||||
actionBoxTitle.innerHTML = "<h3 class='actionBox-title'>Settings</h3>";
|
||||
actionBox.append(actionBoxTitle);
|
||||
|
||||
// add toggle event
|
||||
document
|
||||
.getElementById("scrollingToggle")
|
||||
.addEventListener("click", function (e) {
|
||||
const theList =
|
||||
document.getElementById("gridContainer").classList;
|
||||
const theList = document.getElementById("gridContainer").classList;
|
||||
|
||||
theList.toggle("js-isAnimated");
|
||||
Cookies.set(
|
||||
"scrollToggle",
|
||||
!!theList.contains("js-isAnimated")
|
||||
);
|
||||
Cookies.set("scrollToggle", !!theList.contains("js-isAnimated"));
|
||||
});
|
||||
|
||||
// add class if active at startup
|
||||
if (hasScrollToggle)
|
||||
document
|
||||
.getElementById("gridContainer")
|
||||
.classList.add("js-isAnimated");
|
||||
|
||||
document.getElementById("gridContainer").classList.add("js-isAnimated");
|
||||
};
|
||||
// @license-end
|
||||
|
||||
@@ -2,76 +2,76 @@
|
||||
/****************************************************************************
|
||||
* It's Eric Woodward's Site
|
||||
*
|
||||
* Copyright 2014-2025 Eric Woodward
|
||||
* Copyright 2014-2026 Eric Woodward
|
||||
* Source released under CC0 Public Domain License v1.0
|
||||
* https://www.itsericwoodward.com/licenses/cc0/
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
****************************************************************************/
|
||||
import backgroundScroller from './backgroundScroller.js';
|
||||
import themeSwitcher from './themeSwitcher.js';
|
||||
import backgroundScroller from "./backgroundScroller.js";
|
||||
import themeSwitcher from "./themeSwitcher.js";
|
||||
|
||||
export default (() => {
|
||||
// we load this library via "module" to guarantee baseline ES6 functionality
|
||||
// we load this library via "module" to guarantee baseline ES6 functionality
|
||||
|
||||
// check for loaded libraries
|
||||
if (!window.Cookies) return;
|
||||
// check for loaded libraries
|
||||
if (!window.Cookies) return;
|
||||
|
||||
if (window.dayjs) dayjs.extend(window.dayjs_plugin_relativeTime);
|
||||
if (window.dayjs) dayjs.extend(window.dayjs_plugin_relativeTime);
|
||||
|
||||
// Indicate JS is loaded
|
||||
document.documentElement.className =
|
||||
document.documentElement.className.replace("no-js", "js");
|
||||
// Indicate JS is loaded
|
||||
document.documentElement.className =
|
||||
document.documentElement.className.replace("no-js", "js");
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
setTimeout(() => {
|
||||
if (!window.Cookies) return;
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
setTimeout(() => {
|
||||
if (!window.Cookies) return;
|
||||
|
||||
// Lazy-Load Media
|
||||
if (typeof loadMedia === "function") {
|
||||
loadMedia(".js-lazyLoader", null, true);
|
||||
}
|
||||
// Lazy-Load Media
|
||||
if (typeof loadMedia === "function") {
|
||||
loadMedia(".js-lazyLoader", null, true);
|
||||
}
|
||||
|
||||
// Add relative dates via dayjs
|
||||
if (window.dayjs) {
|
||||
const times = document.getElementsByTagName("time");
|
||||
// Add relative dates via dayjs
|
||||
if (window.dayjs) {
|
||||
const times = document.getElementsByTagName("time");
|
||||
|
||||
[].forEach.call(times, function (the_time) {
|
||||
let pub_time = the_time.getAttribute("datetime");
|
||||
if (the_time.className.indexOf("js-noRelativeTime") === -1)
|
||||
the_time.innerHTML +=
|
||||
' <span class="js-momentTime">(' +
|
||||
dayjs(pub_time).from(dayjs()) +
|
||||
")</span>";
|
||||
the_time.classList.add("isDone");
|
||||
});
|
||||
}
|
||||
[].forEach.call(times, function (the_time) {
|
||||
let pub_time = the_time.getAttribute("datetime");
|
||||
if (the_time.className.indexOf("js-noRelativeTime") === -1)
|
||||
the_time.innerHTML +=
|
||||
' <span class="js-momentTime">(' +
|
||||
dayjs(pub_time).from(dayjs()) +
|
||||
")</span>";
|
||||
the_time.classList.add("isDone");
|
||||
});
|
||||
}
|
||||
|
||||
const actionBoxDiv = document.querySelector("#bio .actionBox");
|
||||
const actionBoxDiv = document.querySelector("#bio .actionBox");
|
||||
|
||||
const actionBox = document.createElement("details");
|
||||
const actionBox = document.createElement("details");
|
||||
|
||||
actionBoxDiv.append(actionBox);
|
||||
actionBoxDiv.append(actionBox);
|
||||
|
||||
actionBox.setAttribute("open", "true");
|
||||
actionBox.setAttribute("open", "true");
|
||||
|
||||
themeSwitcher(actionBox);
|
||||
themeSwitcher(actionBox);
|
||||
|
||||
backgroundScroller(actionBox);
|
||||
backgroundScroller(actionBox);
|
||||
|
||||
if (document.documentElement.className.indexOf("is404") > -1) {
|
||||
document.getElementById("searchQuery").value =
|
||||
window.location.pathname
|
||||
.replace(/\\.html?$/, "")
|
||||
.replace(/\//g, " ");
|
||||
}
|
||||
if (document.documentElement.className.indexOf("is404") > -1) {
|
||||
document.getElementById("searchQuery").value =
|
||||
window.location.pathname
|
||||
.replace(/\\.html?$/, "")
|
||||
.replace(/\//g, " ");
|
||||
}
|
||||
|
||||
document
|
||||
.getElementById("searchForm")
|
||||
.addEventListener("submit", function (e) {
|
||||
document.getElementById("searchQuery").value +=
|
||||
" site:" + window.location.hostname;
|
||||
});
|
||||
}, 1);
|
||||
});
|
||||
document
|
||||
.getElementById("searchForm")
|
||||
.addEventListener("submit", function (e) {
|
||||
document.getElementById("searchQuery").value +=
|
||||
" site:" + window.location.hostname;
|
||||
});
|
||||
}, 1);
|
||||
});
|
||||
})();
|
||||
// @license-end
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/****************************************************************************
|
||||
* It's Eric Woodward's Site
|
||||
*
|
||||
* Copyright 2014-2025 Eric Woodward
|
||||
* Copyright 2014-2026 Eric Woodward
|
||||
* Source released under CC0 Public Domain License v1.0
|
||||
* https://www.itsericwoodward.com/licenses/cc0/
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
@@ -54,9 +54,7 @@ export default (actionBox) => {
|
||||
themeSwitch.classList.add("js-themeSwitch", "themeSwitch");
|
||||
|
||||
if (currentTheme)
|
||||
document
|
||||
.getElementsByTagName("body")[0]
|
||||
.classList.add(currentTheme);
|
||||
document.getElementsByTagName("body")[0].classList.add(currentTheme);
|
||||
|
||||
actionBox.append(themeSwitch);
|
||||
|
||||
@@ -72,5 +70,5 @@ export default (actionBox) => {
|
||||
.join(" ");
|
||||
Cookies.set("currentTheme", e.target.value);
|
||||
});
|
||||
}
|
||||
};
|
||||
// @license-end
|
||||
|
||||
@@ -41,7 +41,10 @@
|
||||
|
||||
<ul class="asideMenu-list socialList">
|
||||
<li class="asideMenu-item socialList-item">
|
||||
<a rel="me auth" class="asideMenu-link u-url url" title="It's Eric Woodward's Gitea Server" href="https://git.itsericwoodward.com/explore/repos">My Git Repos</a>
|
||||
<a rel="me" class="asideMenu-link u-url url" title="It's Eric Woodward's twtxt.txt File" href="https://itsericwoodward.com/twtxt.txt">twtxt.txt</a>
|
||||
</li>
|
||||
<li class="asideMenu-item socialList-item">
|
||||
<a rel="me auth" class="asideMenu-link u-url url" title="It's Eric Woodward's Gitea Server" href="https://git.itsericwoodward.com/explore/repos">Git Repos</a>
|
||||
</li>
|
||||
<li class="asideMenu-item socialList-item">
|
||||
<a rel="me" class="asideMenu-link u-url url" title="itsericwoodward on LinkedIn" href="https://www.linkedin.com/in/itsericwoodward">LinkedIn</a>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
class="licenseImg"
|
||||
src="https://i.creativecommons.org/l/by-sa/4.0/80x15.png" />
|
||||
</a>
|
||||
Except where otherwise noted, content on this site is © 2014-2024
|
||||
Except where otherwise noted, content on this site is © 2014-2026
|
||||
<a
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
href="<%=site.author.uri ?? '/'%>"
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
<!--
|
||||
<li class="navMenu-list-item"><a class="navMenu-list-link<%= (page.path && page.path.indexOf('/updates') === 0 ? ' isCurrentSection' : '') %>" href="/updates">Updates</a></li>
|
||||
-->
|
||||
<li class="navMenu-list-item"><a
|
||||
class="navMenu-list-link<%= (page.section && page.section === 'code' ? ' isCurrentSection' : '') %>"
|
||||
href="/code/index.html">Code</a></li>
|
||||
<li class="navMenu-list-item"><a
|
||||
class="navMenu-list-link<%= (page.section && page.section === 'games' ? ' isCurrentSection' : '') %>"
|
||||
href="/games/index.html">Games</a></li>
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
I've been programming since I was 8, first on an Apple IIe, then on an Atari 130XE, followed by various
|
||||
x86 PCs, and finally the World Wide Web itself. Along the way, I've used (and abused) various forms of
|
||||
BASIC, C++, LISP, x86 Assembly, PL-SQL, Perl, PHP, Java, and shell scripting, before ultimately settling on
|
||||
my current day-to-day usage of JavaScript and HTML.
|
||||
my current day-to-day usage of JavaScript / TypeScript and HTML.
|
||||
</li>
|
||||
|
||||
<li>In January, 2016, my first officially published tabletop game,
|
||||
@@ -60,9 +60,9 @@
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Since 2018, I've gotten back into RPGs in a big way, running (and playing in) several
|
||||
weekly games over the course of the pandemic. Currently, I'm running a high/weird-fantasy campaign based
|
||||
in the astral plane called
|
||||
Since 2018, I've gotten back into RPGs in a big way, running (and playing in) several
|
||||
weekly games since the pandemic. Although I'm not currently running a weekly game,
|
||||
I do still run the odd one-shot game, and publish my RPG-related content as part of
|
||||
<a href="https://www.planarvagabond.com">The Planar Vagabond's Guide to the Multiverse</a>.
|
||||
</li>
|
||||
|
||||
@@ -82,7 +82,11 @@
|
||||
(where I keep my code).
|
||||
</li>
|
||||
<li>
|
||||
I am sporadically active on various corporate social media silos, and have accounts on
|
||||
I have a
|
||||
<a rel="me authn" class="u-url url" title="It's Eric Woodward's twtxt.txt"
|
||||
href="https://git.itsericwoodward.com/explore/repos">twtxt.txt file</a>
|
||||
(which I sporadically post to),
|
||||
and I maintain accounts on various corporate social media silos, including
|
||||
<a rel="me" class="u-url url" title="itsericwoodward on LinkedIn"
|
||||
href="https://www.linkedin.com/in/itsericwoodward">LinkedIn</a>,
|
||||
<a rel="me authn" class="u-url url" title="ItsEricWoodward on GitHub"
|
||||
|
||||
@@ -30,12 +30,12 @@ In 1997, I released my first (and, so far, only) computer game, **Camp Happy Isl
|
||||
|
||||
If you have a functional DOS machine (or an emulator, like [DOSBox](https://www.dosbox.com/)), you can download the game in a [ZIP file](/files/chim/chim.zip), which contains the following files:
|
||||
|
||||
- [`CHIM.EXE`](/files/chim/chim.exe) _(the main executable file)_
|
||||
- [`CHIM.FAQ`](/files/chim/chim.faq) _(list of frequently asked questions)_
|
||||
- [`FILE_ID.DIZ`](/files/chim/file_id.diz) _(ZIP file descriptor)_
|
||||
- [`INTRO.TXT`](/files/chim/intro.txt) _(the intro screen)_
|
||||
- [`LICENSE.TXT`](/files/chim/license.txt) _(the distribution license)_
|
||||
- [`MAP.TXT`](/files/chim/map.txt) _(a text map of the island)_
|
||||
- [`CHIM.EXE`](/files/chim/chim.exe) _(the main executable file)_
|
||||
- [`CHIM.FAQ`](/files/chim/chim.faq) _(list of frequently asked questions)_
|
||||
- [`FILE_ID.DIZ`](/files/chim/file_id.diz) _(ZIP file descriptor)_
|
||||
- [`INTRO.TXT`](/files/chim/intro.txt) _(the intro screen)_
|
||||
- [`LICENSE.TXT`](/files/chim/license.txt) _(the distribution license)_
|
||||
- [`MAP.TXT`](/files/chim/map.txt) _(a text map of the island)_
|
||||
|
||||
And now, thanks to [DOSBox](https://www.dosbox.com/), [Emscripten](http://emscripten.org/), and their unholy lovechild, [JS-DOS](https://js-dos.com/), you can play **Camp Happy Island Massacre** in your browser:
|
||||
|
||||
|
||||
26
src/pages/code/index.md
Normal file
26
src/pages/code/index.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
title: Code
|
||||
description: A small collection of my code-related projects.
|
||||
date_pub: 2026-01-01T17:10:39-05:00
|
||||
section: code
|
||||
content_type: feature
|
||||
short_code: mc
|
||||
---
|
||||
|
||||
Code, and the writing of it, has been an obsession of mine since I was 10. To this day, I think writing code is both an art and a science, and _good_ code is the perfect convergence of poetry and knowledge, form and function.
|
||||
|
||||
In a more practical sense, I've been writing code professionally for over 25 years, and while most of that is owned by other people / corporations / whatnot, here's where I give away what I can. :D
|
||||
|
||||
### Libraries
|
||||
|
||||
- [fluent-dom-esm](https://jsr.io/@itsericwoodward/fluent-dom-esm) [[source](https://git.itsericwoodward.com/eric/fluent-dom-esm/)]: JSR package and ESM library of a remarkably simple but surprisingly powerful DOM element creation library, featuring an easy-to-use syntax inspired by the classic JS libraries of yesterday.
|
||||
- [markdown-it-implicit-figures-video](https://www.npmjs.com/package/markdown-it-implicit-figures-video) [[source](https://github.com/ItsEricWoodward/markdown-it-implicit-figures-video)]: NPM package for a [markdown-it](https://github.com/markdown-it/markdown-it) plugin to wrap videos occurring by themselves in a paragraph with `<figure>` elements, similar to [pandoc's implicit figures for images](http://pandoc.org/README.html#images). Based on the excellent [markdown-it-implicit-figures](https://www.npmjs.com/package/markdown-it-implicit-figures) package by [Arve Seljebu](https://arve0.github.io/).
|
||||
|
||||
### Other Open Source
|
||||
|
||||
Pretty much everything hosted at [my code repos](https://git.itsericwoodward.com/explore/repos) is _some_ kind of open source, but here are some highlights from there:
|
||||
|
||||
- The [backgroundScroller](/scripts/backgroundScroller.js), [themeSwitcher](/scripts/themeSwitcher.js), and [main script](/scripts/scripts.js) for [this site](https://git.itsericwoodward.com/eric/itsericwoodward-site-v2) are all pretty cool int heir own way, and all are released under a [CC0 Public Domain license](/licenses/cc0/).
|
||||
- I have an obligatory collection of [utility scripts](https://git.itsericwoodward.com/eric/utils) which are published under an [MIT](/licenses/mit/) license.
|
||||
|
||||
More to come!
|
||||
@@ -1,11 +1,12 @@
|
||||
---
|
||||
title: Creative Commons Attribution-ShareAlike 4.0 International
|
||||
description: A local copy of the Creative Commons Attribution-ShareAlike 4.0 International license.
|
||||
date_pub: 2023-03-19T00:55:00-04:00
|
||||
section: web
|
||||
subsection: licenses
|
||||
content_type: feature
|
||||
date_pub: 2023-03-19T00:55:00-04:00
|
||||
description: A local copy of the Creative Commons Attribution-ShareAlike 4.0 International license.
|
||||
redirectTo: /licenses/cc-by-sa/index.html
|
||||
section: web
|
||||
status: hidden
|
||||
subsection: licenses
|
||||
---
|
||||
|
||||
!!!include(license/cc-by-sa.md)!!!
|
||||
|
||||
@@ -9,9 +9,15 @@ short_code: mn
|
||||
|
||||
Between the hours of roughly 8AM and 11PM (`America/New_York` time, give or take an hour or two), you'll most likely find me doing any or all of the following:
|
||||
|
||||
- working (especially between 9a and 6p, Monday to Friday),
|
||||
- [developing](/journal/2015/03-18-developing-the-web) this website (or [something](/webtoys/bbe/) [else](/webtoys/bps/) [fun](/webtoys/maze/)),
|
||||
- building out [The Planar Vagabond's Guide to the Multiverse](https://www.planarvagabond.com/),
|
||||
- playing (and hopefully winning) a casual game of [MtG Commander](https://magic.wizards.com/en/formats/commander) (or making another [magic deck](/magic-decks) to play and win with),
|
||||
- working on (or running) one of my RPGs (be it an IRL game wih my kids or one of my [One Night... one shots](https://www.planarvagabond.com/campaigns/one-night/)), or
|
||||
- messing around with some crazy side project (probably involving a game, the web, and/or some cool hardware).
|
||||
- Working from my home office (especially between 9a and 7p, Monday to Friday).
|
||||
- [Developing](/journal/2015/03-18-developing-the-web) this website (or [something](/webtoys/bbe/) [else](/webtoys/bps/) [fun](/webtoys/maze/)).
|
||||
- Building out [The Planar Vagabond's Guide to the Multiverse](https://www.planarvagabond.com/).
|
||||
- Playing (and hopefully winning) a casual game of [MtG Commander](https://magic.wizards.com/en/formats/commander) (or making another [magic deck](/magic-decks) to play and win with).
|
||||
- Working on (or running) one of my RPGs (be it my IRL game wih my kids or one of my [One Night... one shots](https://www.planarvagabond.com/campaigns/one-night/)).
|
||||
- Playing [Marvel: Contest of Champions](https://playcontestofchampions.com/) on my phone.
|
||||
- Playing an old game via emulation (either on a console, my laptop, or phone + Backbone setup), such as:
|
||||
- [Castlevania: Symphony of the Night](https://en.wikipedia.org/wiki/Castlevania:_Symphony_of_the_Night) (PS1),
|
||||
- [NFL Blitz 2000](https://en.wikipedia.org/wiki/NFL_Blitz_2000) (PS1),
|
||||
- [Pinball Hall of Fame: The Williams Collection](https://en.wikipedia.org/wiki/Pinball_Hall_of_Fame:_The_Williams_Collection) (PSP),
|
||||
- or any of a couple dozen arcade games (including 1943, Aliens, Bad Dudes, Super Mario Bros., Samurai Shodown, Shinobi, TMNT, or X-Men).
|
||||
- Or messing around with some crazy side project (probably involving a game, the web, awesome software and/or some cool hardware).
|
||||
|
||||
@@ -3,7 +3,7 @@ title: One Night, on White Plume Mountain...
|
||||
content_type: journal
|
||||
date_pub: 2024-04-27T10:13:40.000-04:00
|
||||
description: An overview of a recent one-shot RPG I ran, based on the classic module.
|
||||
tags: DnD games OSR PlanarVagabond RPG
|
||||
tags: DnD games osr PlanarVagabond RPG
|
||||
---
|
||||
|
||||
A few weeks ago, I had the good fortune to run a one-shot version of Lawrence Schick's classic AD&D adventure [White Plume Mountain](https://en.wikipedia.org/wiki/White_Plume_Mountain) for some friends and family, and I thought I do a bit of a post-mortem on it here.
|
||||
|
||||
53
src/sitePosts/journal/2025/12-31-year-in-review.md
Normal file
53
src/sitePosts/journal/2025/12-31-year-in-review.md
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: 2025 - A Year in Review
|
||||
content_type: journal
|
||||
date_pub: 2025-12-31T16:15:45-05:00
|
||||
description: Taking a look back at the the things I fiddled with in 2025.
|
||||
tags: blogging code meatspace meta web
|
||||
---
|
||||
|
||||
So, 2025 has obviously been a doozy of a year. I'll let future historians put it into its proper context, but being in the middle of it wasn't always easy, and sometimes it felt like the best thing to do was just to stay busy.
|
||||
|
||||
However, in this push to stay busy, it appears that I forgot to post anything here at all for over 365 days.
|
||||
|
||||
So now, on this, the final day of this banner year, I thought I'd share a brief rundown of the various things I've been fiddling with since the year began.
|
||||
|
||||
- The year started out with the publication of the beta version of my RPG website, [PlanarVagabond.com](https://planarvagabond.com/), featuring updated rules with aa unified skill check mechanic and the addition of a _metric tonne_ of new content (something I would continue to add as the year progressed).
|
||||
- About the same time, I ended our [Isle of Dread mini-campaign](https://www.planarvagabond.com/campaigns/mini-campaigns/isle-of-dread.html) (or rather, the players did, by killing and/or gaining control over the big baddies and finding the means to rule the island and/or return home).
|
||||
- In the spring, I started my first truly collaborative (mini?) campaign, set at the prestigious [ Hexhall, Royal Academy of Faerie Arts and Arcane Sciences](https://www.planarvagabond.com/planes/near/faewolde/hexhall.html), a school which exists in both the material plane and the [Faewolde](https://www.planarvagabond.com/planes/near/faewolde/). It's also a special campaign to me, as it's both the first in-person game I've run since the pandemic, and the players are my son, my daughter, and my daughter-in-law (a first-time player).
|
||||
- Also this spring, at the suggestion of my son, I picked up a lightly-used [Backbone mobile controller](https://backbone.com/). Combined with a "spare" Galaxy S23 (which I loaded with emulators) and a pair of Raycon headphones he gave me for Father's Day, it's been my game system of choice ever since.
|
||||
- In June, as part of a code challenge for my employer, I wrote and released [Maze of the Minotaur](/webtoys/maze/), a web game which also stands as my first my first (and, to date, only) Android release.
|
||||
- Also in June, I started running some players through the classic D&D module, [Tomb of Horrors](https://www.planarvagabond.com/campaigns/one-night/one-night-in-toh.html). Although it was intended to be a one-shot, we're now up to 3 sessions, no one has died (yet), and there's still a good bit left of the crypt, so... it's turning into a mini-campaign after all. Who knew? :shrug:
|
||||
- This July brought an update to [Camp Happy Island Massacre](/chim/) as I migrated its web runtime to js-dos, enabling it to run more smoothly, and on more machines.
|
||||
- In late summer, I finally completed a long-running, off-again/on-again project, and (briefly) launched the Deus Reloaded BBS. Unfortunately, I ran into some technical issues which made it effectively useless, and I shut it down shortly after launching it (I might go into the story a bit deeper in the future).
|
||||
- Fall brought a new obsession: the humble [twtxt.txt](https://github.com/buckket/twtxt) file, a decade-old "decentralised, minimalist microblogging service for hackers." The simplicity of the concept really inspired me, and I started working on several iterations of both [my own twtxt.txt file](https://itsericwoodward.com/twtxt.txt), as well as utilities to read, write, process, and display those files:
|
||||
- **TwtKpr**: A small node application to view, edit, and update a `twtxt.txt` file (pronounced "TweetKeeper", still WIP).
|
||||
- **TwtStrm**: A small node application to load, parse, and display the content from all of the `twtxt.txt` files followed by a single source file (pronounced "TweetStream"[^1], also still WIP).
|
||||
- [fluent-dom-esm](https://jsr.io/@itsericwoodward/fluent-dom-esm): a small client-side JS library (published via [jsr.io](https://jsr.io/)) that provides a fluent, jQuery-like interface to the modern browser DOM.
|
||||
- In early November, I ran my third annual (and likely final) rendition of the Halloween one-shot, [One Night in Ravenloft](https://www.planarvagabond.com/campaigns/one-night/one-night-in-ravenloft.html), this time played with a twist of cosmic horror via the introduction of [Neurovores](https://www.planarvagabond.com/bestiary/neurovores/) (aka creatures that _Flay Minds_). Also, I had enough players for two sessions this year, with both ending in defeat for the forces of evil once again.
|
||||
- Earlier this month, I participated in the [Advent of Code](https://adventofcode.com/). I ran out of steam about 2/3 of the way through, but I fully intend to finish [my solutions](https://git.itsericwoodward.com/eric/aoc-2025) as time permits (maybe even over the remaining holidays).
|
||||
- Finally, concurrent with the release of this post, I made a few small updates to this site, adding links to [my twtxt.txt file](https://itsericwoodward.com/twtxt.txt) to several pages, updating my [/now](/now) page, and adding a [Code Page](/code.html) to collect my libraries and code-related links together.
|
||||
|
||||
So, what about 2026? What projects might see the light of day before the calendar turns again?
|
||||
|
||||
- I'd really like to finish (and release) TwtKpr and TwtStrm: both are fully functional, albeit somewhat rough in terms of user experience, so with a bit of polishing, I hope to have them ready to turn loose in the next year.
|
||||
- I'm also close to finishing a long-simmering project: an actual Planar Vagabond's Guide to the Multiverse zine! I've got issue #1 mostly laid out and ready, but I'd really like to at least get _started_ on a couple more issues before I release anything (just so I can keep things organized over the long-term).
|
||||
- I've been playing with the fantastic [A-Frame library](https://aframe.io/) a bit on the side, trying to create immersive experiences inspired by my hazy recollections of 90s VR (and [VRML](https://en.wikipedia.org/wiki/VRML), in particular), so maybe something will come out of that which is worth sharing...
|
||||
- I'm working on some fairly major updates for Planar Vagabond, introducing a series of classes with a unified, roll-to-cast, freeform magic system, along with (maybe, hopefully, finally) publishing rules for summoning and binding elementals (including demons).
|
||||
- I plan to run a few one-shots this year, including possibly writing a _new_ halloween one-shot (based on my experiences with the previous Ravenloft games).
|
||||
- Finally, I hope to start up another mini-campaign, potentially set somewhere other than a medieval-fantasy world (maybe something modern supernatural, or post-apocalyptic cyberpunk, or even _post_-post-apocalyptic science fantasy :O).
|
||||
|
||||
Of course, these a just the ideas I have right now - who knows what new depravities will seize my crazed imagination as the year unfolds?
|
||||
|
||||
I guess we'll have to wait and see.
|
||||
|
||||
[^1]: Although, during testing, it was occasionally referred to as "TweetStorm" by those who were spammed by it, which I again apologize for. :)
|
||||
|
||||
<!--
|
||||
- Other Things
|
||||
- Update `/now`
|
||||
- Add link in Bio to "status updates" (iew.com)
|
||||
- Addd libraries somewhere in the main site
|
||||
- JSDom
|
||||
- implicit-figure-video
|
||||
-->
|
||||
@@ -38,6 +38,7 @@
|
||||
color: #fff;
|
||||
line-height: 1.3em;
|
||||
vertical-align: middle;
|
||||
height: 100%;
|
||||
}
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
<%
|
||||
/*
|
||||
This is broken too, adds an unnecessary "undefine" to output.
|
||||
*/
|
||||
|
||||
var
|
||||
generateSitemapXML = function(the_head, the_tail, the_base) {
|
||||
var
|
||||
filter = /(\.html$)/,
|
||||
replace = /(\.html$)|(^index\.html$)/,
|
||||
tree = function (head, tail, base) {
|
||||
var
|
||||
output = '',
|
||||
tree_output = '',
|
||||
data, content;
|
||||
for (var key in head) {
|
||||
var
|
||||
val = head[key];
|
||||
if (key && val && key !== '.git') {
|
||||
if (key == '_data') {
|
||||
data = val;
|
||||
} else if (key == '_contents') {
|
||||
content = val;
|
||||
} else {
|
||||
tree_output += tree(val, tail + key + "/", base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (content) {
|
||||
for (var i in content) {
|
||||
var
|
||||
file = content[i],
|
||||
slug = file.replace(filter, ""),
|
||||
file_data = data && data[slug] ? data[slug] : {},
|
||||
now = new Date(),
|
||||
show_item = false,
|
||||
upd_date;
|
||||
if (filter.test(file)) {
|
||||
show_item = true;
|
||||
if (file_data) {
|
||||
var
|
||||
is_draft = file_data.is_draft || false,
|
||||
is_sys_file = file_data.is_sys_file || false,
|
||||
title = (file_data.title || '').trim();
|
||||
if (is_draft || is_sys_file || title === '') {
|
||||
show_item = false;
|
||||
} else {
|
||||
upd_date = file_data.date_last_mod ? new Date(file_data.date_last_mod) : '';
|
||||
upd_date = upd_date !== '' && file_data.date_pub ? new Date(file_data.date_pub) : '';
|
||||
if ((upd_date && upd_date.getTime() > now.getTime())) {
|
||||
show_item = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
show_item = false;
|
||||
}
|
||||
}
|
||||
if (show_item) {
|
||||
output +=
|
||||
'\n<url>\n <loc>' + the_base + tail + file + '</loc>\n' +
|
||||
(upd_date ? '\n <lastmod>' + upd_date.toUTCString() + '</lastmod>' : '') + '\n</url>';
|
||||
}
|
||||
}
|
||||
return output + (['','undefined'].indexOf(tree_output.trim()) == -1 ? tree_output : '');
|
||||
}
|
||||
};
|
||||
return tree(the_head, the_tail, the_base)
|
||||
.replace('undefined', ''); // hack, not sure where the extra "undefined" is coming from. TODO: Fix this
|
||||
}
|
||||
-%>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
|
||||
<%- generateSitemapXML(public, "/", site.uri.production) %>
|
||||
</urlset>
|
||||
@@ -1,62 +0,0 @@
|
||||
<%
|
||||
var
|
||||
generateSitemapList = function(the_head, the_tail) {
|
||||
var
|
||||
filter = /(\.html$)/,
|
||||
replace = /(\.html$)|(^index\.html$)/,
|
||||
tree = function (head, tail) {
|
||||
var
|
||||
output = '',
|
||||
tree_output = '',
|
||||
data, content;
|
||||
for (var key in head) {
|
||||
var
|
||||
val = head[key];
|
||||
if (key !== '.git') {
|
||||
if (key == '_data') {
|
||||
data = val;
|
||||
} else if (key == '_contents') {
|
||||
content = val;
|
||||
} else {
|
||||
tree_output += tree(val, tail + key + "/");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (content && data) {
|
||||
for (var i in content) {
|
||||
var
|
||||
file = content[i],
|
||||
slug = file.replace(replace, ""),
|
||||
file_data = data && data[slug] ? data[slug] : {},
|
||||
now = new Date(),
|
||||
show_item = false,
|
||||
title, date;
|
||||
if (filter.test(file) && !(/^404\.html/).test(file)) {
|
||||
show_item = true;
|
||||
if (file_data) {
|
||||
var is_draft = file_data.is_draft || false;
|
||||
date = file_data.date_pub ? new Date(file_data.date_pub) : '';
|
||||
title = file_data.title || '';
|
||||
if (is_draft || title === '' || (date && date.getTime() > now.getTime())) {
|
||||
show_item = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (show_item) {
|
||||
// file = file.replace(replace, "");
|
||||
output +=
|
||||
'\n<li><a href="' + tail + file + '">' + title + '</a></li>\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
return output + tree_output;
|
||||
};
|
||||
return tree(the_head, the_tail);
|
||||
};
|
||||
%>
|
||||
|
||||
<urlset>
|
||||
<%- generateSitemapList(public, "/") %>
|
||||
</urlset>
|
||||
|
||||
Reference in New Issue
Block a user