diff --git a/.gitmodules b/.gitmodules index c2ddda4..ded6229 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,9 @@ -[submodule "views/projects/midsim"] - path = views/projects/midsim +[submodule "views/projects/item/midsim"] + path = views/projects/item/midsim url = https://git.abtmtr.link/MeowcaTheoRange/Mid-Simulator +[submodule "views/projects/item/clock"] + path = views/projects/item/clock + url = https://git.abtmtr.link/MeowcaTheoRange/Clock +[submodule "views/projects/item/dice"] + path = views/projects/item/dice + url = https://git.abtmtr.link/MeowcaTheoRange/DiceApp diff --git a/package.json b/package.json index c07e195..3efa218 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,7 @@ "dev": "nodemon --exec 'rm -rf output/*;gulp;node debug.js' --ext '*' --ignore 'output/*'" }, "devDependencies": { - "gulp": "^4.0.2" - }, - "dependencies": { + "gulp": "^4.0.2", "express": "^4.18.2", "through2": "^4.0.2" } diff --git a/views/index.html b/views/index.html index c1b04c8..e61f049 100755 --- a/views/index.html +++ b/views/index.html @@ -65,7 +65,7 @@ - + + + + + +
+
+
+
+ + + + + + +
+
+ + + +
+
+
+
+
+

Loading...


+

Loading...

+

+ +
+ +
+
+ +
open_with
+ +
+
+
+
+

Customize Color

+

+

Customize Background

+
+
+ +
+
+
+
+
+
+

Select Timezone

+
+ +
+ +
+
+
+
+
+
+

Configure Timer

+
+ + :
+
+

Configure Tone

+ +
+ +
+
+
+
+
+
+

About FunnyClock²

+
+ +

FunnyClock² is the successor of FunnyClock, an application made for my school to show when smartboards are idle.

+

FunnyClock was originally a single-file local webpage hosted on the computers of the teachers, and now with FunnyClock², it's a multi-file customizable suite for clocks and timers.

+

Special Thanks to

+
    +
  • Josh, science and tech teacher
  • +
  • Everyone who accepted my pitch for the FunnyClock² app
  • +
  • Among Us (Sussy background)
  • +
  • Portal 2 (Tile background)
  • +
  • Kaboom.js (Mark background)
  • +
  • Material Design (UI inspiration)
  • +
+
+ +
+
+
+
+
+ + + + + diff --git a/views/projects/item/clock/jqtp.js b/views/projects/item/clock/jqtp.js new file mode 100644 index 0000000..31272ce --- /dev/null +++ b/views/projects/item/clock/jqtp.js @@ -0,0 +1,11 @@ +/*! + * jQuery UI Touch Punch 0.2.3 + * + * Copyright 2011–2014, Dave Furfero + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Depends: + * jquery.ui.widget.js + * jquery.ui.mouse.js + */ +!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery); \ No newline at end of file diff --git a/views/projects/item/clock/styles/clock.css b/views/projects/item/clock/styles/clock.css new file mode 100644 index 0000000..4359174 --- /dev/null +++ b/views/projects/item/clock/styles/clock.css @@ -0,0 +1,148 @@ + +.body { + width: calc(100vw - 64px); + height: 100%; + position: fixed; + left: 64px; + top: 0; + padding: 0 16px; + box-sizing: border-box; + z-index: 1; + overflow-y: auto; +} + +.body .clock, .body .timer, .body .noteobject { + width: 100%; + min-height: max-content; + border-radius: 8px; + position: relative; + overflow: hidden; + padding: 16px; + box-sizing: border-box; + color: var(--foreground); + margin: 16px 0; + zoom: 1.25; +} + +.body .clock::before, .body .timer::before, .body .noteobject::before { + content: ""; + background-color: #FFFFFF40; + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + backdrop-filter: blur(8px); + z-index: -1; +} + +.body .timer-paused::before { + content: ""; + background-color: #40404040; + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + backdrop-filter: blur(8px); + z-index: -1; +} + + + +.body .clock h1, .body .timer h1, .body .noteobject h1 { + margin: 0; + margin-top: 16px; + padding: 0; + color: var(--foreground); + font-weight: lighter; + vertical-align: middle; +} + + + +.body .clock div.labels, .body .timer div.labels, .body .noteobject div.labels { + display: inline-block; + vertical-align: middle; +} + +.body .clock div.labels *, .body .timer div.labels *, .body .noteobject div.labels * { + margin: 0; + padding: 0; + color: var(--foreground); + font-weight: lighter; + display: inline-block; + vertical-align: middle; +} + +canvas { + margin: 0; + margin-right: 16px; + padding: 0; + vertical-align: middle; +} + +textarea { + resize: none; + width: 100%; + margin-top: 8px; + box-sizing: border-box; + height: max-content; + font-size: 48px; + max-height: 100%; + padding: 8px; + border: none; + border-radius: 4px; + background-color: #00000040; + color: var(--foreground); +} + +.deleteclock { + margin-top: 16px; + min-width: 32px; + width: 32px; + height: 32px; + padding: 0; + border: none; + background-color: #FF000080; + color: var(--foreground); + border-radius: 16px; + transition: background-color 0.125s; +} + +.deleteclock:focus { + background-color: #FF0000A0; +} + +.deleteclock:hover { + background-color: #FF0000C0; +} + +.deleteclock:active { + background-color: #FF0000FF; +} + +.normalclock { + margin-top: 16px; + min-width: 32px; + width: 32px; + height: 32px; + padding: 0; + border: none; + background-color: #00000040; + color: var(--foreground); + border-radius: 16px; + transition: background-color 0.125s; +} + +.normalclock:focus { + background-color: #00000030; +} + +.normalclock:hover { + background-color: #00000010; +} + +.normalclock:active { + background-color: #00000020; +} \ No newline at end of file diff --git a/views/projects/item/clock/styles/dialog.css b/views/projects/item/clock/styles/dialog.css new file mode 100644 index 0000000..0b2f594 --- /dev/null +++ b/views/projects/item/clock/styles/dialog.css @@ -0,0 +1,186 @@ +.scrim-over--.open { + background-color: #0006; + backdrop-filter: blur(4px); + pointer-events: auto; +} + +@keyframes myAnim { + from { + box-shadow: 0px 0px 6px -6px #FFFFFF80; + } + to { + box-shadow: 0px 0px 6px 32px #FFFFFF00; + } +} + +#updatedialog { + box-shadow: 0px 0px 6px 32px #FFFFFF00; + animation: myAnim 2s ease 0s infinite normal forwards; +} + +#updatedialog button { + animation: myAnim 2s ease 1s infinite normal forwards; +} + +.dialog { + display: none; +} + +.body .dialog { + width: 100%; +} + +.scrim-over--.open .dialog, .dialog.open { + display: inline-block !important; +} + +.dialog { + min-width: 320px; + max-width: calc(100vw - 64px); + min-height: 128px; + max-height: calc(100vh - 64px); + background-color: var(--background-light); + transition: background-color 0.125s; + color: var(--foreground); + border-radius: 8px; + padding: 16px; + box-sizing: border-box; + pointer-events: auto; + overflow-y: auto; +} + +.dialog p { + margin: 0; + padding: 0; + margin-bottom: 4px; +} + +.dialog .dlg-top { + display: block; + font-weight: bold; + font-size: 18px; + margin: 8px 0; +} + +.dialog div { + text-align: right; + margin-top: 8px; + box-sizing: border-box; +} + +.dialog div input[type=submit], .dialog div button { + margin: 0; + padding: 8px; + height: 32px; + box-sizing: border-box; + border: none; + background-color: transparent; + color: var(--main-color); + font-weight: bold; + border-radius: 4px; + transition: background-color 0.125s, color 0.125s; +} + +.dialog div input:focus, .dialog div button:focus { + background-color: #00000020; +} + +.dialog div input:hover, .dialog div button:hover { + background-color: #00000040; +} + +.dialog div input:active, .dialog div button:active { + background-color: #00000080; +} + +input[type="radio"] { + opacity: 0; + width: 0; + margin: 0; + padding: 0; +} + +input[type="radio"] + label { + display: inline-block; + margin: 8px; + padding: 0; + width: 96px; + height: 64px; + border-radius: 4px; + box-shadow: 0 0 4px 2px rgba(0,0,0,0.25); + color: #FFFFFF; + transition: border 0.25s; + box-sizing: border-box; + border: 8px solid transparent; + background-size: 96px; + background-repeat: no-repeat; +} + +input[type="radio"] + label[for^="bg"] { + color: var(--foreground); +} + +input[type="radio"]:checked + label { + border: 8px solid #FFF6; +} + +input[type="radio"]:focus + label { + outline: 4px solid white; +} + +.dialog select { + width: 100%; + margin: 8px 0; + box-sizing: border-box; + height: max-content; + max-height: 100%; + padding: 8px; + border: none; + border-radius: 4px; + background-color: #00000040; + color: var(--foreground); +} + +.dialog input[type="number"] { + width: 16ch; + margin: 8px 0; + box-sizing: border-box; + height: max-content; + max-height: 100%; + padding: 8px; + border: none; + border-radius: 4px; + background-color: #00000040; + color: var(--foreground); +} + +.checkobject input[type="text"] { + width: 100%; + margin: 8px 0; + box-sizing: border-box; + height: max-content; + max-height: 100%; + padding: 8px; + border: none; + border-radius: 4px; + font-size: 48px; + background-color: #00000040; + color: var(--foreground); +} + +.checkobject { + display: flex; + gap: 12px; + flex-direction: row; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: flex-start; + align-content: space-around; + align-items: center; +} + +.checkobject .deleteclock { + padding: 0; + margin: 0; +} \ No newline at end of file diff --git a/views/projects/item/clock/styles/root.css b/views/projects/item/clock/styles/root.css new file mode 100644 index 0000000..5fff121 --- /dev/null +++ b/views/projects/item/clock/styles/root.css @@ -0,0 +1,7 @@ +:root { + --main-color: #FFFF00; + --background: #202020; + --background-light: #404040; + --foreground: #FFFFFF; + --background-image: url("../assets/clock.png"); +} \ No newline at end of file diff --git a/views/projects/item/clock/styles/style.css b/views/projects/item/clock/styles/style.css new file mode 100644 index 0000000..3c7e602 --- /dev/null +++ b/views/projects/item/clock/styles/style.css @@ -0,0 +1,338 @@ +body { + background: var(--background); + background-size: 100vw 100vh; + image-rendering: -webkit-optimize-contrast; + image-rendering: crisp-edges; + transition: background 0.125s; + margin: 0; + padding: 0; +} + +#back { + background-image: var(--background-image); + background-size: 128px; + background-position: center; + opacity: 0.35; + position: fixed; + height: 100vh; + width: 100vw; +} + +#backconstrain { + position: fixed; + height: calc(100vh + 128px); + width: calc(100vw - 36px); + left: 20px; + top: 64px; +} + +* { + font-family: monospace; +} + +.header { + width: 64px; + height: 100%; + position: fixed; + left: 0; + top: 0; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + justify-content: space-between; + align-content: stretch; + align-items: center; + z-index: 9; + transition: width 0.125s; +} + +.header.wide { + width: 256px; +} +.scrim--, .scrim-over-- { + display: inline-block; + width: 100vw; + height: 100vh; + z-index: 8; + position: absolute; + top: 0; + left: 0; + background-color: transparent; + backdrop-filter: none; + pointer-events: none; + transition: background-color 0.125s, backdrop-filter 0.125s; +} +.scrim-over-- { + z-index: 10; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + justify-content: center; + align-content: center; + align-items: center; +} +.header.wide ~ .scrim-- { + background-color: #0006; + backdrop-filter: blur(4px); + pointer-events: auto; +} + +.header::before { + background-color: #FFFFFF40; + content: ""; + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + backdrop-filter: blur(8px); +} + +.header div { + display: flex; + flex-direction: column; + flex-wrap: nowrap; + align-content: space-around; + align-items: center; + gap: 8px; + padding: 8px; + width: 100%; + box-sizing: border-box; + height: 50%; +} + +.header div:first-child { + justify-content: flex-start; +} + +.header div:last-child { + justify-content: flex-end; +} + +.header button { + height: 48px; + width: 100%; + border-radius: 24px; + border: none; + padding: 12px; + margin: none; + background-color: transparent; + transition: background-color 0.125s; + color: var(--foreground); + position: relative; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: flex-start; + align-items: center; +} +.header.wide button { + overflow: hidden; +} + +.header button:hover { + background-color: #FFFFFF40; +} + +.header button::after { + position: absolute; + display: inline-block; + content: attr(data-title); + font-family: monospace; + font-size: 12px; + height: 12px; + box-sizing: content-box; + background-color: transparent; + color: transparent; + left: calc(100% + 16px); + border-radius: 4px; + top: calc(50% - 14px); + transition: color 0.125s, width 0.125s; + width: 0; + padding: 8px 0; + overflow: hidden; +} + +.header:not(.wide) button:hover::after { + background-color: #202020; + color: #FFFFFF; + width: initial; + padding: 8px; +} + +.header:not(.wide) button:focus::after { + background-color: #202020; + color: #FFFFFF; + width: initial; + padding: 8px; +} + +.header.wide button::after { + left: 48px; + top: calc(50% - 7px); + color: var(--foreground); + width: initial; + height: 14px; + padding: 0; + font-size: 14px; +} + +.header button:focus { + background-color: #FFFFFF20; +} + +.header button:active { + background-color: #FFFFFF80; +} + +sep { + display: inline-block; + width: 100%; + height: 0; + background-color: transparent; + border: 1px dashed var(--foreground); + margin: 4px; + z-index: 9; +} + +.poplight { + position: fixed; + right: 16px; + bottom: 16px; + width: 192px; + height: 192px; + transition: bottom 0.125s; + z-index: 9; +} + +.poplight.hidden { + bottom: -128px; +} + +.poplight button.hide { + position: absolute; + width: 32px; + height: 32px; + right: 48px; + top: -48px; + margin: 0; + padding: 0; + border: none; + border-radius: 16px; + background-color: transparent; + color: var(--foreground); +} + +.poplight button.hide::after { + position: absolute; + display: inline-block; + content: attr(data-title); + font-family: monospace; + font-size: 12px; + height: 12px; + box-sizing: content-box; + background-color: transparent; + color: transparent; + right: 0; + border-radius: 4px; + top: -48px; + transition: color 0.125s, width 0.125s; + width: 0; + padding: 8px 0; + overflow: hidden; +} + +.poplight button.hide:not(:disabled):hover::after { + background-color: #202020; + color: #FFFFFF; + width: initial; + padding: 8px; +} + +.poplight button.hide:not(:disabled):focus { + background-color: #FFFFFF20; +} + +.poplight button.hide:disabled { + color: #808080; +} + +.poplight button.hide:not(:disabled):hover { + background-color: #FFFFFF40; +} + +.poplight button.hide:not(:disabled):active { + background-color: #FFFFFF80; +} + +.poplight button.press { + position: absolute; + top: 0; + right: 0; + width: 100%; + height: 100%; + border-radius: 96px; + background-color: #808080; + overflow: hidden; + border: none; + font-size: 96px; + transition: top 0.125s, right 0.125s, width 0.125s, height 0.125s, background-color 0.125s, color 0.125s, font-size 0.125s; +} + +.poplight.hidden button.press { + top: -48px; + right: 96px; + width: 32px; + height: 32px; + border-radius: 128px; + font-size: 24px; + color: transparent; +} + +.poplight button.press.popped { + background-color: var(--main-color); + box-shadow: 0px 0px 32px 0px var(--main-color); +} + +.poplight button.press::after { + position: absolute; + content: "devices"; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + border-radius: 128px; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: transparent; +} + +.poplight button.press:hover::after { + background-color: #ffffff40; +} + +.poplight button.press:active::after { + background-color: #ffffff80; +} + +.poplight button.press.popped::after { + content: "phonelink_off"; +} + +.poplight .drag { + position: absolute; + width: 32px; + height: 32px; + right: 0; + top: -48px; + margin: 0; + padding: 4px; + border: none; + border-radius: 16px; + box-sizing: border-box; + user-select: none; + background-color: transparent; + color: var(--foreground); +} \ No newline at end of file diff --git a/views/projects/item/clock/update.js b/views/projects/item/clock/update.js new file mode 100644 index 0000000..fe0e12a --- /dev/null +++ b/views/projects/item/clock/update.js @@ -0,0 +1,23 @@ +function reqData(start) { + console.log("Pinged API server. Starting: " + start); + var donedata = (e) => { + var resp = e; + var prevSha = "A"; + if (!start) prevSha = window.sessionStorage.getItem("commitsha"); + + if (resp != prevSha) { + window.sessionStorage.setItem("commitsha", resp); + if (start) return; + document.querySelector("#updatesha").innerHTML = `from job v. ${prevSha} to job v. ${resp}`; + document.querySelector("#updatedialog").classList.add("open"); + } + }; + + fetch("https://ClockCheckGithub.meowcatheorange.repl.co") + .then(x => x.text()) + .then(y => donedata(y)); +} + +setInterval(reqData, 60000); + +reqData(true); diff --git a/views/projects/item/dice/assets/ProFontWindows.ttf b/views/projects/item/dice/assets/ProFontWindows.ttf new file mode 100644 index 0000000..b3d66b2 Binary files /dev/null and b/views/projects/item/dice/assets/ProFontWindows.ttf differ diff --git a/views/projects/item/dice/index.html b/views/projects/item/dice/index.html new file mode 100644 index 0000000..04663bf --- /dev/null +++ b/views/projects/item/dice/index.html @@ -0,0 +1,58 @@ + + + + + + Dice Tool + + + + + + +
+
+ Dice Tool +
+
+ + + +
+
+
+ + + +
+
+ + + + + + + diff --git a/views/projects/item/dice/script.js b/views/projects/item/dice/script.js new file mode 100644 index 0000000..7ac0956 --- /dev/null +++ b/views/projects/item/dice/script.js @@ -0,0 +1,65 @@ +var cont = document.querySelector(".content > div"); +var dieTemp = document.querySelector("template#dieUI"); +var dieBagTemp = document.querySelector("template#dieBagUI"); + +var ids = { + die: 0, + bag: 0 +}; +function addDie(ctx, int, name, count) { + ctx.innerHTML += dieTemp.innerHTML + .replace("{RAND_ID}", "die" + ids.die) + .replace("{TITLE_DIE}", name ?? "") + .replace("{DIE_SIDES}", int ?? "6") + .replace("{IS_COUNTER}", count ? " counter" : "") + .replace("{DIE_VALUE}", Math.round(Math.random() * ((int ?? 6) - 1)) + 1); + ids.die++; +} +function addDieBag(ctx) { + ctx.innerHTML += dieBagTemp.innerHTML + .replace("{RAND_ID}", "dieBag" + ids.bag) + .replace("{TITLE_DIE}", ""); + ids.bag++; +} +function rollDie(thisObj) { + var val = thisObj.querySelector('.die-value'); + var sides = thisObj.querySelector('.die-sides'); + val.innerHTML = Math.round(Math.random() * (sides.value - 1)) + 1; +} +function rollAllDie(ctx) { + var allDies = ctx.querySelectorAll(".rollable"); + console.log(allDies, ctx); + allDies.forEach((v) => { + rollDie(v); + }) +} + +function cutVal(thisObj) { + var val = thisObj.parentElement.querySelector('.die-value'); + var sides = thisObj.parentElement.querySelector('.die-sides'); + sides.value = val.innerHTML; +} + +function changeVal(thisObj, int) { + var val = thisObj.parentElement.querySelector('.die-value'); + val.innerHTML = parseInt(val.innerHTML) + int; +} + +function allowDrop(ev) { + ev.preventDefault(); +} + +function drag(ev) { + ev.dataTransfer.setData("element", ev.target.id); +} + +function drop(ev) { + if (!ev.target.classList.contains("dropHere")) return; + ev.preventDefault(); + var data = ev.dataTransfer.getData("element"); + ev.target.appendChild(document.getElementById(data)); +} + +var tp = (t) => {return $(t).parent().parent()}; +var tpp = (t) => {return $(t).parent().parent().parent()}; +var ht = (t) => {return t.get(0)}; \ No newline at end of file diff --git a/views/projects/item/dice/style.css b/views/projects/item/dice/style.css new file mode 100644 index 0000000..52cd9ff --- /dev/null +++ b/views/projects/item/dice/style.css @@ -0,0 +1,375 @@ +@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;900&display=swap'); +@font-face { + font-family: 'PFW'; + src: url('assets/ProFontWindows.ttf'); +} + +:root { + --mainColor: #f80; + --mainColorThemed: #fdb; + --mainColorThemedLight: #fed; + --mainFG: #000; + --mainFGDark: #FFF; + --mainFGTP: #0002; + --mainFGDarkTP: #FFF2; + --mainFGTP4: #0008; + --mainFGDarkTP4: #FFF8; + --negColor: #f00; + --negColorThemed: #fbb; + --negColorThemedLight: #fdd; + --posColor: #f80; + --posColorThemed: #ffd0a0; + --material-outline-boxshadow: #0004 0 0 4px; + --material-outline-border: none; +} + +* { + font-family: 'PFW', 'Roboto', 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; + transition: background-color 0.25s; +} + +@media (prefers-color-scheme: dark) { + :root { + --mainColorThemed: #840; + --mainColorThemedLight: #420; + --mainFG: #FFF; + --mainFGDark: #000; + --mainFGTP: #FFF2; + --mainFGDarkTP: #0002; + --mainFGTP4: #FFF8; + --mainFGDarkTP4: #0008; + --negColorThemed: #800; + --negColorThemedLight: #400; + --posColorThemed: #840; + --posColorThemedLight: #630; + --material-outline-boxshadow: none; + --material-outline-border: var(--mainFGTP) 1px solid; + } +} + +body {padding:0;margin:0;background-color:var(--mainColorThemedLight);} + +.headerBar { + width: 100%; + height: 56px; + z-index: 9; + display: inline-grid; + grid-template-columns: auto auto; + grid-template-rows: 40px; + position: fixed; + -webkit-user-select: none; + user-select: none; + top: 0; + background-color: var(--mainColorThemed); + box-shadow: var(--material-outline-boxshadow); + border-bottom: var(--material-outline-border); + line-height: 40px; + color: var(--mainFG); + font-size: 24px; + font-weight: bold; + padding: 8px 16px; + box-sizing: border-box; + transition: box-shadow 0.25s, background-color 0.25s; +} + +.fab { + position: fixed; + z-index: 9; + background-color: var(--mainColorThemed); + border-radius: 64px; + height: 64px; + width: 192px; + right: 32px; + bottom: 32px; + display: grid; + overflow: hidden; + user-select: none; + grid-template-columns: auto auto auto; + box-shadow: #0004 0 0 4px 0; +} + +.fab button { + border: none; + background-color: transparent; + color: var(--mainFG); + font-size: 32px; +} +.fab button:hover { + background-color: var(--mainFGTP); +} +.fab button:active { + transition: none; + background-color: var(--mainColor); +} + +.headerBar button { + height: 40px; + background-color: transparent; + padding: 4px; margin: 0; + margin-left: 8px; + color: var(--mainFG); + border: none; + border-radius: 40px; + transition: background 0.25s; + vertical-align: middle; +} + +.headerBar button:hover { + background-color: var(--mainFGTP); +} + +.content { + background-color: var(--mainColorThemedLight); + color: var(--mainFG); + height: calc(100vh - 56px); + margin-top: 56px; + overflow-y: auto; + box-sizing: border-box; + padding: 0 64px; +} +.content > div:empty::before { + position: absolute; + top: 56px; + left: 0; + width: 100vw; + text-align: center; + padding: 8px; + box-sizing: border-box; + content: "No dice."; + font-size: 24px; +} + +.content > div { + padding-bottom: 64px; + min-height: calc(100% - 16px); + box-sizing:border-box; +} + +templates, template { + display: none; +} + +div.die { + width: 100%; + border: var(--material-outline-border); + box-shadow: var(--material-outline-boxshadow); + color: var(--mainFG); + margin: 16px 0; + border-radius: 8px; + padding: 16px; + padding-bottom: 8px; + box-sizing: border-box; + display: grid; + grid-template-columns: auto auto; + animation-name: horizontal-shaking; + animation-duration: 0.25s; +} + +.counter .hideIfCounter { + display: none; +} + +.compactMode .hos { + display: none; +} +div.hideIfCounter { + display: inline-block; +} +body:not(.compactMode) .headerBar button.toc { + color: var(--posColor); +} + +.compactMode div.die h2 { + height: 32px; + line-height: 32px; + margin-top: -16px; + margin-right: 8px; +} + +div.bag { + grid-template-columns: auto; + grid-template-rows: auto auto; + height: max-content; +} + +div.die > div { + user-select: none; +} + +div.bag > div.dropHere { + border: var(--mainFGTP) 1px solid; + border-radius: 4px; + padding: 16px; + padding-bottom: 64px; + position: relative; +} + +div.bag > div.dropHere:empty { + padding: 32px; +} +div.bag > div.dropHere:empty::before { + position: absolute; + top: 0; + left: 0; + width: 100%; + text-align: center; + padding: 8px; + box-sizing: border-box; + content: "No dice."; + font-size: 24px; +} + +div.die h2 { + padding: 0; margin: 0; + display: inline-block; +} + +div.die input { + border-radius: 4px; + padding: 4px; + margin: 0; + font-size: 16px; + margin-bottom: 8px; + background-color: var(--mainFGDarkTP4); + border: 1px solid var(--mainFGTP); + color: var(--mainFG); + outline: none; + transition: border 0.25s, border-radius 0.25s, background-color 0.25s; + vertical-align: middle; +} + +div.die input[type=color] { + height: 34px; + width: 34px; + margin-left: -8px; + position: absolute; + left: -10000px; +} +div.bag > div > input[type=color] { + margin-left: 0; +} + +div.die input[type=color]:hover { + position: static; +} +div.die input[type=color]:focus { + position: static; +} + +div.die input[type=text]:hover + input[type=color] { + position: static; +} + +div.die .die-value { + vertical-align: middle; +} + +div.die input.die-sides { + vertical-align: baseline; + width: 48px; + height: 24px; +} +div.die input.title { + padding: 8px; +} + +div.die input:focus { + background-color: var(--mainFGTP); + border: 1px solid var(--mainFG); +} + +div.die input.title:not(:placeholder-shown) { + border: none; + border-radius: 0; + background-color: transparent; +} + +div.die input.title:not(:placeholder-shown):hover { + border-bottom: 1px solid var(--mainFG); +} + +div.die button { + border-radius: 4px; + padding: 8px; + margin: 0; + font-size: 12px; + background-color: transparent; + border: 1px solid var(--mainFGTP); + color: var(--mainFG); + transition: background-color 0.25s; +} + +div.die button.icon { + margin-bottom: 8px; + font-size: 19px; + vertical-align: middle; +} +div.die button:hover { + background-color: var(--mainFGTP); +} +div.die button:active { + border: 1px solid var(--mainFG); +} + +.indi.neg { + background-color: var(--negColorThemed); +} + +.indi.neg:hover { + background-color: var(--negColorThemedLight); +} + +.indi.pos { + background-color: var(--posColorThemed); +} + +.ident { + font-size: 19px; + vertical-align: top; + margin: 6px; + margin-right: 8px; +} + +@media (max-width: 675px) { + div.content { + padding: 0 16px; + } +} + +@media (min-width: 875px) { + div.content { + padding: 0 20%; + } +} + +@media (min-width: 1200px) { + div.content { + padding: 0 10%; + padding-top: 16px; + padding-bottom: 16px; + overflow-y: auto; + } + div.content > div { + column-count: 2; + } + div.die { + break-inside: avoid-column; + list-style-type: none; + margin-top: 0; + border: var(--mainFGTP) 1px solid; + box-shadow: none; + } + div.bag { + column-span: all; + margin-top: 16px; + } + div.bag div.dropHere { + column-count: 2; + } +} + +@media (min-width: 1775px) { + div.content > div { + column-count: 3; + } +} diff --git a/views/projects/hex/index.html b/views/projects/item/hex/index.html similarity index 100% rename from views/projects/hex/index.html rename to views/projects/item/hex/index.html diff --git a/views/projects/hex/scripts/index.js b/views/projects/item/hex/scripts/index.js similarity index 100% rename from views/projects/hex/scripts/index.js rename to views/projects/item/hex/scripts/index.js diff --git a/views/projects/item/midsim/code/charts.js b/views/projects/item/midsim/code/charts.js new file mode 100644 index 0000000..77a4ba1 --- /dev/null +++ b/views/projects/item/midsim/code/charts.js @@ -0,0 +1,545 @@ +import { kaboom } from "../deps.js"; + +export var charts = [ + { + id: "tutorial", + name: "Tutorial", + speed: 5, // How much seconds it takes to get from Right Stage to the hitmarker + bpm: 135, // Song BPM + events: { + preload: function() { + loadSound("hitsoundJellyBean", "sounds/hitsoundJellyBean.wav"); + loadSound("hitsoundCarterRedacted", "sounds/hitsoundJellyBean.wav"); + loadSound("hitsoundMarc", "sounds/hitsoundJellyBean.wav"); + loadSound("hitsoundRedVelvety", "sounds/hitsoundRedVelvety.wav"); + loadSound("hitsoundMarkyMark", "sounds/burp.mp3"); + loadSprite("JellyBeanPre", "sprites/previews/JellyBeanPre.png"); + loadSprite("RedVelvetyPre", "sprites/previews/RedVelvetyPre.png"); + loadSprite("MarkyMarkPre", "sprites/previews/MarkyMarkPre.png"); + loadSprite("CarterRedactedPre", "sprites/previews/CarterRedactedPre.png"); + loadSprite("MarcPre", "sprites/previews/MarcPre.png"); + loadSprite("tutorialBG0", "sprites/bgCake.png"); + loadSprite("tutorialFG0", "sprites/fgCake0.png"); + loadSprite("tutorialFG1", "sprites/fgCake1.png"); + loadSprite("Marctutorial", "sprites/marcCake.png", { + sliceX: 3, + sliceY: 3, + anims: { + idle: { + from: 0, + to: 3, + speed: 20 + }, + talk: { + from: 4, + to: 5, + speed: 20 + }, + miss: { + from: 6, + to: 8, + speed: 10 + }, + }, + }) + loadSprite("CarterRedactedtutorial", "sprites/carterredactedCake.png", { + sliceX: 3, + sliceY: 3, + anims: { + idle: { + from: 0, + to: 3, + speed: 20 + }, + talk: { + from: 4, + to: 5, + speed: 20 + }, + miss: { + from: 6, + to: 8, + speed: 10 + }, + }, + }) + loadSprite("MarkyMarktutorial", "sprites/markymarkCake.png", { + sliceX: 3, + sliceY: 4, + anims: { + idle: { + from: 0, + to: 3, + speed: 20 + }, + talk: { + from: 4, + to: 7, + speed: 40 + }, + miss: { + from: 8, + to: 10, + speed: 10 + }, + }, + }) + loadSprite("RedVelvetytutorial", "sprites/redvelvetyCake.png", { + sliceX: 3, + sliceY: 4, + anims: { + idle: { + from: 0, + to: 3, + speed: 20 + }, + talk: { + from: 4, + to: 5, + speed: 20 + }, + dox: { + from: 6, + to: 7, + speed: 20 + }, + miss: { + from: 8, + to: 10, + speed: 10 + }, + }, + }) + loadSprite("JellyBeantutorial", "sprites/jellybeanCake.png", { + sliceX: 3, + sliceY: 4, + anims: { + idle: { + from: 0, + to: 3, + speed: 20 + }, + talk: { + from: 4, + to: 5, + speed: 20 + }, + dox: { + from: 6, + to: 7, + speed: 20 + }, + miss: { + from: 8, + to: 10, + speed: 10 + }, + }, + }) + } + }, + characters: [ + ["JellyBean", "JellyBean", 186, 0], + ["RedVelvety", "RedVelvety", 186, 0], + ["Marc", "Marc", 186, 0], + ["CarterRedacted", "CarterRedacted", 186, 0], + ["MarkyMark", "Mark", 186, 0] + ], + noteTypes: { + "J": noteDefault, + }, + makeScript: { + customChar: false, + customBG: false, + charPos: [], + script: function() { + add([ + sprite("tutorialFG1"), + layer("fg"), + scale(1) + ]); + return {returnType: null}; + } + }, + chart: "................................................................................................................................J...........J.J...........J.J.J.............J.J.................J...........J.J...........J.J...J...............................J...........J.J...........J.J.J.............J.J...J.............J...........J.J...........J.J...J...............................J...........J.J...........J.J.J.............J.J...J.............J...........J.J...........J.J...J...............................J...........J.J...........J.J.J.............J.J...J...J...J.J...J...........J.J...........J.J...J...............................J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J...................................J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.....J.............................J.J.J.J.J.J.J.J.J.J.J.J.J.J.J...................................J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.....J.J.....J.J.....J...........J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.................................J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.....J.J.....J.J.....J.J.....J...................................................................................................................................J...........J.J...........J.J.J.............J.J...J...J...J.J...J...........J.J...........J.J...J...............................J...........J.J...........J.J.J.............J.J...J...J...J.J...J...........J.J...........J.J...J...............................J...........J.J...........J.J.J.............J.J...J...J...J.J...J...........J.J...........J.J...J...............................J...........J.J...........J.J.J.............J.J...J...J...J.J...J...........J.J...........J.J...J...............................................................................................................................................................................................................................................................", + scale: 1 //Texture Scale (too lazy to upsize sprites sometimes) + }, + { + id: "faith", + name: "Friendly Faith Plate", + speed: 2, + bpm: 120, + events: { + preload: function() { + loadSound("faith", "sounds/The Friendly Faith Plate.mp3"); //120 + loadSound("hitsoundFaithPlate", "sounds/hitsoundFaithPlate.mp3"); + loadSprite("FaithPlatePre", "sprites/previews/FaithPlatePre.png"); + loadSprite("faithBG0", "sprites/bgFaith.png"); + loadSprite("faithFG0", "sprites/fgFaith.png"); + loadSprite("FaithPlatefaith", "sprites/faithplateFaith.png", { + sliceX: 3, + sliceY: 3, + anims: { + idle: { + from: 0, + to: 3, + speed: 20 + }, + talk: { + from: 4, + to: 5, + speed: 20 + }, + miss: { + from: 6, + to: 8, + speed: 10 + }, + }, + }) + } + }, + characters: [ + ["FaithPlate", "Faith Plate", 0, 0] + ], + noteTypes: { + "J": noteDefault, + }, + makeScript: { + customChar: false, + customBG: false, + charPos: [], + script: function() { + return {returnType: null}; + } + }, + chart: "................................................................................................................................J...J...J...JJJJJ...J...J...J...J.J.J.J.J.J.J.J.JJJJJJJJJ.J.J.JJJ.J.J.J.J.J.JJJJJ.JJJ.J.J.J.J.J.J.JJJ.JJJ.J.J.J.JJJJJJJJJJJJJJJJJ.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.JJJ.JJJ.JJJ.JJJ.JJJ.J.J.J.J.JJJ.J.JJJJJJJJJJJJJ.J.J.J.JJJJJ.J.J.J.J.J.J.J.JJJJJ.J.J.J.J.JJ.J..J.JJJ.JJJ.J.J.JJJ.JJJ.J.J.J.JJJJJ.J.J.JJJ.JJJJJJJJJJJJJJJJJ.J.JJJ.J.J.JJJ.J.J.JJJ.J.J.JJJ.J.J.JJJ.J.J.JJJ.J.J.JJJJJJJJJJJJJ.J.J.JJJ.J.JJJ.J.J.JJJ.J.J.JJJ.J.J.J.J.J.J.JJJ.JJJJ.JJ.J.J.J.JJ..J...J.J.J.J.J.J.JJJJJJJJJJJJJ.J.J.J.J.J.J.J.J.J.JJJJJ.J.J.J.J.J.J.J.J...J...J.J.J.J.JJJJJJJJJ.J.J.J.J.J.J.JJJ.J.JJJJJJJJJJJJJJJ.J.J.JJJ.J.JJJ.JJJJJJJJJJJJJJJJJ.J.J.JJJ.J.JJJ.JJJJJJJJJJJJJJJJJ.J.J.JJJ.J.JJJ.JJJJJJJJJJJJJJJJJ.J.J.JJJJ.JJJJJJJJJJJJJJJ.JJJJJJJJJJJJJ..J.JJJ.JJJJJJJJJJ....J.J.JJJJJJJ.J.JJJ.JJJJJJJJJJJJJJJJJJJJJ.J.J.J.JJJ.JJJJJJJJJ....JJJJJJJJJ....JJJJJJJ.JJJJJJJ..JJJ..J.JJJJJJJJJJJJJJJ.JJJJJJJ..JJJ....JJJJJJJJJJJJJJJ.JJJJJJJ..JJJ....JJJJJJJJJJJJJJJ.JJJJJJJJ.JJJ..J.JJJJJJJ.J.JJJ.JJJJJJJJJJJJJ.JJJ.J...JJJ.J.JJJ.JJJJJJJJJJJJJ.JJJ.JJJ.JJJ.J.JJJJJJJJJJJJJJJJJJJJJ.JJJ.JJJ.J.JJJ.JJJJJJJJJJJJJJJJJ.JJJ.JJJ.J.JJJ.JJJJJJJJJJJJJJJ...JJJJ........J...JJJJ........J...JJJJ........J...JJJJ........J.J.JJJJ........JJJ.JJJ.JJJ.J.JJJ.J.JJJJ........JJJ.JJJ.JJJ.JJJJJ.J.JJJJ........JJJ.JJJ.JJJ.J.JJJ.J.JJJJ........JJJ.JJJ.JJJ.JJJJJ.J.JJJJJ.......JJJ.J.............", + scale: 4 + }, + { + id: "green", + name: "Green Hill Zone", + speed: 2, + bpm: 150, + events: { + preload: function() { + loadSound("green", "sounds/GreenHill.wav"); //139 + loadSound("hitsoundSonicAndTails", "sounds/hitsoundJellyBean.wav"); + loadSound("hitsoundTails", "sounds/hitsoundJellyBean.wav"); + loadSprite("SonicAndTailsPre", "sprites/previews/SonicAndTailsPre.png"); + loadSprite("TailsPre", "sprites/previews/TailsPre.png"); + loadSprite("sonicBG0", "sprites/SonicBG.png", { + sliceX: 3, + sliceY: 3, + anims: { + idle: { + from: 0, + to: 6, + speed: 10, + loop: true + } + }, + }); + loadSprite("sonicFG0", "sprites/SonicFG.png", { + sliceX: 3, + sliceY: 3, + anims: { + idle: { + from: 0, + to: 0, + speed: 20 + } + }, + }); + loadSprite("SonicAndTailssonic0", "sprites/SonicMidSim.png", { + sliceX: 3, + sliceY: 4, + anims: { + idle: { + from: 0, + to: 6, + speed: 20 + }, + talk: { + from: 7, + to: 8, + speed: 20 + }, + miss: { + from: 9, + to: 11, + speed: 10 + }, + }, + }); + loadSprite("SonicAndTailssonic1", "sprites/TailsMidSim.png", { + sliceX: 3, + sliceY: 9, + anims: { + idle: { + from: 0, + to: 15, + speed: 20 + }, + talk: { + from: 16, + to: 23, + speed: 20 + }, + miss: { + from: 24, + to: 26, + speed: 10 + }, + }, + }); + loadSprite("greenBG0", "sprites/SonicBG.png", { + sliceX: 3, + sliceY: 3, + anims: { + idle: { + from: 0, + to: 6, + speed: 10, + loop: true + } + }, + }); + loadSprite("greenFG0", "sprites/SonicFG.png", { + sliceX: 3, + sliceY: 3, + anims: { + idle: { + from: 0, + to: 0, + speed: 20 + } + }, + }); + loadSprite("SonicAndTailsgreen0", "sprites/SonicMidSim.png", { + sliceX: 3, + sliceY: 4, + anims: { + idle: { + from: 0, + to: 6, + speed: 20 + }, + talk: { + from: 7, + to: 8, + speed: 20 + }, + miss: { + from: 9, + to: 11, + speed: 10 + }, + }, + }); + loadSprite("SonicAndTailsgreen1", "sprites/TailsMidSim.png", { + sliceX: 3, + sliceY: 9, + anims: { + idle: { + from: 0, + to: 15, + speed: 20 + }, + talk: { + from: 16, + to: 23, + speed: 20 + }, + miss: { + from: 24, + to: 26, + speed: 10 + }, + }, + }); + } + }, + characters: [ + ["SonicAndTails", "Sonic"], + ["Tails", "Tails"] + ], + noteTypes: { + "J": function(time, prevStep, char) { + if (char == "Tails") { + customNote(time, "J", prevStep, 0, [0, 0, 0], true); + } else { + noteDefault(time, prevStep) + } + }, + "T": function(time, prevStep, char) { + if (char == "Tails") { + noteDefault(time, prevStep) + } else { + customNote(time, "T", prevStep, 0, [0, 0, 0], true); + } + }, + "D": function(time, prevStep) { + noteDefault(time, prevStep); + customNote(time, "D", prevStep, 0, [0, 0, 0], true); + } + }, + makeScript: { + customChar: true, + customBG: false, + charPos: [], + script: function(players, char, bgEl) { + var player, player2; + bgEl.play("idle"); + if (char == "Tails") { + player = add([ + sprite("SonicAnd" + char + "green" + "1"), + layer("JELLYBEAN"), + "dances", + pos(224, 20), + scale(1) + ]) + player2 = add([ + sprite("SonicAnd" + char + "green" + "0"), + layer("JELLYBEAN"), + "dances", + pos(20, 108), + scale(1) + ]) + } else { + player = add([ + sprite(char + "green" + "0"), + layer("JELLYBEAN"), + "dances", + pos(20, 108), + scale(1) + ]) + player2 = add([ + sprite(char + "green" + "1"), + layer("JELLYBEAN"), + "dances", + pos(224, 20), + scale(1) + ]) + } + return {returnType: "character", main: player, empty: player2}; + } + }, + chart: "................J.....J.....J.....J.....J...J...J.....J.....J...................J.....J.....J...J.....J.....J...J.....J.................................T.T...T.T...T.T...T...........T.T.T...T.T...T.T...T.............T.T...T.T...T.T...T...........T.T.T...T.T...T.T...T.....T.......J.J...J.J...D.J.T.J.T...T.....J.J.J...J.J...D.J.T.J.T...T.......J.J...J.J...D.J.T.J.T...T.....J.J.J...J.J...D.J.T.J.D...D.....J.....J.....J.....J.T.D.T.J.....J.....J.....J.....J.T.D.T.J.....J.....J.....J.....J.T.D.T.J.T.T.T...T.T.T...T.T.T.T.T.T.T.........J.J...J.J...J.J...J...........J.J.J...J.J...J.J...J.............J.J...J.J...J.J...J...........J.J.J...J.J...J.J...J.....J.......T.T...T.T...D.T.J.T.J...J.....T.T.T...T.T...D.T.J.T.J...J.......T.T...T.T...D.T.J.T.J...J.....T.T.T...T.T...D.T.J.T.J.T.D.....T.....T.....T.....T.J.D.J.T.....T.....T.....T.....T.J.D.J.T.....T.....T.....T.....T.J.D.J.T.J.J.J...J.J.J...J.J.J.J.J.J.J................................................................................................................................................................", + scale: 1 + }, + { + id: "sonic", + name: "Emerald Hill Zone", + speed: 2, + bpm: 139, + events: { + preload: function() { + loadSound("tutorial", "sounds/Getting it Done.mp3"); //135 + loadSound("faith", "sounds/The Friendly Faith Plate.mp3"); //120 + loadSound("sonic", "sounds/SonicInMidSim.wav"); //139 + loadSound("green", "sounds/GreenHill.wav"); //139 + } + }, + characters: [ + ["SonicAndTails", "Sonic"], + ["Tails", "Tails"] + ], + noteTypes: { + "J": function(time, prevStep, char) { + if (char == "Tails") { + customNote(time, "J", prevStep, 0, [0, 0, 0], true); + } else { + noteDefault(time, prevStep) + } + }, + "T": function(time, prevStep, char) { + if (char == "Tails") { + noteDefault(time, prevStep) + } else { + customNote(time, "T", prevStep, 0, [0, 0, 0], true); + } + }, + "D": function(time, prevStep) { + noteDefault(time, prevStep); + customNote(time, "D", prevStep, 0, [0, 0, 0], true); + } + }, + makeScript: { + customChar: true, + customBG: false, + charPos: [], + script: function(players, char, bgEl) { + var player, player2; + bgEl.play("idle"); + if (char == "Tails") { + player = add([ + sprite("SonicAnd" + char + "green" + "1"), + layer("JELLYBEAN"), + "dances", + pos(224, 20), + scale(1) + ]) + player2 = add([ + sprite("SonicAnd" + char + "green" + "0"), + layer("JELLYBEAN"), + "dances", + pos(20, 108), + scale(1) + ]) + } else { + player = add([ + sprite(char + "green" + "0"), + layer("JELLYBEAN"), + "dances", + pos(20, 108), + scale(1) + ]) + player2 = add([ + sprite(char + "green" + "1"), + layer("JELLYBEAN"), + "dances", + pos(224, 20), + scale(1) + ]) + } + return {returnType: "character", main: player, empty: player2}; + } + }, + chart: "..................................................J.J.J.J.J.JJ....J.J.J.J..J.........JJJJ.J.JJ.J..................T.T.T.T.T.TT....T...T.T..T........TTT.T.T.TT.T..................J.J.J.J.J.J.J.J.J...J...........J.J.J.J.J.JJ..J.................T.T.T.T.T.T.T.T.T...T...........T.T.T.T.T.TT..T...............J.....J.....J.J.J.JJ....T.TT........J.J.J.J.J.J.J.J...J.........T.....T.....T.T.T.TT....J.JJ....DD.D.............................................................", + scale: 1 + }, +] + +export function noteDefault(time, prevStep) { + add([ + rect(10, 50), + pos(width(), 20), + color(232, 3, 252), + ("note" + prevStep), + "note", + { + created: time, + type: "J", + empty: false, + normal: true + } + ]); +} + +export function customNote(time, letter, prevStep, w, colorArray, empty, funclol) { + add([ + rect(w, 50), + pos(width(), 20), + colorArray ? color(colorArray[0], colorArray[1], colorArray[2]) : color(0, 0, 0), + ("note" + prevStep), + "note", + { + created: time, + type: letter, + function: funclol, + empty: empty, + normal: funclol != undefined ? false : true + } + ]); +} diff --git a/views/projects/item/midsim/code/easing.js b/views/projects/item/midsim/code/easing.js new file mode 100644 index 0000000..7bdf7c4 --- /dev/null +++ b/views/projects/item/midsim/code/easing.js @@ -0,0 +1,175 @@ +export var easings = { // Easings taken from https://easings.net/ + linear: (x) => { + return x; + }, + easeInSine: (x) => { + return 1 - Math.cos((x * Math.PI) / 2); + }, + easeOutSine: (x) => { + return Math.sin((x * Math.PI) / 2); + }, + easeInOutSine: (x) => { + return -(Math.cos(Math.PI * x) - 1) / 2; + }, + easeInQuad: (x) => { + return x * x; + }, + easeOutQuad: (x) => { + return 1 - (1 - x) * (1 - x); + }, + easeInOutQuad: (x) => { + return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2; + }, + easeInCubic: (x) => { + return x * x * x; + }, + easeOutCubic: (x) => { + return 1 - Math.pow(1 - x, 3); + }, + easeInOutCubic: (x) => { + return x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2; + }, + easeInQuart: (x) => { + return x * x * x * x; + }, + easeOutQuart: (x) => { + return 1 - Math.pow(1 - x, 4); + }, + easeInOutQuart: (x) => { + return x < 0.5 ? 8 * x * x * x * x : 1 - Math.pow(-2 * x + 2, 4) / 2; + }, + easeInQuint: (x) => { + return x * x * x * x * x; + }, + easeOutQuint: (x) => { + return 1 - Math.pow(1 - x, 5); + }, + easeInOutQuint: (x) => { + return x < 0.5 ? 16 * x * x * x * x * x : 1 - Math.pow(-2 * x + 2, 5) / 2; + }, + easeInExpo: (x) => { + return x === 0 ? 0 : Math.pow(2, 10 * x - 10); + }, + easeOutExpo: (x) => { + return x === 1 ? 1 : 1 - Math.pow(2, -10 * x); + }, + easeInOutExpo: (x) => { + return x === 0 + ? 0 + : x === 1 + ? 1 + : x < 0.5 ? Math.pow(2, 20 * x - 10) / 2 + : (2 - Math.pow(2, -20 * x + 10)) / 2; + }, + easeInCirc: (x) => { + return 1 - Math.sqrt(1 - Math.pow(x, 2)); + }, + easeOutCirc: (x) => { + return Math.sqrt(1 - Math.pow(x - 1, 2)); + }, + easeInOutCirc: (x) => { + return x < 0.5 + ? (1 - Math.sqrt(1 - Math.pow(2 * x, 2))) / 2 + : (Math.sqrt(1 - Math.pow(-2 * x + 2, 2)) + 1) / 2; + }, + easeInBack: (x) => { + const c1 = 1.70158; + const c3 = c1 + 1; + return c3 * x * x * x - c1 * x * x; + }, + easeOutBack: (x) => { + const c1 = 1.70158; + const c3 = c1 + 1; + return 1 + c3 * Math.pow(x - 1, 3) + c1 * Math.pow(x - 1, 2); + }, + easeInOutBack: (x) => { + const c1 = 1.70158; + const c2 = c1 * 1.525; + return x < 0.5 + ? (Math.pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2 + : (Math.pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2; + }, + easeInBounce: (x) => { + return 1 - easings.easeOutBounce(1 - x); + }, + easeOutBounce: (x) => { + const n1 = 7.5625; + const d1 = 2.75; + + if (x < 1 / d1) { + return n1 * x * x; + } else if (x < 2 / d1) { + return n1 * (x -= 1.5 / d1) * x + 0.75; + } else if (x < 2.5 / d1) { + return n1 * (x -= 2.25 / d1) * x + 0.9375; + } else { + return n1 * (x -= 2.625 / d1) * x + 0.984375; + } + }, + easeInOutBounce: (x) => { + return x < 0.5 + ? (1 - easings.easeOutBounce(1 - 2 * x)) / 2 + : (1 + easings.easeOutBounce(2 * x - 1)) / 2; + } +} + +export var tweentypes = { + FOREVER: (t, st, tl) => { + if (t - st >= tl) { + return "FOREVER"; + } + return "CONTINUE"; + }, + LERPFOREVER: (t, st, tl) => { + return "LF"; + }, + PINGPONG: (t, st, tl) => { + if (t - st >= tl) { + return "PING"; + } + return "CONTINUE"; + }, + NORMAL: (t, st, tl) => { + if (t - st >= tl) { + return "CALLBACK"; + } + return "CONTINUE"; + } +} + +export function tween(func, attrs, timeLen, minVal, maxVal, ease, type, onFinish) { + var minVal = minVal != undefined ? minVal : func[attrs[0]]; + var ease = ease != undefined ? ease : easings.linear; + var type = type != undefined ? type : tweentypes.NORMAL; + var stTime = time(); + var onFinish = onFinish != undefined ? onFinish : "ud"; + var upd = onUpdate(() => { + switch (type(time(), stTime, timeLen)) { + case "CALLBACK": + for (let h in attrs) { + func[attrs[h]] = maxVal; + } + upd(); + return onFinish == "ud" ? true : onFinish(); + case "FOREVER": + stTime = time(); + break; + case "CONTINUE": + for (let h in attrs) { + func[attrs[h]] = minVal; + } + break; + case "PING": + var buffer = minVal; + minVal = maxVal; + maxVal = buffer; + stTime = time(); + break; + default: + break; + } + for (let i in attrs) { + func[attrs[i]] = lerp(minVal, maxVal, ease((time() - stTime) / timeLen)); + } + }); +} \ No newline at end of file diff --git a/views/projects/item/midsim/code/main.js b/views/projects/item/midsim/code/main.js new file mode 100644 index 0000000..5d8e25b --- /dev/null +++ b/views/projects/item/midsim/code/main.js @@ -0,0 +1,981 @@ +"use strict"; +import { kaboom, easings, tween, tweentypes } from "../deps.js"; +import { charts } from "./charts.js"; + +// initialize context +kaboom({ + width: 700, + height: 400, + background: [ 0, 0, 0 ], + crisp: true, + touchToMouse: true, + canvas: document.querySelector("#kaboom"), + font: "MidSim", + scale: 1, + +}); +var ismobile = isTouch(); + +load(new Promise((resolve, reject) => { + loadFont("unscii", "sprites/unscii_8x8.png", 8, 8, {chars: " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"}); + loadFont("MidSim", "sprites/MidSimFont2.png", 10, 10, {chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz:;><^%-.!?/()[]\"'|1234567890"}); + // Music + loadSound("gameover", "sounds/gameover.mp3"); + // + + // Sounds + loadSound("nullHit", "sounds/nullHit.mp3"); + loadSound("score", "sounds/score.mp3"); + loadSound("metro", "sounds/metro.wav"); + loadSound("explode", "sounds/explode.mp3"); + // + + //Menus + loadSprite("bgCake", "sprites/bgCake.png"); + loadSprite("jellybeanTitle", "sprites/jellybeanTitle.png"); + loadSprite("logo", "sprites/logo.png"); + loadSprite("jellybeanFail", "sprites/jellybeanFail.png"); + // + + // Main Game + loadSprite("noteClick", "sprites/noteClick.png", { + sliceX: 4, + sliceY: 2, + anims: { + idle: { + from: 7, + to: 7, + speed: 30 + }, + click: { + from: 0, + to: 7, + speed: 60 + } + }, + }) + + for (let ided in charts) { + console.log("Loading game assets..."); + charts[ided].events.preload(); + console.log("Assets of song " + charts[ided].name + " loaded."); + } + + resolve("All assets loaded."); +})); + +scene("Game", (idx, noTrans) => { + var song = charts[idx.song].id; //Also Chart access + var char = charts[idx.song].characters[idx.character][0]; + var hitsound = "hitsound" + charts[idx.song].characters[idx.character][0]; + var chart = charts[idx.song].chart; + var crochet = ((60 / charts[idx.song].bpm) * 1000); + var board = width() - strumLine; + var curBeat; + var prevBeat; + var prevStep; + var curStep; + var autoplay = false; + var debugMode = false; + var score = 0; + var combo = 0; + var health = 1; + var font = "MidSim"; + if (char == "MarkyMark") { + font = "unscii"; + } + + // Music + var strumLine = width() / 2; + const music = play(charts[idx.song].id, { + volume: 1, + loop: false + }); + const underlay = play("score", { + volume: 1, + loop: false + }); + music.pause() + wait(charts[idx.song].speed, () => { + underlay.pause(); + music.play(); + underlay.play(music.time() + charts[idx.song].speed); + }); + + // Sprites + layers([ + "bg", + "JELLYBEAN", + "SKELETONS", + "fg", + "ui0", + "ui1" + ], "ui0"); + var players = { + main: 0, + empty: 0, + }; + var bg; + var tweenVals = { + fade: 1, + triggered: false + } + tween(tweenVals, ["fade"], 1, 1, 0, easings.easeOutCirc, tweentypes.NORMAL); + if (!charts[idx.song].makeScript.customChar) { + players.main = add([ + sprite(char + song), + layer("JELLYBEAN"), + "dances", + pos(charts[idx.song].characters[idx.character][2], charts[idx.song].characters[idx.character][3]), + scale(charts[idx.song].scale) + ]); + } + if (!charts[idx.song].makeScript.customBG) { + bg = add([ + sprite(song + "BG0"), + layer("bg"), + scale(charts[idx.song].scale) + ]); + const fg = add([ + sprite(song + "FG0"), + (song == "faith" ? layer("bg") : layer("fg")), + scale(charts[idx.song].scale) + ]); + } + var script = charts[idx.song].makeScript.script(players, char, bg); + if (script.returnType != undefined && script.returnType == "character") { + players.main = script.main; + players.empty = script.empty; + } + const noteClick = add([ + sprite("noteClick"), + scale(0.25), + pos(strumLine, 15) + ]) + const bspButton = add([ + pos(0, 0), + color(CYAN), + text(ismobile ? "<" : "BACKSPACE TO EXIT", { + size: ismobile? 32 : 20, // 48 pixels tall + }), + area({ + offset: ismobile ? vec2(canvas.offsetLeft, canvas.offsetTop) : vec2(0, 0), + }), + "back" + ]) + const entButton = add([ + pos(width(), 0), + origin("topright"), + color(YELLOW), + text(ismobile ? "||" : "ENTER TO PAUSE", { + size: ismobile? 32 : 20, // 48 pixels tall + }), + area({ + offset: ismobile ? vec2(canvas.offsetLeft, canvas.offsetTop) : vec2(0, 0), + }), + "ent" + ]) + // Gameplay + onUpdate(() => { + if (health > 1) health = 1; + if (health < 0) { + health = 0; + if(!tweenVals.triggered) { + tween(tweenVals, ["fade"], 1, 0, 1, easings.easeOutCirc, tweentypes.NORMAL, function () { + underlay.stop(); + music.stop(); + go("Lose", score, idx); + }); + underlay.pause(); + music.pause(); + tweenVals.triggered = true; + } + } + if (music.time() > music.duration() && health >= 0) { + if(!tweenVals.triggered) { + tween(tweenVals, ["fade"], 1, 0, 1, easings.easeOutCirc, tweentypes.NORMAL, function () { + go("Help"); + }); + tweenVals.triggered = true; + } + } + strumLine = lerp(18, width() / 2, health); + noteClick.pos.x = strumLine - 5; + curBeat = Math.floor(((music.time() * 1000) / crochet) * 10) / 10; + curStep = Math.floor((music.time() * 1000) / (crochet / 4)); + prevBeat = Math.floor(((underlay.time() * 1000) / crochet)); + prevStep = Math.floor((underlay.time() * 1000) / (crochet / 4)); + if (!get("bar" + prevBeat).length) { + var bar = add([ + prevBeat % 4 == 0 ? rect(3, 50) : rect(2, 50), + pos(width(), 20), + color(255, 255, 255), + ("bar" + prevBeat), + { + mainBar: prevBeat % 4 == 0, + created: underlay.time() + }, + "bar" + ]); + } + if (get("note" + prevStep).length <= 0) { + makeNote(charts[idx.song].chart[Math.floor(prevStep)]); + } + if (!underlay.isPaused()) { + every("bar", (j) => { + j.pos.x = lerp(width(), strumLine, (underlay.time() - j.created) / charts[idx.song].speed); + if(j.pos.x <= strumLine) { + beatHit(); + if (debugMode) play("metro", {detune: j.mainBar ? 200 : 0}); + destroy(j); + } + if (charts[idx.song].events.onBeat != undefined) { + charts[idx.song].events.onBeat(curBeat); + } + }); + every("note", (j) => { + j.pos.x = lerp(width(), strumLine, (underlay.time() - j.created) / charts[idx.song].speed); + if(autoplay) { + if(j.pos.x <= strumLine && !j.empty) { + play(hitsound); + players.main.play("talk"); //Check this area later, you want to add in Note Modularity! + destroy(j); + } + } else { + if(j.pos.x <= strumLine - 20 && !j.empty) { + score -= 200; + destroy(j); + play("explode"); + players.main.play("miss"); + shake(5); + combo = 0; + health -= 0.1; + } + } + if(j.pos.x <= strumLine && j.empty) { + if (!j.normal) { + j.function(j.empty, curBeat, j.type); + } + destroy(j); + players.empty?.play("talk"); + } + }); + } + }) + var mt; + onKeyPress("enter", () => { + if (!underlay.isPaused()) { + underlay.pause(); + music.pause(); + mt = [underlay.time(), music.time()]; + } else { + underlay.play(mt[0]); + music.play(mt[1]); + } + }); + onKeyPress("space", () => {judgeHitsLol()}); + onKeyPress("backspace", () => { + tween(tweenVals, ["fade"], 1, 0, 1, easings.easeOutCirc, tweentypes.NORMAL, function () { + underlay.stop(); + music.stop(); + go("Help"); + }); + underlay.pause(); + music.pause(); + }); + onKeyPress("a", () => {autoplay = !autoplay}); + onKeyPress("d", () => {debugMode = !debugMode}); + onClick("back", () => { + tween(tweenVals, ["fade"], 1, 0, 1, easings.easeOutCirc, tweentypes.NORMAL, function () { + underlay.stop(); + music.stop(); + go("Help"); + }); + underlay.pause(); + music.pause(); + }); + onClick("ent", () => { + if (!underlay.isPaused()) { + underlay.pause(); + music.pause(); + mt = [underlay.time(), music.time()]; + } else { + underlay.play(mt[0]); + music.play(mt[1]); + } + }); + onClick(() => {judgeHitsLol()}); + onDraw(() => { + drawLine({ + p1: vec2(0, 20), + p2: vec2(width(), 20), + width: 2, + color: rgb(255, 255, 255), + }) + drawLine({ + p1: vec2(0, 70), + p2: vec2(width(), 70), + width: 2, + color: rgb(255, 255, 255), + }) + drawLines({ // 80 * 240, 20 * 60 + pts: [ vec2(strumLine, 18), vec2(strumLine + 10, 18), vec2(strumLine + 10, 72), vec2(strumLine, 72), vec2(strumLine, 18) ], + width: 2, + pos: vec2(100, 200), + color: rgb(255, 255, 255), + }) + drawText({ + text: "MID-SIMULATOR DEMO", + size: 20, + pos: vec2(0, height() - 20), + font: font + }); + if (debugMode) { + drawText({ + text: underlay.time() * 1000, + size: 20, + pos: vec2(0, 20), + font: font + }); + drawText({ + text: curBeat, + size: 20, + pos: vec2(0, 40), + font: font + }); + drawText({ + text: prevStep + "/" + (charts[idx.song].chart.length - 1), + size: 20, + pos: vec2(0, 60), + font: font + }); + drawText({ + text: (charts[idx.song].chart[Math.floor(prevStep)] ? charts[idx.song].chart[Math.floor(prevStep)] : "."), + size: 20, + pos: vec2(0, 80), + font: font + }); + drawText({ + text: (charts[idx.song].chart[Math.floor(curStep)] ? charts[idx.song].chart[Math.floor(curStep)] : "."), + size: 20, + pos: vec2(0, 100), + font: font + }); + drawText({ + text: "Health: " + health, + size: 20, + pos: vec2(strumLine, 120), + font: font + }); + } + drawText({ + text: "Score: " + score, + size: 20, + pos: vec2(strumLine, 80), + font: font + }); + drawText({ + text: "Combo: " + combo, + size: 20, + pos: vec2(strumLine, 100), + font: font + }); + if (autoplay) { + drawText({ + text: "AUTOPLAY", + size: 20, + pos: vec2(strumLine, debugMode? 140: 120), + font: font + }); + } + drawRect({ + width: 702, + height: 402, + pos: vec2(-1, -1), + color: BLACK, + opacity: tweenVals.fade + }) + }) + + //Functions + + function makeNote(letter) { + if (charts[idx.song].noteTypes.hasOwnProperty(letter)) { + charts[idx.song].noteTypes[letter](underlay.time(), prevStep, char); + } + } + function judgeHitsLol() { + var iv = false; + var hits = 0; + every("note", (j) => { + if (!iv) { + if (!j.empty) { + var str = "No Rating"; + var theColor = WHITE; + if(j.pos.x >= strumLine - 20) { + if(j.pos.x <= strumLine + 22) { + hits++; + iv = true; + if (!j.normal) { + j.function(j.empty, curBeat, j.type); + } + destroy(j); //Destroys note. No score. + noteClick.play("click"); + combo += 1; + str = "MID"; + theColor = RED; + } + if(j.pos.x <= strumLine + 12) { + play(hitsound); //Plays sound! + players.main.play("talk"); + score += 20; + health += 0.01; + str = "Perfect!"; + theColor = MAGENTA; + } + if(j.pos.x <= strumLine + 5) { + score += 50; + health += 0.02; + str = "Perfect!!"; + } + if(j.pos.x <= strumLine - 3) { + score += 50; + health -= 0.01; + str = "Perfect!"; + } + if(j.pos.x <= strumLine - 8) { + score -= 100; + health -= 0.02; + str = "Overshot"; + theColor = CYAN; + } + } + if (str != "No Rating") { + var origpos = strumLine - 16; + var ratingtxt = add([ + text(str, { + size: 30, // 48 pixels tall + }), + pos(origpos, 48), + color(theColor), + origin("right") + ]); + tween(ratingtxt.pos, ["y"], 5, 48, 300, easings.easeOutSine, tweentypes.NORMAL); + tween(ratingtxt, ["opacity"], 5, 1, 0, easings.easeOutSine, tweentypes.NORMAL, function() { + destroy(ratingtxt); + }); + } + } + } + }); + if (hits <= 0) { + play("nullHit"); + } + } + function beatHit() { + every("dances", (obj) => { + if (obj.curAnim() != "talk" && obj.curAnim() != "miss") { + obj.play("idle"); + } + }); + } +}); + +scene("Help", (noTrans) => { + var index = { + character: 0, + song: 0 + } + var tweenVals = { + fade: 0 + } + if (!noTrans) tween(tweenVals, ["fade"], 1, 1, 0, easings.easeOutCirc, tweentypes.NORMAL); + const bg = add([ + sprite("bgCake") + ]); + onDraw(() => { + if (!ismobile) { + drawText({ + text: "D: ENABLE DEBUG MODE", + size: 30, + pos: vec2(25, 25) + }); + drawText({ + text: "A: ENABLE AUTOPLAY", + size: 30, + pos: vec2(25, 60) + }); + } + drawText({ + text: ismobile ? "TAP TO HIT NOTES" : "SPACE/CLICK: HIT NOTE", + size: 30, + pos: ismobile ? vec2(25, 60) : vec2(25, 95) + }); + drawText({ + text: charts[index.song].characters[index.character][1] + " ("+ (index.character + 1) +"/"+ charts[index.song].characters.length +")", + size: 30, + pos: vec2(width() / 2, 200), + origin: "top" + }); + drawText({ + text: charts[index.song].name, + size: 30, + pos: vec2(width() / 2, 160), + origin: "top" + }); + drawSprite({ + sprite: charts[index.song].characters[index.character][0] + "Pre", + width: 64, + height: 64, + pos: vec2((width() / 2) - 34, 248) + }); + drawRect({ + width: 702, + height: 402, + pos: vec2(-1, -1), + color: BLACK, + opacity: tweenVals.fade + }) + }) + add([ + pos(0, 140), + rect(700, 200), + color(0, 0, 0) + ]) + var lt = add([ + pos(10, 200), + text("<", { + size: 30 + }), + area({ + height: 30, + offset: ismobile ? vec2(canvas.offsetLeft, canvas.offsetTop) : vec2(0, 0), + width: 30, + cursor: "pointer" + }), + "LeftText" + ]) + var rt = add([ + pos(width() - 10, 200), + origin("topright"), + text(">", { + size: 30 + }), + area({ + height: 30, + offset: ismobile ? vec2(canvas.offsetLeft, canvas.offsetTop) : vec2(0, 0), + width: 30, + cursor: "pointer" + }), + "RightText" + ]) + var dt = add([ + pos(10, 160), + text("%", { + size: 30 + }), + area({ + height: 30, + offset: ismobile ? vec2(canvas.offsetLeft, canvas.offsetTop) : vec2(0, 0), + width: 30, + cursor: "pointer" + }), + "DownText" + ]) + var ut = add([ + pos(width() - 10, 160), + origin("topright"), + text("^", { + size: 30 + }), + area({ + height: 30, + offset: ismobile ? vec2(canvas.offsetLeft, canvas.offsetTop) : vec2(0, 0), + width: 30, + cursor: "pointer" + }), + "UpText" + ]) + var clickText = add([ + pos(width() / 2, height() - 45), + text(ismobile ? "TAP HERE TO START" : "SPACE TO START", { + size: 30 + }), + origin("top"), + area({ + height: 30, + offset: ismobile ? vec2(canvas.offsetLeft, canvas.offsetTop) : vec2(0, 0), + width: 700, + cursor: "pointer" + }), + "TEXT TEXT" + ]) + function changeIdx(amt) { + index.character += amt; + if (index.character < 0) { + index.character = charts[index.song].characters.length - 1; + } else if (index.character >= charts[index.song].characters.length) { + index.character = 0; + } + } + function changeSongIdx(amt) { + index.song += amt; + index.character = 0; + if (index.song < 0) { + index.song = charts.length - 1; + } else if (index.song >= charts.length) { + index.song = 0; + } + } + + onKeyPress("left", () => {changeIdx(-1)}); + onKeyPress("right", () => {changeIdx(1)}); + onKeyPress("down", () => {changeSongIdx(-1)}); + onKeyPress("up", () => {changeSongIdx(1)}); + onKeyPress("`", () => {go("Chart", index.song)}); + onKeyPress("D", () => {go("Chart", index.song)}); + onKeyPress("/", () => {go("Chart", index.song)}); + onKeyPress("7", () => {go("Chart", index.song)}); + lt.onClick(() => {changeIdx(-1)}); + rt.onClick(() => {changeIdx(1)}); + dt.onClick(() => {changeSongIdx(-1)}); + ut.onClick(() => {changeSongIdx(1)}); + onKeyPress("space", () => { + tween(tweenVals, ["fade"], 1, 0, 1, easings.easeOutCirc, tweentypes.NORMAL, function () { + go("Game", index); + }); + }); + clickText.onClick(() => {go("Game", index);/*losemus.stop();*/}); +}); + +scene("Title", () => { + const bg = add([ + sprite("bgCake") + ]); + const jb = add([ + sprite("jellybeanTitle"), + pos(0, height() - 320) + ]); + const logo = add([ + sprite("logo"), + pos(0, 0), + scale(0.5, 0.5) + ]); + onDraw(() => { + drawText({ + text: "SPACE TO START", + size: 30, + origin: "top", + pos: vec2(width() / 2, height() - 45) + }); + }) + onKeyPress("space", () => {go("Help", true);/*losemus.stop();*/}); + onClick(() => {go("Help", true);/*losemus.stop();*/}); + onTouchStart(() => {go("Help", true);/*losemus.stop();*/}); +}); + +scene("Lose", (score, song) => { + const lost = add([ + sprite("jellybeanFail"), + "dances", + pos((width() / 2) - 162, height() / 2 - 162) + ]) + const losemus = play("gameover", { + volume: 1, + loop: true + }); + onDraw(() => { + drawText({ + text: "OUCHIE!", + size: 60, + pos: vec2(0, height() - 120) + }); + drawText({ + text: ismobile ? "TAP TO RESTART" : "SPACE TO RESTART", + size: 30, + pos: vec2(0, height() - 60) + }); + drawText({ + text: "SCORE: " + score, + size: 30, + pos: vec2(0, height() - 30) + }); + }) + onKeyPress("space", () => {go("Game", song);losemus.stop();}); + onClick(() => {go("Game", song);losemus.stop();}); +}); + +scene("Chart", (idx) => { + var chart = charts[idx].chart; + var crochet = ((60 / charts[idx].bpm) * 1000); + var curBeat; + var curStep; + var songTime = 0; + var tool = "J"; + const music = play(charts[idx].id, { + volume: 1, + loop: false + }); + music.pause(); + + var lastTargeted = 4; + var tempChart = Array.from(Array(Math.floor((music.duration() * 1000) / (crochet / 4))), () => "."); + // Incredibly redundant, sadly I don't care + var coords = [ + width() * 0.1, + width() * 0.2, + width() * 0.3, + width() * 0.4, + width() * 0.5, + width() * 0.6, + width() * 0.7, + width() * 0.8, + width() * 0.9 + ]; + var theEmpty = add([ + pos(width() * 0.2, height() * 0.8), + rect(60, 60), + text(".", { + size: 48, // 48 pixels tall + width: 60 + }), + color(255, 255, 255), + outline(4, WHITE), + origin("center"), + area(), + "theEmpty" + ]); + var theJ = add([ + pos(width() * 0.4, height() * 0.8), + rect(60, 60), + text("J", { + size: 48, // 48 pixels tall + width: 60 + }), + color(255, 255, 255), + outline(4, WHITE), + origin("center"), + area(), + "theJ" + ]); + var theP = add([ + pos(width() * 0.6, height() * 0.8), + rect(60, 30), + text("P", { + size: 24, // 48 pixels tall + width: 60 + }), + color(255, 255, 255), + outline(4, WHITE), + origin("center"), + area(), + "theP" + ]); + var theD = add([ + pos(width() * 0.6, height() * 0.8 + 30), + rect(60, 30), + text("D", { + size: 24, // 48 pixels tall + width: 60 + }), + color(255, 255, 255), + outline(4, WHITE), + origin("center"), + area(), + "theD" + ]); + var consoleButton = add([ + pos(width() * 0.8, height() * 0.8), + rect(60, 60), + text("EXPORT", { + size: 30, // 48 pixels tall + }), + color(255, 255, 255), + outline(4, WHITE), + origin("center"), + area(), + "consoleButton" + ]); + onClick("theEmpty", (o) => {tool = "."}) + onClick("theJ", (o) => {tool = "J"}) + onClick("theP", (o) => {tool = "P"}) + onClick("theD", (o) => {tool = "D"}) + onClick("consoleButton", (o) => {console.log(tempChart.join(""));}) + onUpdate(() => { + curBeat = Math.floor(((music.time() * 1000) / crochet) * 10) / 10; + curStep = Math.floor((music.time() * 1000) / (crochet / 4)); + if (mousePos().y >= height() * 0.4 && mousePos().y < (height() / 2) + 34) { // I shouldve used a Switch Case here :/ + if (mousePos().x < width() * 0.15) { + // blk0 + lastTargeted = 0; + } else if (mousePos().x < width() * 0.25) { + // blk1 + lastTargeted = 1; + } else if (mousePos().x < width() * 0.35) { + // blk2 + lastTargeted = 2; + } else if (mousePos().x < width() * 0.45) { + // blk3 + lastTargeted = 3; + } else if (mousePos().x < width() * 0.55) { + // blk4 + lastTargeted = 4; + } else if (mousePos().x < width() * 0.65) { + // blk5 + lastTargeted = 5; + } else if (mousePos().x < width() * 0.75) { + // blk6 + lastTargeted = 6; + } else if (mousePos().x < width() * 0.85) { + // blk7 + lastTargeted = 7; + } else if (mousePos().x < width()) { + // blk8 + lastTargeted = 8; + } + } + }); + onMouseDown(() => { + if (mousePos().y >= height() * 0.4 && mousePos().y < (height() / 2) + 34) { + tempChart[curStep + lastTargeted] = tool; + } + }); + onDraw(() => { + drawText({ + text: songTime * 1000, + size: 20, + pos: vec2(0, ) + }); + drawText({ + text: music.time() * 1000, + size: 20, + pos: vec2(0, 20) + }); + drawText({ + text: curBeat, + size: 20, + pos: vec2(0, 40) + }); + drawText({ + text: curStep + "/" + (tempChart.length - 1), + size: 20, + pos: vec2(0, 60) + }); + drawText({ + text: tool, + size: 50, + pos: vec2(width() / 2, height() * 0.65), + origin: "center" + }); + drawLine({ + p1: vec2(coords[lastTargeted] - 30, (height() / 2) + 30), + p2: vec2(coords[lastTargeted] + 30, (height() / 2) + 30), + width: 4, + color: rgb(255, 0, 0), + }) + drawText({ + text: tempChart[curStep] ? tempChart[curStep] : "", + size: 30, + pos: vec2(coords[0], height() / 2), + color: curStep % 4 == 0 ? RED : MAGENTA, + origin: "center" + }) + drawText({ + text: tempChart[curStep + 1] ? tempChart[curStep + 1] : "", + size: 30, + pos: vec2(coords[1], height() / 2), + color: (curStep + 1) % 4 == 0 ? RED : WHITE, + origin: "center" + }) + drawText({ + text: tempChart[curStep + 2] ? tempChart[curStep + 2] : "", + size: 30, + pos: vec2(coords[2], height() / 2), + color: (curStep + 2) % 4 == 0 ? RED : WHITE, + origin: "center" + }) + drawText({ + text: tempChart[curStep + 3] ? tempChart[curStep + 3] : "", + size: 30, + pos: vec2(coords[3], height() / 2), + color: (curStep + 3) % 4 == 0 ? RED : WHITE, + origin: "center" + }) + drawText({ + text: tempChart[curStep + 4] ? tempChart[curStep + 4] : "", + size: 30, + pos: vec2(coords[4], height() / 2), + color: (curStep + 4) % 4 == 0 ? RED : WHITE, + origin: "center" + }) + drawText({ + text: tempChart[curStep + 5] ? tempChart[curStep + 5] : "", + size: 30, + pos: vec2(coords[5], height() / 2), + color: (curStep + 5) % 4 == 0 ? RED : WHITE, + origin: "center" + }) + drawText({ + text: tempChart[curStep + 6] ? tempChart[curStep + 6] : "", + size: 30, + pos: vec2(coords[6], height() / 2), + color: (curStep + 6) % 4 == 0 ? RED : WHITE, + origin: "center" + }) + drawText({ + text: tempChart[curStep + 7] ? tempChart[curStep + 7] : "", + size: 30, + pos: vec2(coords[7], height() / 2), + color: (curStep + 7) % 4 == 0 ? RED : WHITE, + origin: "center" + }) + drawText({ + text: tempChart[curStep + 8] ? tempChart[curStep + 8] : "", + size: 30, + pos: vec2(coords[8], height() / 2), + color: (curStep + 8) % 4 == 0 ? RED : WHITE, + origin: "center" + }) + }); + + onKeyPress("left", () => { + music.pause(); + songTime = songTime - ((crochet / 4) / 1000); + try { + music.play(songTime); + } catch (err) { + console.log(err); + songTime = 0; + music.play(0); + } + music.pause(); + }); + onKeyPress("right", () => { + music.pause(); + songTime = songTime + ((crochet / 4) / 1000); + try { + music.play(songTime); + } catch (err) { + console.log(err); + songTime = 0; + music.play(0); + } + music.pause(); + }); + onKeyPress("space", () => { + if (!music.isPaused()) { + music.pause(); + songTime = music.time(); + } else { + try { + music.play(songTime); + } catch (err) { + console.log(err); + songTime = 0; + music.play(0); + } + } + }); +}); + +go("Title"); diff --git a/views/projects/item/midsim/deps.js b/views/projects/item/midsim/deps.js new file mode 100644 index 0000000..1f29c1a --- /dev/null +++ b/views/projects/item/midsim/deps.js @@ -0,0 +1,6 @@ +import kaboom from "https://unpkg.com/kaboom@2000.2.9/dist/kaboom.mjs"; +import { easings, tween, tweentypes } from "./code/easing.js" + +export { + kaboom, easings, tween, tweentypes +} \ No newline at end of file diff --git a/views/projects/item/midsim/index.html b/views/projects/item/midsim/index.html new file mode 100644 index 0000000..e196b61 --- /dev/null +++ b/views/projects/item/midsim/index.html @@ -0,0 +1,17 @@ + + + + + + + Mid Sim + + + + + + + + \ No newline at end of file diff --git a/views/projects/item/midsim/sounds/Getting it Done.mp3 b/views/projects/item/midsim/sounds/Getting it Done.mp3 new file mode 100644 index 0000000..42e68f4 Binary files /dev/null and b/views/projects/item/midsim/sounds/Getting it Done.mp3 differ diff --git a/views/projects/item/midsim/sounds/GreenHill.wav b/views/projects/item/midsim/sounds/GreenHill.wav new file mode 100644 index 0000000..cf98a12 Binary files /dev/null and b/views/projects/item/midsim/sounds/GreenHill.wav differ diff --git a/views/projects/item/midsim/sounds/SonicInMidSim.wav b/views/projects/item/midsim/sounds/SonicInMidSim.wav new file mode 100644 index 0000000..cb3542b Binary files /dev/null and b/views/projects/item/midsim/sounds/SonicInMidSim.wav differ diff --git a/views/projects/item/midsim/sounds/The Friendly Faith Plate.mp3 b/views/projects/item/midsim/sounds/The Friendly Faith Plate.mp3 new file mode 100644 index 0000000..81c2011 Binary files /dev/null and b/views/projects/item/midsim/sounds/The Friendly Faith Plate.mp3 differ diff --git a/views/projects/item/midsim/sounds/burp.mp3 b/views/projects/item/midsim/sounds/burp.mp3 new file mode 100644 index 0000000..1c8c782 Binary files /dev/null and b/views/projects/item/midsim/sounds/burp.mp3 differ diff --git a/views/projects/item/midsim/sounds/explode.mp3 b/views/projects/item/midsim/sounds/explode.mp3 new file mode 100644 index 0000000..e0d8d6a Binary files /dev/null and b/views/projects/item/midsim/sounds/explode.mp3 differ diff --git a/views/projects/item/midsim/sounds/gameover.mp3 b/views/projects/item/midsim/sounds/gameover.mp3 new file mode 100644 index 0000000..e887205 Binary files /dev/null and b/views/projects/item/midsim/sounds/gameover.mp3 differ diff --git a/views/projects/item/midsim/sounds/hitsoundFaithPlate.mp3 b/views/projects/item/midsim/sounds/hitsoundFaithPlate.mp3 new file mode 100644 index 0000000..b2d053e Binary files /dev/null and b/views/projects/item/midsim/sounds/hitsoundFaithPlate.mp3 differ diff --git a/views/projects/item/midsim/sounds/hitsoundJellyBean.wav b/views/projects/item/midsim/sounds/hitsoundJellyBean.wav new file mode 100644 index 0000000..f7b4c80 Binary files /dev/null and b/views/projects/item/midsim/sounds/hitsoundJellyBean.wav differ diff --git a/views/projects/item/midsim/sounds/hitsoundRedVelvety.wav b/views/projects/item/midsim/sounds/hitsoundRedVelvety.wav new file mode 100644 index 0000000..8d98eb1 Binary files /dev/null and b/views/projects/item/midsim/sounds/hitsoundRedVelvety.wav differ diff --git a/views/projects/item/midsim/sounds/metro.wav b/views/projects/item/midsim/sounds/metro.wav new file mode 100644 index 0000000..c641db3 Binary files /dev/null and b/views/projects/item/midsim/sounds/metro.wav differ diff --git a/views/projects/item/midsim/sounds/nullHit.mp3 b/views/projects/item/midsim/sounds/nullHit.mp3 new file mode 100644 index 0000000..f31f305 Binary files /dev/null and b/views/projects/item/midsim/sounds/nullHit.mp3 differ diff --git a/views/projects/item/midsim/sounds/score.mp3 b/views/projects/item/midsim/sounds/score.mp3 new file mode 100644 index 0000000..e068db0 Binary files /dev/null and b/views/projects/item/midsim/sounds/score.mp3 differ diff --git a/views/projects/item/midsim/sprites/321go.png b/views/projects/item/midsim/sprites/321go.png new file mode 100644 index 0000000..86c552a Binary files /dev/null and b/views/projects/item/midsim/sprites/321go.png differ diff --git a/views/projects/item/midsim/sprites/MidSimFont2.png b/views/projects/item/midsim/sprites/MidSimFont2.png new file mode 100644 index 0000000..fd2d481 Binary files /dev/null and b/views/projects/item/midsim/sprites/MidSimFont2.png differ diff --git a/views/projects/item/midsim/sprites/SonicBG.png b/views/projects/item/midsim/sprites/SonicBG.png new file mode 100644 index 0000000..eb0ddc7 Binary files /dev/null and b/views/projects/item/midsim/sprites/SonicBG.png differ diff --git a/views/projects/item/midsim/sprites/SonicFG.png b/views/projects/item/midsim/sprites/SonicFG.png new file mode 100644 index 0000000..1d370c1 Binary files /dev/null and b/views/projects/item/midsim/sprites/SonicFG.png differ diff --git a/views/projects/item/midsim/sprites/SonicMidSim.png b/views/projects/item/midsim/sprites/SonicMidSim.png new file mode 100644 index 0000000..39da7c0 Binary files /dev/null and b/views/projects/item/midsim/sprites/SonicMidSim.png differ diff --git a/views/projects/item/midsim/sprites/TailsMidSim.png b/views/projects/item/midsim/sprites/TailsMidSim.png new file mode 100644 index 0000000..b43bc08 Binary files /dev/null and b/views/projects/item/midsim/sprites/TailsMidSim.png differ diff --git a/views/projects/item/midsim/sprites/bgCake.png b/views/projects/item/midsim/sprites/bgCake.png new file mode 100644 index 0000000..58d9ed2 Binary files /dev/null and b/views/projects/item/midsim/sprites/bgCake.png differ diff --git a/views/projects/item/midsim/sprites/bgFaith.png b/views/projects/item/midsim/sprites/bgFaith.png new file mode 100644 index 0000000..f112f9f Binary files /dev/null and b/views/projects/item/midsim/sprites/bgFaith.png differ diff --git a/views/projects/item/midsim/sprites/carterredactedCake.png b/views/projects/item/midsim/sprites/carterredactedCake.png new file mode 100644 index 0000000..0b5ce94 Binary files /dev/null and b/views/projects/item/midsim/sprites/carterredactedCake.png differ diff --git a/views/projects/item/midsim/sprites/faithplateFaith.png b/views/projects/item/midsim/sprites/faithplateFaith.png new file mode 100644 index 0000000..577b346 Binary files /dev/null and b/views/projects/item/midsim/sprites/faithplateFaith.png differ diff --git a/views/projects/item/midsim/sprites/fgCake0.png b/views/projects/item/midsim/sprites/fgCake0.png new file mode 100644 index 0000000..dab4fca Binary files /dev/null and b/views/projects/item/midsim/sprites/fgCake0.png differ diff --git a/views/projects/item/midsim/sprites/fgCake1.png b/views/projects/item/midsim/sprites/fgCake1.png new file mode 100644 index 0000000..7027fb9 Binary files /dev/null and b/views/projects/item/midsim/sprites/fgCake1.png differ diff --git a/views/projects/item/midsim/sprites/fgFaith.png b/views/projects/item/midsim/sprites/fgFaith.png new file mode 100644 index 0000000..601231b Binary files /dev/null and b/views/projects/item/midsim/sprites/fgFaith.png differ diff --git a/views/projects/item/midsim/sprites/jellybeanCake.png b/views/projects/item/midsim/sprites/jellybeanCake.png new file mode 100644 index 0000000..efbfc2d Binary files /dev/null and b/views/projects/item/midsim/sprites/jellybeanCake.png differ diff --git a/views/projects/item/midsim/sprites/jellybeanFail.png b/views/projects/item/midsim/sprites/jellybeanFail.png new file mode 100644 index 0000000..f467e24 Binary files /dev/null and b/views/projects/item/midsim/sprites/jellybeanFail.png differ diff --git a/views/projects/item/midsim/sprites/jellybeanTitle.png b/views/projects/item/midsim/sprites/jellybeanTitle.png new file mode 100644 index 0000000..40f67be Binary files /dev/null and b/views/projects/item/midsim/sprites/jellybeanTitle.png differ diff --git a/views/projects/item/midsim/sprites/logo.png b/views/projects/item/midsim/sprites/logo.png new file mode 100644 index 0000000..7f7da6b Binary files /dev/null and b/views/projects/item/midsim/sprites/logo.png differ diff --git a/views/projects/item/midsim/sprites/marcCake.png b/views/projects/item/midsim/sprites/marcCake.png new file mode 100644 index 0000000..328cefd Binary files /dev/null and b/views/projects/item/midsim/sprites/marcCake.png differ diff --git a/views/projects/item/midsim/sprites/markymarkCake.png b/views/projects/item/midsim/sprites/markymarkCake.png new file mode 100644 index 0000000..a197602 Binary files /dev/null and b/views/projects/item/midsim/sprites/markymarkCake.png differ diff --git a/views/projects/item/midsim/sprites/noteClick.png b/views/projects/item/midsim/sprites/noteClick.png new file mode 100644 index 0000000..855cbf3 Binary files /dev/null and b/views/projects/item/midsim/sprites/noteClick.png differ diff --git a/views/projects/item/midsim/sprites/previews/CarterRedactedPre.png b/views/projects/item/midsim/sprites/previews/CarterRedactedPre.png new file mode 100644 index 0000000..9398a6e Binary files /dev/null and b/views/projects/item/midsim/sprites/previews/CarterRedactedPre.png differ diff --git a/views/projects/item/midsim/sprites/previews/FaithPlatePre.png b/views/projects/item/midsim/sprites/previews/FaithPlatePre.png new file mode 100644 index 0000000..24bbdf2 Binary files /dev/null and b/views/projects/item/midsim/sprites/previews/FaithPlatePre.png differ diff --git a/views/projects/item/midsim/sprites/previews/JellyBeanPre.png b/views/projects/item/midsim/sprites/previews/JellyBeanPre.png new file mode 100644 index 0000000..7dc87c1 Binary files /dev/null and b/views/projects/item/midsim/sprites/previews/JellyBeanPre.png differ diff --git a/views/projects/item/midsim/sprites/previews/MarcPre.png b/views/projects/item/midsim/sprites/previews/MarcPre.png new file mode 100644 index 0000000..096bc7f Binary files /dev/null and b/views/projects/item/midsim/sprites/previews/MarcPre.png differ diff --git a/views/projects/item/midsim/sprites/previews/MarkyMarkPre.png b/views/projects/item/midsim/sprites/previews/MarkyMarkPre.png new file mode 100644 index 0000000..d7170fe Binary files /dev/null and b/views/projects/item/midsim/sprites/previews/MarkyMarkPre.png differ diff --git a/views/projects/item/midsim/sprites/previews/RedVelvetyPre.png b/views/projects/item/midsim/sprites/previews/RedVelvetyPre.png new file mode 100644 index 0000000..ce2ef0f Binary files /dev/null and b/views/projects/item/midsim/sprites/previews/RedVelvetyPre.png differ diff --git a/views/projects/item/midsim/sprites/previews/SonicAndTailsPre.png b/views/projects/item/midsim/sprites/previews/SonicAndTailsPre.png new file mode 100644 index 0000000..0c1869a Binary files /dev/null and b/views/projects/item/midsim/sprites/previews/SonicAndTailsPre.png differ diff --git a/views/projects/item/midsim/sprites/previews/TailsPre.png b/views/projects/item/midsim/sprites/previews/TailsPre.png new file mode 100644 index 0000000..fcfda76 Binary files /dev/null and b/views/projects/item/midsim/sprites/previews/TailsPre.png differ diff --git a/views/projects/item/midsim/sprites/redvelvetyCake.png b/views/projects/item/midsim/sprites/redvelvetyCake.png new file mode 100644 index 0000000..876cdc3 Binary files /dev/null and b/views/projects/item/midsim/sprites/redvelvetyCake.png differ diff --git a/views/projects/item/midsim/sprites/unscii_8x8.png b/views/projects/item/midsim/sprites/unscii_8x8.png new file mode 100644 index 0000000..95eb7e3 Binary files /dev/null and b/views/projects/item/midsim/sprites/unscii_8x8.png differ diff --git a/views/projects/normalize/index.html b/views/projects/item/normalize/index.html similarity index 100% rename from views/projects/normalize/index.html rename to views/projects/item/normalize/index.html diff --git a/views/projects/item/wm/index.html b/views/projects/item/wm/index.html new file mode 100644 index 0000000..0068f1b --- /dev/null +++ b/views/projects/item/wm/index.html @@ -0,0 +1,59 @@ + + + + + MTRUWSaDMfHTML5 + + + + + + + + <$ loader.html $> +
+
+

MTRUWSaDMfHTML5

+
+ +
+
+
+ + +
+
+ + + + + + + diff --git a/views/projects/item/wm/pages/welcome.html b/views/projects/item/wm/pages/welcome.html new file mode 100644 index 0000000..7dab1ba --- /dev/null +++ b/views/projects/item/wm/pages/welcome.html @@ -0,0 +1,33 @@ + + + + + Welcome! + + + + + + <$ loader.html $> +
+
+

Welcome to MTRUWSaDMfHTML5!

+

+ (MeowcaTheoRange's Unnecessary Windowing System and Desktop Manager + for HTML5) +

+

A basic windowing system made in HTML5 and JavaScript.

+
+ +
+ + + + + diff --git a/views/projects/item/wm/scripts/endplorer.js b/views/projects/item/wm/scripts/endplorer.js new file mode 100644 index 0000000..6cd14c0 --- /dev/null +++ b/views/projects/item/wm/scripts/endplorer.js @@ -0,0 +1,110 @@ +class TaskbarObject { + parentManager; + taskbarObject; + + taskbarStart; + + children; + + constructor(manager) { + this.parentManager = manager; + this.taskbarObject = TaskbarObject.createTaskbar(this); + this.parentManager.addExtension(this, "taskbarObject"); + this.parentManager.overscan_bottom = "2.5625em"; + + this.taskbarStart = this.taskbarObject.querySelector(".taskbar-start"); + + this.children = []; + + this.parentManager.managerObject.addEventListener("windowcreate", (e) => + this.addToTabs(e) + ); + + this.parentManager.managerObject.addEventListener("windowdestroy", (e) => + this.removeFromTabs(e) + ); + + this.parentManager.managerObject.addEventListener("windowfocus", (e) => + this.refocusTabs(e) + ); + + this.parentManager.managerObject.addEventListener( + "windowmanager_title", + (e) => this.updateTab(e) + ); + } + + addToTabs(e) { + const button = document.createElement("button"); + button.classList.add("taskbar-button"); + + button.addEventListener("click", (e2) => this.event_raiseWindow(e, e2)); + + console.log(button); + + this.children.splice(e.detail.windowId, 0, button); + this.taskbarStart.appendChild(button); + } + + removeFromTabs(e) { + const button = this.children[e.detail.windowId]; + + console.log(this.children, e.detail.windowId); + + this.children.splice(e.detail.windowId, 1); + this.taskbarStart.removeChild(button); + } + + updateTab(e, mode) { + const button = this.children[e.detail.windowId]; + + button.textContent = e.detail.title; + } + + refocusTabs(e) { + this.parentManager.children.forEach((child) => { + if (child.focusOrder <= 0) { + this.children[child.windowId].classList.add("taskbar-button-focusing"); + } else + this.children[child.windowId].classList.remove( + "taskbar-button-focusing" + ); + }); + } + + destroy() { + this.parentManager.overscan_bottom = "0px"; + } + + event_raiseWindow(e, e2) { + if (e.detail.focusOrder <= 0) { + e.detail.minimizeWindow(); + } else { + this.parentManager.raiseWindow(e.detail); + } + refocusTabs(); + } + + static createTaskbar(taskbarRef) { + const taskbarObject = document.createElement("div"); + taskbarObject.classList.add("taskbar-object"); + taskbarObject.tabIndex = "0"; + taskbarObject.style.zIndex = taskbarRef.parentManager.maxZIndex + 1; + + { + const taskbarStart = document.createElement("div"); + taskbarStart.classList.add("taskbar-start"); + + taskbarObject.appendChild(taskbarStart); + } + + { + const taskbarEnd = document.createElement("div"); + taskbarEnd.classList.add("taskbar-end"); + + taskbarObject.appendChild(taskbarEnd); + } + + return taskbarObject; + } +} diff --git a/views/projects/item/wm/styles/endplorer.css b/views/projects/item/wm/styles/endplorer.css new file mode 100644 index 0000000..2988023 --- /dev/null +++ b/views/projects/item/wm/styles/endplorer.css @@ -0,0 +1,46 @@ +.taskbar-object { + position: fixed; + width: 100%; + left: 0; + bottom: 0; + + display: grid; + grid-template-columns: auto auto; + vertical-align: middle; + user-select: none; + + background-color: var(--accent-color); + color: var(--accent-color-fg); + border: var(--border-style); + overflow: hidden; + padding: 0.25em; +} + +.taskbar-object > .taskbar-start { + text-align: start; + height: 2em; +} + +.taskbar-object > .taskbar-end { + text-align: end; + height: 2em; +} + +.taskbar-object > .taskbar-start > button { + height: 2em; + padding: 0.5em; + margin: 0; + margin-inline-end: 0.25em; + border: var(--border-style); + background-color: transparent; + color: currentColor; + text-align: center; + vertical-align: middle; + font-size: 1em; + line-height: 1em; +} + +.taskbar-object > .taskbar-start > button.taskbar-button-focusing { + background-color: var(--accent-color-fg); + color: var(--accent-color); +} diff --git a/views/projects/woz/index.html b/views/projects/item/woz/index.html similarity index 100% rename from views/projects/woz/index.html rename to views/projects/item/woz/index.html diff --git a/views/projects/woz/public/woz0.png b/views/projects/item/woz/public/woz0.png similarity index 100% rename from views/projects/woz/public/woz0.png rename to views/projects/item/woz/public/woz0.png diff --git a/views/projects/woz/public/woz1.png b/views/projects/item/woz/public/woz1.png similarity index 100% rename from views/projects/woz/public/woz1.png rename to views/projects/item/woz/public/woz1.png diff --git a/views/projects/woz/public/woz2.png b/views/projects/item/woz/public/woz2.png similarity index 100% rename from views/projects/woz/public/woz2.png rename to views/projects/item/woz/public/woz2.png diff --git a/views/projects/woz/public/woz3.png b/views/projects/item/woz/public/woz3.png similarity index 100% rename from views/projects/woz/public/woz3.png rename to views/projects/item/woz/public/woz3.png diff --git a/views/projects/woz/public/woz4.png b/views/projects/item/woz/public/woz4.png similarity index 100% rename from views/projects/woz/public/woz4.png rename to views/projects/item/woz/public/woz4.png diff --git a/views/projects/woz/public/woz5.png b/views/projects/item/woz/public/woz5.png similarity index 100% rename from views/projects/woz/public/woz5.png rename to views/projects/item/woz/public/woz5.png diff --git a/views/projects/woz/public/woz6.png b/views/projects/item/woz/public/woz6.png similarity index 100% rename from views/projects/woz/public/woz6.png rename to views/projects/item/woz/public/woz6.png diff --git a/views/projects/woz/public/woz7.png b/views/projects/item/woz/public/woz7.png similarity index 100% rename from views/projects/woz/public/woz7.png rename to views/projects/item/woz/public/woz7.png diff --git a/views/projects/woz/public/woz8.png b/views/projects/item/woz/public/woz8.png similarity index 100% rename from views/projects/woz/public/woz8.png rename to views/projects/item/woz/public/woz8.png diff --git a/views/projects/woz/public/woz9.png b/views/projects/item/woz/public/woz9.png similarity index 100% rename from views/projects/woz/public/woz9.png rename to views/projects/item/woz/public/woz9.png diff --git a/views/projects/woz/public/wozstash.png b/views/projects/item/woz/public/wozstash.png similarity index 100% rename from views/projects/woz/public/wozstash.png rename to views/projects/item/woz/public/wozstash.png diff --git a/views/projects/woz/scripts/index.js b/views/projects/item/woz/scripts/index.js similarity index 100% rename from views/projects/woz/scripts/index.js rename to views/projects/item/woz/scripts/index.js diff --git a/views/projects/midsim b/views/projects/midsim deleted file mode 160000 index 81568fa..0000000 --- a/views/projects/midsim +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 81568fa474de7547284eedfccd8045c7edbd4cad diff --git a/views/projects/public/projects.json b/views/projects/public/projects.json index 773f5b8..7440855 100644 --- a/views/projects/public/projects.json +++ b/views/projects/public/projects.json @@ -1,37 +1,73 @@ -[ - { - "name": "Normalize", - "date": 1701404400000, - "description": [ - "Normalize is a simple CSS library made to provide good-looking yet simple HTML element styles." - ], - "url": "/projects/normalize/" +{ + "tags": { + "old": "#800000", + "new": "#008000", + "normalize": "#808080" }, - { - "name": "WozSteamGen", - "date": 1700200800000, - "description": [ - "WozSteamGen is a Scott The Woz thumbnail generator for Steam games.", - "It's an API-less adaptation of Steam The Woz, running completely locally." - ], - "url": "/projects/woz/" - }, - { - "name": "HexFlagGen", - "date": 1700114400000, - "description": [ - "HexFlagGen is a flag generator inspired by how the Free Speech Flag was made.", - "I dislike DRM and support trans rights." - ], - "url": "/projects/hex/" - }, - { - "name": "JellyBean's Mid-Sim", - "date": 1651986000000, - "description": [ - "JellyBean's Mid-Sim, a 1K rhythm game made in the HTML5-JS game engine Kaboom." - ], - "url": "/projects/midsim/", - "size": [700, 400] - } -] + "items": [ + { + "name": "DiceApp", + "date": 1655589660000, + "description": ["An app. For managing virtual dice."], + "url": "/projects/item/dice/", + "tags": ["old"] + }, + { + "name": "FunnyClock²", + "date": 1662695100000, + "description": [ + "FunnyClock² is the successor of FunnyClock, an application made for my school to show when smartboards are idle." + ], + "url": "/projects/item/clock/", + "tags": ["old"] + }, + { + "name": "MTRUWSaDMfHTML5", + "date": 1701743828350, + "description": [ + "MeowcaTheoRange's Unnecessary Windowing System and Desktop Manager for HTML5.
Works best outside of windowed mode." + ], + "url": "/projects/item/wm/", + "tags": ["normalize", "new"] + }, + { + "name": "Normalize", + "date": 1701404400000, + "description": [ + "Normalize is a simple CSS library made to provide good-looking yet simple HTML element styles." + ], + "url": "/projects/item/normalize/", + "tags": ["normalize"] + }, + { + "name": "JellyBean's Mid-Sim", + "date": 1651986000000, + "description": [ + "JellyBean's Mid-Sim, a 1K rhythm game made in the HTML5-JS game engine Kaboom." + ], + "url": "/projects/item/midsim/", + "size": [700, 400], + "tags": ["old"] + }, + { + "name": "WozSteamGen", + "date": 1700200800000, + "description": [ + "WozSteamGen is a Scott The Woz thumbnail generator for Steam games.", + "It's an API-less adaptation of Steam The Woz, running completely locally." + ], + "url": "/projects/item/woz/", + "tags": ["normalize"] + }, + { + "name": "HexFlagGen", + "date": 1700114400000, + "description": [ + "HexFlagGen is a flag generator inspired by how the Free Speech Flag was made.", + "I dislike DRM and support trans rights." + ], + "url": "/projects/item/hex/", + "tags": ["normalize"] + } + ] +} diff --git a/views/projects/scripts/data_get_projects.js b/views/projects/scripts/data_get_projects.js index a158aac..f676a7a 100644 --- a/views/projects/scripts/data_get_projects.js +++ b/views/projects/scripts/data_get_projects.js @@ -2,10 +2,25 @@ const data_get = document.getElementById("data_get"); fetch("./public/projects.json") .then((x) => x.json()) .then((projects) => { - data_get.innerHTML = projects.reduce( - (html, project) => - html + - `

${project.name}

+ data_get.innerHTML = projects.items + .sort((a, b) => b.date - a.date) + .reduce( + (html, project) => + html + + `

${project.name}${ + /*${project.tags.reduce( + (html, tag) => + html + + ``, + "" + )}*/ "" + }

${new Date(project.date).toLocaleDateString()}

${project.description.reduce( (html, descfragment) => html + `

${descfragment}

`, @@ -20,12 +35,12 @@ fetch("./public/projects.json") or

`, - "" - ); + "" + ); }); diff --git a/views/scripts/windows.js b/views/scripts/windows.js index 314c342..36b540b 100755 --- a/views/scripts/windows.js +++ b/views/scripts/windows.js @@ -10,16 +10,25 @@ class WindowManager { managerObject; children; + extensions; minZIndex = 50; maxZIndex = 100; + screen_overscan = { + l: "0px", + r: "0px", + t: "0px", + b: "0px", + }; + constructor(manager) { this.managerObject = manager; this.managerObject.classList.add("window-master"); this.managerObject.style.zIndex = this.minZIndex; this.children = []; + this.extensions = []; window.addEventListener("beforeunload", () => this.destroy()); @@ -34,6 +43,30 @@ class WindowManager { ); } + set overscan_left(os) { + this.screen_overscan.l = os; + this.#event_manageMinimized(); + } + + set overscan_right(os) { + this.screen_overscan.r = os; + this.#event_manageMinimized(); + } + + set overscan_bottom(os) { + this.screen_overscan.b = os; + this.#event_manageMinimized(); + } + + set overscan_top(os) { + this.screen_overscan.t = os; + this.#event_manageMinimized(); + } + + get overscan() { + return this.screen_overscan; + } + createWindow(content, srcdoc, w, h) { return new WindowObject(this, content, srcdoc, w, h); } @@ -42,7 +75,7 @@ class WindowManager { this.children .filter((x) => x.minimized) .forEach((curWinObj, i) => { - curWinObj.windowObject.style.bottom = `calc(2em * ${i})`; + curWinObj.windowObject.style.bottom = `calc(${this.screen_overscan.b} + (2em * ${i}))`; }); } @@ -64,6 +97,12 @@ class WindowManager { this.managerObject.appendChild(windowObj.windowObject); } + addExtension(ext, obj) { + this.extensions.push(ext); + + this.managerObject.appendChild(ext[obj]); + } + removeWindow(windowId) { this.children.splice(windowId, 1); if (this.children.length > 0) @@ -72,13 +111,22 @@ class WindowManager { ); } + removeExtension(extId) { + this.extensions.splice(extId, 1); + } + destroy() { this.children.forEach((x) => { console.log(x); x.destroy(); }); + this.extensions.forEach((x) => { + console.log(x); + x.destroy(); + }); this.managerObject.remove(); this.children = []; + this.extensions = []; } dispatchEvent(eventName, data) { @@ -220,22 +268,27 @@ class WindowObject { set title(content) { this.windowManagerLabel.textContent = content; + this.dispatchEvent("windowmanager_title", { detail: this }); } set content(src) { this.windowContent.srcdoc = src; + this.dispatchEvent("windowmanager_content", { detail: this }); } set contentUrl(url) { this.windowContent.src = url; + this.dispatchEvent("windowmanager_content", { detail: this }); } set x(x) { this.windowObject.style.left = x + "px"; + this.dispatchEvent("windowmove", { detail: this, mouse: e }); } set y(y) { this.windowObject.style.top = y = "px"; + this.dispatchEvent("windowmove", { detail: this, mouse: e }); } set width(w) { @@ -246,6 +299,10 @@ class WindowObject { this.windowObject.style.height = h = "px"; } + // raiseWindow() { + // this.parentManager.raiseWindow(this); + // } + freezeWindow() { this.#isFrozen = !this.#isFrozen; @@ -397,9 +454,9 @@ class WindowObject { } catch (err) {} this.windowObject.remove(); + this.dispatchEvent("windowdestroy", { detail: this }); this.parentManager.removeWindow(this.windowId); - this.dispatchEvent("windowdestroy", { detail: this }); } event__dragMouseDown(e, touch) { @@ -444,7 +501,7 @@ class WindowObject { this.windowObject.style.top = this.#orig_selfPosY - (this.#orig_mousePosY - cY) + "px"; - this.dispatchEvent("windowdragmove", { detail: this, mouse: e }); + this.dispatchEvent("windowmove", { detail: this, mouse: e }); } } diff --git a/views/styles/normal.css b/views/styles/normal.css index 507dcc2..49a364f 100755 --- a/views/styles/normal.css +++ b/views/styles/normal.css @@ -143,6 +143,10 @@ p { margin-block: 0.5em; } +img { + max-width: 100%; +} + ul, ol { padding: 0; diff --git a/views/styles/style.css b/views/styles/style.css index cfc4bee..e553942 100644 --- a/views/styles/style.css +++ b/views/styles/style.css @@ -20,10 +20,6 @@ transition: background-color 0.25s, color 0.25s, opacity 0.25s; } -img { - max-width: 100%; -} - .nav { max-width: 38em; margin: auto;