SteamTheWoz v2

This commit is contained in:
MeowcaTheoRange 2023-11-17 14:38:19 -06:00
parent 41bf4a46af
commit 5468f972be
14 changed files with 95 additions and 346 deletions

View file

@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>HexFlagGen</title> <title>HexFlagGen</title>
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="styles/normal.css" /> <link rel="stylesheet" href="https://cdn.abtmtr.link/cdn/css/normal.css" />
<style> <style>
@import url("https://fonts.googleapis.com/css2?family=Lexend+Deca:wght@100;200;300;400;500;600;700;800;900&display=swap"); @import url("https://fonts.googleapis.com/css2?family=Lexend+Deca:wght@100;200;300;400;500;600;700;800;900&display=swap");
@ -21,13 +21,13 @@
} }
* { * {
transition: background-color 0.125s, color 0.125s; transition: background-color 0.125s, color 0.125s, opacity 0.125s;
} }
</style> </style>
</head> </head>
<body> <body>
<section> <section>
<h1>HexFlagGen</h1> <h1>SteamTheWoz</h1>
<label for="size_width" <label for="size_width"
><input ><input
type="number" type="number"
@ -48,53 +48,53 @@
Base style Base style
</label> </label>
<p>by <a href="https://abtmtr.link/">MeowcaTheoRange</a></p> <p>by <a href="https://abtmtr.link/">MeowcaTheoRange</a></p>
<p> <p>Make a Scott The Woz thumbnail out of any Steam game.</p>
Welcome, here you can make a flag out of the hexadecimal bytes of your
choice!
</p>
</section> </section>
<hr /> <hr />
<section> <section>
<label for="data">Generator string</label><br />
<input <input
type="text" type="number"
id="data" id="steam_game"
value="5BCEFAF5A9B8FFFFFFF5A9B85BCEFABA53" style="width: 8ch"
style="width: 100%" min="10"
/><br /> value="620"
/>
<label for="steam_game">Steam Game ID</label><br />
<button id="generateButton">Generate!</button> <button id="generateButton">Generate!</button>
</section> </section>
<section> <section>
<label for="scott_index">Extras</label><br />
<input <input
type="number" type="number"
id="size_width" id="scott_index"
style="width: 8ch" style="width: 8ch"
min="0" min="0"
max="3000" max="9"
value="300" value="0"
/> />
<label for="size_width">Width (px)</label><br /> <label for="scott_index">Scott Index</label>
<input <small
type="number" >(
id="size_height" <label for="stash" class="checkbox">
style="width: 8ch" <input
min="0" type="checkbox"
max="3000" id="stash"
value="200" onchange="scott_index.disabled = event.target.checked"
/> />
<label for="size_height">Height (px)</label><br /> <span class="checkbox">O</span>
<select id="flag_type"> Scott's Stash </label
<option value="horiz">Horizontal</option> >)</small
<option value="vert" selected>Vertical</option> ><br />
<select id="align">
<option value="left">Left</option>
<option value="center" selected>Center</option>
<option value="right">Right</option>
</select> </select>
<label for="flag_type">Flag type</label> <label for="align">Background Alignment</label>
</section> </section>
<hr /> <hr />
<section> <section>
<p> <canvas id="canvas" width="1280" height="720"></canvas>
Hex: <code><span id="hexdisplay">...</span></code>
</p>
<canvas id="canvas" width="300" height="200"></canvas>
</section> </section>
<script src="scripts/index.js"></script> <script src="scripts/index.js"></script>
</body> </body>

BIN
public/woz0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 KiB

BIN
public/woz1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 KiB

BIN
public/woz2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 KiB

BIN
public/woz3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 KiB

BIN
public/woz4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 KiB

BIN
public/woz5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 687 KiB

BIN
public/woz6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 KiB

BIN
public/woz7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 KiB

BIN
public/woz8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 KiB

BIN
public/woz9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

BIN
public/wozstash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

View file

@ -3,113 +3,79 @@ const data = document.getElementById("data");
const generateButton = document.getElementById("generateButton"); const generateButton = document.getElementById("generateButton");
const hexdisplay = document.getElementById("hexdisplay"); const hexdisplay = document.getElementById("hexdisplay");
const size_width = document.getElementById("size_width"); const steam_game = document.getElementById("steam_game");
const size_height = document.getElementById("size_height"); const scott_index = document.getElementById("scott_index");
const flag_type = document.getElementById("flag_type"); const stash = document.getElementById("stash");
const align = document.getElementById("align");
const root = document.querySelector(":root"); const root = document.querySelector(":root");
const ctx = canvas.getContext("2d"); const ctx = canvas.getContext("2d");
function getData() { async function loadImage(url) {
data.value = data.value.toUpperCase().replace(/[^0-9A-F]*/g, ""); return new Promise((r) => {
let img = new Image();
var hexValue = data.value.match(/.{1,2}/g).map((x) => x.padStart(2, "0")); img.onload = () => r(img);
img.src = url;
hexdisplay.innerHTML = hexValue.join(" ");
createFlag(
hexValue.join("").match(/.{1,6}/g),
size_width.value,
size_height.value,
flag_type.value
);
var ac = averageColors(hexValue);
console.log(ac);
root.style.setProperty(
"--background-color",
arrayToColor(darkenColor(ac, 70))
);
root.style.setProperty("--color", arrayToColor(lightenColor(ac, 70)));
root.style.setProperty("--accent-color", arrayToColor(ac));
root.style.setProperty(
"--accent-color-fg",
arrayToColor(lightenColor(ac, 90))
);
}
generateButton.addEventListener("click", getData);
function averageColors(hex) {
var averageSet = [[], [], []];
hex.forEach((number, index) => {
averageSet[index % 3].push(parseInt(number, 16));
}); });
return averageSet.map((array) =>
Math.floor(array.reduce((a, b) => a + b) / array.length)
);
} }
function createFlag(hex, w, h, type) { async function getScott() {
canvas.width = w; var gameID = steam_game.value;
canvas.height = h; var scottID = scott_index.value;
var alignment = align.value;
// Initialize stuff const ctx = canvas.getContext("2d");
var width = ctx.canvas.width; var hero = await loadImage(
var height = ctx.canvas.height; `https://cdn.cloudflare.steamstatic.com/steam/apps/${gameID}/library_hero.jpg`
var textHeight = 24; ).catch(() => "404");
ctx.font = `${textHeight}px "Lexend Deca"`; var scott = await loadImage(
stash.checked ? `public/wozstash.png` : `public/woz${scottID}.png`
).catch(() => "404");
var logo = await loadImage(
`https://cdn.cloudflare.steamstatic.com/steam/apps/${gameID}/logo.png`
).catch(() => "404");
ctx.clearRect(0, 0, width, height); if (scott === "404") {
console.log("Scott error: " + scottID);
console.log(hex); return `Scott ID ${scottID} does not exist.`;
var hexColors = [];
var excessHex = "";
hex.forEach((compound) => {
if (compound.length < 6) excessHex = compound;
else hexColors.push(compound);
});
var rectWidth = width / hexColors.length;
var rectHeight = height / hexColors.length;
for (color in hexColors) {
ctx.fillStyle = "#" + hexColors[color];
if (type === "horiz") ctx.fillRect(rectWidth * color, 0, rectWidth, height);
else if (type === "vert")
ctx.fillRect(0, rectHeight * color, width, rectHeight);
} }
if (excessHex.length > 0) { if (hero === "404" || logo === "404") {
var text = "+ " + excessHex.match(/.{1,2}/g).join(" "); console.log("404 error: " + gameID);
var textWidth = ctx.measureText(text).width; return `Steam ID ${gameID} does not have logo, hero image, or does not exist.`;
ctx.strokeStyle = "black";
ctx.lineWidth = 4;
ctx.fillStyle = "white";
ctx.strokeText(text, width - (textWidth + 8), height - textHeight / 2);
ctx.fillText(text, width - (textWidth + 8), height - textHeight / 2);
} }
var xalign;
switch (alignment) {
case "left":
xalign = 0;
break;
case "right":
xalign = -950;
break;
default:
xalign = -505;
break;
}
console.log("Generating: " + gameID);
ctx.drawImage(hero, xalign, 0, 2229, 720);
ctx.drawImage(scott, 0, 0, 1280, 720);
const newHeight = 800 / (logo.width / logo.height);
ctx.fillStyle = "#000";
ctx.shadowColor = "#000";
ctx.shadowBlur = 16;
if (stash.checked)
ctx.drawImage(
logo,
400,
Math.min(560 - newHeight / 2, 669 - newHeight),
800,
newHeight
);
else
ctx.drawImage(logo, 64, Math.max(240 - newHeight / 2, 32), 800, newHeight);
} }
const clamp = (n, mi, ma) => Math.max(mi, Math.min(n, ma)); generateButton.addEventListener("click", getScott);
function lightenColor(color, mult) {
return [
clamp(color[0] + (mult / 100) * (255 - color[0]), 0, 255),
clamp(color[1] + (mult / 100) * (255 - color[1]), 0, 255),
clamp(color[2] + (mult / 100) * (255 - color[2]), 0, 255),
];
}
function darkenColor(color, mult) {
return [
clamp(color[0] - (mult / 100) * color[0], 0, 255),
clamp(color[1] - (mult / 100) * color[1], 0, 255),
clamp(color[2] - (mult / 100) * color[2], 0, 255),
];
}
function arrayToColor(color) {
return (
"#" + color.map((x) => Math.floor(x).toString(16).padStart(2, "0")).join("")
);
}

View file

@ -1,217 +0,0 @@
/* Document form */
:root {
--base-scale: 16px;
--background-color: hsl(0, 0%, 15%);
--color: hsl(0, 0%, 85%);
--accent-color: #808080;
--accent-color-fg: hsl(0, 0%, 95%);
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
--document-width: 40em;
--border-style: 0.0625em solid var(--color);
}
body {
width: 100vw;
max-width: var(--document-width);
margin: auto;
padding: 0.5em;
}
html.base {
--background-color: #fff !important;
--color: #000 !important;
--accent-color: #000 !important;
--accent-color-fg: #fff !important;
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol" !important;
--document-width: 40em;
--border-style: 0.0625em solid var(--color);
}
html.base body {
margin: 0;
}
/* Size and type normalize */
html {
font-size: var(--base-scale);
background-color: var(--background-color);
color: var(--color);
}
h1 {
font-size: 2em;
line-height: 1.5em;
margin: 0;
margin-bottom: 0.125em;
}
h2 {
font-size: 1.5em;
line-height: 1.25em;
margin: 0;
margin-bottom: 0.25em;
}
h3 {
font-size: 1.1em;
line-height: 1.25em;
margin: 0;
margin-bottom: 0.25em;
}
p {
font-size: 1em;
line-height: 1.25em;
margin: 0.5em 0;
}
small {
font-size: 0.75em;
}
big {
font-size: 1.5em;
}
code {
font-size: 1em;
line-height: 1.25em;
font-family: monospace;
}
hr {
border: none;
border-top: var(--border-style);
background-color: transparent;
margin: 0.25em 0;
}
/* Form normalize */
html {
font-family: var(--font-family);
}
* {
box-sizing: border-box;
}
*:focus {
outline: 2px solid var(--accent-color-fg);
}
/* Interactive normalize */
a {
color: var(--accent-color);
}
a:hover,
a:focus {
opacity: 0.8;
}
a:active {
opacity: 0.5;
}
input,
select,
textarea {
font-family: inherit;
border: var(--border-style);
padding: 0.25em 0.5em;
margin: 0.25em 0;
font-size: 1em;
background-color: var(--background-color);
color: var(--color);
}
button,
input[type="button"],
input[type="submit"],
input[type="reset"] {
border: var(--border-style);
padding: 0.25em 0.5em;
margin: 0.25em 0;
font-size: 1em;
font-family: inherit;
background-color: var(--accent-color);
color: var(--accent-color-fg);
}
button[data-outlined],
input[type="button"][data-outlined],
input[type="submit"][data-outlined],
input[type="reset"][data-outlined] {
border: var(--border-style);
background-color: var(--background-color);
color: var(--accent-color);
}
button:hover,
input[type="button"]:hover,
input[type="submit"]:hover,
input[type="reset"]:hover,
button:focus,
input[type="button"]:focus,
input[type="submit"]:focus,
input[type="reset"]:focus {
opacity: 0.8;
}
button:active,
input[type="button"]:active,
input[type="submit"]:active,
input[type="reset"]:active {
opacity: 0.5;
}
/* -- Checkbox styling */
label.checkbox {
display: inline-block;
position: relative;
margin: 0.25em 0;
}
label.checkbox input[type="checkbox"] {
/* visibility: hidden; */
opacity: 0;
width: 0;
height: 0;
position: absolute;
top: 0;
left: 0;
}
label.checkbox input[type="checkbox"] + span.checkbox {
display: inline-block;
width: 1em;
height: 1em;
line-height: 1em;
padding: 0.25em;
box-sizing: content-box;
border: var(--border-style);
color: transparent;
text-align: center;
user-select: none;
}
label.checkbox input[type="checkbox"]:focus + span.checkbox {
outline: 2px solid var(--accent-color-fg);
}
label.checkbox input[type="checkbox"]:checked + span.checkbox {
background-color: var(--accent-color);
border: var(--border-style);
color: var(--accent-color-fg);
}