Last active
December 1, 2019 07:11
-
-
Save nwtgck/76a0cc249a4e6147eaf426b3f00a63ce to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// kac-kac code is made by @abagames | |
// kac-kac is on https://github.com/abagames/kackac | |
// Load JS from URL | |
function loadScript(src) { | |
return new Promise((resolve, reject) => { | |
const script = document.createElement("script"); | |
script.src = src; | |
script.onload = resolve; | |
document.head.appendChild(script); | |
}); | |
} | |
(async ()=>{ | |
await loadScript("https://unpkg.com/[email protected]/dist/bundle.min.js"); | |
await loadScript("https://unpkg.com/[email protected]/build/index.js"); | |
await loadScript("https://unpkg.com/[email protected]/build/index.js"); | |
(function (exports) { | |
exports = window; | |
'use strict'; | |
function clamp(v, low = 0, high = 1) { | |
return Math.max(low, Math.min(v, high)); | |
} | |
function wrap(v, low, high) { | |
const w = high - low; | |
const o = v - low; | |
if (o >= 0) { | |
return (o % w) + low; | |
} | |
else { | |
let wv = w + (o % w) + low; | |
if (wv >= high) { | |
wv -= w; | |
} | |
return wv; | |
} | |
} | |
function isInRange(v, low, high) { | |
return low <= v && v < high; | |
} | |
function range(v) { | |
return [...Array(v).keys()]; | |
} | |
function isVectorLike(v) { | |
return v.x != null && v.y != null; | |
} | |
class Vector { | |
constructor(x, y) { | |
this.x = 0; | |
this.y = 0; | |
this.set(x, y); | |
} | |
set(x = 0, y = 0) { | |
if (isVectorLike(x)) { | |
this.x = x.x; | |
this.y = x.y; | |
return this; | |
} | |
this.x = x; | |
this.y = y; | |
return this; | |
} | |
add(x, y) { | |
if (isVectorLike(x)) { | |
this.x += x.x; | |
this.y += x.y; | |
return this; | |
} | |
this.x += x; | |
this.y += y; | |
return this; | |
} | |
sub(x, y) { | |
if (isVectorLike(x)) { | |
this.x -= x.x; | |
this.y -= x.y; | |
return this; | |
} | |
this.x -= x; | |
this.y -= y; | |
return this; | |
} | |
mul(v) { | |
this.x *= v; | |
this.y *= v; | |
return this; | |
} | |
div(v) { | |
this.x /= v; | |
this.y /= v; | |
return this; | |
} | |
clamp(xLow, xHigh, yLow, yHigh) { | |
this.x = clamp(this.x, xLow, xHigh); | |
this.y = clamp(this.y, yLow, yHigh); | |
return this; | |
} | |
wrap(xLow, xHigh, yLow, yHigh) { | |
this.x = wrap(this.x, xLow, xHigh); | |
this.y = wrap(this.y, yLow, yHigh); | |
return this; | |
} | |
addAngle(angle, value) { | |
this.x += Math.cos(angle) * value; | |
this.y += Math.sin(angle) * value; | |
return this; | |
} | |
swapXy() { | |
const t = this.x; | |
this.x = this.y; | |
this.y = t; | |
return this; | |
} | |
normalize() { | |
this.div(this.length); | |
return this; | |
} | |
rotate(angle) { | |
if (angle === 0) { | |
return this; | |
} | |
const tx = this.x; | |
this.x = tx * Math.cos(angle) - this.y * Math.sin(angle); | |
this.y = tx * Math.sin(angle) + this.y * Math.cos(angle); | |
return this; | |
} | |
getAngle(to) { | |
return to == null | |
? Math.atan2(this.y, this.x) | |
: Math.atan2(to.y - this.y, to.x - this.x); | |
} | |
distanceTo(to) { | |
const ox = this.x - to.x; | |
const oy = this.y - to.y; | |
return Math.sqrt(ox * ox + oy * oy); | |
} | |
isInRect(x, y, width, height) { | |
return isInRange(this.x, x, x + width) && isInRange(this.y, y, y + height); | |
} | |
equals(other) { | |
return this.x === other.x && this.y === other.y; | |
} | |
floor() { | |
this.x = Math.floor(this.x); | |
this.y = Math.floor(this.y); | |
return this; | |
} | |
round() { | |
this.x = Math.round(this.x); | |
this.y = Math.round(this.y); | |
return this; | |
} | |
ceil() { | |
this.x = Math.ceil(this.x); | |
this.y = Math.ceil(this.y); | |
return this; | |
} | |
get length() { | |
return Math.sqrt(this.x * this.x + this.y * this.y); | |
} | |
} | |
const size = new Vector(); | |
let canvas; | |
let context; | |
let bodyCss; | |
const canvasCss = ` | |
position: absolute; | |
left: 50%; | |
top: 50%; | |
transform: translate(-50%, -50%); | |
image-rendering: -moz-crisp-edges; | |
image-rendering: -webkit-optimize-contrast; | |
image-rendering: -o-crisp-edges; | |
image-rendering: pixelated; | |
`; | |
let background = document.createElement("img"); | |
let captureCanvas; | |
let captureContext; | |
let viewBackground = "black"; | |
function init(_size, _bodyBackground, _viewBackground, isCapturing) { | |
size.set(_size); | |
viewBackground = _viewBackground; | |
bodyCss = ` | |
-webkit-touch-callout: none; | |
-webkit-tap-highlight-color: ${_bodyBackground}; | |
-webkit-user-select: none; | |
-moz-user-select: none; | |
-ms-user-select: none; | |
user-select: none; | |
background: ${_bodyBackground}; | |
color: #888; | |
`; | |
document.body.style.cssText = bodyCss; | |
canvas = document.createElement("canvas"); | |
canvas.width = size.x; | |
canvas.height = size.y; | |
canvas.style.cssText = canvasCss; | |
const cs = 95; | |
const cw = size.x >= size.y ? cs : (cs / size.y) * size.x; | |
const ch = size.y >= size.x ? cs : (cs / size.x) * size.y; | |
canvas.style.width = `${cw}vmin`; | |
canvas.style.height = `${ch}vmin`; | |
context = canvas.getContext("2d"); | |
context.imageSmoothingEnabled = false; | |
document.body.appendChild(canvas); | |
if (isCapturing) { | |
captureCanvas = document.createElement("canvas"); | |
const cw = size.y * 2; | |
captureCanvas.width = size.x > cw ? size.x : cw; | |
captureCanvas.height = size.y; | |
captureContext = captureCanvas.getContext("2d"); | |
captureContext.fillStyle = _bodyBackground; | |
gcc.setOptions({ scale: 2, capturingFps: 60 }); | |
} | |
} | |
function clear() { | |
context.fillStyle = viewBackground; | |
context.fillRect(0, 0, size.x, size.y); | |
} | |
function capture() { | |
captureContext.fillRect(0, 0, captureCanvas.width, captureCanvas.height); | |
captureContext.drawImage(canvas, (captureCanvas.width - canvas.width) / 2, 0); | |
gcc.capture(captureCanvas); | |
} | |
const letterPatterns = [ | |
// ! | |
` | |
w | |
w | |
w | |
w | |
`, | |
` | |
w w | |
w w | |
`, | |
` | |
w w | |
wwwww | |
w w | |
wwwww | |
w w | |
`, | |
` | |
www | |
w w | |
www | |
w w | |
www | |
`, | |
` | |
w w | |
w w | |
w | |
w w | |
w w | |
`, | |
` | |
w | |
w w | |
ww w | |
w w | |
ww w | |
`, | |
` | |
w | |
w | |
`, | |
` | |
w | |
w | |
w | |
w | |
w | |
`, | |
` | |
w | |
w | |
w | |
w | |
w | |
`, | |
` | |
w | |
w w w | |
www | |
w w w | |
w | |
`, | |
` | |
w | |
w | |
wwwww | |
w | |
w | |
`, | |
` | |
w | |
w | |
`, | |
` | |
wwwww | |
`, | |
` | |
w | |
`, | |
` | |
w | |
w | |
w | |
w | |
w | |
`, | |
// 0 | |
` | |
www | |
w ww | |
w w w | |
ww w | |
www | |
`, | |
` | |
ww | |
w w | |
w | |
w | |
wwwww | |
`, | |
` | |
www | |
w w | |
ww | |
w | |
wwwww | |
`, | |
` | |
www | |
w w | |
ww | |
w w | |
www | |
`, | |
` | |
ww | |
w w | |
w w | |
wwwww | |
w | |
`, | |
` | |
wwwww | |
w | |
wwww | |
w | |
wwww | |
`, | |
` | |
www | |
w | |
wwww | |
w w | |
www | |
`, | |
` | |
wwwww | |
w w | |
w | |
w | |
w | |
`, | |
` | |
www | |
w w | |
www | |
w w | |
www | |
`, | |
` | |
www | |
w w | |
wwww | |
w | |
www | |
`, | |
// : | |
` | |
w | |
w | |
`, | |
` | |
w | |
w | |
w | |
`, | |
` | |
ww | |
ww | |
w | |
ww | |
ww | |
`, | |
` | |
wwwww | |
wwwww | |
`, | |
` | |
ww | |
ww | |
w | |
ww | |
ww | |
`, | |
` | |
www | |
w w | |
ww | |
w | |
`, | |
` | |
www | |
w w | |
w www | |
w | |
www | |
`, | |
// A | |
` | |
www | |
w w | |
wwwww | |
w w | |
w w | |
`, | |
` | |
wwww | |
w w | |
wwww | |
w w | |
wwww | |
`, | |
` | |
www | |
w w | |
w | |
w w | |
www | |
`, | |
` | |
wwww | |
w w | |
w w | |
w w | |
wwww | |
`, | |
` | |
wwwww | |
w | |
wwww | |
w | |
wwwww | |
`, | |
` | |
wwwww | |
w | |
wwww | |
w | |
w | |
`, | |
` | |
www | |
w | |
w ww | |
w w | |
wwww | |
`, | |
` | |
w w | |
w w | |
wwwww | |
w w | |
w w | |
`, | |
` | |
wwwww | |
w | |
w | |
w | |
wwwww | |
`, | |
` | |
wwww | |
w | |
w | |
w w | |
ww | |
`, | |
` | |
w w | |
w w | |
www | |
w w | |
w w | |
`, | |
` | |
w | |
w | |
w | |
w | |
wwwww | |
`, | |
` | |
w w | |
ww ww | |
w w w | |
w w | |
w w | |
`, | |
` | |
w w | |
ww w | |
w w w | |
w ww | |
w w | |
`, | |
` | |
www | |
w w | |
w w | |
w w | |
www | |
`, | |
` | |
wwww | |
w w | |
wwww | |
w | |
w | |
`, | |
` | |
www | |
w w | |
w w | |
w ww | |
wwww | |
`, | |
` | |
wwww | |
w w | |
wwww | |
w w | |
w w | |
`, | |
` | |
wwww | |
w | |
www | |
w | |
wwww | |
`, | |
` | |
wwwww | |
w | |
w | |
w | |
w | |
`, | |
` | |
w w | |
w w | |
w w | |
w w | |
www | |
`, | |
` | |
w w | |
w w | |
w w | |
w w | |
w | |
`, | |
` | |
w w | |
w w | |
w w w | |
w w w | |
w w | |
`, | |
` | |
w w | |
w w | |
w | |
w w | |
w w | |
`, | |
` | |
w w | |
w w | |
w | |
w | |
w | |
`, | |
` | |
wwwww | |
w | |
w | |
w | |
wwwww | |
`, | |
` | |
ww | |
w | |
w | |
w | |
ww | |
`, | |
` | |
w | |
w | |
w | |
w | |
w | |
`, | |
` | |
ww | |
w | |
w | |
w | |
ww | |
`, | |
` | |
w | |
w w | |
`, | |
` | |
wwwww | |
`, | |
` | |
w | |
w | |
`, | |
// a | |
` | |
ww | |
w | |
www | |
w w | |
ww | |
`, | |
` | |
w | |
w | |
www | |
w w | |
www | |
`, | |
` | |
ww | |
w | |
w | |
ww | |
`, | |
` | |
w | |
w | |
www | |
w w | |
www | |
`, | |
` | |
ww | |
w w | |
www | |
w | |
ww | |
`, | |
` | |
w | |
w | |
www | |
w | |
w | |
`, | |
` | |
www | |
w w | |
www | |
w | |
ww | |
`, | |
` | |
w | |
w | |
www | |
w w | |
w w | |
`, | |
` | |
w | |
w | |
w | |
w | |
`, | |
` | |
w | |
w | |
w | |
ww | |
`, | |
` | |
w | |
w | |
w w | |
ww | |
w w | |
`, | |
` | |
ww | |
w | |
w | |
w | |
www | |
`, | |
` | |
ww w | |
w w w | |
w w w | |
w w w | |
`, | |
` | |
w ww | |
ww w | |
w w | |
w w | |
`, | |
` | |
ww | |
w w | |
w w | |
ww | |
`, | |
` | |
www | |
w w | |
www | |
w | |
`, | |
` | |
www | |
w w | |
www | |
w | |
`, | |
` | |
w ww | |
ww | |
w | |
w | |
`, | |
` | |
ww | |
w | |
ww | |
w | |
ww | |
`, | |
` | |
w | |
www | |
w | |
w | |
w | |
`, | |
` | |
w w | |
w w | |
w w | |
ww | |
`, | |
` | |
w w | |
w w | |
ww | |
ww | |
`, | |
` | |
w w w | |
w w w | |
w w w | |
w w | |
`, | |
` | |
w w | |
ww | |
ww | |
w w | |
`, | |
` | |
w w | |
ww | |
w | |
w | |
`, | |
` | |
wwww | |
w | |
w | |
wwww | |
`, | |
//{ | |
` | |
ww | |
w | |
w | |
w | |
ww | |
`, | |
` | |
w | |
w | |
w | |
w | |
w | |
`, | |
` | |
ww | |
w | |
w | |
w | |
ww | |
`, | |
` | |
w | |
w w w | |
w | |
` | |
]; | |
const symbolPatterns = [ | |
// a | |
` | |
w | |
w | |
wwwww | |
w | |
w | |
`, | |
// b | |
` | |
wwwwww | |
wwwwww | |
wwwww | |
wwwww | |
wwww | |
ww | |
`, | |
// c | |
` | |
ww | |
wwww | |
wwww | |
ww | |
`, | |
// d | |
` | |
www | |
www | |
www | |
`, | |
// e | |
` | |
w | |
w | |
w | |
w | |
w | |
w | |
`, | |
// f | |
` | |
wwwwww | |
wwwwww | |
wwwwww | |
`, | |
// g | |
` | |
www | |
www | |
www | |
www | |
www | |
www | |
`, | |
// h | |
` | |
wwww | |
w w | |
w w | |
wwww | |
`, | |
// i | |
` | |
w | |
w w | |
w w | |
w w | |
wwwww | |
`, | |
// j | |
` | |
w | |
w | |
www | |
`, | |
// k | |
` | |
w | |
w | |
wwwwww | |
`, | |
// l | |
` | |
w | |
w | |
wwwwwww | |
w | |
w | |
w | |
`, | |
// m | |
` | |
w | |
w | |
ww | |
`, | |
// n | |
` | |
ww | |
w w | |
w w | |
ww | |
`, | |
// o | |
` | |
w | |
w | |
w | |
`, | |
// p | |
` | |
w | |
w | |
w | |
w | |
w | |
w | |
`, | |
// q | |
` | |
ww | |
ww | |
wwwwww | |
ww | |
w w | |
w w | |
`, | |
// r | |
` | |
wwww | |
w w | |
ww ww | |
w w | |
w ww w | |
wwww | |
`, | |
// s | |
` | |
wwww | |
wwww | |
wwww | |
wwww | |
`, | |
// t | |
` | |
w | |
www | |
www | |
wwwww | |
wwwww | |
`, | |
// u | |
` | |
wwwwww | |
wwwww | |
wwww | |
www | |
ww | |
w | |
`, | |
// v | |
` | |
www | |
www | |
ww | |
`, | |
// w | |
` | |
w w w | |
w w w | |
w w w | |
w w w | |
w w w | |
w w w | |
`, | |
// x | |
` | |
w w | |
w w | |
ww | |
ww | |
w w | |
w w | |
`, | |
// y | |
` | |
www | |
ww | |
w | |
`, | |
// z | |
` | |
w | |
w | |
w w | |
ww | |
www | |
` | |
]; | |
let letterImages; | |
let symbolImages; | |
let cachedImages; | |
let isCacheEnabled = false; | |
let letterCanvas; | |
let letterContext; | |
const dotCount = 6; | |
const dotSize = 1; | |
const letterSize = dotCount * dotSize; | |
const rgbNumbers = [ | |
undefined, | |
0x000000, | |
0xe91e63, | |
0x4caf50, | |
0xffeb3b, | |
0x3f51b5, | |
0x9c27b0, | |
0x03a9f4, | |
0xeeeeee | |
]; | |
let rgbObjects; | |
const colorChars = "tlrgybpcwRGYBPCW"; | |
const rotationChars = "kljhnmbvopiu9087"; | |
function init$1() { | |
letterCanvas = document.createElement("canvas"); | |
letterCanvas.width = letterCanvas.height = letterSize; | |
letterContext = letterCanvas.getContext("2d"); | |
rgbObjects = []; | |
rgbNumbers.forEach(n => { | |
rgbObjects.push({ | |
r: (n & 0xff0000) >> 16, | |
g: (n & 0xff00) >> 8, | |
b: n & 0xff | |
}); | |
}); | |
rgbNumbers.forEach((n, i) => { | |
if (i < 2) { | |
return; | |
} | |
rgbObjects.push({ | |
r: Math.floor((n & 0xff0000) * 0.5) >> 16, | |
g: Math.floor((n & 0xff00) * 0.5) >> 8, | |
b: Math.floor((n & 0xff) * 0.5) | |
}); | |
}); | |
letterImages = letterPatterns.map(lp => createLetterImages(lp)); | |
symbolImages = range(64).map(() => undefined); | |
defineSymbols(symbolPatterns, "a"); | |
cachedImages = {}; | |
} | |
function defineSymbols(pattern, startChar) { | |
const index = startChar.charCodeAt(0) - 0x21; | |
pattern.forEach((p, i) => { | |
symbolImages[index + i] = createLetterImages(p); | |
}); | |
} | |
function enableCache() { | |
isCacheEnabled = true; | |
} | |
function print(_str, x, y, options = {}) { | |
const bx = Math.floor(x); | |
let colorLines = options.colorPattern != null ? options.colorPattern.split("\n") : undefined; | |
const backgroundColorLines = options.backgroundColorPattern != null | |
? options.backgroundColorPattern.split("\n") | |
: undefined; | |
const rotationLines = options.rotationPattern != null | |
? options.rotationPattern.split("\n") | |
: undefined; | |
const symbolLines = options.symbolPattern != null | |
? options.symbolPattern.split("\n") | |
: undefined; | |
const scale = options.scale == null ? 1 : options.scale; | |
const alpha = options.alpha == null ? 1 : options.alpha; | |
let str = _str; | |
if (options.charAndColorPattern != null) { | |
const [_lines, _colorLines] = getColorLines(options.charAndColorPattern); | |
str = _lines.join("\n"); | |
colorLines = _colorLines; | |
} | |
let px = bx; | |
let py = Math.floor(y); | |
let lx = 0; | |
let ly = 0; | |
for (let i = 0; i < str.length; i++) { | |
const c = str[i]; | |
if (c === "\n") { | |
px = bx; | |
py += letterSize * scale; | |
lx = 0; | |
ly++; | |
continue; | |
} | |
printChar(c, px, py, Object.assign(Object.assign({}, getCharOption(options.color != null | |
? options.color | |
: getCharFromLines(colorLines, lx, ly), options.backgroundColor != null | |
? options.backgroundColor | |
: getCharFromLines(backgroundColorLines, lx, ly), options.rotation != null | |
? options.rotation | |
: getCharFromLines(rotationLines, lx, ly), options.symbol != null | |
? options.symbol | |
: getCharFromLines(symbolLines, lx, ly))), { scale, alpha })); | |
px += letterSize * scale; | |
lx++; | |
} | |
} | |
function getColorLines(str) { | |
const _cc = str.split("\n"); | |
const cc = _cc.slice(1, _cc.length - 1); | |
const lines = []; | |
const colorLines = []; | |
let isNormalLine = true; | |
for (const l of cc) { | |
if (isNormalLine) { | |
lines.push(l); | |
isNormalLine = false; | |
continue; | |
} | |
if (isColorLine(l)) { | |
colorLines.push(l); | |
isNormalLine = true; | |
} | |
else { | |
lines.push(l); | |
colorLines.push(""); | |
} | |
} | |
return [lines, colorLines]; | |
} | |
function isColorLine(line) { | |
return (line.trim().length > 0 && | |
line.replace(new RegExp(`[\\s${colorChars}]`, "g"), "").length === 0); | |
} | |
function getCharFromLines(lines, x, y) { | |
if (lines == null) { | |
return undefined; | |
} | |
if (y >= lines.length) { | |
return undefined; | |
} | |
const c = lines[y].charAt(x); | |
return c === "" || c === " " ? undefined : c; | |
} | |
function getCharOption(cg, bg, rg, sg) { | |
let options = { | |
color: "l", | |
backgroundColor: "t", | |
angleIndex: 0, | |
isMirrorX: false, | |
isMirrorY: false, | |
isSymbol: false | |
}; | |
if (cg != null && isColorChars(cg)) { | |
options.color = cg; | |
} | |
if (bg != null && isColorChars(bg)) { | |
options.backgroundColor = bg; | |
} | |
if (rg != null) { | |
const ri = rotationChars.indexOf(rg); | |
if (ri >= 0) { | |
options.angleIndex = ri % 4; | |
options.isMirrorX = (ri & 4) > 0; | |
options.isMirrorY = (ri & 8) > 0; | |
} | |
} | |
if (sg === "s") { | |
options.isSymbol = true; | |
} | |
return options; | |
} | |
function printChar(c, x, y, options) { | |
const cca = c.charCodeAt(0); | |
if (cca < 0x20 || cca > 0x7e) { | |
return; | |
} | |
const scaledSize = letterSize * options.scale; | |
if (options.backgroundColor !== "t") { | |
const rgb = rgbObjects[colorChars.indexOf(options.backgroundColor)]; | |
context.fillStyle = `rgba(${rgb.r},${rgb.g},${rgb.b},${Math.floor(options.alpha * 255)})`; | |
context.fillRect(x, y, scaledSize, scaledSize); | |
} | |
if (cca == 0x20 || options.color === "t") { | |
return; | |
} | |
const cc = cca - 0x21; | |
const img = options.isSymbol ? symbolImages[cc] : letterImages[cc]; | |
if (options.color === "w" && | |
options.angleIndex % 4 === 0 && | |
!options.isMirrorX && | |
!options.isMirrorY && | |
options.alpha === 1) { | |
if (options.scale === 1) { | |
context.drawImage(img, x, y); | |
} | |
else { | |
context.drawImage(img, x, y, scaledSize, scaledSize); | |
} | |
return; | |
} | |
const cacheIndex = JSON.stringify({ c, options }); | |
const ci = cachedImages[cacheIndex]; | |
if (ci != null) { | |
context.drawImage(ci, x, y); | |
return; | |
} | |
letterContext.clearRect(0, 0, letterSize, letterSize); | |
letterContext.globalAlpha = options.alpha; | |
if (options.angleIndex % 4 === 0 && | |
!options.isMirrorX && | |
!options.isMirrorY) { | |
letterContext.drawImage(img, 0, 0); | |
} | |
else { | |
letterContext.save(); | |
letterContext.translate(letterSize / 2, letterSize / 2); | |
letterContext.rotate((Math.PI / 2) * options.angleIndex); | |
if (options.isMirrorX || options.isMirrorY) { | |
letterContext.scale(options.isMirrorX ? -1 : 1, options.isMirrorY ? -1 : 1); | |
} | |
letterContext.drawImage(img, -letterSize / 2, -letterSize / 2); | |
letterContext.restore(); | |
} | |
if (options.color !== "w") { | |
letterContext.globalCompositeOperation = "source-in"; | |
const rgb = rgbObjects[colorChars.indexOf(options.color)]; | |
letterContext.fillStyle = `rgb(${rgb.r},${rgb.g},${rgb.b})`; | |
letterContext.fillRect(0, 0, letterSize, letterSize); | |
letterContext.globalCompositeOperation = "source-over"; | |
} | |
context.drawImage(letterCanvas, x, y, scaledSize, scaledSize); | |
if (isCacheEnabled) { | |
const cachedImage = document.createElement("img"); | |
cachedImage.src = letterCanvas.toDataURL(); | |
cachedImages[cacheIndex] = cachedImage; | |
} | |
} | |
function isColorChars(c) { | |
return colorChars.indexOf(c) >= 0; | |
} | |
function createLetterImages(pattern, isSkippingFirstAndLastLine = true) { | |
letterContext.clearRect(0, 0, letterSize, letterSize); | |
let p = pattern.split("\n"); | |
if (isSkippingFirstAndLastLine) { | |
p = p.slice(1, p.length - 1); | |
} | |
let pw = 0; | |
p.forEach(l => { | |
pw = Math.max(l.length, pw); | |
}); | |
const xPadding = Math.max(Math.ceil((dotCount - pw) / 2), 0); | |
const ph = p.length; | |
const yPadding = Math.max(Math.ceil((dotCount - ph) / 2), 0); | |
p.forEach((l, y) => { | |
if (y + yPadding >= dotCount) { | |
return; | |
} | |
for (let x = 0; x < dotCount - xPadding; x++) { | |
const c = l.charAt(x); | |
let ci = colorChars.indexOf(c); | |
if (c !== "" && ci >= 1) { | |
const rgb = rgbObjects[ci]; | |
letterContext.fillStyle = `rgb(${rgb.r},${rgb.g},${rgb.b})`; | |
letterContext.fillRect((x + xPadding) * dotSize, (y + yPadding) * dotSize, dotSize, dotSize); | |
} | |
} | |
}); | |
const img = document.createElement("img"); | |
img.src = letterCanvas.toDataURL(); | |
return img; | |
} | |
let isPressed = false; | |
let isJustPressed = false; | |
let isJustReleased = false; | |
const stick = new Vector(); | |
let stickAngle; | |
const isStickPressed = range(4).map(() => false); | |
const isStickJustPressed = range(4).map(() => false); | |
const isStickJustReleased = range(4).map(() => false); | |
const defaultOptions = { | |
isUsingStickKeysAsButton: false, | |
isFourWaysStick: false, | |
onKeyDown: undefined | |
}; | |
let options$1; | |
const isKeyPressing = range(256).map(() => false); | |
const isKeyPressed = range(256).map(() => false); | |
const isKeyReleased = range(256).map(() => false); | |
const stickKeys = [ | |
[39, 68, 102], | |
[40, 83, 101, 98], | |
[37, 65, 100], | |
[38, 87, 104] | |
]; | |
const stickXys = [[1, 0], [0, 1], [-1, 0], [0, -1]]; | |
const buttonKeys = [ | |
90, | |
88, | |
67, | |
86, | |
66, | |
78, | |
77, | |
188, | |
190, | |
191, | |
17, | |
16, | |
18, | |
32, | |
13 | |
]; | |
function init$2(_options) { | |
options$1 = Object.assign(Object.assign({}, defaultOptions), _options); | |
document.addEventListener("keydown", e => { | |
isKeyPressing[e.keyCode] = isKeyPressed[e.keyCode] = true; | |
if (options$1.onKeyDown != null) { | |
options$1.onKeyDown(); | |
} | |
}); | |
document.addEventListener("keyup", e => { | |
isKeyPressing[e.keyCode] = false; | |
isKeyReleased[e.keyCode] = true; | |
}); | |
} | |
function update$1() { | |
const pp = isPressed; | |
isPressed = isJustPressed = isJustReleased = false; | |
range(4).forEach(i => { | |
isStickPressed[i] = isStickJustPressed[i] = isStickJustReleased[i] = false; | |
}); | |
stick.set(0); | |
stickKeys.forEach((ks, i) => { | |
ks.forEach(k => { | |
if (isKeyPressing[k] || isKeyPressed[k]) { | |
stick.x += stickXys[i][0]; | |
stick.y += stickXys[i][1]; | |
isStickPressed[i] = true; | |
if (options$1.isUsingStickKeysAsButton) { | |
isPressed = true; | |
} | |
if (isKeyPressed[k]) { | |
isKeyPressed[k] = false; | |
isStickJustPressed[i] = true; | |
if (options$1.isUsingStickKeysAsButton && !pp) { | |
isJustPressed = true; | |
} | |
} | |
} | |
if (isKeyReleased[k]) { | |
isKeyReleased[k] = false; | |
isStickJustReleased[i] = true; | |
if (options$1.isUsingStickKeysAsButton && pp) { | |
isJustReleased = true; | |
} | |
} | |
}); | |
}); | |
stickAngle = -1; | |
if (stick.length > 0) { | |
setStickAngle(stick.getAngle()); | |
} | |
buttonKeys.forEach(k => { | |
if (isKeyPressing[k]) { | |
isPressed = true; | |
} | |
if (isKeyPressed[k]) { | |
isKeyPressed[k] = false; | |
if (!pp) { | |
isPressed = isJustPressed = true; | |
} | |
} | |
if (isKeyReleased[k]) { | |
isKeyReleased[k] = false; | |
if (pp) { | |
isJustReleased = true; | |
} | |
} | |
}); | |
} | |
const angleOffsets = [1, 0, 1, 1, 0, 1, -1, 1, -1, 0, -1, -1, 0, -1, 1, -1]; | |
function setStickAngle(a) { | |
const wayAngle = options$1.isFourWaysStick ? Math.PI / 2 : Math.PI / 4; | |
const angleStep = options$1.isFourWaysStick ? 2 : 1; | |
stickAngle = wrap(Math.round(a / wayAngle) * angleStep, 0, 8); | |
stick.set(angleOffsets[stickAngle * 2], angleOffsets[stickAngle * 2 + 1]); | |
} | |
function clearJustPressed() { | |
isJustPressed = false; | |
isPressed = true; | |
} | |
class Random { | |
constructor(seed = null) { | |
this.setSeed(seed); | |
} | |
get(lowOrHigh = 1, high) { | |
if (high == null) { | |
high = lowOrHigh; | |
lowOrHigh = 0; | |
} | |
return (this.next() / 0xffffffff) * (high - lowOrHigh) + lowOrHigh; | |
} | |
getInt(lowOrHigh, high) { | |
if (high == null) { | |
high = lowOrHigh; | |
lowOrHigh = 0; | |
} | |
return (this.next() % (high - lowOrHigh)) + lowOrHigh; | |
} | |
getPlusOrMinus() { | |
return this.getInt(2) * 2 - 1; | |
} | |
select(values) { | |
return values[this.getInt(values.length)]; | |
} | |
setSeed(w, x = 123456789, y = 362436069, z = 521288629, loopCount = 32) { | |
this.w = w != null ? w >>> 0 : Math.floor(Math.random() * 0xffffffff) >>> 0; | |
this.x = x >>> 0; | |
this.y = y >>> 0; | |
this.z = z >>> 0; | |
for (let i = 0; i < loopCount; i++) { | |
this.next(); | |
} | |
return this; | |
} | |
next() { | |
const t = this.x ^ (this.x << 11); | |
this.x = this.y; | |
this.y = this.z; | |
this.z = this.w; | |
this.w = (this.w ^ (this.w >>> 19) ^ (t ^ (t >>> 8))) >>> 0; | |
return this.w; | |
} | |
} | |
const pos = new Vector(); | |
const move = new Vector(); | |
const pressedPos = new Vector(); | |
const targetPos = new Vector(); | |
let isPressed$1 = false; | |
let isJustPressed$1 = false; | |
let isJustReleased$1 = false; | |
let defaultOptions$1 = { | |
isDebugMode: false, | |
anchor: new Vector(), | |
padding: new Vector(), | |
onPointerDownOrUp: undefined | |
}; | |
let screen; | |
let pixelSize; | |
let options$2; | |
const prevPos = new Vector(); | |
const debugRandom = new Random(); | |
const debugPos = new Vector(); | |
const debugMoveVel = new Vector(); | |
let debugIsDown = false; | |
let cursorPos = new Vector(-9999, -9999); | |
let isDown = false; | |
let isClicked = false; | |
let isReleased = false; | |
let isResettingTargetPos = false; | |
function init$3(_screen, _pixelSize, _options) { | |
options$2 = Object.assign(Object.assign({}, defaultOptions$1), _options); | |
screen = _screen; | |
pixelSize = new Vector(_pixelSize.x + options$2.padding.x * 2, _pixelSize.y + options$2.padding.y * 2); | |
targetPos.set(pixelSize.x / 2, pixelSize.y / 2); | |
if (options$2.isDebugMode) { | |
debugPos.set(pixelSize.x / 2, pixelSize.y / 2); | |
} | |
document.addEventListener("mousedown", e => { | |
onDown(e.pageX, e.pageY); | |
}); | |
document.addEventListener("touchstart", e => { | |
onDown(e.touches[0].pageX, e.touches[0].pageY); | |
}); | |
document.addEventListener("mousemove", e => { | |
onMove(e.pageX, e.pageY); | |
}); | |
document.addEventListener("touchmove", e => { | |
e.preventDefault(); | |
onMove(e.touches[0].pageX, e.touches[0].pageY); | |
}, { passive: false }); | |
document.addEventListener("mouseup", e => { | |
onUp(); | |
}); | |
document.addEventListener("touchend", e => { | |
e.preventDefault(); | |
e.target.click(); | |
onUp(); | |
}, { passive: false }); | |
} | |
function update$2() { | |
calcPointerPos(cursorPos.x, cursorPos.y, pos); | |
if (options$2.isDebugMode && !pos.isInRect(0, 0, pixelSize.x, pixelSize.y)) { | |
updateDebug(); | |
pos.set(debugPos); | |
isJustPressed$1 = !isPressed$1 && debugIsDown; | |
isJustReleased$1 = isPressed$1 && !debugIsDown; | |
isPressed$1 = debugIsDown; | |
} | |
else { | |
isJustPressed$1 = !isPressed$1 && isClicked; | |
isJustReleased$1 = isPressed$1 && isReleased; | |
isPressed$1 = isDown; | |
} | |
if (isJustPressed$1) { | |
pressedPos.set(pos); | |
prevPos.set(pos); | |
} | |
move.set(pos.x - prevPos.x, pos.y - prevPos.y); | |
prevPos.set(pos); | |
if (isResettingTargetPos) { | |
targetPos.set(pos); | |
} | |
else { | |
targetPos.add(move); | |
} | |
isClicked = isReleased = false; | |
} | |
function clearJustPressed$1() { | |
isJustPressed$1 = false; | |
isPressed$1 = true; | |
} | |
function setTargetPos(v) { | |
targetPos.set(v); | |
} | |
function calcPointerPos(x, y, v) { | |
if (screen == null) { | |
return; | |
} | |
v.x = | |
((x - screen.offsetLeft) / screen.clientWidth + options$2.anchor.x) * | |
pixelSize.x - | |
options$2.padding.x; | |
v.y = | |
((y - screen.offsetTop) / screen.clientHeight + options$2.anchor.y) * | |
pixelSize.y - | |
options$2.padding.y; | |
} | |
function updateDebug() { | |
if (debugMoveVel.length > 0) { | |
debugPos.add(debugMoveVel); | |
if (!isInRange(debugPos.x, -pixelSize.x * 0.1, pixelSize.x * 1.1) && | |
debugPos.x * debugMoveVel.x > 0) { | |
debugMoveVel.x *= -1; | |
} | |
if (!isInRange(debugPos.y, -pixelSize.y * 0.1, pixelSize.y * 1.1) && | |
debugPos.y * debugMoveVel.y > 0) { | |
debugMoveVel.y *= -1; | |
} | |
if (debugRandom.get() < 0.05) { | |
debugMoveVel.set(0); | |
} | |
} | |
else { | |
if (debugRandom.get() < 0.1) { | |
debugMoveVel.set(0); | |
debugMoveVel.addAngle(debugRandom.get(Math.PI * 2), (pixelSize.x + pixelSize.y) * debugRandom.get(0.01, 0.03)); | |
} | |
} | |
if (debugRandom.get() < 0.05) { | |
debugIsDown = !debugIsDown; | |
} | |
} | |
function onDown(x, y) { | |
cursorPos.set(x, y); | |
isDown = isClicked = true; | |
isResettingTargetPos = false; | |
if (options$2.onPointerDownOrUp != null) { | |
options$2.onPointerDownOrUp(); | |
} | |
} | |
function onMove(x, y) { | |
cursorPos.set(x, y); | |
if (!isDown) { | |
isResettingTargetPos = true; | |
} | |
} | |
function onUp(e) { | |
isDown = false; | |
isReleased = true; | |
isResettingTargetPos = false; | |
if (options$2.onPointerDownOrUp != null) { | |
options$2.onPointerDownOrUp(); | |
} | |
} | |
let stickAngle$1 = 0; | |
let isPressed$2 = false; | |
let isJustPressed$2 = false; | |
let isJustReleased$2 = false; | |
let isUsingVirtualPad; | |
let isFourWaysStick; | |
let centerPos = new Vector(); | |
let offsetFromCenter = new Vector(); | |
function init$4(_isUsingVirtualPad = true, _isFourWaysStick = false) { | |
isUsingVirtualPad = _isUsingVirtualPad; | |
isFourWaysStick = _isFourWaysStick; | |
centerPos.set(size.x / 2, size.y / 2); | |
init$2({ | |
onKeyDown: sss.playEmpty, | |
isUsingStickKeysAsButton: true, | |
isFourWaysStick | |
}); | |
init$3(canvas, size, { | |
onPointerDownOrUp: sss.playEmpty, | |
anchor: new Vector(0.5, 0.5) | |
}); | |
} | |
function update$3() { | |
stickAngle$1 = -1; | |
update$1(); | |
if (stickAngle >= 0) { | |
stickAngle$1 = stickAngle; | |
} | |
update$2(); | |
if (isPressed$1) { | |
if (isJustPressed$1) { | |
setTargetPos(centerPos); | |
} | |
if (isUsingVirtualPad) { | |
offsetFromCenter.set(targetPos).sub(centerPos); | |
if (offsetFromCenter.length > 10) { | |
const oa = offsetFromCenter.getAngle() / (Math.PI / 4); | |
stickAngle$1 = wrap(Math.round(oa), 0, 8); | |
if (isFourWaysStick) { | |
stickAngle$1 = Math.floor(stickAngle$1 / 2) * 2; | |
} | |
} | |
} | |
} | |
isPressed$2 = isPressed || isPressed$1; | |
isJustPressed$2 = isJustPressed || isJustPressed$1; | |
isJustReleased$2 = isJustReleased || isJustReleased$1; | |
} | |
function draw() { | |
if (isUsingVirtualPad && isPressed$1) { | |
print("c", size.x / 2 - 2, size.y / 2 - 2, { | |
colorPattern: "b", | |
backgroundColorPattern: "t", | |
symbolPattern: "s", | |
alpha: 0.5 | |
}); | |
let cc = "c"; | |
let rc = "k"; | |
if (stickAngle$1 >= 0) { | |
cc = stickAngle$1 % 2 === 0 ? "a" : "z"; | |
rc = "kljh".charAt(Math.floor(stickAngle$1 / 2)); | |
} | |
print(cc, targetPos.x - 2, targetPos.y - 2, { | |
colorPattern: "g", | |
backgroundColorPattern: "t", | |
symbolPattern: "s", | |
rotationPattern: rc, | |
alpha: 0.5 | |
}); | |
} | |
} | |
function clearJustPressed$2() { | |
clearJustPressed(); | |
clearJustPressed$1(); | |
} | |
let lastFrameTime = 0; | |
let _init; | |
let _update; | |
const defaultOptions$2 = { | |
viewSize: { x: 126, y: 126 }, | |
bodyBackground: "#111", | |
viewBackground: "black", | |
isUsingVirtualPad: true, | |
isFourWaysStick: false, | |
isCapturing: false | |
}; | |
let options$3; | |
let textCacheEnableTicks = 10; | |
function init$5(__init, __update, _options) { | |
_init = __init; | |
_update = __update; | |
options$3 = Object.assign(Object.assign({}, defaultOptions$2), _options); | |
init(options$3.viewSize, options$3.bodyBackground, options$3.viewBackground, options$3.isCapturing); | |
init$4(options$3.isUsingVirtualPad, options$3.isFourWaysStick); | |
init$1(); | |
_init(); | |
update$4(); | |
} | |
function update$4() { | |
requestAnimationFrame(update$4); | |
const now = window.performance.now(); | |
const timeSinceLast = now - lastFrameTime; | |
if (timeSinceLast < 1000 / 60 - 5) { | |
return; | |
} | |
lastFrameTime = now; | |
sss.update(); | |
update$3(); | |
_update(); | |
draw(); | |
if (options$3.isCapturing) { | |
capture(); | |
} | |
textCacheEnableTicks--; | |
if (textCacheEnableTicks === 0) { | |
enableCache(); | |
} | |
} | |
class Terminal { | |
constructor(_size) { | |
this.size = new Vector(); | |
this.size.set(_size); | |
this.charGrid = range(this.size.x).map(() => range(this.size.y).map(() => undefined)); | |
this.colorGrid = range(this.size.x).map(() => range(this.size.y).map(() => undefined)); | |
this.backgroundColorGrid = range(this.size.x).map(() => range(this.size.y).map(() => undefined)); | |
this.rotationGrid = range(this.size.x).map(() => range(this.size.y).map(() => undefined)); | |
this.symbolGrid = range(this.size.x).map(() => range(this.size.y).map(() => undefined)); | |
} | |
print(_str, _x, _y, options = {}) { | |
let x = Math.floor(_x); | |
let y = Math.floor(_y); | |
const bx = x; | |
let colorLines = options.colorPattern != null | |
? options.colorPattern.split("\n") | |
: undefined; | |
const backgroundColorLines = options.backgroundColorPattern != null | |
? options.backgroundColorPattern.split("\n") | |
: undefined; | |
const rotationLines = options.rotationPattern != null | |
? options.rotationPattern.split("\n") | |
: undefined; | |
const symbolLines = options.symbolPattern != null | |
? options.symbolPattern.split("\n") | |
: undefined; | |
let str = _str; | |
if (options.charAndColorPattern != null) { | |
const [_lines, _colorLines] = getColorLines(options.charAndColorPattern); | |
str = _lines.join("\n"); | |
colorLines = _colorLines; | |
} | |
let lx = 0; | |
let ly = 0; | |
for (let i = 0; i < str.length; i++) { | |
const c = str[i]; | |
if (c === "\n") { | |
x = bx; | |
y++; | |
lx = 0; | |
ly++; | |
continue; | |
} | |
if (x < 0 || x >= this.size.x || y < 0 || y >= this.size.y) { | |
x++; | |
lx++; | |
continue; | |
} | |
this.charGrid[x][y] = c; | |
this.colorGrid[x][y] = | |
options.color != null | |
? options.color | |
: getCharFromLines(colorLines, lx, ly); | |
this.backgroundColorGrid[x][y] = | |
options.backgroundColor != null | |
? options.backgroundColor | |
: getCharFromLines(backgroundColorLines, lx, ly); | |
this.rotationGrid[x][y] = | |
options.rotation != null | |
? options.rotation | |
: getCharFromLines(rotationLines, lx, ly); | |
this.symbolGrid[x][y] = | |
options.symbol != null | |
? options.symbol | |
: getCharFromLines(symbolLines, lx, ly); | |
x++; | |
lx++; | |
} | |
} | |
getCharAt(_x, _y) { | |
if (_x < 0 || _x >= this.size.x || _y < 0 || _y >= this.size.y) { | |
return undefined; | |
} | |
const x = Math.floor(_x); | |
const y = Math.floor(_y); | |
const char = this.charGrid[x][y]; | |
const cg = this.colorGrid[x][y]; | |
const bg = this.backgroundColorGrid[x][y]; | |
const rg = this.rotationGrid[x][y]; | |
const sg = this.symbolGrid[x][y]; | |
return { char, options: getCharOption(cg, bg, rg, sg) }; | |
} | |
setCharAt(_x, _y, char, options) { | |
if (_x < 0 || _x >= this.size.x || _y < 0 || _y >= this.size.y) { | |
return; | |
} | |
const x = Math.floor(_x); | |
const y = Math.floor(_y); | |
this.charGrid[x][y] = char; | |
if (options == null) { | |
this.colorGrid[x][y] = this.backgroundColorGrid[x][y] = this.rotationGrid[x][y] = undefined; | |
return; | |
} | |
this.colorGrid[x][y] = options.color; | |
this.backgroundColorGrid[x][y] = options.backgroundColor; | |
if (options.angleIndex == null) { | |
this.rotationGrid[x][y] = undefined; | |
} | |
else { | |
let ri = options.angleIndex; | |
if (options.isMirrorX) { | |
ri |= 4; | |
} | |
if (options.isMirrorY) { | |
ri |= 8; | |
} | |
this.rotationGrid[x][y] = rotationChars.charAt(ri); | |
} | |
this.symbolGrid[x][y] = options.isSymbol ? "s" : undefined; | |
} | |
draw() { | |
for (let x = 0; x < this.size.x; x++) { | |
for (let y = 0; y < this.size.y; y++) { | |
const c = this.charGrid[x][y]; | |
if (c == null) { | |
continue; | |
} | |
const cg = this.colorGrid[x][y]; | |
const bg = this.backgroundColorGrid[x][y]; | |
const rg = this.rotationGrid[x][y]; | |
const sg = this.symbolGrid[x][y]; | |
printChar(c, x * letterSize, y * letterSize, Object.assign(Object.assign({}, getCharOption(cg, bg, rg, sg)), { scale: 1, alpha: 1 })); | |
} | |
} | |
} | |
clear() { | |
for (let x = 0; x < this.size.x; x++) { | |
for (let y = 0; y < this.size.y; y++) { | |
this.charGrid[x][y] = this.colorGrid[x][y] = this.backgroundColorGrid[x][y] = this.rotationGrid[x][y] = this.symbolGrid[x][y] = undefined; | |
} | |
} | |
} | |
scrollUp() { | |
for (let x = 0; x < this.size.x; x++) { | |
for (let y = 1; y < this.size.y; y++) { | |
this.charGrid[x][y - 1] = this.charGrid[x][y]; | |
this.colorGrid[x][y - 1] = this.colorGrid[x][y]; | |
this.backgroundColorGrid[x][y - 1] = this.backgroundColorGrid[x][y]; | |
this.rotationGrid[x][y - 1] = this.rotationGrid[x][y]; | |
this.symbolGrid[x][y - 1] = this.symbolGrid[x][y]; | |
} | |
} | |
const y = this.size.y - 1; | |
for (let x = 0; x < this.size.x; x++) { | |
this.charGrid[x][y] = this.colorGrid[x][y] = this.backgroundColorGrid[x][y] = this.rotationGrid[x][y] = this.symbolGrid[x][y] = undefined; | |
} | |
} | |
getState() { | |
return { | |
charGrid: this.charGrid.map(l => [].concat(l)), | |
colorGrid: this.colorGrid.map(l => [].concat(l)), | |
backgroundColorGrid: this.backgroundColorGrid.map(l => [].concat(l)), | |
rotationGrid: this.rotationGrid.map(l => [].concat(l)), | |
symbolGrid: this.symbolGrid.map(l => [].concat(l)) | |
}; | |
} | |
setState(state) { | |
this.charGrid = state.charGrid.map(l => [].concat(l)); | |
this.colorGrid = state.colorGrid.map(l => [].concat(l)); | |
this.backgroundColorGrid = state.backgroundColorGrid.map(l => [].concat(l)); | |
this.rotationGrid = state.rotationGrid.map(l => [].concat(l)); | |
this.symbolGrid = state.symbolGrid.map(l => [].concat(l)); | |
} | |
} | |
const PI = Math.PI; | |
const abs = Math.abs; | |
const sin = Math.sin; | |
const cos = Math.cos; | |
const atan2 = Math.atan2; | |
const sqrt = Math.sqrt; | |
const pow = Math.pow; | |
const floor = Math.floor; | |
const round = Math.round; | |
const ceil = Math.ceil; | |
exports.scr = 0; | |
const defaultOptions$3 = { | |
seed: 0, | |
isCapturing: false, | |
viewSize: { x: 100, y: 100 }, | |
isPlayingBgm: false | |
}; | |
function end() { | |
initGameOver(); | |
} | |
function rect(x, y, width, height) { | |
return drawRect(false, x, y, width, height); | |
} | |
function box(x, y, width, height) { | |
return drawRect(true, x, y, width, height); | |
} | |
function bar(x, y, length, thickness, rotate = 0.5, centerPosRatio = 0.5) { | |
if (typeof x !== "number") { | |
centerPosRatio = rotate; | |
rotate = thickness; | |
thickness = length; | |
length = y; | |
y = x.y; | |
x = x.x; | |
} | |
const l = new Vector(length).rotate(rotate); | |
const p = new Vector(x - l.x * centerPosRatio, y - l.y * centerPosRatio); | |
return drawLine(p, l, thickness); | |
} | |
function line(x1, y1, x2 = 3, y2 = 3, thickness = 3) { | |
const p = new Vector(); | |
const p2 = new Vector(); | |
if (typeof x1 === "number") { | |
if (typeof y1 === "number") { | |
if (typeof x2 === "number") { | |
p.set(x1, y1); | |
p2.set(x2, y2); | |
} | |
else { | |
p.set(x1, y1); | |
p2.set(x2); | |
thickness = y1; | |
} | |
} | |
else { | |
throw "invalid params"; | |
} | |
} | |
else { | |
if (typeof y1 === "number") { | |
if (typeof x2 === "number") { | |
p.set(x1); | |
p2.set(y1, x2); | |
thickness = y2; | |
} | |
else { | |
throw "invalid params"; | |
} | |
} | |
else { | |
if (typeof x2 === "number") { | |
p.set(x1); | |
p2.set(y1); | |
thickness = x2; | |
} | |
else { | |
throw "invalid params"; | |
} | |
} | |
} | |
return drawLine(p, p2.sub(p), thickness); | |
} | |
function vec(x, y) { | |
return new Vector(x, y); | |
} | |
function rnd(lowOrHigh = 1, high) { | |
return random.get(lowOrHigh, high); | |
} | |
function rndi(lowOrHigh = 2, high) { | |
return random.getInt(lowOrHigh, high); | |
} | |
function rnds(lowOrHigh = 1, high) { | |
return random.get(lowOrHigh, high) * random.getPlusOrMinus(); | |
} | |
class inp { | |
} | |
inp.p = new Vector(); | |
inp.ip = false; | |
inp.ijp = false; | |
inp.ijr = false; | |
function play(type) { | |
sss.play(capitalLetterStrings[type]); | |
} | |
let state; | |
let updateFunc = { | |
title: updateTitle, | |
inGame: updateInGame, | |
gameOver: updateGameOver | |
}; | |
let terminal; | |
let random = new Random(); | |
let ticks = 0; | |
let hiScore = 0; | |
let capitalLetterStrings = {}; | |
let rects; | |
let tmpRects; | |
let isNoTitle = true; | |
let seed = 0; | |
let loopOptions; | |
let terminalSize; | |
let isPlayingBgm; | |
const loadPromise = addGameScript(); | |
loadPromise.then(onLoad); | |
function onLoad() { | |
loopOptions = { | |
viewSize: { x: 100, y: 100 }, | |
bodyBackground: "#ddd", | |
viewBackground: "#eee", | |
isUsingVirtualPad: false | |
}; | |
let opts; | |
if (typeof options !== "undefined" && options() != null) { | |
opts = Object.assign(Object.assign({}, defaultOptions$3), options()); | |
} | |
else { | |
opts = defaultOptions$3; | |
} | |
seed = opts.seed; | |
loopOptions.isCapturing = opts.isCapturing; | |
loopOptions.viewSize = opts.viewSize; | |
isPlayingBgm = opts.isPlayingBgm; | |
init$5(init$6, _update$1, loopOptions); | |
} | |
function init$6() { | |
if (typeof description !== "undefined" && | |
description() != null && | |
description().trim().length > 0) { | |
isNoTitle = false; | |
seed += getHash(description()); | |
} | |
if (typeof title !== "undefined" && | |
title() != null && | |
title().trim().length > 0) { | |
isNoTitle = false; | |
document.title = title(); | |
} | |
sss.init(seed); | |
showScript(); | |
addCapitalVariables(); | |
exports.col = L; | |
const sz = loopOptions.viewSize; | |
terminalSize = { x: Math.floor(sz.x / 6), y: Math.floor(sz.y / 6) }; | |
terminal = new Terminal(terminalSize); | |
if (isNoTitle) { | |
initInGame(); | |
ticks = 0; | |
} | |
else { | |
initTitle(); | |
} | |
} | |
function _update$1() { | |
rects = []; | |
tmpRects = []; | |
exports.tc = ticks; | |
exports.df = ticks / 3600 + 1; | |
inp.p = pos; | |
inp.ip = isPressed$2; | |
inp.ijp = isJustPressed$2; | |
inp.ijr = isJustReleased$2; | |
updateFunc[state](); | |
ticks++; | |
} | |
function initInGame() { | |
state = "inGame"; | |
ticks = -1; | |
const s = Math.floor(exports.scr); | |
if (s > hiScore) { | |
hiScore = s; | |
} | |
exports.scr = 0; | |
if (isPlayingBgm) { | |
sss.playBgm(); | |
} | |
} | |
function updateInGame() { | |
terminal.clear(); | |
clear(); | |
update(); | |
drawScore(); | |
terminal.draw(); | |
} | |
function initTitle() { | |
state = "title"; | |
ticks = -1; | |
terminal.clear(); | |
clear(); | |
} | |
function updateTitle() { | |
if (ticks === 0) { | |
drawScore(); | |
if (typeof title !== "undefined" && title() != null) { | |
terminal.print(title(), Math.floor(terminalSize.x - title().length) / 2, 3); | |
} | |
terminal.draw(); | |
} | |
if (ticks === 30 || ticks == 40) { | |
if (typeof description !== "undefined" && description() != null) { | |
let maxLineLength = 0; | |
description() | |
.split("\n") | |
.forEach(l => { | |
if (l.length > maxLineLength) { | |
maxLineLength = l.length; | |
} | |
}); | |
const x = Math.floor((terminalSize.x - maxLineLength) / 2); | |
description() | |
.split("\n") | |
.forEach((l, i) => { | |
terminal.print(l, x, Math.floor(terminalSize.y / 2) + i); | |
}); | |
terminal.draw(); | |
} | |
} | |
if (isJustPressed$2) { | |
initInGame(); | |
} | |
} | |
function initGameOver() { | |
state = "gameOver"; | |
clearJustPressed$2(); | |
ticks = -1; | |
drawGameOver(); | |
if (isPlayingBgm) { | |
sss.stopBgm(); | |
} | |
} | |
function updateGameOver() { | |
if (ticks > 20 && isJustPressed$2) { | |
initInGame(); | |
} | |
else if (ticks === 500 && !isNoTitle) { | |
initTitle(); | |
} | |
if (ticks === 10) { | |
drawGameOver(); | |
} | |
} | |
function drawGameOver() { | |
terminal.print("GAME OVER", Math.floor((terminalSize.x - 9) / 2), Math.floor(terminalSize.y / 2)); | |
terminal.draw(); | |
} | |
function drawScore() { | |
terminal.print(`${Math.floor(exports.scr)}`, 0, 0); | |
const hs = `HI ${hiScore}`; | |
terminal.print(hs, terminalSize.x - hs.length, 0); | |
} | |
function addGameScript() { | |
return new Promise(resolve => { | |
const script = document.createElement("script"); | |
const game = ( | |
` | |
function title() { | |
return document.title; | |
} | |
function description() { | |
return ""; | |
} | |
function options() { | |
return { | |
isPlayingBgm: true, | |
isCapturing: true | |
}; | |
} | |
function update() { | |
${window.INPUT} | |
} | |
`); | |
const dataUri = "data:text/javascript;base64," + btoa(game); | |
script.setAttribute("src", dataUri); | |
script.onload = resolve; | |
document.head.appendChild(script); | |
}); | |
} | |
function showScript() { | |
const minifiedCode = Terser.minify(update.toString(), { mangle: false }) | |
.code.slice(18, -1) | |
.replace(/(var |let |const )/g, ""); | |
console.log(minifiedCode); | |
console.log(`${minifiedCode.length} letters`); | |
} | |
function addCapitalVariables() { | |
let v = 1; | |
for (let i = "A".charCodeAt(0); i <= "Z".charCodeAt(0); i++) { | |
window[String.fromCharCode(i)] = v; | |
capitalLetterStrings[v] = String.fromCharCode(i - "A".charCodeAt(0) + "a".charCodeAt(0)); | |
v <<= 1; | |
} | |
} | |
function drawRect(isAlignCenter, x, y, width, height) { | |
if (typeof x === "number") { | |
if (typeof y === "number") { | |
if (typeof width === "number") { | |
return addRect(isAlignCenter, x, y, width, height); | |
} | |
else { | |
return addRect(isAlignCenter, x, y, width.x, width.y); | |
} | |
} | |
else { | |
throw "invalid params"; | |
} | |
} | |
else { | |
if (typeof y === "number") { | |
if (typeof width === "number") { | |
return addRect(isAlignCenter, x.x, x.y, y, width); | |
} | |
else { | |
throw "invalid params"; | |
} | |
} | |
else { | |
return addRect(isAlignCenter, x.x, x.y, y.x, y.y); | |
} | |
} | |
} | |
function drawLine(p, l, thickness) { | |
const t = Math.floor(clamp(thickness, 3, 10)); | |
const lx = Math.abs(l.x); | |
const ly = Math.abs(l.y); | |
const rn = clamp(Math.ceil(lx > ly ? lx / t : ly / t) + 1, 3, 99); | |
l.div(rn - 1); | |
let collision = 0; | |
for (let i = 0; i < rn; i++) { | |
collision |= addRect(true, p.x, p.y, thickness, thickness, true); | |
p.add(l); | |
} | |
concatTmpRects(); | |
return collision; | |
} | |
function addRect(isAlignCenter, x, y, width, height, isAddingToTmp = false) { | |
let pos = isAlignCenter | |
? { x: Math.floor(x - width / 2), y: Math.floor(y - height / 2) } | |
: { x: Math.floor(x), y: Math.floor(y) }; | |
const size = { x: Math.floor(width), y: Math.floor(height) }; | |
let rect = { pos, size, color: exports.col }; | |
const collision = checkRects(rect); | |
if (!(exports.col & T)) { | |
(isAddingToTmp ? tmpRects : rects).push(rect); | |
setFillStyleFromCol(); | |
context.fillRect(pos.x, pos.y, size.x, size.y); | |
} | |
return collision; | |
} | |
function setFillStyleFromCol() { | |
const fill = capitalLetterStrings[exports.col]; | |
const f = rgbObjects[colorChars.indexOf(fill)]; | |
context.fillStyle = `rgb(${f.r},${f.g},${f.b})`; | |
} | |
function concatTmpRects() { | |
rects = rects.concat(tmpRects); | |
tmpRects = []; | |
} | |
function checkRects(rect) { | |
let collision = 0; | |
rects.forEach(r => { | |
if (testCollision(rect, r)) { | |
collision |= r.color; | |
} | |
}); | |
return collision; | |
} | |
function testCollision(r1, r2) { | |
const ox = r2.pos.x - r1.pos.x; | |
const oy = r2.pos.y - r1.pos.y; | |
return -r2.size.x < ox && ox < r1.size.x && -r2.size.y < oy && oy < r1.size.y; | |
} | |
function getHash(v) { | |
let hash = 0; | |
for (let i = 0; i < v.length; i++) { | |
const chr = v.charCodeAt(i); | |
hash = (hash << 5) - hash + chr; | |
hash |= 0; | |
} | |
return hash; | |
} | |
exports.PI = PI; | |
exports.abs = abs; | |
exports.atan2 = atan2; | |
exports.bar = bar; | |
exports.box = box; | |
exports.ceil = ceil; | |
exports.clamp = clamp; | |
exports.cos = cos; | |
exports.end = end; | |
exports.floor = floor; | |
exports.inp = inp; | |
exports.line = line; | |
exports.play = play; | |
exports.pow = pow; | |
exports.range = range; | |
exports.rect = rect; | |
exports.rnd = rnd; | |
exports.rndi = rndi; | |
exports.rnds = rnds; | |
exports.round = round; | |
exports.sin = sin; | |
exports.sqrt = sqrt; | |
exports.vec = vec; | |
exports.wrap = wrap; | |
}(this.window = this.window || {})); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment