Merge pull request 'games' (#22) from selenite/pages:main into main
Reviewed-on: https://codeberg.org/skysthelimitt/selenite/pulls/22
32
404.html
@ -59,7 +59,37 @@
|
|||||||
<main id="main" class="noscroll">
|
<main id="main" class="noscroll">
|
||||||
<h1>Page not found!</h1>
|
<h1>Page not found!</h1>
|
||||||
<p>We could not find this page.</p>
|
<p>We could not find this page.</p>
|
||||||
<a href="/index.html">Go home</a>
|
<a href="/index.html"><button>Go home</button></a>
|
||||||
|
<button onclick="statsForNerds()">Stats for nerds</button>
|
||||||
|
<div id="sfn" style="display: none;" class="message">
|
||||||
|
Please report this to our <a href="https://discord.gg/7jyufnwJNf">Discord</a> or <a href="mailto:support@selenite.cc">email.</a> <br>
|
||||||
|
Requested URL: <span id="full">You need Javascript to show the Stats for nerds</span><br>
|
||||||
|
Referrer: <span id="ref">You need Javascript to show the Stats for nerds</span><br>
|
||||||
|
Title: <span id="title">You need Javascript to show the Stats for nerds</span><br>
|
||||||
|
Screen height: <span id="height">You need Javascript to show the Stats for nerds</span><br>
|
||||||
|
Screen width: <span id="width">You need Javascript to show the Stats for nerds</span><br>
|
||||||
|
Window height: <span id="winheight">You need Javascript to show the Stats for nerds</span><br>
|
||||||
|
Window width: <span id="winwidth">You need Javascript to show the Stats for nerds</span><br>
|
||||||
|
Cookies: <span id="cookie">You need Javascript to show the Stats for nerds</span><br>
|
||||||
|
User agent: <span id="ua">You need Javascript to show the Stats for nerds</span><br>
|
||||||
|
OS platform: <span id="plat">You need Javascript to show the Stats for nerds</span><br>
|
||||||
|
Online: <span id="online">You need Javascript to show the Stats for nerds</span>
|
||||||
|
<br />IP: <span id="ip">You need Javascript to show the Stats for nerds</span><br>
|
||||||
|
Error code: 404<br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
"innerText"in document.body||Object.defineProperty(HTMLElement.prototype,"innerText",{get:function(){return this.textContent},set:function(a){this.textContent=a}}),window.fetch||(window.fetch=function(a){return new Promise(function(b,c){var d=new XMLHttpRequest;d.open("GET",a),d.onload=function(){200===d.status?b(JSON.parse(d.responseText)):c(Error(d.statusText))},d.onerror=function(){c(Error("Network Error"))},d.send()})}),window.XMLHttpRequest||(window.XMLHttpRequest=function(){try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(a){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(a){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(a){}throw new Error("This browser does not support XMLHttpRequest.")});function statsForNerds(){var a=document.getElementById("sfn");"none"===a.style.display?(a.style.display="block",console.log("[\u2139\uFE0F] Showing the stats for nerds!")):(a.style.display="none",console.log("[\u2139\uFE0F] Hiding the stats for nerds!"))}document.getElementById("full").innerText=window.location.href,document.getElementById("ref").innerHTML=document.referrer,document.getElementById("title").innerText=document.title,document.getElementById("height").innerHTML=screen.height+"px",document.getElementById("width").innerHTML=screen.width+"px",document.getElementById("winheight").innerHTML=window.innerHeight+"px",document.getElementById("winwidth").innerHTML=window.innerWidth+"px",document.getElementById("cookie").innerText=navigator.cookieEnabled,document.getElementById("ua").innerHTML=navigator.userAgent,document.getElementById("plat").innerHTML=navigator.platform,document.getElementById("online").innerHTML=navigator.onLine;var echolog={};fetch("//wtfismyip.com/json").then(function(a){return a.json()}).then(function(a){var b={ipAddress:a.YourFuckingIPAddress,hostname:a.YourFuckingHostname},c=document.getElementById("ip");c.innerText=b.ipAddress})["catch"](function(a){return console.error(a)});
|
||||||
|
</script>
|
||||||
|
<div id="adcontainer">
|
||||||
|
<h3><a href="ad.html">AD (click to read more):</a></h3>
|
||||||
|
<script async="async" data-cfasync="false" src="//snailthreatenedinvited.com/92108816b5da54426d1639bcbfb5785c/invoke.js"></script>
|
||||||
|
<div id="container-92108816b5da54426d1639bcbfb5785c"></div>
|
||||||
|
</div>
|
||||||
|
<div id="adcontainer">
|
||||||
|
<script type='text/javascript' src='//snailthreatenedinvited.com/f9/78/06/f97806fd0f338057a67abb4e5e710970.js'></script>
|
||||||
|
</div>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer class="noscroll">
|
<footer class="noscroll">
|
||||||
|
@ -2,17 +2,17 @@
|
|||||||
The better unblocked games website.
|
The better unblocked games website.
|
||||||
## Deploy to a cloud service
|
## Deploy to a cloud service
|
||||||
[](https://railway.app/new/template?template=https://gitlab.com/skysthelimit.dev/selenite)
|
[](https://railway.app/new/template?template=https://gitlab.com/skysthelimit.dev/selenite)
|
||||||
[](https://app.cyclic.sh/api/app/deploy/selenite-cc/selenite)
|
[](https://app.cyclic.sh/api/app/deploy/selenite-cc/selenite-old)
|
||||||
[](https://app.koyeb.com/deploy?type=git&repository=gitlab.com/skysthelimit.dev/selenite&branch=main&name=selenite)
|
[](https://app.koyeb.com/deploy?type=git&repository=gitlab.com/skysthelimit.dev/selenite&branch=main&name=selenite)
|
||||||
[](https://render.com/deploy?repo=https://gitlab.com/skysthelimit.dev/selenite)
|
[](https://render.com/deploy?repo=https://gitlab.com/skysthelimit.dev/selenite)
|
||||||
[](https://replit.com/github/selenite-cc/selenite)
|
[](https://replit.com/github/selenite-cc/selenite-old)
|
||||||
[](https://glitch.com/edit/#!/import/github/selenite-cc/selenite)
|
[](https://glitch.com/edit/#!/import/github/selenite-cc/selenite-old)
|
||||||
[](https://vercel.com/new/clone?repository-url=https://gitlab.com/skysthelimit.dev/selenite)
|
[](https://vercel.com/new/clone?repository-url=https://gitlab.com/skysthelimit.dev/selenite)
|
||||||
## Contributors
|
## Contributors
|
||||||
<img height="40px" width="40px" src="https://avatars.githubusercontent.com/u/64362346?v=4"></img>
|
<img height="40px" width="40px" src="https://avatars.githubusercontent.com/u/64362346?v=4"></img>
|
||||||
<a href="https://github.com/skysthelimitt"><p>Sky</p></a><br>
|
<a href="https://github.com/skysthelimitt"><p>Sky</p></a><br>
|
||||||
<img height="40px" width="40px" src="https://cdn.discordapp.com/avatars/578300487678558208/e3ae410d681e77823c1df58a6d7ccab9?size=1024"></img>
|
<img height="40px" width="40px" src="https://cdn.discordapp.com/avatars/578300487678558208/e3ae410d681e77823c1df58a6d7ccab9?size=1024"></img>
|
||||||
<a href="https://codeberg.org/LEGALISE_PIRACY"><p>LEGALLISE_PIRACY</p></a><br>
|
<a href="https://codeberg.org/LEGALISE_PIRACY"><p>LEGALISE_PIRACY</p></a><br>
|
||||||
<img height="40px" width="40px" src="https://cdn.discordapp.com/avatars/510677660775743500/79bb34e1537d9e670db4a0ea2ad6f56f?size=1024"></img>
|
<img height="40px" width="40px" src="https://cdn.discordapp.com/avatars/510677660775743500/79bb34e1537d9e670db4a0ea2ad6f56f?size=1024"></img>
|
||||||
<a href="https://github.com/a456pur"><p>Astralogical</p></a>
|
<a href="https://github.com/a456pur"><p>Astralogical</p></a>
|
||||||
|
|
||||||
|
33
about.html
@ -49,6 +49,14 @@
|
|||||||
<main id="main">
|
<main id="main">
|
||||||
<h1>About Selenite</h1>
|
<h1>About Selenite</h1>
|
||||||
<p style="padding-left: 100px; padding-right: 100px; padding-bottom: 20px">Selenite is a unblocked games website with over 200 games, with a simple tab cloak. Selenite was started as a small project started on Padlet, shared between friends. After ~1 month, we transferred to a custom made website. After a few rebrandings and redesigns, we've ended up at the Selenite you know and love (unless you work at a school).</p>
|
<p style="padding-left: 100px; padding-right: 100px; padding-bottom: 20px">Selenite is a unblocked games website with over 200 games, with a simple tab cloak. Selenite was started as a small project started on Padlet, shared between friends. After ~1 month, we transferred to a custom made website. After a few rebrandings and redesigns, we've ended up at the Selenite you know and love (unless you work at a school).</p>
|
||||||
|
<div id="adcontainer">
|
||||||
|
<h3><a href="ad.html">AD (click to read more):</a></h3>
|
||||||
|
<script async="async" data-cfasync="false" src="//snailthreatenedinvited.com/92108816b5da54426d1639bcbfb5785c/invoke.js"></script>
|
||||||
|
<div id="container-92108816b5da54426d1639bcbfb5785c"></div>
|
||||||
|
</div>
|
||||||
|
<div id="adcontainer">
|
||||||
|
<script type='text/javascript' src='//snailthreatenedinvited.com/f9/78/06/f97806fd0f338057a67abb4e5e710970.js'></script>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>Credits</h2>
|
<h2>Credits</h2>
|
||||||
<p><a href="https://jquery.com/">jQuery</a>: a lot of the more technical stuff.</p>
|
<p><a href="https://jquery.com/">jQuery</a>: a lot of the more technical stuff.</p>
|
||||||
@ -57,6 +65,14 @@
|
|||||||
<p><a href="https://www.bootcss.com/">Bootstrap</a>: useful as a base for some smaller, styling such as the new games popup</p>
|
<p><a href="https://www.bootcss.com/">Bootstrap</a>: useful as a base for some smaller, styling such as the new games popup</p>
|
||||||
<p><a href="https://3kh0.net">3kh0</a>: a lot of games, the download/upload save feature, and the main inspiration</p>
|
<p><a href="https://3kh0.net">3kh0</a>: a lot of games, the download/upload save feature, and the main inspiration</p>
|
||||||
<p><a href="/backgrounds.html">View Background Credits</a></p>
|
<p><a href="/backgrounds.html">View Background Credits</a></p>
|
||||||
|
<div id="adcontainer">
|
||||||
|
<h3><a href="ad.html">AD (click to read more):</a></h3>
|
||||||
|
<script async="async" data-cfasync="false" src="//snailthreatenedinvited.com/92108816b5da54426d1639bcbfb5785c/invoke.js"></script>
|
||||||
|
<div id="container-92108816b5da54426d1639bcbfb5785c"></div>
|
||||||
|
</div>
|
||||||
|
<div id="adcontainer">
|
||||||
|
<script type='text/javascript' src='//snailthreatenedinvited.com/f9/78/06/f97806fd0f338057a67abb4e5e710970.js'></script>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>Developers</h2>
|
<h2>Developers</h2>
|
||||||
<div class="samerow">
|
<div class="samerow">
|
||||||
@ -73,6 +89,14 @@
|
|||||||
<p>a456pur</p></a
|
<p>a456pur</p></a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="adcontainer">
|
||||||
|
<h3><a href="ad.html">AD (click to read more):</a></h3>
|
||||||
|
<script async="async" data-cfasync="false" src="//snailthreatenedinvited.com/92108816b5da54426d1639bcbfb5785c/invoke.js"></script>
|
||||||
|
<div id="container-92108816b5da54426d1639bcbfb5785c"></div>
|
||||||
|
</div>
|
||||||
|
<div id="adcontainer">
|
||||||
|
<script type='text/javascript' src='//snailthreatenedinvited.com/f9/78/06/f97806fd0f338057a67abb4e5e710970.js'></script>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>Supporters</h2>
|
<h2>Supporters</h2>
|
||||||
<div class="samerow">
|
<div class="samerow">
|
||||||
@ -101,6 +125,15 @@
|
|||||||
<p>Awesome-XV</p></a
|
<p>Awesome-XV</p></a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="adcontainer">
|
||||||
|
<h3><a href="ad.html">AD (click to read more):</a></h3>
|
||||||
|
<script async="async" data-cfasync="false" src="//snailthreatenedinvited.com/92108816b5da54426d1639bcbfb5785c/invoke.js"></script>
|
||||||
|
<div id="container-92108816b5da54426d1639bcbfb5785c"></div>
|
||||||
|
</div>
|
||||||
|
<div id="adcontainer">
|
||||||
|
<script type='text/javascript' src='//snailthreatenedinvited.com/f9/78/06/f97806fd0f338057a67abb4e5e710970.js'></script>
|
||||||
|
</div>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
|
405
css/style.css
Normal file
@ -0,0 +1,405 @@
|
|||||||
|
@import url("https://fonts.googleapis.com/css2?family=Prompt:wght@300&display=swap");
|
||||||
|
|
||||||
|
@keyframes loadInAnimation {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--inputbg: #3c096c;
|
||||||
|
--inputborder: #5a189a;
|
||||||
|
--uibg: #240046;
|
||||||
|
--textcolor: #fff;
|
||||||
|
--bg: #10002b;
|
||||||
|
}
|
||||||
|
.hiddenUpload {
|
||||||
|
display: none;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
* {
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
align-content: center;
|
||||||
|
text-align: center;
|
||||||
|
font-family: "Prompt", sans-serif;
|
||||||
|
color: var(--textcolor);
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: var(--bg);
|
||||||
|
color: var(--textcolor);
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
background-attachment: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
header,
|
||||||
|
footer {
|
||||||
|
background-color: var(--uibg);
|
||||||
|
display: flex;
|
||||||
|
border-bottom: none;
|
||||||
|
font-weight:700;
|
||||||
|
padding: 0.7rem;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 1;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#time {
|
||||||
|
font-weight:100;
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
top: 0;
|
||||||
|
border-radius: 0 0 20px 20px;
|
||||||
|
position: fixed;
|
||||||
|
box-shadow: 0 5px 10px var(--uibg);
|
||||||
|
}
|
||||||
|
|
||||||
|
footer.noscroll {
|
||||||
|
position: fixed;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
bottom: 0;
|
||||||
|
border-radius: 20px 20px 0 0;
|
||||||
|
box-shadow: 0 -5px 10px var(--uibg);
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a,
|
||||||
|
footer a:visited,
|
||||||
|
header a,
|
||||||
|
header a:visited {
|
||||||
|
margin-right: 2rem;
|
||||||
|
margin-left: 1rem;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a:hover,
|
||||||
|
header a:hover {
|
||||||
|
text-shadow: 2px 2px 6px var(--textcolor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media only screen and (max-width: 768px) {
|
||||||
|
header,
|
||||||
|
footer {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
animation: 1.25s ease-in-out 0s 1 loadInAnimation;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
display: flex;
|
||||||
|
min-height: calc(100vh - (2 * 0.7rem));
|
||||||
|
gap: 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 4rem;
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
main#main.noscroll {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
p,
|
||||||
|
a,
|
||||||
|
label {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
text-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
.samerow {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 40px;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
p,
|
||||||
|
a {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
input#websubmit.submit,
|
||||||
|
input[type="submit"] {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: var(--inputbg);
|
||||||
|
border-color: var(--inputborder);
|
||||||
|
border-width: 2px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border-style: solid;
|
||||||
|
padding: 7px;
|
||||||
|
margin-left: 20px;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover,
|
||||||
|
input#websubmit.submit:hover,
|
||||||
|
input[type="submit"]:hover {
|
||||||
|
filter: brightness(80%);
|
||||||
|
transform: scale(1.07);
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
aspect-ratio: auto;
|
||||||
|
user-select: none;
|
||||||
|
filter: drop-shadow(var(--shadow));
|
||||||
|
image-rendering: pixelated;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-container a {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 6%;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
margin: 2%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game,
|
||||||
|
.suggest {
|
||||||
|
width: 15%;
|
||||||
|
border-radius: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
background-color: var(--uibg);
|
||||||
|
margin: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0px 0px 5px 5px var(--uibg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.game:hover,
|
||||||
|
.suggest:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
filter: brightness(85%);
|
||||||
|
box-shadow: 0px 0px 5px 5px var(--uibg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.game h1,
|
||||||
|
.suggest h1 {
|
||||||
|
font-size: 12px;
|
||||||
|
float: right;
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game img,
|
||||||
|
.suggest img {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 20px;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.star {
|
||||||
|
float: left;
|
||||||
|
width: 10%;
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#noscroll {
|
||||||
|
overflow-y: hidden;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#games,
|
||||||
|
#pinned {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
width: 50%;
|
||||||
|
background-color: var(--inputbg);
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 20px;
|
||||||
|
padding: 0.8% 0.8%;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 5px;
|
||||||
|
outline: none;
|
||||||
|
margin: 10px;
|
||||||
|
border: 2px solid var(--inputborder);
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: opacity 0.25s ease-in-out;
|
||||||
|
opacity: 100%;
|
||||||
|
}
|
||||||
|
input[type="text"]:hover {
|
||||||
|
opacity: 80%;
|
||||||
|
}
|
||||||
|
::placeholder {
|
||||||
|
color: var(--textcolor);
|
||||||
|
opacity: 0.4; /* Firefox */
|
||||||
|
}
|
||||||
|
|
||||||
|
.bookmarkletdiv {
|
||||||
|
width: 30%;
|
||||||
|
background-color: var(--uibg);
|
||||||
|
box-shadow: 0px 0px 5px 5px var(--uibg);
|
||||||
|
padding: 5px;
|
||||||
|
margin: 15px;
|
||||||
|
border-radius: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bookmarkletdiv a {
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.samerow.themebtns {
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: var(--inputbg);
|
||||||
|
border-color: var(--inputborder);
|
||||||
|
border-width: 5px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border-style: solid;
|
||||||
|
padding: 0.5% 0.5%;
|
||||||
|
margin: 0.25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
gameframe {
|
||||||
|
width: 100vw;
|
||||||
|
height: 90vh;
|
||||||
|
}
|
||||||
|
gameframe iframe {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
gameframe.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
sl-icon-button {
|
||||||
|
font-size: 2rem;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3#gametitle {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
thumb.png .img-credits {
|
||||||
|
height: 40vh;
|
||||||
|
width: auto;
|
||||||
|
box-shadow: 0px 0px 20px rgba(255, 255, 255, 0.555);
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: 20px;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
.avatar {
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
#bgimg {
|
||||||
|
width: 30vw;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
#status {
|
||||||
|
position: absolute;
|
||||||
|
right: 2%;
|
||||||
|
}
|
||||||
|
#toast {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: var(--inputbg);
|
||||||
|
border-radius: 10px;
|
||||||
|
border-width: 10px;
|
||||||
|
border-color: var(--inputborder);
|
||||||
|
border-style: solid;
|
||||||
|
z-index: 10000;
|
||||||
|
text-align: center;
|
||||||
|
opacity: 0;
|
||||||
|
transition-duration: 1s;
|
||||||
|
max-width: 30%;
|
||||||
|
}
|
||||||
|
#toast h1 {
|
||||||
|
font-size: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#toast p {
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#discord {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 10px;
|
||||||
|
right: 10px;
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
z-index: 199975;
|
||||||
|
border-radius: 100%;
|
||||||
|
background-image: url("/img/discord-mark-white.png");
|
||||||
|
background-size: 60%;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
|
@keyframes toastFade {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
15% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
85% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,21 @@ body[theme=threekho] {
|
|||||||
--textcolor: #fff;
|
--textcolor: #fff;
|
||||||
--bg: #000000;
|
--bg: #000000;
|
||||||
}
|
}
|
||||||
|
body[theme=art] {
|
||||||
|
--inputbg: #0284d4;
|
||||||
|
--inputborder: #0284d4;
|
||||||
|
--uibg: #0284d4;
|
||||||
|
--textcolor: #fffff;
|
||||||
|
--bg: #1a2023;
|
||||||
|
}
|
||||||
|
body[theme=dogcat] {
|
||||||
|
--inputbg: #537294;
|
||||||
|
--inputborder: #30719c;
|
||||||
|
--uibg: #2a7491;
|
||||||
|
--textcolor: #fff;
|
||||||
|
--bg: url("img/backgrounds/dogcat.svg"), rgb(26, 127, 158);
|
||||||
|
/* https://wallpaperaccess.com/full/115544.jpg */
|
||||||
|
}
|
||||||
body[theme=custom] {
|
body[theme=custom] {
|
||||||
--inputbg: #3c096c;
|
--inputbg: #3c096c;
|
||||||
--inputborder: #5a189a;
|
--inputborder: #5a189a;
|
||||||
@ -119,14 +134,7 @@ body[theme=mochafalse] {
|
|||||||
--shadow: 0px 0px 4px #313244;
|
--shadow: 0px 0px 4px #313244;
|
||||||
/* surface 0 */
|
/* surface 0 */
|
||||||
}
|
}
|
||||||
body[theme=bgsfalse] {
|
|
||||||
--inputbg: #553113;
|
|
||||||
--inputborder: #3d220c;
|
|
||||||
--uibg: #553113;
|
|
||||||
--textcolor: #ffffff;
|
|
||||||
--bg: #2f1d0f;
|
|
||||||
/* https://bfs-bdp.pages.dev/images/GAMES-BG.png */
|
|
||||||
}
|
|
||||||
body[theme=sunsetfalse] {
|
body[theme=sunsetfalse] {
|
||||||
--inputbg: #537294;
|
--inputbg: #537294;
|
||||||
--inputborder: #30719c;
|
--inputborder: #30719c;
|
||||||
@ -231,14 +239,7 @@ body[theme=mocha] {
|
|||||||
--shadow: 0px 0px 4px #313244;
|
--shadow: 0px 0px 4px #313244;
|
||||||
/* surface 0 */
|
/* surface 0 */
|
||||||
}
|
}
|
||||||
body[theme=bgs] {
|
|
||||||
--inputbg: #553113;
|
|
||||||
--inputborder: #3d220c;
|
|
||||||
--uibg: #553113;
|
|
||||||
--textcolor: #ffffff;
|
|
||||||
--bg: url("img/backgrounds/bgs_theme.png"), #61437a;
|
|
||||||
/* https://bfs-bdp.pages.dev/images/GAMES-BG.png */
|
|
||||||
}
|
|
||||||
body[theme=sunset] {
|
body[theme=sunset] {
|
||||||
--inputbg: #537294;
|
--inputbg: #537294;
|
||||||
--inputborder: #30719c;
|
--inputborder: #30719c;
|
||||||
@ -283,4 +284,5 @@ body[theme=nighttime] {
|
|||||||
--bg: url("img/backgrounds/nighttime_theme.png"), #61437a;
|
--bg: url("img/backgrounds/nighttime_theme.png"), #61437a;
|
||||||
/* https://wallhaven.cc/w/l882py */
|
/* https://wallhaven.cc/w/l882py */
|
||||||
--shadow: 0px 0px 4px #fff;
|
--shadow: 0px 0px 4px #fff;
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,55 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"name": "Ruffle",
|
||||||
|
"directory": "ruffle",
|
||||||
|
"image": "cover.svg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ZIP Unarchiver",
|
||||||
|
"directory": "zip",
|
||||||
|
"image": "cover.svg"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "GBA Emulator",
|
||||||
|
"directory": "gba",
|
||||||
|
"image": "cover.svg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "EmulatorJS",
|
||||||
|
"directory": "emu",
|
||||||
|
"image": "cover.svg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Scratch 1",
|
||||||
|
"directory": "scratch1",
|
||||||
|
"image": "cover.svg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AyunWebEPK",
|
||||||
|
"directory": "ayun",
|
||||||
|
"image": "cover.svg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Scratch 2",
|
||||||
|
"directory": "scratch2",
|
||||||
|
"image": "cover.svg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SB2 to SWF",
|
||||||
|
"directory": "sb2toswf",
|
||||||
|
"image": "cover.svg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "MiniWiki",
|
||||||
|
"directory": "wiki",
|
||||||
|
"image": "cover.svg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Windows 11",
|
||||||
|
"directory": "11",
|
||||||
|
"image": "cover.svg"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Javascript Deobfuscator",
|
"name": "Javascript Deobfuscator",
|
||||||
"directory": "deobsfucator",
|
"directory": "deobsfucator",
|
||||||
|
@ -1,4 +1,79 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"name": "CrossNRoad",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "crossnroad"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tappy Plane",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "tappyplane"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Putin on the Ritz",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "ritz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sandboxels",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "box"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Flappy Race",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "flappyrace"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Karlson",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "karlson"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Adventure",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "adventure"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "The Heist",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "heist"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Age of War 2",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "aow2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Star Clicker",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "star"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Racer",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "racer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fort@dmin",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "fort"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Flappy Dino",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "fld"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Connect Four",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "c4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "13 Days of Hell",
|
||||||
|
"image": "cover.svg",
|
||||||
|
"directory": "13"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Mindustry",
|
"name": "Mindustry",
|
||||||
"image": "cover.svg",
|
"image": "cover.svg",
|
||||||
@ -279,11 +354,6 @@
|
|||||||
"directory": "worldshardestgame",
|
"directory": "worldshardestgame",
|
||||||
"image": "icon.png"
|
"image": "icon.png"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "GBA Emulator",
|
|
||||||
"directory": "gba",
|
|
||||||
"image": "icon.png"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Celeste",
|
"name": "Celeste",
|
||||||
"directory": "celeste",
|
"directory": "celeste",
|
||||||
@ -624,11 +694,6 @@
|
|||||||
"directory": "universal-paperclips",
|
"directory": "universal-paperclips",
|
||||||
"image": "universal-paperclips.png"
|
"image": "universal-paperclips.png"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Windows 11",
|
|
||||||
"directory": "win11",
|
|
||||||
"image": "favicon.png"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Learn to Fly 2",
|
"name": "Learn to Fly 2",
|
||||||
"directory": "learntofly2",
|
"directory": "learntofly2",
|
||||||
@ -984,16 +1049,7 @@
|
|||||||
"directory": "amazing-rope-police",
|
"directory": "amazing-rope-police",
|
||||||
"image": "splash.jpeg"
|
"image": "splash.jpeg"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Ruffle",
|
|
||||||
"directory": "ruffle",
|
|
||||||
"image": "favicon-180.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "emulatorJS",
|
|
||||||
"directory": "emulatorjs",
|
|
||||||
"image": "logo.png"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Geometry Rash",
|
"name": "Geometry Rash",
|
||||||
"directory": "geometryrash",
|
"directory": "geometryrash",
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
"we love about:blank",
|
"we love about:blank",
|
||||||
"make sure to back up ur saves incase we ever get blocked",
|
"make sure to back up ur saves incase we ever get blocked",
|
||||||
"join the discord to be cool",
|
"join the discord to be cool",
|
||||||
"rip bigfoot games shack 🕊",
|
"bigfoot is an L",
|
||||||
"check steam",
|
"check steam",
|
||||||
"selentine",
|
"selentine",
|
||||||
"geometry dash two point two",
|
"geometry dash two point two",
|
||||||
@ -55,7 +55,6 @@
|
|||||||
"selenite",
|
"selenite",
|
||||||
"yocorvettekid loves gay men",
|
"yocorvettekid loves gay men",
|
||||||
"3kh0",
|
"3kh0",
|
||||||
"bigfoot games shack",
|
|
||||||
"selenite is the best",
|
"selenite is the best",
|
||||||
"selenite is the best website",
|
"selenite is the best website",
|
||||||
"selenite is the best website ever",
|
"selenite is the best website ever",
|
||||||
|
Before Width: | Height: | Size: 73 KiB |
3
img/backgrounds/dogcat.svg
Normal file
After Width: | Height: | Size: 131 KiB |
@ -194,3 +194,8 @@ var polyfillScript = document.createElement("script");
|
|||||||
polyfillScript.src = "https://polyfill.io/v3/polyfill.js";
|
polyfillScript.src = "https://polyfill.io/v3/polyfill.js";
|
||||||
document.head.appendChild(polyfillScript);
|
document.head.appendChild(polyfillScript);
|
||||||
// polyfill.io
|
// polyfill.io
|
||||||
|
$(document).ready(function(){
|
||||||
|
$.getScript('https://cdnjs.cloudflare.com/ajax/libs/core-js/3.37.0/minified.js');
|
||||||
|
});
|
||||||
|
// core js
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
var interval;
|
var interval;
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
if (localStorage.getItem("theme")) {
|
if (localStorage.getItem("theme")) {
|
||||||
@ -195,3 +194,4 @@ let cookieConsentStyle = document.createElement("link");
|
|||||||
cookieConsentStyle.href = "/js/cookieConsent.css";
|
cookieConsentStyle.href = "/js/cookieConsent.css";
|
||||||
cookieConsentStyle.rel = "stylesheet";
|
cookieConsentStyle.rel = "stylesheet";
|
||||||
document.head.appendChild(cookieConsentStyle);
|
document.head.appendChild(cookieConsentStyle);
|
||||||
|
|
||||||
|
3484
semag/030/app.js
Normal file
22
semag/030/index.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>0.30 Classic</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=utf8">
|
||||||
|
<script type="text/javascript" charset="utf-8" src="app.js"></script>
|
||||||
|
<script src="./js/all.js"></script>
|
||||||
|
|
||||||
|
<script type = text/javascript>
|
||||||
|
if(document.location.href.startsWith("file:")) {
|
||||||
|
alert("Offline Download is not supported, please upload all the game files to a HTTP(s) server");
|
||||||
|
} else {
|
||||||
|
window.addEventListener("load", function() {
|
||||||
|
window.classicConfig = ["game","resources.mc"];
|
||||||
|
main();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body style="margin:0px;width:100vw;height:100vh;" id="game">
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
semag/030/resources.mc
Normal file
2
semag/125/ cheerpj-natives/natives/jawt.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Unimplemented, but prevents bad HTTP servers from responding with 206 and HTML(!) instead of 404 when this file is requested.
|
||||||
|
export default {};
|
1465
semag/125/ cheerpj-natives/natives/lwjgl.js
Normal file
3
semag/125/.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "cheerpj-natives"]
|
||||||
|
path = cheerpj-natives
|
||||||
|
url = https://github.com/leaningtech/cheerpj-natives.git
|
26
semag/125/404.html
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" style="width:100%;height:100%;">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Not found - Browsercraft</title>
|
||||||
|
<script src="https://cjrtnc.leaningtech.com/3_20231218_321/cj3loader.js"></script>
|
||||||
|
<script defer data-domain="browsercraft.cheerpj.com" src="https://plausible.leaningtech.com/js/script.js"></script>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
|
||||||
|
<meta name="description" content="Open-source port of Minecraft to the web. Play Minecraft in your browser!">
|
||||||
|
<meta property="og:title" content="Browsercraft">
|
||||||
|
<meta property="og:description" content="Open-source port of Minecraft to the web. Play Minecraft in your browser!">
|
||||||
|
<meta property="og:url" content="https://browsercraft.cheerpj.com">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<h1>
|
||||||
|
Not found
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
This page was not found. Try going back to the <a href="/">homepage</a>.
|
||||||
|
</p>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
201
semag/125/LICENSE
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
5
semag/125/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Browsercraft
|
||||||
|
|
||||||
|
This is a proof of concept of Minecraft running unmodified in the browser, using [CheerpJ](https://labs.leaningtech.com/cheerpj).
|
||||||
|
|
||||||
|
See [the website](https://browsercraft.cheerpj.com) for a live demo and more information.
|
2
semag/125/_headers
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/cheerpj-natives/natives/lwjgl.js
|
||||||
|
Content-Type: application/octet-stream
|
BIN
semag/125/client.jar
Normal file
BIN
semag/125/fonts/minecrafter/License.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
10
semag/125/fonts/minecrafter/License.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
This Font "MineCrafter" is under the creative commons license and can be used non-commercialy,
|
||||||
|
as long as it is passed along unchanged and in whole, with credit to one of the following names ;
|
||||||
|
|
||||||
|
"PurePixel", "MadPixel"
|
||||||
|
|
||||||
|
If your looking to use this font commercially please contact me before using the font.
|
||||||
|
|
||||||
|
Enjoy and donations appreciated.
|
||||||
|
|
||||||
|
{http://creativecommons.org/licenses/}
|
BIN
semag/125/fonts/minecrafter/Minecrafter.Reg.woff2
Normal file
9
semag/125/fonts/minecrafter/Read Me.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
The font in this archive was created by madpixel with credits to mojang for original design of font.
|
||||||
|
please read the license information before using this font
|
||||||
|
|
||||||
|
|
||||||
|
LEGAL NOTICE:
|
||||||
|
In using this font you must comply with the licensing terms described in the
|
||||||
|
file “License.txt” included with this archive.
|
||||||
|
If you redistribute the font file in this archive, it must be accompanied by
|
||||||
|
all the other files from this archive, including this one and credited to madpixel.
|
107
semag/125/index.html
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" style="width:100%;height:100%;">
|
||||||
|
<head>
|
||||||
|
<script src="./js/all.js"></script>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Browsercraft</title>
|
||||||
|
<script src="https://cjrtnc.leaningtech.com/3.0/cj3loader.js"></script>
|
||||||
|
<script defer data-domain="browsercraft.cheerpj.com" src="https://plausible.leaningtech.com/js/script.js"></script>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<script>
|
||||||
|
alert("NOTE: Chromium 120 and up is required to run this program");
|
||||||
|
</script>
|
||||||
|
<meta name="description" content="Unmodified Minecraft running in the browser using CheerpJ. Play Minecraft in your browser!">
|
||||||
|
<meta property="og:title" content="Browsercraft">
|
||||||
|
<meta property="og:description" content="Unmodified Minecraft running in the browser using CheerpJ. Play Minecraft in your browser!">
|
||||||
|
<meta property="og:url" content="https://browsercraft.cheerpj.com">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Browsercraft</h1>
|
||||||
|
<div class="desktop-only">
|
||||||
|
<minecraft-client></minecraft-client>
|
||||||
|
<div class="controls">
|
||||||
|
<button id="fullscreen" title="Enter fullscreen">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-maximize"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"></path></svg>
|
||||||
|
</button>
|
||||||
|
<a href="https://twitter.com/intent/tweet?url=https://browsercraft.cheerpj.com" title="Share on X (formerly known as Twitter)">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-twitter"><path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path></svg>
|
||||||
|
</a>
|
||||||
|
<button id="share" title="Share">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-share-2"><circle cx="18" cy="5" r="3"></circle><circle cx="6" cy="12" r="3"></circle><circle cx="18" cy="19" r="3"></circle><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"></line><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"></line></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mobile-only">
|
||||||
|
Browsercraft does not support mobile devices yet. Please visit this page on a desktop or laptop computer to try Browsercraft, or make the window wider if you're already on a desktop or laptop.
|
||||||
|
</div>
|
||||||
|
<a href="https://github.com/leaningtech/browsercraft" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#fff; color:#151513; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<h2>What is this</h2>
|
||||||
|
<p>
|
||||||
|
<b>Browsercraft</b> makes unmodified Minecraft run in the browser using <a href="https://cheerpj.com">CheerpJ</a>, a Java runtime for modern browsers.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>What this is not</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://classic.minecraft.net">Minecraft Classic</a>, an alpha version of Minecraft playable in the browser</li>
|
||||||
|
<li>Minecraft Bedrock Edition</li>
|
||||||
|
<li>The latest version of Minecraft. Newer releases of Minecraft use a newer version of Java and OpenGL which we currently do not support.</li>
|
||||||
|
<li>A modified version of Minecraft. We do not modify the game in any way, we just run the original JARs.</li>
|
||||||
|
<li>A reimplementation of Minecraft in another programming language</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>How it works</h2>
|
||||||
|
<p>
|
||||||
|
<a href="https://labs.leaningtech.com/cheerpj3/guides/Implementing-Java-native-methods-in-JavaScript">CheerpJ supports specifying JavaScript implementations of Java native methods.</a>
|
||||||
|
We use this feature to implement portions of LWJGL (a library used by Minecraft for rendering, audio, input, etc.) in JavaScript. On desktop, LWJGL uses C++ implementations of these methods.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://github.com/leaningtech/cheerpj-natives/blob/main/natives/lwjgl.js">View the LWJGL implementation.</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This project is a work-in-progress and not everything works yet. In particular:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>Audio is not supported</li>
|
||||||
|
<li>Many textures are not rendered correctly</li>
|
||||||
|
<li>Probably other subtle problems</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
None of these issues are fundamental limitations, they just haven't been implemented yet.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you're a programmer, we'd love your help in fixing these issues! <a href="https://discord.gg/7xXW6NAdHT">Join the Discord server</a> and <a href="https://github.com/leaningtech/browsercraft">contribute on GitHub</a>.
|
||||||
|
</p>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
import MinecraftClient from "./minecraft-web.js";
|
||||||
|
await cheerpjInit({
|
||||||
|
version: 8,
|
||||||
|
javaProperties: ["java.library.path=/app/cheerpj-natives/natives", "org.lwjgl.util.NoChecks=true"],
|
||||||
|
});
|
||||||
|
MinecraftClient.register();
|
||||||
|
|
||||||
|
const client = document.querySelector("minecraft-client");
|
||||||
|
|
||||||
|
document.getElementById("fullscreen").addEventListener("click", () => client.requestFullscreen());
|
||||||
|
|
||||||
|
const share = document.getElementById("share");
|
||||||
|
const shareData = {
|
||||||
|
title: "Browsercraft",
|
||||||
|
text: "Unmodified Minecraft running in the browser using CheerpJ. Play Minecraft in your browser!",
|
||||||
|
url: "https://browsercraft.cheerpj.com",
|
||||||
|
};
|
||||||
|
if (navigator.canShare?.(shareData)) {
|
||||||
|
share.addEventListener("click", () => navigator.share(shareData));
|
||||||
|
} else {
|
||||||
|
share.remove();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
BIN
semag/125/lwjgl-2.9.0.jar
Normal file
BIN
semag/125/lwjgl_util-2.9.0.jar
Normal file
31
semag/125/mc_server.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>CheerpJ test</title>
|
||||||
|
<script src="mcutils.js"></script>
|
||||||
|
<script src="https://cjrtnc.leaningtech.com/3_20231222_329/cj3loader.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="display" style="width:100%;height:100%;position:absolute;top:0;left:0px;"></div>
|
||||||
|
<p id="ip"></p>
|
||||||
|
<script>
|
||||||
|
function ipCallback(ip)
|
||||||
|
{
|
||||||
|
document.getElementById("ip").textContent = "Server IP: "+ip;
|
||||||
|
}
|
||||||
|
async function runServer()
|
||||||
|
{
|
||||||
|
await cheerpjInit({tailscaleAuthKey:"tskey-auth-k9RsJp3CNTRL-xcmTEoqDeYjUVQpzCwwUejtL5bLq9MZVS",tailscaleIpCb:ipCallback});
|
||||||
|
// TODO: Run with nogui
|
||||||
|
cheerpjCreateDisplay(-1, -1, document.getElementById("display"));
|
||||||
|
// The server needs to write a few files to its cwd, copy it over to /files/
|
||||||
|
await installFile("https://piston-data.mojang.com/v1/objects/d8321edc9470e56b8ad5c67bbd16beba25843336/server.jar", "/files/server_1.2.5.jar");
|
||||||
|
// Copy over a modified configuration allowing any client to connect
|
||||||
|
await installFile("/server.properties", "/files/server.properties");
|
||||||
|
await cheerpjRunJar("/files/server_1.2.5.jar");
|
||||||
|
}
|
||||||
|
runServer();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
192
semag/125/minecraft-web.js
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
/**
|
||||||
|
* Downloads a file from a url and writes it to the CheerpJ filesystem.
|
||||||
|
* @param {string} url
|
||||||
|
* @param {string} destPath
|
||||||
|
* @param {(downloadedBytes: number, totalBytes: number) => void} [progressCallback]
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async function downloadFileToCheerpJ(url, destPath, progressCallback) {
|
||||||
|
const response = await fetch(url);
|
||||||
|
const reader = response.body.getReader();
|
||||||
|
const contentLength = +response.headers.get('Content-Length');
|
||||||
|
|
||||||
|
const bytes = new Uint8Array(contentLength);
|
||||||
|
progressCallback?.(0, contentLength);
|
||||||
|
|
||||||
|
let pos = 0;
|
||||||
|
while (true) {
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
if (done)
|
||||||
|
break;
|
||||||
|
bytes.set(value, pos);
|
||||||
|
pos += value.length;
|
||||||
|
progressCallback?.(pos, contentLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to CheerpJ filesystem
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
cheerpOSOpen(cjFDs, destPath, "w", fd => {
|
||||||
|
cheerpOSWrite(cjFDs, fd, bytes, 0, bytes.length, w => {
|
||||||
|
cheerpOSClose(cjFDs, fd);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const template = document.createElement('template');
|
||||||
|
template.innerHTML = `
|
||||||
|
<style>
|
||||||
|
:host {
|
||||||
|
display: inline-block;
|
||||||
|
aspect-ratio: 854 / 480;
|
||||||
|
|
||||||
|
background: black;
|
||||||
|
color: #eee;
|
||||||
|
color-scheme: dark;
|
||||||
|
|
||||||
|
width: 854px;
|
||||||
|
height: 480px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([hidden]) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
width: inherit;
|
||||||
|
height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display {
|
||||||
|
width: 854px;
|
||||||
|
height: 480px;
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
max-width: 60ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disclaimer {
|
||||||
|
font-size: 0.8em;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 0.5em 1em;
|
||||||
|
margin: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress {
|
||||||
|
width: calc(100% - 2em);
|
||||||
|
margin: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
*:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<canvas width="854" height="480" tabindex="-1"></canvas>
|
||||||
|
<div class="display"></div>
|
||||||
|
<div class="intro">
|
||||||
|
<p>
|
||||||
|
This is a proof-of-concept demo of Minecraft 1.2.5 running unmodified in the browser.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Clicking the button below will download the client from mojang.com.
|
||||||
|
By clicking it, you agree to the <a href="https://www.minecraft.net/eula">Minecraft EULA</a>.
|
||||||
|
</p>
|
||||||
|
<button>Play!</button>
|
||||||
|
<div class="disclaimer">
|
||||||
|
This is not an official Minecraft product. It is not approved by or associated with Mojang or Microsoft.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<progress style="display: none"></progress>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default class MinecraftClient extends HTMLElement {
|
||||||
|
#canvas;
|
||||||
|
#progress;
|
||||||
|
#button;
|
||||||
|
#display;
|
||||||
|
#intro;
|
||||||
|
#isRunning;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const shadowRoot = this.attachShadow({ mode: 'open' });
|
||||||
|
shadowRoot.appendChild(template.content.cloneNode(true));
|
||||||
|
|
||||||
|
this.#button = shadowRoot.querySelector('button');
|
||||||
|
this.#button.addEventListener('click', () => this.run());
|
||||||
|
|
||||||
|
this.#canvas = shadowRoot.querySelector('canvas');
|
||||||
|
this.#canvas.width = 854;
|
||||||
|
this.#canvas.height = 480;
|
||||||
|
this.#canvas.tabIndex = -1;
|
||||||
|
this.#canvas.style.display = 'none';
|
||||||
|
|
||||||
|
this.#progress = shadowRoot.querySelector('progress');
|
||||||
|
this.#progress.style.display = 'none';
|
||||||
|
|
||||||
|
this.#intro = shadowRoot.querySelector('.intro');
|
||||||
|
|
||||||
|
// CheerpJ needs an element to render to, but we are going to render to own canvas
|
||||||
|
this.#display = shadowRoot.querySelector('.display');
|
||||||
|
this.#display.setAttribute('style', 'width:100%;height:100%;position:absolute;top:0;left:0px;visibility:hidden;');
|
||||||
|
cheerpjCreateDisplay(-1, -1, this.#display);
|
||||||
|
|
||||||
|
this.#isRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static register() {
|
||||||
|
customElements.define('minecraft-client', this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {Promise<number>} Exit code */
|
||||||
|
async run() {
|
||||||
|
if (this.#isRunning) {
|
||||||
|
throw new Error('Already running');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#intro.style.display = 'none';
|
||||||
|
|
||||||
|
this.#progress.style.display = 'unset';
|
||||||
|
const jarPath = "./semag/125/client.jar"
|
||||||
|
await downloadFileToCheerpJ(
|
||||||
|
"./semag/125/client.jar",
|
||||||
|
jarPath,
|
||||||
|
(downloadedBytes, totalBytes) => {
|
||||||
|
this.#progress.value = downloadedBytes;
|
||||||
|
this.#progress.max = totalBytes;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.#progress.style.display = 'none';
|
||||||
|
|
||||||
|
this.#canvas.style.display = 'unset';
|
||||||
|
window.lwjglCanvasElement = this.#canvas;
|
||||||
|
const exitCode = await cheerpjRunMain("net.minecraft.client.Minecraft", `/app/lwjgl-2.9.0.jar:/app/lwjgl_util-2.9.0.jar:${jarPath}`)
|
||||||
|
|
||||||
|
this.#canvas.style.display = 'none';
|
||||||
|
this.#isRunning = false;
|
||||||
|
|
||||||
|
return exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {boolean} */
|
||||||
|
get isRunning() {
|
||||||
|
return this.#isRunning;
|
||||||
|
}
|
||||||
|
}
|
26
semag/125/server.properties
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#Minecraft server properties
|
||||||
|
#Sun Dec 17 14:36:54 CET 2023
|
||||||
|
view-distance=10
|
||||||
|
max-build-height=256
|
||||||
|
server-ip=
|
||||||
|
level-seed=
|
||||||
|
allow-nether=true
|
||||||
|
gamemode=0
|
||||||
|
server-port=25565
|
||||||
|
enable-rcon=false
|
||||||
|
enable-query=false
|
||||||
|
level-name=world
|
||||||
|
motd=A Minecraft Server
|
||||||
|
white-list=false
|
||||||
|
pvp=true
|
||||||
|
texture-pack=
|
||||||
|
spawn-npcs=true
|
||||||
|
spawn-animals=true
|
||||||
|
generate-structures=true
|
||||||
|
snooper-enabled=true
|
||||||
|
difficulty=1
|
||||||
|
level-type=DEFAULT
|
||||||
|
spawn-monsters=true
|
||||||
|
max-players=20
|
||||||
|
online-mode=false
|
||||||
|
allow-flight=false
|
92
semag/125/style.css
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
font-family: system-ui, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Minecrafter";
|
||||||
|
src: url("fonts/minecrafter/Minecrafter.Reg.woff2"), sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
background: #171615;
|
||||||
|
color: white;
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header h1 {
|
||||||
|
color: #c6b8b4;
|
||||||
|
font: 48px Minecrafter;
|
||||||
|
transform: perspective(24px) translateZ(0) rotate3d(1, 0, 0, 2deg);
|
||||||
|
text-shadow: 0px 5px 4px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 1rem;
|
||||||
|
max-width: 60ch;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
main h2 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin: 1rem 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
main li {
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
minecraft-client {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls > * {
|
||||||
|
appearance: none;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls svg {
|
||||||
|
stroke: #c6b8b4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls > *:hover svg {
|
||||||
|
stroke: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-only {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 854px) {
|
||||||
|
.mobile-only {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-only {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
BIN
semag/13/13-days-in-hell.swf
Normal file
4
semag/13/cover.svg
Normal file
After Width: | Height: | Size: 11 KiB |
2
semag/13/index.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<script src="https://unpkg.com/@ruffle-rs/ruffle"></script>
|
||||||
|
<embed src="13-days-in-hell.swf" width="100%" height="100%"></embed>
|
21
semag/adventure/Adventure (1978) (Atari).html
Normal file
3
semag/adventure/cover.svg
Normal file
After Width: | Height: | Size: 44 KiB |
2
semag/adventure/index.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<iframe src="Adventure (1978) (Atari).html" width="100%" height="100%"></iframe>
|
||||||
|
<script src="./js/all.js"></script>
|
9065
semag/alpha/index.html
Normal file
BIN
semag/aow2/aow2.swf
Normal file
4
semag/aow2/cover.svg
Normal file
After Width: | Height: | Size: 13 KiB |
3
semag/aow2/index.html
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<embed width="100%" height="100% "src="aow2.swf"></embed>
|
||||||
|
<script src="https://unpkg.com/@ruffle-rs/ruffle"></script>
|
||||||
|
<script src="./js/all.js"></script>
|
3
semag/box/cover.svg
Normal file
After Width: | Height: | Size: 23 KiB |
16804
semag/box/index.html
Normal file
16
semag/box/service-worker.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
self.addEventListener('fetch', function(event) {
|
||||||
|
if(!event.request.url.startsWith('http')){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
event.respondWith(async function() {
|
||||||
|
try{
|
||||||
|
var res = await fetch(event.request);
|
||||||
|
var cache = await caches.open('cache');
|
||||||
|
cache.put(event.request.url, res.clone());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
catch(error){
|
||||||
|
return caches.match(event.request);
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
});
|
3
semag/c4/cover.svg
Normal file
After Width: | Height: | Size: 433 KiB |
646
semag/c4/index.html
Normal file
@ -0,0 +1,646 @@
|
|||||||
|
<html style="height: 100%;" lang="en"><head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="apple-touch-icon" type="image/png" href="https://cpwebassets.codepen.io/assets/favicon/apple-touch-icon-5ae1a0698dcc2402e9712f7d01ed509a57814f994c660df9f7a952f3060705ee.png">
|
||||||
|
|
||||||
|
<meta name="apple-mobile-web-app-title" content="CodePen">
|
||||||
|
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="https://cpwebassets.codepen.io/assets/favicon/favicon-aec34940fbc1a6e787974dcd360f2c6b63348d4b1f4e06c77743096d55480f33.ico">
|
||||||
|
|
||||||
|
<link rel="mask-icon" type="image/x-icon" href="https://cpwebassets.codepen.io/assets/favicon/logo-pin-b4b4269c16397ad2f0f7a01bcdf513a1994f4c94b8af2f191c09eb0d601762b1.svg" color="#111">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="https://cpwebassets.codepen.io/assets/common/stopExecutionOnTimeout-2c7831bb44f98c1391d6a4ffda0e1fd302503391ca806e7fcc7b9b87197aec26.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<title>CodePen - Connect 4 with Phaser</title>
|
||||||
|
|
||||||
|
<link rel="canonical" href="https://codepen.io/osbulbul/pen/poBQOqM">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@900&display=swap">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body{
|
||||||
|
background: #0f0f0f;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
window.console = window.console || function(t) {};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body translate="no" style="height: 100%;">
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/3.80.1/phaser.min.js"></script>
|
||||||
|
<script id="rendered-js">
|
||||||
|
class Ui {
|
||||||
|
constructor(scene) {
|
||||||
|
this.scene = scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
addInfos() {
|
||||||
|
let userDisc = this.scene.add.circle(100, 100, 30, 0xE06C75);
|
||||||
|
let userText = this.scene.add.text(150, 70, "User", {
|
||||||
|
fontFamily: "Nunito",
|
||||||
|
fontSize: 48,
|
||||||
|
color: "#e6e6e6",
|
||||||
|
align: "center" });
|
||||||
|
|
||||||
|
|
||||||
|
let aiDisc = this.scene.add.circle(900, 100, 30, 0xE5C07B);
|
||||||
|
let aiText = this.scene.add.text(800, 70, "AI", {
|
||||||
|
fontFamily: "Nunito",
|
||||||
|
fontSize: 48,
|
||||||
|
color: "#e6e6e6",
|
||||||
|
align: "center" });
|
||||||
|
|
||||||
|
|
||||||
|
// Helper Text
|
||||||
|
this.helperText = this.scene.add.text(500, 200, "Your turn!", {
|
||||||
|
fontFamily: "Nunito",
|
||||||
|
fontSize: 48,
|
||||||
|
color: "#e6e6e6",
|
||||||
|
align: "center" }).
|
||||||
|
setOrigin(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
fireworks() {
|
||||||
|
let graphics = this.scene.make.graphics({ x: 0, y: 0, add: false });
|
||||||
|
graphics.fillStyle(0xffffff, 1);
|
||||||
|
graphics.fillCircle(4, 4, 4); // x, y, radius
|
||||||
|
graphics.generateTexture('spark', 8, 8);
|
||||||
|
graphics.destroy();
|
||||||
|
|
||||||
|
this.scene.time.addEvent({
|
||||||
|
delay: 50,
|
||||||
|
repeat: 50,
|
||||||
|
callback: () => {
|
||||||
|
this.explode(Math.random() * 1000, Math.random() * 600);
|
||||||
|
} });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
explode(x, y) {
|
||||||
|
const hsv = Phaser.Display.Color.HSVColorWheel();
|
||||||
|
const tint = hsv.map(entry => entry.color);
|
||||||
|
|
||||||
|
let particles = this.scene.add.particles(x, y, 'spark', {
|
||||||
|
speed: { min: -200, max: 200 },
|
||||||
|
angle: { min: 0, max: 360 },
|
||||||
|
scale: { start: 1, end: 0 },
|
||||||
|
blendMode: 'ADD',
|
||||||
|
lifespan: 1500,
|
||||||
|
gravityY: 300,
|
||||||
|
quantity: 25,
|
||||||
|
duration: 50,
|
||||||
|
tint: tint });
|
||||||
|
|
||||||
|
particles.setDepth(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
addRestartButton() {
|
||||||
|
const overlay = this.scene.add.rectangle(0, 0, 1000, 1200, 0x000000, 0.5).setOrigin(0);
|
||||||
|
overlay.setDepth(3);
|
||||||
|
|
||||||
|
// Restart button
|
||||||
|
const restartButtonBackground = this.scene.add.graphics();
|
||||||
|
restartButtonBackground.setDepth(4);
|
||||||
|
restartButtonBackground.fillStyle(0xC678DD, 1);
|
||||||
|
restartButtonBackground.fillRoundedRect(400, 655, 240, 100, 20);
|
||||||
|
|
||||||
|
const restartButton = this.scene.add.text(520, 700, "restart", {
|
||||||
|
fontFamily: "Nunito",
|
||||||
|
fontSize: 52,
|
||||||
|
color: "#e6e6e6",
|
||||||
|
align: "center" }).
|
||||||
|
setOrigin(0.5);
|
||||||
|
restartButton.setDepth(5);
|
||||||
|
|
||||||
|
restartButtonBackground.setInteractive(new Phaser.Geom.Rectangle(400, 655, 200, 100), Phaser.Geom.Rectangle.Contains);
|
||||||
|
restartButtonBackground.on("pointerdown", () => {
|
||||||
|
this.scene.scene.start("Game");
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
class Board {
|
||||||
|
constructor(scene) {
|
||||||
|
this.scene = scene;
|
||||||
|
|
||||||
|
// keep track of the board state
|
||||||
|
this.status = [
|
||||||
|
[0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0]];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
create() {
|
||||||
|
// create board graphics
|
||||||
|
const board = this.scene.add.graphics();
|
||||||
|
board.fillStyle(0x61AFEF, 1);
|
||||||
|
board.fillRoundedRect(50, 350, 900, 800, 20);
|
||||||
|
board.setDepth(1);
|
||||||
|
|
||||||
|
// create board mask
|
||||||
|
const boardMask = this.scene.add.graphics().setVisible(false);
|
||||||
|
boardMask.fillStyle(0xffffff, 1);
|
||||||
|
const mask = boardMask.createGeometryMask().setInvertAlpha(true);
|
||||||
|
board.setMask(mask);
|
||||||
|
|
||||||
|
// create board holes
|
||||||
|
for (let row = 0; row < 6; row++) {if (window.CP.shouldStopExecution(0)) break;
|
||||||
|
for (let col = 0; col < 7; col++) {if (window.CP.shouldStopExecution(1)) break;
|
||||||
|
boardMask.fillCircle(150 + col * 120, 350 + row * 120 + 110, 50);
|
||||||
|
}window.CP.exitedLoop(1);
|
||||||
|
}window.CP.exitedLoop(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
dropDisc(disc, callback) {
|
||||||
|
let col = this.getColumn(disc.x);
|
||||||
|
let row = this.getEmptyRow(col);
|
||||||
|
if (row == -1) return;
|
||||||
|
|
||||||
|
let y = 350 + row * 120 + 110;
|
||||||
|
this.scene.tweens.add({
|
||||||
|
targets: disc,
|
||||||
|
y: y,
|
||||||
|
duration: 500,
|
||||||
|
ease: "Bounce",
|
||||||
|
onComplete: () => {
|
||||||
|
|
||||||
|
if (this.scene.turn == 'player') {
|
||||||
|
this.status[row][col] = 1;
|
||||||
|
} else {
|
||||||
|
this.status[row][col] = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = this.checkWin();
|
||||||
|
|
||||||
|
if (result.length) {
|
||||||
|
this.scene.ui.helperText.setText(this.scene.turn == 'player' ? "Congratulations!" : "Game Over!");
|
||||||
|
if (this.scene.turn == 'player') {
|
||||||
|
this.scene.ui.fireworks();
|
||||||
|
this.scene.time.delayedCall(2500, () => {
|
||||||
|
this.scene.ui.addRestartButton();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.scene.time.delayedCall(500, () => {
|
||||||
|
this.scene.ui.addRestartButton();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.drawWinLine(result);
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
} });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
getColumn(x) {
|
||||||
|
return Math.floor((x - 50) / 120);
|
||||||
|
}
|
||||||
|
|
||||||
|
getEmptyRow(col) {
|
||||||
|
for (let row = 5; row >= 0; row--) {if (window.CP.shouldStopExecution(2)) break;
|
||||||
|
if (this.status[row][col] == 0) return row;
|
||||||
|
}window.CP.exitedLoop(2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkWin() {
|
||||||
|
// check vertical or horizontal win
|
||||||
|
let result = [];
|
||||||
|
let player = this.scene.turn == 'player' ? 1 : 2;
|
||||||
|
|
||||||
|
// check vertical
|
||||||
|
for (let col = 0; col < 7; col++) {if (window.CP.shouldStopExecution(3)) break;
|
||||||
|
result = [];
|
||||||
|
for (let row = 0; row < 6; row++) {if (window.CP.shouldStopExecution(4)) break;
|
||||||
|
if (this.status[row][col] == player) {
|
||||||
|
result.push({ row: row, col: col });
|
||||||
|
if (result.length >= 4) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = [];
|
||||||
|
}
|
||||||
|
}window.CP.exitedLoop(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check horizontal
|
||||||
|
window.CP.exitedLoop(3);for (let row = 0; row < 6; row++) {if (window.CP.shouldStopExecution(5)) break;
|
||||||
|
result = [];
|
||||||
|
for (let col = 0; col < 7; col++) {if (window.CP.shouldStopExecution(6)) break;
|
||||||
|
if (this.status[row][col] == player) {
|
||||||
|
result.push({ row: row, col: col });
|
||||||
|
if (result.length >= 4) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = [];
|
||||||
|
}
|
||||||
|
}window.CP.exitedLoop(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check downward diagonals (top-left to bottom-right)
|
||||||
|
window.CP.exitedLoop(5);for (let col = 0; col <= 7 - 4; col++) {if (window.CP.shouldStopExecution(7)) break; // Ensures there's space for at least 4 discs
|
||||||
|
for (let row = 0; row <= 6 - 4; row++) {if (window.CP.shouldStopExecution(8)) break; // Similar boundary for rows
|
||||||
|
result = [];
|
||||||
|
for (let i = 0; i < 4; i++) {if (window.CP.shouldStopExecution(9)) break; // Only need to check the next 4 spots
|
||||||
|
if (this.status[row + i][col + i] == player) {
|
||||||
|
result.push({ row: row + i, col: col + i });
|
||||||
|
if (result.length >= 4) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}window.CP.exitedLoop(9);
|
||||||
|
}window.CP.exitedLoop(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check upward diagonals (bottom-left to top-right)
|
||||||
|
window.CP.exitedLoop(7);for (let col = 0; col <= 7 - 4; col++) {if (window.CP.shouldStopExecution(10)) break; // Ensures there's space for at least 4 discs
|
||||||
|
for (let row = 3; row < 6; row++) {if (window.CP.shouldStopExecution(11)) break; // Starts from row 3 to ensure space for 4 upward
|
||||||
|
result = [];
|
||||||
|
for (let i = 0; i < 4; i++) {if (window.CP.shouldStopExecution(12)) break; // Only need to check the next 4 spots
|
||||||
|
if (this.status[row - i][col + i] == player) {
|
||||||
|
result.push({ row: row - i, col: col + i });
|
||||||
|
if (result.length >= 4) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}window.CP.exitedLoop(12);
|
||||||
|
}window.CP.exitedLoop(11);
|
||||||
|
}window.CP.exitedLoop(10);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawWinLine(result) {
|
||||||
|
let glowColor = this.scene.turn == 'player' ? 0x00ff00 : 0xff0000;
|
||||||
|
let lineColor = this.scene.turn == 'player' ? 0x98C379 : 0xE06C75;
|
||||||
|
let line = this.scene.add.graphics();
|
||||||
|
line.setDepth(2);
|
||||||
|
|
||||||
|
let first = result[0];
|
||||||
|
let last = result[result.length - 1];
|
||||||
|
|
||||||
|
let x1 = 150 + first.col * 120;
|
||||||
|
let y1 = 350 + first.row * 120 + 110;
|
||||||
|
line.x2 = x1;
|
||||||
|
line.y2 = y1;
|
||||||
|
let x2 = 150 + last.col * 120;
|
||||||
|
let y2 = 350 + last.row * 120 + 110;
|
||||||
|
|
||||||
|
// draw line from first to last disc animated
|
||||||
|
this.scene.tweens.add({
|
||||||
|
targets: line,
|
||||||
|
duration: 500,
|
||||||
|
x2: x2,
|
||||||
|
y2: y2,
|
||||||
|
onUpdate: () => {
|
||||||
|
line.clear();
|
||||||
|
|
||||||
|
line.fillStyle(lineColor, 1);
|
||||||
|
line.fillCircle(x1, y1, 10);
|
||||||
|
|
||||||
|
line.lineStyle(20, lineColor, 1);
|
||||||
|
line.beginPath();
|
||||||
|
line.moveTo(x1, y1);
|
||||||
|
line.lineTo(line.x2, line.y2);
|
||||||
|
line.strokePath();
|
||||||
|
},
|
||||||
|
onComplete: () => {
|
||||||
|
line.fillCircle(x2, y2, 10);
|
||||||
|
} });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const effect = line.postFX.addGlow(glowColor, 0);
|
||||||
|
this.scene.tweens.add({
|
||||||
|
targets: effect,
|
||||||
|
duration: 500,
|
||||||
|
outerStrength: 5,
|
||||||
|
yoyo: true,
|
||||||
|
repeat: -1,
|
||||||
|
ease: "Sine.easeInOut" });
|
||||||
|
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
class Ai {
|
||||||
|
constructor(scene) {
|
||||||
|
this.scene = scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
makeMove(board) {
|
||||||
|
this.board = board;
|
||||||
|
this.scene.time.delayedCall(1000, () => {
|
||||||
|
let decidedPos = this.think();
|
||||||
|
this.scene.tweens.add({
|
||||||
|
targets: this.scene.discOnHand,
|
||||||
|
duration: 150,
|
||||||
|
x: decidedPos.x,
|
||||||
|
onComplete: () => {
|
||||||
|
board.dropDisc(this.scene.discOnHand, () => {
|
||||||
|
this.scene.changeTurn('player');
|
||||||
|
});
|
||||||
|
} });
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
think() {
|
||||||
|
let possibleMoves = this.getPossibleColumns();
|
||||||
|
let bestMove = false;
|
||||||
|
|
||||||
|
for (let move of possibleMoves) {
|
||||||
|
if (this.isWinningMove(move)) {
|
||||||
|
bestMove = move;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isBlockingMove(move)) {
|
||||||
|
bestMove = move;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bestMove) {
|
||||||
|
bestMove = possibleMoves[Math.floor(Math.random() * possibleMoves.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
let x = 150 + bestMove.col * 120;
|
||||||
|
let y = 350 - 110;
|
||||||
|
return { x: x, y: y };
|
||||||
|
}
|
||||||
|
|
||||||
|
getPossibleColumns() {
|
||||||
|
let possibleMoves = [];
|
||||||
|
for (let col = 0; col < 7; col++) {if (window.CP.shouldStopExecution(13)) break;
|
||||||
|
let row = this.board.getEmptyRow(col);
|
||||||
|
if (row != -1) {
|
||||||
|
possibleMoves.push({ col: col, row: row });
|
||||||
|
}
|
||||||
|
}window.CP.exitedLoop(13);
|
||||||
|
return possibleMoves;
|
||||||
|
}
|
||||||
|
|
||||||
|
isWinningMove(move) {
|
||||||
|
// check vertical or horizontal win
|
||||||
|
let count = 1;
|
||||||
|
let row = move.row;
|
||||||
|
let col = move.col;
|
||||||
|
let player = this.scene.turn == 'player' ? 1 : 2;
|
||||||
|
|
||||||
|
// check vertical
|
||||||
|
for (let i = row + 1; i < 6; i++) {if (window.CP.shouldStopExecution(14)) break;
|
||||||
|
if (this.board.status[i][col] == player) count++;else
|
||||||
|
break;
|
||||||
|
}window.CP.exitedLoop(14);
|
||||||
|
if (count >= 4) return true;
|
||||||
|
|
||||||
|
// check horizontal
|
||||||
|
count = 1;
|
||||||
|
for (let i = col + 1; i < 7; i++) {if (window.CP.shouldStopExecution(15)) break;
|
||||||
|
if (this.board.status[row][i] == player) count++;else
|
||||||
|
break;
|
||||||
|
}window.CP.exitedLoop(15);
|
||||||
|
for (let i = col - 1; i >= 0; i--) {if (window.CP.shouldStopExecution(16)) break;
|
||||||
|
if (this.board.status[row][i] == player) count++;else
|
||||||
|
break;
|
||||||
|
}window.CP.exitedLoop(16);
|
||||||
|
if (count >= 4) return true;
|
||||||
|
|
||||||
|
// check diagonal
|
||||||
|
count = 1;
|
||||||
|
let i = row + 1;
|
||||||
|
let j = col + 1;
|
||||||
|
while (i < 6 && j < 7) {if (window.CP.shouldStopExecution(17)) break;
|
||||||
|
if (this.board.status[i][j] == player) count++;else
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
j++;
|
||||||
|
}window.CP.exitedLoop(17);
|
||||||
|
i = row - 1;
|
||||||
|
j = col - 1;
|
||||||
|
while (i >= 0 && j >= 0) {if (window.CP.shouldStopExecution(18)) break;
|
||||||
|
if (this.board.status[i][j] == player) count++;else
|
||||||
|
break;
|
||||||
|
i--;
|
||||||
|
j--;
|
||||||
|
}window.CP.exitedLoop(18);
|
||||||
|
if (count >= 4) return true;
|
||||||
|
|
||||||
|
count = 1;
|
||||||
|
i = row + 1;
|
||||||
|
j = col - 1;
|
||||||
|
while (i < 6 && j >= 0) {if (window.CP.shouldStopExecution(19)) break;
|
||||||
|
if (this.board.status[i][j] == player) count++;else
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
j--;
|
||||||
|
}window.CP.exitedLoop(19);
|
||||||
|
i = row - 1;
|
||||||
|
j = col + 1;
|
||||||
|
while (i >= 0 && j < 7) {if (window.CP.shouldStopExecution(20)) break;
|
||||||
|
if (this.board.status[i][j] == player) count++;else
|
||||||
|
break;
|
||||||
|
i--;
|
||||||
|
j++;
|
||||||
|
}window.CP.exitedLoop(20);
|
||||||
|
if (count >= 4) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
isBlockingMove(move) {
|
||||||
|
// check vertical or horizontal win
|
||||||
|
let count = 1;
|
||||||
|
let row = move.row;
|
||||||
|
let col = move.col;
|
||||||
|
let player = this.scene.turn == 'player' ? 2 : 1;
|
||||||
|
|
||||||
|
// check vertical
|
||||||
|
for (let i = row + 1; i < 6; i++) {if (window.CP.shouldStopExecution(21)) break;
|
||||||
|
if (this.board.status[i][col] == player) count++;else
|
||||||
|
break;
|
||||||
|
}window.CP.exitedLoop(21);
|
||||||
|
if (count >= 4) return true;
|
||||||
|
|
||||||
|
// check horizontal
|
||||||
|
count = 1;
|
||||||
|
for (let i = col + 1; i < 7; i++) {if (window.CP.shouldStopExecution(22)) break;
|
||||||
|
if (this.board.status[row][i] == player) count++;else
|
||||||
|
break;
|
||||||
|
}window.CP.exitedLoop(22);
|
||||||
|
for (let i = col - 1; i >= 0; i--) {if (window.CP.shouldStopExecution(23)) break;
|
||||||
|
if (this.board.status[row][i] == player) count++;else
|
||||||
|
break;
|
||||||
|
}window.CP.exitedLoop(23);
|
||||||
|
if (count >= 4) return true;
|
||||||
|
|
||||||
|
// check diagonal
|
||||||
|
count = 1;
|
||||||
|
let i = row + 1;
|
||||||
|
let j = col + 1;
|
||||||
|
while (i < 6 && j < 7) {if (window.CP.shouldStopExecution(24)) break;
|
||||||
|
if (this.board.status[i][j] == player) count++;else
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
j++;
|
||||||
|
}window.CP.exitedLoop(24);
|
||||||
|
i = row - 1;
|
||||||
|
j = col - 1;
|
||||||
|
while (i >= 0 && j >= 0) {if (window.CP.shouldStopExecution(25)) break;
|
||||||
|
if (this.board.status[i][j] == player) count++;else
|
||||||
|
break;
|
||||||
|
i--;
|
||||||
|
j--;
|
||||||
|
}window.CP.exitedLoop(25);
|
||||||
|
if (count >= 4) return true;
|
||||||
|
|
||||||
|
count = 1;
|
||||||
|
i = row + 1;
|
||||||
|
j = col - 1;
|
||||||
|
while (i < 6 && j >= 0) {if (window.CP.shouldStopExecution(26)) break;
|
||||||
|
if (this.board.status[i][j] == player) count++;else
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
j--;
|
||||||
|
}window.CP.exitedLoop(26);
|
||||||
|
i = row - 1;
|
||||||
|
j = col + 1;
|
||||||
|
while (i >= 0 && j < 7) {if (window.CP.shouldStopExecution(27)) break;
|
||||||
|
if (this.board.status[i][j] == player) count++;else
|
||||||
|
break;
|
||||||
|
i--;
|
||||||
|
j++;
|
||||||
|
}window.CP.exitedLoop(27);
|
||||||
|
if (count >= 4) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
class Game extends Phaser.Scene {
|
||||||
|
constructor() {
|
||||||
|
super("Game");
|
||||||
|
}
|
||||||
|
|
||||||
|
create() {
|
||||||
|
this.ui = new Ui(this);
|
||||||
|
// Info
|
||||||
|
this.ui.addInfos();
|
||||||
|
|
||||||
|
this.board = new Board(this);
|
||||||
|
this.board.create();
|
||||||
|
|
||||||
|
this.allowInteraction = false;
|
||||||
|
this.targetX = false;
|
||||||
|
this.changeTurn('player');
|
||||||
|
|
||||||
|
this.ai = new Ai(this);
|
||||||
|
|
||||||
|
this.input.on("pointermove", pointer => {
|
||||||
|
if (!this.allowInteraction) return;
|
||||||
|
|
||||||
|
if (this.turn == 'player') {
|
||||||
|
let newX = this.limitX(pointer.x);
|
||||||
|
this.targetX = newX;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.input.on("pointerup", pointer => {
|
||||||
|
if (!this.allowInteraction) return;
|
||||||
|
|
||||||
|
if (this.turn == 'player') {
|
||||||
|
this.allowInteraction = false;
|
||||||
|
this.discOnHand.x = this.limitX(pointer.x);
|
||||||
|
this.board.dropDisc(this.discOnHand, () => {
|
||||||
|
this.changeTurn('ai');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
changeTurn(side) {
|
||||||
|
this.turn = side;
|
||||||
|
if (side == 'player') {
|
||||||
|
this.ui.helperText.setText("Your turn!");
|
||||||
|
|
||||||
|
this.discOnHand = this.add.circle(510, 285, 50, 0xE06C75);
|
||||||
|
this.discOnHand.setDepth(0);
|
||||||
|
this.time.delayedCall(150, () => {
|
||||||
|
this.allowInteraction = true;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.ui.helperText.setText("AI's turn!");
|
||||||
|
|
||||||
|
this.discOnHand = this.add.circle(510, 285, 50, 0xE5C07B);
|
||||||
|
this.discOnHand.setDepth(0);
|
||||||
|
this.ai.makeMove(this.board);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
limitX(x) {
|
||||||
|
const positions = [150, 270, 390, 510, 630, 750, 870];
|
||||||
|
let closest = positions.reduce((prev, curr) => {
|
||||||
|
return Math.abs(curr - x) < Math.abs(prev - x) ? curr : prev;
|
||||||
|
});
|
||||||
|
return closest;
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
if (this.turn == 'player' && this.targetX !== false && this.allowInteraction) {
|
||||||
|
if (this.targetX > this.discOnHand.x) {
|
||||||
|
this.discOnHand.x += 15;
|
||||||
|
} else if (this.targetX < this.discOnHand.x) {
|
||||||
|
this.discOnHand.x -= 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
new Phaser.Game({
|
||||||
|
type: Phaser.AUTO,
|
||||||
|
width: 1000,
|
||||||
|
height: 1200,
|
||||||
|
parent: "game6scene",
|
||||||
|
backgroundColor: "#0f0f0f",
|
||||||
|
roundPixels: false,
|
||||||
|
banner: false,
|
||||||
|
scale: {
|
||||||
|
mode: Phaser.Scale.FIT,
|
||||||
|
autoCenter: Phaser.Scale.CENTER_BOTH },
|
||||||
|
|
||||||
|
audio: {
|
||||||
|
noAudio: true },
|
||||||
|
|
||||||
|
scene: [Game] });
|
||||||
|
//# sourceURL=pen.js
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<canvas style="width: 68.3333px; height: 82px; margin-left: 765px; margin-top: 0px;" width="1000" height="1200"></canvas></body></html>
|
BIN
semag/crossnroad/assets/Press.ttf
Normal file
4
semag/crossnroad/cover.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<image href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABkCAYAAAA8CJisAAAE3ElEQVR4Xu2bPWgUQRSA3xoCItgGlDTB1koLhYAYSGcUoyiSlEnhT2XwpxF/K3+ilT9F0iVBFINo7AwGIaCFVraSJiikFUQIcX1vz5Xzbmb2zcx7F3POwObI7cyb972fmdnZmyzLIYc2L1mCbBMPJ0+2iSMheTJ5cgNZQD9cfwLkb9EiX/D6+tsy2/BzO0C2Dz836VtLDTKfReUf4/UKr+8WkC34/QG8TiDwET1Yecgf6LmzqPAjT6VPIug9bLPZsx2juihk/hJ7JMDPjJ5NVXbglwiaHQxsb2kmBpmP1RQUKWio7K6IpEKICGThwUNyShWSXsh5NB6ScnBnRIjabIOhm32SydFoyPxU9SDT2QkwMADQ01MjWloCmJsDWF2t8D4NRg/jIyQKspgmjrqVGBrCVMVc7er6u97KCo5RmHszMxUQz+KnlzjI46jgU7uSIyMAExNuiNFRgMlJR51jCPkkzpvhkLSS2YqdWyb64WGAqSmeclTX6lFcMGTfUE7EyigYMl/AjvvMEJSDy8vNIWpDptDt7nbk6BsE3c8zmKlWOCTlEnrAVAYHAWYpXz1KHxpsgQxnKjcQ8pKHsIaq4ZDjKOmcueMxXBiM032P0t8PMD9vaYDr2gwHoNCSIF2Wy/+LcKX8afeBByqmEFoETE/zsuifnUJI/bztFwMEudGXdflHpHiHV4bXHvzYZQ497gK9txego6MmY20NYHExboHO1Y/6M04h+R28c74B6iZWvmAAXYdHrfwW6nGxQZfbqJ9l3m6CLCy02zJgWEBb+dBsBCzV/WCOuGZIen477RgVbaAt2P5wApLK9xHSoHsz5AOsfKZi6Hd5VGkjqxKQVEbdM3qIbyh+4Vrf2JWjwluSLEDSjRuuVJct1AZKMsrN5ef4j22bAx/J4DBejs1lri74MtlarAt0rnBwgBYGu4J/rlv6v4zhdc2unJQOzqcQiU7yqwhhA0EDZHTfUCT6LsVWPmrFdhYCGdtn5cAjbVVfSGlA4qn0ZAkd2rkPZGgf9qyu3WFDho66XEgtQG/IEFAOpCZgEKQvaLEv6xhdgV7ENi62TfFXMVW5QtYrXOsFsa2Pu3Dw2qKC6159kwjAYE96D0ZVI4PrfiRgNKRX6IaACgCKQKqBCgGKQYqDCgKKQoqBCgOKQ0aDKgCqQAaDKgGqQXqDKgKqQrJBlQHVIQvQvfjnvWWSpE1r2sBWLsHLOq5enAU6V1ZovQQZarn6dsmTjo0sCQOXMlK4SlgzhWsKV4k4qslIOSlhy5STKScl4ijlpJwVU06mnJSLJv15st0fmlnvSzby9gcLsIxIZVCVcPUCbAGoOGQQoDKoKGQUoCKoGKQIoBKoCCQbEAeYoii/Pm+cYaMhfQDLHwWHtIlZGkRBxigb09YXOBhSQkkJGRzgIEhJ5SRl2YC9ITWU0pBZD+wFqamMpmw2pKYSpdW1+mBBanVuyiGNviohNTqtGhGl+1T/eXYVkO2+JKj6D+1DIamdFKj5rJbpLJRJW+WHXSlQ+cMvMa6ztGV7lHv4Ja86q0WKtMCDjbwsULGzWusAyJ5HRc5qrSMgC5QbrkWy+xwSVchBjsicTujWF59Don8sRodF6ZdUdNALN4htx305CmnUKQ6zMvWrXPFoKNhqmQmy1RbX6u+/8OQvgdCzH5ppE9kAAAAASUVORK5CYII=" height="200" width="200" />
|
||||||
|
</svg>
|
||||||
|
|
After Width: | Height: | Size: 1.8 KiB |
381
semag/crossnroad/index.html
Normal file
@ -0,0 +1,381 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>CrossNRoad</title>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.3/p5.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.3/addons/p5.sound.min.js"></script>
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<!-- Latest compiled and minified CSS -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<!-- Optional theme -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<!-- Latest compiled and minified JavaScript -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
||||||
|
<style>
|
||||||
|
@import url('https://fonts.cdnfonts.com/css/press-start-2p');
|
||||||
|
body {
|
||||||
|
font-family: 'Press Start 2P', sans-serif;
|
||||||
|
background-color:green; color:white;
|
||||||
|
}
|
||||||
|
.a {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
background-color:green;
|
||||||
|
border:0;
|
||||||
|
}
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("button").click(function(){
|
||||||
|
$(".a").css("display", "inline");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("button").click(function(){
|
||||||
|
$(".b").css("display", "none");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("button").click(function(){
|
||||||
|
$("body").css("background-color", "#00FF00")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main class="a">
|
||||||
|
</main>
|
||||||
|
<center>
|
||||||
|
<br>
|
||||||
|
<h1 class="b">CrossNRoad</h1>
|
||||||
|
<button class="b">Click to Play</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let Press;
|
||||||
|
|
||||||
|
|
||||||
|
var carX = 740;
|
||||||
|
var carSpeed;
|
||||||
|
var carType;
|
||||||
|
|
||||||
|
var carX2 = 740;
|
||||||
|
var carSpeed2;
|
||||||
|
var carType2;
|
||||||
|
|
||||||
|
var carX3 = 740;
|
||||||
|
var carSpeed3;
|
||||||
|
var carType3;
|
||||||
|
|
||||||
|
var peepX = 350;
|
||||||
|
var peepY = 622;
|
||||||
|
var peepRadius = 10;
|
||||||
|
|
||||||
|
var hasKey = "false";
|
||||||
|
var keyX;
|
||||||
|
var keyY;
|
||||||
|
|
||||||
|
var score = 0;
|
||||||
|
|
||||||
|
var lives = 3;
|
||||||
|
var loseMode = false;
|
||||||
|
|
||||||
|
function preload() {
|
||||||
|
Press = loadFont('assets/Press.ttf');
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
createCanvas(1280, 720);
|
||||||
|
carSpeed = random(5, 15);
|
||||||
|
carType = random(["🚗", "🚙", "🚓"]);
|
||||||
|
|
||||||
|
carSpeed2 = random(5, 15);
|
||||||
|
carType2 = random(["🚗", "🚙", "🚓"]);
|
||||||
|
|
||||||
|
carSpeed3 = random(5, 15);
|
||||||
|
carType3 = random(["🚗", "🚙", "🚓"]);
|
||||||
|
|
||||||
|
keyX = random([100, 200, 300, 400, 500, 600]);
|
||||||
|
keyY = random([560, 430, 280, 180]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
background(0, 255, 0);
|
||||||
|
|
||||||
|
lifeCount();
|
||||||
|
if (loseMode == false) {
|
||||||
|
push();
|
||||||
|
fill("grey");
|
||||||
|
noStroke();
|
||||||
|
rect(0, 330, 700, 275);
|
||||||
|
rect(0, 100, 700, 115);
|
||||||
|
pop();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
push();
|
||||||
|
textFont('Press');
|
||||||
|
textSize(20);
|
||||||
|
text("Score: " + score, 10, 50);
|
||||||
|
pop();
|
||||||
|
|
||||||
|
cars();
|
||||||
|
player();
|
||||||
|
doorKey();
|
||||||
|
door();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cars() {
|
||||||
|
var hitCar1 = rectRect(
|
||||||
|
peepX - peepRadius,
|
||||||
|
peepY - peepRadius,
|
||||||
|
20,
|
||||||
|
80,
|
||||||
|
carX,
|
||||||
|
500,
|
||||||
|
100,
|
||||||
|
70
|
||||||
|
);
|
||||||
|
|
||||||
|
var hitCar2 = rectRect(
|
||||||
|
peepX - peepRadius,
|
||||||
|
peepY - peepRadius,
|
||||||
|
20,
|
||||||
|
80,
|
||||||
|
carX2,
|
||||||
|
360,
|
||||||
|
100,
|
||||||
|
70
|
||||||
|
);
|
||||||
|
|
||||||
|
var hitCar3 = rectRect(
|
||||||
|
peepX - peepRadius,
|
||||||
|
peepY - peepRadius,
|
||||||
|
20,
|
||||||
|
80,
|
||||||
|
carX3,
|
||||||
|
115,
|
||||||
|
100,
|
||||||
|
70
|
||||||
|
);
|
||||||
|
|
||||||
|
push();
|
||||||
|
textSize(100);
|
||||||
|
text(carType, carX, 570);
|
||||||
|
pop();
|
||||||
|
carX -= carSpeed;
|
||||||
|
|
||||||
|
if (carX < -120) {
|
||||||
|
carX = 740;
|
||||||
|
carSpeed = random(5, 15);
|
||||||
|
carType = random(["🚗", "🚙", "🚓"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
push();
|
||||||
|
textSize(100);
|
||||||
|
text(carType2, carX2, 430);
|
||||||
|
pop();
|
||||||
|
carX2 -= carSpeed2;
|
||||||
|
|
||||||
|
if (carX2 < -120) {
|
||||||
|
carX2 = 740;
|
||||||
|
carSpeed2 = random(5, 15);
|
||||||
|
carType2 = random(["🛻", "🚐", "🛺"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
push();
|
||||||
|
textSize(100);
|
||||||
|
text(carType3, carX3, 185);
|
||||||
|
pop();
|
||||||
|
carX3 -= carSpeed3;
|
||||||
|
|
||||||
|
if (carX3 < -120) {
|
||||||
|
carX3 = 740;
|
||||||
|
carSpeed3 = random(5, 15);
|
||||||
|
carType3 = random(["🏍️", "🛵", "🚛"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hitCar1 || hitCar2 || hitCar3) {
|
||||||
|
peepX = 350;
|
||||||
|
peepY = 622;
|
||||||
|
hasKey = "false"
|
||||||
|
keyX = random([100, 200, 300, 400, 500, 600]);
|
||||||
|
keyY = random([560, 430, 280, 180]);
|
||||||
|
lives--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawPeep(x, y, size) {
|
||||||
|
push();
|
||||||
|
strokeWeight(7);
|
||||||
|
fill("yellow");
|
||||||
|
ellipse(x, y, size);
|
||||||
|
|
||||||
|
let x0 = x;
|
||||||
|
let y0 = y + size / 2;
|
||||||
|
line(x0, y0, x0, y0 + 2 * size);
|
||||||
|
|
||||||
|
line(x0, y0 + size, x0 - size, y0);
|
||||||
|
line(x0, y0 + size, x0 + size, y0);
|
||||||
|
|
||||||
|
line(x0, y0 + 2 * size, x0 + size, y0 + size * 3);
|
||||||
|
line(x0, y0 + 2 * size, x0 - size, y0 + size * 3);
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
function player() {
|
||||||
|
drawPeep(peepX, peepY, peepRadius * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function keyPressed() {
|
||||||
|
if (key == "w" || keyCode == UP_ARROW) {
|
||||||
|
peepY -= 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key == "s" || keyCode == DOWN_ARROW) && peepY < 620) {
|
||||||
|
peepY += 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key == "a" || keyCode == LEFT_ARROW) && peepX > 0) {
|
||||||
|
peepX -= 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key == "d" || keyCode == RIGHT_ARROW) && peepX < 700) {
|
||||||
|
peepX += 50;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function doorKey() {
|
||||||
|
push();
|
||||||
|
textSize(60);
|
||||||
|
text("🔑", keyX, keyY);
|
||||||
|
pop();
|
||||||
|
|
||||||
|
var hitKey = rectRect(
|
||||||
|
peepX - peepRadius,
|
||||||
|
peepY - peepRadius,
|
||||||
|
20,
|
||||||
|
80,
|
||||||
|
keyX,
|
||||||
|
keyY - 60,
|
||||||
|
60,
|
||||||
|
80
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hitKey) {
|
||||||
|
hasKey = "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasKey == "true") {
|
||||||
|
keyX = peepX - 20;
|
||||||
|
keyY = peepY + 30;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function rectRect(r1x, r1y, r1w, r1h, r2x, r2y, r2w, r2h) {
|
||||||
|
if (
|
||||||
|
r1x + r1w >= r2x &&
|
||||||
|
r1x <= r2x + r2w &&
|
||||||
|
r1y + r1h >= r2y &&
|
||||||
|
r1y <= r2y + r2h
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function door() {
|
||||||
|
|
||||||
|
push();
|
||||||
|
textSize(80);
|
||||||
|
text("🚪", 320, 60);
|
||||||
|
pop();
|
||||||
|
|
||||||
|
if (peepX == 350 && peepY == 22 && hasKey == "true") {
|
||||||
|
peepY = 622;
|
||||||
|
peepX = 350;
|
||||||
|
keyX = random([100, 200, 300, 400, 500, 600]);
|
||||||
|
keyY = random([550, 450, 350, 250, 150]);
|
||||||
|
hasKey = "false";
|
||||||
|
score++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function lifeCount() {
|
||||||
|
push();
|
||||||
|
textSize(50);
|
||||||
|
text("❤️", 510, 50);
|
||||||
|
text("❤️", 570, 50);
|
||||||
|
text("❤️", 630, 50);
|
||||||
|
pop();
|
||||||
|
|
||||||
|
if (lives <= 2) {
|
||||||
|
push();
|
||||||
|
fill(0, 255, 0);
|
||||||
|
noStroke();
|
||||||
|
rect(500, 0, 70, 80);
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lives <= 1) {
|
||||||
|
push();
|
||||||
|
fill(0, 255, 0);
|
||||||
|
noStroke();
|
||||||
|
rect(560, 0, 70, 80);
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lives <= 0) {
|
||||||
|
loseScreen();
|
||||||
|
loseMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loseScreen() {
|
||||||
|
push();
|
||||||
|
fill("red");
|
||||||
|
noStroke();
|
||||||
|
rect(0, 0, 700, 700);
|
||||||
|
pop();
|
||||||
|
|
||||||
|
push();
|
||||||
|
textSize(70);
|
||||||
|
textAlign(CENTER, CENTER);
|
||||||
|
textFont('Press');
|
||||||
|
text("You Lose!", 350, 350);
|
||||||
|
textSize(15);
|
||||||
|
text("You got hit by a car three times.", 350, 420);
|
||||||
|
text("Your score was " + score + ".", 350, 460);
|
||||||
|
text("If you want to try again, just reload the page.", 350, 500);
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -103,7 +103,15 @@
|
|||||||
<div><a href="/semag/shadow/index.html"><h2>Shadow Client</h2><img src="https://selenite.cc/semag/offline-mc/logo.png"></a><br></div>
|
<div><a href="/semag/shadow/index.html"><h2>Shadow Client</h2><img src="https://selenite.cc/semag/offline-mc/logo.png"></a><br></div>
|
||||||
<div><a href="/semag/mcclassic/index.html"><h2>Minecraft 0.31</h2><img src="https://selenite.cc/semag/offline-mc/logo.png"></a><br></div>
|
<div><a href="/semag/mcclassic/index.html"><h2>Minecraft 0.31</h2><img src="https://selenite.cc/semag/offline-mc/logo.png"></a><br></div>
|
||||||
<div><a href="/semag/mcdemo/index.html"><h2>Minecraft Demo</h2><img src="https://selenite.cc/semag/offline-mc/logo.png"></a><br></div>
|
<div><a href="/semag/mcdemo/index.html"><h2>Minecraft Demo</h2><img src="https://selenite.cc/semag/offline-mc/logo.png"></a><br></div>
|
||||||
|
<div><a href="/semag/forge/index.html"><h2>EaglerForge</h2><img src="https://selenite.cc/semag/offline-mc/logo.png"></a><br></div>
|
||||||
|
<div><a href="/semag/alpha/index.html"><h2>Minecraft 1.2.6</h2><img src="https://selenite.cc/semag/offline-mc/logo.png"></a><br></div>
|
||||||
|
<div><a href="/semag/indev/index.html"><h2>Minecraft Indev</h2><img src="https://selenite.cc/semag/offline-mc/logo.png"></a><br></div>
|
||||||
|
<div><a href="/semag/030/index.html"><h2>Minecraft 0.30</h2><img src="https://selenite.cc/semag/offline-mc/logo.png"></a><br></div>
|
||||||
|
<div><a href="/semag/125/index.html"><h2>Minecraft 1.2.5</h2><img src="https://selenite.cc/semag/offline-mc/logo.png"></a><br></div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<div id="adcontainer">
|
<div id="adcontainer">
|
||||||
|
3
semag/flappyrace/cover.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<image href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAABAJJREFUeJzlm7FOHDEQhv+F5CKkk06ChhRAAaJJyUPkGVLRk44HuS7pU/EMPAQlDQpFckXSECkSUsSduE2R+OKdm7HHXtvr6H4Jibvzef39Mx6v93aBDVdT8mAHL7daTbvZYllsXFkPpAX2KachyTtOBS0ptRnJOtOAXx9NVH29/fLT2yaVEb07cYFrgX1yGdLXiF5fluBTgVNJRvQxIfqLHHwucCrOiFgTgr80JDhVCiOCGpeAl9LcPo6vSIaYoG44JHyMtCaoGlH4HCkfA/91/rz6/3C0vfa5xgRvgyHgbTAjCqhpA/hN2FKN8K9KFDsOzPV+aBsqpwG5T2tD5QJsmgZN02C2WHbe9zGIBpRIfSoO0ICZP6kNALTtnyGHmMAaMAQ8JwMG/IMzJnDzvWmaYBO8NWAoeCobzjaGa2ekqQlrBtQ27225wDXi2JwZUEv0fTKZEaOOAUNHn87rELC2bTvtpe9SRjEDaol+aHSpET4FnQjlks9sCmRecytBqFYG2KlBB5Ryk+KTBGUi27Ztp83haHv1R/uR+rJZvRlg4GswQfOZBC5l2Yvw4eXR9dGkY7KBcO34bi6PAQB3D3O8+zRz9i1ptbByU4BGvURh1GaagTe6e5gDgNcI07/ZJTaAPP/twZReFVxGUHgjY4It2xCaZbPFsqlmClBJgZDgAeB0b9QxwZUNRmIRLFn0XNLCG53ujQDo4AHleUDJ9LeBY4OghQcqWgWA7pJLTfdF/2x6z75/dX7gNKQqA1ySAF26Oj/wtqnGgFQ15+byOKgQqgzgUjKnpGNpimCoRANORtv4HHGVNUauX4Psz+xpoDGDngNwqmI3aIsOVBq4VBM0Z4S2toDujwel13/N8a6PJqwRZ9P7jhESPHdqb5jVRbBEHfD1L+1RXCuEr09xCnx4PcZJggsOOSRlBNfOp0GXwb7TLcXGrXOdme4K3397XFsJUk6DkrtNbv4DnlWAmwapimQtm60qdoMlo0/VMYD7Lf1idyd5FgwZfcronAJmoClNKH2ZzTfONQNcd1T0XRbpYKb7Y9w+5Tndvn16XuubY2Nh6c9H0/0xAODjj1/RqwIHT/XmVT+DKfDl98fOa84AdgrQhnZHMVNBO11issFEOgYecNQAzoSL3R0AcSbY4qJvxMGEttPCA54iKK0KgN4E+r62jnCRlaLtku8useDb5Ox6AMBZEzh4Y2AuhUQfiLxRUmPC/wAP9LxVdro/Fk2wZdI+lwEUHEh8q6xRjAk1wwOJbpeXTKgdHkj8wARX4XPApwA3yvLITK7Ic+BAv0dmel0Rmi2WDWdC6svpErgZQ5++iz425zoDtOUCNqrmsTmqjX1wktNGPjrrUo0PT2+8fgMI04M7MWgCTQAAAABJRU5ErkJggg==" height="200" width="200" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
35
semag/flappyrace/index.apple-touch-icon.png.import
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="StreamTexture"
|
||||||
|
path="res://.import/index.apple-touch-icon.png-939ec69c79bbf504b92ad8ceed469d51.stex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://web/index.apple-touch-icon.png"
|
||||||
|
dest_files=[ "res://.import/index.apple-touch-icon.png-939ec69c79bbf504b92ad8ceed469d51.stex" ]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_mode=0
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
flags/repeat=0
|
||||||
|
flags/filter=true
|
||||||
|
flags/mipmaps=false
|
||||||
|
flags/anisotropic=false
|
||||||
|
flags/srgb=2
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/HDR_as_SRGB=false
|
||||||
|
process/invert_color=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
stream=false
|
||||||
|
size_limit=0
|
||||||
|
detect_3d=true
|
||||||
|
svg/scale=1.0
|
211
semag/flappyrace/index.audio.worklet.js
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/**************************************************************************/
|
||||||
|
/* audio.worklet.js */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
class RingBuffer {
|
||||||
|
constructor(p_buffer, p_state, p_threads) {
|
||||||
|
this.buffer = p_buffer;
|
||||||
|
this.avail = p_state;
|
||||||
|
this.threads = p_threads;
|
||||||
|
this.rpos = 0;
|
||||||
|
this.wpos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_left() {
|
||||||
|
return this.threads ? Atomics.load(this.avail, 0) : this.avail;
|
||||||
|
}
|
||||||
|
|
||||||
|
space_left() {
|
||||||
|
return this.buffer.length - this.data_left();
|
||||||
|
}
|
||||||
|
|
||||||
|
read(output) {
|
||||||
|
const size = this.buffer.length;
|
||||||
|
let from = 0;
|
||||||
|
let to_write = output.length;
|
||||||
|
if (this.rpos + to_write > size) {
|
||||||
|
const high = size - this.rpos;
|
||||||
|
output.set(this.buffer.subarray(this.rpos, size));
|
||||||
|
from = high;
|
||||||
|
to_write -= high;
|
||||||
|
this.rpos = 0;
|
||||||
|
}
|
||||||
|
if (to_write) {
|
||||||
|
output.set(this.buffer.subarray(this.rpos, this.rpos + to_write), from);
|
||||||
|
}
|
||||||
|
this.rpos += to_write;
|
||||||
|
if (this.threads) {
|
||||||
|
Atomics.add(this.avail, 0, -output.length);
|
||||||
|
Atomics.notify(this.avail, 0);
|
||||||
|
} else {
|
||||||
|
this.avail -= output.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write(p_buffer) {
|
||||||
|
const to_write = p_buffer.length;
|
||||||
|
const mw = this.buffer.length - this.wpos;
|
||||||
|
if (mw >= to_write) {
|
||||||
|
this.buffer.set(p_buffer, this.wpos);
|
||||||
|
this.wpos += to_write;
|
||||||
|
if (mw === to_write) {
|
||||||
|
this.wpos = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const high = p_buffer.subarray(0, mw);
|
||||||
|
const low = p_buffer.subarray(mw);
|
||||||
|
this.buffer.set(high, this.wpos);
|
||||||
|
this.buffer.set(low);
|
||||||
|
this.wpos = low.length;
|
||||||
|
}
|
||||||
|
if (this.threads) {
|
||||||
|
Atomics.add(this.avail, 0, to_write);
|
||||||
|
Atomics.notify(this.avail, 0);
|
||||||
|
} else {
|
||||||
|
this.avail += to_write;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GodotProcessor extends AudioWorkletProcessor {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.threads = false;
|
||||||
|
this.running = true;
|
||||||
|
this.lock = null;
|
||||||
|
this.notifier = null;
|
||||||
|
this.output = null;
|
||||||
|
this.output_buffer = new Float32Array();
|
||||||
|
this.input = null;
|
||||||
|
this.input_buffer = new Float32Array();
|
||||||
|
this.port.onmessage = (event) => {
|
||||||
|
const cmd = event.data['cmd'];
|
||||||
|
const data = event.data['data'];
|
||||||
|
this.parse_message(cmd, data);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
process_notify() {
|
||||||
|
if (this.notifier) {
|
||||||
|
Atomics.add(this.notifier, 0, 1);
|
||||||
|
Atomics.notify(this.notifier, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_message(p_cmd, p_data) {
|
||||||
|
if (p_cmd === 'start' && p_data) {
|
||||||
|
const state = p_data[0];
|
||||||
|
let idx = 0;
|
||||||
|
this.threads = true;
|
||||||
|
this.lock = state.subarray(idx, ++idx);
|
||||||
|
this.notifier = state.subarray(idx, ++idx);
|
||||||
|
const avail_in = state.subarray(idx, ++idx);
|
||||||
|
const avail_out = state.subarray(idx, ++idx);
|
||||||
|
this.input = new RingBuffer(p_data[1], avail_in, true);
|
||||||
|
this.output = new RingBuffer(p_data[2], avail_out, true);
|
||||||
|
} else if (p_cmd === 'stop') {
|
||||||
|
this.running = false;
|
||||||
|
this.output = null;
|
||||||
|
this.input = null;
|
||||||
|
} else if (p_cmd === 'start_nothreads') {
|
||||||
|
this.output = new RingBuffer(p_data[0], p_data[0].length, false);
|
||||||
|
} else if (p_cmd === 'chunk') {
|
||||||
|
this.output.write(p_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static array_has_data(arr) {
|
||||||
|
return arr.length && arr[0].length && arr[0][0].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
process(inputs, outputs, parameters) {
|
||||||
|
if (!this.running) {
|
||||||
|
return false; // Stop processing.
|
||||||
|
}
|
||||||
|
if (this.output === null) {
|
||||||
|
return true; // Not ready yet, keep processing.
|
||||||
|
}
|
||||||
|
const process_input = GodotProcessor.array_has_data(inputs);
|
||||||
|
if (process_input) {
|
||||||
|
const input = inputs[0];
|
||||||
|
const chunk = input[0].length * input.length;
|
||||||
|
if (this.input_buffer.length !== chunk) {
|
||||||
|
this.input_buffer = new Float32Array(chunk);
|
||||||
|
}
|
||||||
|
if (!this.threads) {
|
||||||
|
GodotProcessor.write_input(this.input_buffer, input);
|
||||||
|
this.port.postMessage({ 'cmd': 'input', 'data': this.input_buffer });
|
||||||
|
} else if (this.input.space_left() >= chunk) {
|
||||||
|
GodotProcessor.write_input(this.input_buffer, input);
|
||||||
|
this.input.write(this.input_buffer);
|
||||||
|
} else {
|
||||||
|
this.port.postMessage('Input buffer is full! Skipping input frame.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const process_output = GodotProcessor.array_has_data(outputs);
|
||||||
|
if (process_output) {
|
||||||
|
const output = outputs[0];
|
||||||
|
const chunk = output[0].length * output.length;
|
||||||
|
if (this.output_buffer.length !== chunk) {
|
||||||
|
this.output_buffer = new Float32Array(chunk);
|
||||||
|
}
|
||||||
|
if (this.output.data_left() >= chunk) {
|
||||||
|
this.output.read(this.output_buffer);
|
||||||
|
GodotProcessor.write_output(output, this.output_buffer);
|
||||||
|
if (!this.threads) {
|
||||||
|
this.port.postMessage({ 'cmd': 'read', 'data': chunk });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.port.postMessage('Output buffer has not enough frames! Skipping output frame.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.process_notify();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static write_output(dest, source) {
|
||||||
|
const channels = dest.length;
|
||||||
|
for (let ch = 0; ch < channels; ch++) {
|
||||||
|
for (let sample = 0; sample < dest[ch].length; sample++) {
|
||||||
|
dest[ch][sample] = source[sample * channels + ch];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static write_input(dest, source) {
|
||||||
|
const channels = source.length;
|
||||||
|
for (let ch = 0; ch < channels; ch++) {
|
||||||
|
for (let sample = 0; sample < source[ch].length; sample++) {
|
||||||
|
dest[sample * channels + ch] = source[ch][sample];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
registerProcessor('godot-processor', GodotProcessor);
|
249
semag/flappyrace/index.html
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns='http://www.w3.org/1999/xhtml' lang='' xml:lang=''>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8' />
|
||||||
|
<meta name='viewport' content='width=device-width, user-scalable=no' />
|
||||||
|
<script src="./js/all.js"></script>
|
||||||
|
<title>Flappy Race</title>
|
||||||
|
<style type='text/css'>
|
||||||
|
|
||||||
|
body {
|
||||||
|
touch-action: none;
|
||||||
|
margin: 0;
|
||||||
|
border: 0 none;
|
||||||
|
padding: 0;
|
||||||
|
text-align: center;
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#canvas {
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#canvas:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.godot {
|
||||||
|
font-family: 'Noto Sans', 'Droid Sans', Arial, sans-serif;
|
||||||
|
color: #e0e0e0;
|
||||||
|
background-color: #3b3943;
|
||||||
|
background-image: linear-gradient(to bottom, #403e48, #35333c);
|
||||||
|
border: 1px solid #45434e;
|
||||||
|
box-shadow: 0 0 1px 1px #2f2d35;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Status display
|
||||||
|
* ============== */
|
||||||
|
|
||||||
|
#status {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
/* don't consume click events - make children visible explicitly */
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#status-progress {
|
||||||
|
width: 366px;
|
||||||
|
height: 7px;
|
||||||
|
background-color: #38363A;
|
||||||
|
border: 1px solid #444246;
|
||||||
|
padding: 1px;
|
||||||
|
box-shadow: 0 0 2px 1px #1B1C22;
|
||||||
|
border-radius: 2px;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (orientation:portrait) {
|
||||||
|
#status-progress {
|
||||||
|
width: 61.8%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#status-progress-inner {
|
||||||
|
height: 100%;
|
||||||
|
width: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
transition: width 0.5s linear;
|
||||||
|
background-color: #202020;
|
||||||
|
border: 1px solid #222223;
|
||||||
|
box-shadow: 0 0 1px 1px #27282E;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#status-indeterminate {
|
||||||
|
height: 42px;
|
||||||
|
visibility: visible;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#status-indeterminate > div {
|
||||||
|
width: 4.5px;
|
||||||
|
height: 0;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 9px 3px 0 3px;
|
||||||
|
border-color: #2b2b2b transparent transparent transparent;
|
||||||
|
transform-origin: center 21px;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
#status-indeterminate > div:nth-child(1) { transform: rotate( 22.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(2) { transform: rotate( 67.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(3) { transform: rotate(112.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(4) { transform: rotate(157.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(5) { transform: rotate(202.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(6) { transform: rotate(247.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(7) { transform: rotate(292.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(8) { transform: rotate(337.5deg); }
|
||||||
|
|
||||||
|
#status-notice {
|
||||||
|
margin: 0 100px;
|
||||||
|
line-height: 1.3;
|
||||||
|
visibility: visible;
|
||||||
|
padding: 4px 6px;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link id='-gd-engine-icon' rel='icon' type='image/png' href='index.icon.png' />
|
||||||
|
<link rel='apple-touch-icon' href='index.apple-touch-icon.png'/>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas id='canvas'>
|
||||||
|
HTML5 canvas appears to be unsupported in the current browser.<br />
|
||||||
|
Please try updating or use a different browser.
|
||||||
|
</canvas>
|
||||||
|
<div id='status'>
|
||||||
|
<div id='status-progress' style='display: none;' oncontextmenu='event.preventDefault();'><div id ='status-progress-inner'></div></div>
|
||||||
|
<div id='status-indeterminate' style='display: none;' oncontextmenu='event.preventDefault();'>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<div id='status-notice' class='godot' style='display: none;'></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type='text/javascript' src='index.js'></script>
|
||||||
|
<script type='text/javascript'>//<![CDATA[
|
||||||
|
|
||||||
|
const GODOT_CONFIG = {"args":[],"canvasResizePolicy":2,"executable":"index","experimentalVK":false,"fileSizes":{"index.pck":33078848,"index.wasm":17865444},"focusCanvas":true,"gdnativeLibs":[]};
|
||||||
|
var engine = new Engine(GODOT_CONFIG);
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
const INDETERMINATE_STATUS_STEP_MS = 100;
|
||||||
|
var statusProgress = document.getElementById('status-progress');
|
||||||
|
var statusProgressInner = document.getElementById('status-progress-inner');
|
||||||
|
var statusIndeterminate = document.getElementById('status-indeterminate');
|
||||||
|
var statusNotice = document.getElementById('status-notice');
|
||||||
|
|
||||||
|
var initializing = true;
|
||||||
|
var statusMode = 'hidden';
|
||||||
|
|
||||||
|
var animationCallbacks = [];
|
||||||
|
function animate(time) {
|
||||||
|
animationCallbacks.forEach(callback => callback(time));
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
|
||||||
|
function setStatusMode(mode) {
|
||||||
|
|
||||||
|
if (statusMode === mode || !initializing)
|
||||||
|
return;
|
||||||
|
[statusProgress, statusIndeterminate, statusNotice].forEach(elem => {
|
||||||
|
elem.style.display = 'none';
|
||||||
|
});
|
||||||
|
animationCallbacks = animationCallbacks.filter(function(value) {
|
||||||
|
return (value != animateStatusIndeterminate);
|
||||||
|
});
|
||||||
|
switch (mode) {
|
||||||
|
case 'progress':
|
||||||
|
statusProgress.style.display = 'block';
|
||||||
|
break;
|
||||||
|
case 'indeterminate':
|
||||||
|
statusIndeterminate.style.display = 'block';
|
||||||
|
animationCallbacks.push(animateStatusIndeterminate);
|
||||||
|
break;
|
||||||
|
case 'notice':
|
||||||
|
statusNotice.style.display = 'block';
|
||||||
|
break;
|
||||||
|
case 'hidden':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('Invalid status mode');
|
||||||
|
}
|
||||||
|
statusMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function animateStatusIndeterminate(ms) {
|
||||||
|
var i = Math.floor(ms / INDETERMINATE_STATUS_STEP_MS % 8);
|
||||||
|
if (statusIndeterminate.children[i].style.borderTopColor == '') {
|
||||||
|
Array.prototype.slice.call(statusIndeterminate.children).forEach(child => {
|
||||||
|
child.style.borderTopColor = '';
|
||||||
|
});
|
||||||
|
statusIndeterminate.children[i].style.borderTopColor = '#dfdfdf';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setStatusNotice(text) {
|
||||||
|
while (statusNotice.lastChild) {
|
||||||
|
statusNotice.removeChild(statusNotice.lastChild);
|
||||||
|
}
|
||||||
|
var lines = text.split('\n');
|
||||||
|
lines.forEach((line) => {
|
||||||
|
statusNotice.appendChild(document.createTextNode(line));
|
||||||
|
statusNotice.appendChild(document.createElement('br'));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function displayFailureNotice(err) {
|
||||||
|
var msg = err.message || err;
|
||||||
|
console.error(msg);
|
||||||
|
setStatusNotice(msg);
|
||||||
|
setStatusMode('notice');
|
||||||
|
initializing = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!Engine.isWebGLAvailable()) {
|
||||||
|
displayFailureNotice('WebGL not available');
|
||||||
|
} else {
|
||||||
|
setStatusMode('indeterminate');
|
||||||
|
engine.startGame({
|
||||||
|
'onProgress': function (current, total) {
|
||||||
|
if (total > 0) {
|
||||||
|
statusProgressInner.style.width = current/total * 100 + '%';
|
||||||
|
setStatusMode('progress');
|
||||||
|
if (current === total) {
|
||||||
|
// wait for progress bar animation
|
||||||
|
setTimeout(() => {
|
||||||
|
setStatusMode('indeterminate');
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setStatusMode('indeterminate');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}).then(() => {
|
||||||
|
setStatusMode('hidden');
|
||||||
|
initializing = false;
|
||||||
|
}, displayFailureNotice);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
//]]></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
BIN
semag/flappyrace/index.icon.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
35
semag/flappyrace/index.icon.png.import
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="StreamTexture"
|
||||||
|
path="res://.import/index.icon.png-c615af856eabc03ca93d51f6a8f07b60.stex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://web/index.icon.png"
|
||||||
|
dest_files=[ "res://.import/index.icon.png-c615af856eabc03ca93d51f6a8f07b60.stex" ]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_mode=0
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
flags/repeat=0
|
||||||
|
flags/filter=true
|
||||||
|
flags/mipmaps=false
|
||||||
|
flags/anisotropic=false
|
||||||
|
flags/srgb=2
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/HDR_as_SRGB=false
|
||||||
|
process/invert_color=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
stream=false
|
||||||
|
size_limit=0
|
||||||
|
detect_3d=true
|
||||||
|
svg/scale=1.0
|
796
semag/flappyrace/index.js
Normal file
BIN
semag/flappyrace/index.pck
Normal file
BIN
semag/flappyrace/index.png
Normal file
After Width: | Height: | Size: 21 KiB |
35
semag/flappyrace/index.png.import
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="StreamTexture"
|
||||||
|
path="res://.import/index.png-80964ad67552d78b1e33f58ad16188ff.stex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://web/index.png"
|
||||||
|
dest_files=[ "res://.import/index.png-80964ad67552d78b1e33f58ad16188ff.stex" ]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_mode=0
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
flags/repeat=0
|
||||||
|
flags/filter=true
|
||||||
|
flags/mipmaps=false
|
||||||
|
flags/anisotropic=false
|
||||||
|
flags/srgb=2
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/HDR_as_SRGB=false
|
||||||
|
process/invert_color=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
stream=false
|
||||||
|
size_limit=0
|
||||||
|
detect_3d=true
|
||||||
|
svg/scale=1.0
|
BIN
semag/flappyrace/index.wasm
Normal file
3
semag/fld/cover.svg
Normal file
After Width: | Height: | Size: 8.9 KiB |
537
semag/fld/index.html
Normal file
@ -0,0 +1,537 @@
|
|||||||
|
<div class="ctn">
|
||||||
|
<canvas id="c" width="360px" height="640px"></canvas>
|
||||||
|
<div id="scoreboard">0</div>
|
||||||
|
<div id="start-screen">
|
||||||
|
<div id="ctrl-ctn">
|
||||||
|
<div id="up" class="ctrl-btn">↑</div>
|
||||||
|
<div id="space" class="ctrl-btn">SPACE</div>
|
||||||
|
<div id="tap" class="ctrl-btn">TAP</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="gameover-screen">
|
||||||
|
<div id="gameover">GAME OVER</div>
|
||||||
|
<div id="replay">REPLAY</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-family: Helvetica, sans-serif;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ctn {
|
||||||
|
position: relative;
|
||||||
|
width: 360px;
|
||||||
|
height: 640px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#scoreboard {
|
||||||
|
position: absolute;
|
||||||
|
top: 540px;
|
||||||
|
width: 360px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 50px;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
#start-screen {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gameover-screen {
|
||||||
|
visibility: hidden;
|
||||||
|
position: absolute;
|
||||||
|
width: 360px;
|
||||||
|
height: 640px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 1s;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gameover {
|
||||||
|
width: 280px;
|
||||||
|
background-color: #333333;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 40px;
|
||||||
|
letter-spacing: 4px;
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#replay {
|
||||||
|
width: 100px;
|
||||||
|
background-color: #333333;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 20px;
|
||||||
|
letter-spacing: 4px;
|
||||||
|
transition: background-color 1s;
|
||||||
|
margin: 100px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#replay:hover {
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #333333;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ctrl-ctn {
|
||||||
|
position: absolute;
|
||||||
|
top: 300px;
|
||||||
|
left: 80px;
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ctrl-btn {
|
||||||
|
background-color: #333333;
|
||||||
|
color: #ffffff;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 18px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
var bgSVG = `
|
||||||
|
<svg id="bg-svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="640" viewBox="0 0 360 640.00001" width="360" version="1.1" xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<rect id="rect5189-8" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
height="640" width="360" y="0" x="0" fill="#d7eef4" />
|
||||||
|
<g fill="#333333">
|
||||||
|
<path id="path10590-3-7-0" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
d="m153.94 443.28c-1.6123 0-2.9194 1.2047-2.9194 2.6916v10.868c0 5.5017-2.7017 5.5166-4.9971 5.5166v-11.866c0-2.5165-1.8644-4.5558-4.1642-4.5558-2.2999 0-4.1643 2.0393-4.1643 4.5558v20.342c-2.2954 0-4.9971-0.015-4.9971-5.5165v-9.4802c0-1.4869-1.3071-2.6916-2.9193-2.6916-1.6123 0-2.9193 1.2047-2.9193 2.6916v12.354c0 5.6939 4.6336 9.0964 10.836 9.0964v15.213h8.3285v-23.689c6.2021 0 10.836-3.4012 10.836-9.0952v-13.743c0-1.4869-1.3071-2.6916-2.9193-2.6916z" />
|
||||||
|
<path id="path10590-3-5-8-4" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
d="m225.91 447.5c2.2227 0 4.0245 1.9708 4.0245 4.4028v14.293c2.2182 0 4.8292-0.0145 4.8292-5.3313v-5.9423c0-1.4369 1.2632-2.6012 2.8213-2.6012s2.8213 1.1642 2.8213 2.6012v8.7195c0 5.5027-4.4781 8.7908-10.472 8.7908v20.068h-8.0489v-40.597c0-2.432 1.8018-4.4028 4.0244-4.4028z" />
|
||||||
|
<path id="path10590-3-4-6-4" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
d="m46.842 445.94c-2.2999 0-4.1643 2.0403-4.1643 4.5568v20.342c-2.2954 0-4.9971-0.0161-4.9971-5.5176v-7.2581c0-1.4869-1.307-2.6927-2.9193-2.6927s-2.9193 1.2058-2.9193 2.6927v10.133c0 5.6939 4.6337 9.0952 10.836 9.0952v15.214h8.3285v-17.648c6.2021 0 10.836-3.4013 10.836-9.0952v-5.9699c0-1.4869-1.307-2.6916-2.9193-2.6916s-2.9193 1.2047-2.9193 2.6916v3.095c0 5.5016-2.7017 5.5165-4.9971 5.5165v-17.906c0-2.5165-1.8644-4.5568-4.1642-4.5568z" />
|
||||||
|
<path id="path10590-3-4-6-4-6" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
d="m320.43 445.94c-2.2998 0-4.1642 2.0403-4.1642 4.5568v20.342c-2.2954 0-4.9972-0.0161-4.9972-5.5176v-7.2581c0-1.4869-1.307-2.6927-2.9193-2.6927-1.6122 0-2.9193 1.2058-2.9193 2.6927v10.133c0 5.6939 4.6337 9.0952 10.836 9.0952v15.214h8.3285v-17.648c6.2021 0 10.836-3.4013 10.836-9.0952v-5.9699c0-1.4869-1.307-2.6916-2.9193-2.6916s-2.9193 1.2047-2.9193 2.6916v3.095c0 5.5016-2.7018 5.5165-4.9971 5.5165v-17.906c0-2.5165-1.8644-4.5568-4.1643-4.5568z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
|
|
||||||
|
var fgSVG = `
|
||||||
|
<svg id="fg-svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="150" viewBox="0 0 360 150" width="360" version="1.1" xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<rect style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
height="147.5" width="360" y="2.5" x="0" fill="#ffb380" />
|
||||||
|
<path stroke="#333333" stroke-width="5" fill="none" d="m-0.000001625 2.5h360" />
|
||||||
|
<circle id="a" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
cx="-9.75" cy="11" r="2.5" fill="#333333" />
|
||||||
|
<use xlink:href="#a" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 9.025 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 18.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(15 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 24.025 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 33.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(30 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 39.025 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 48.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(45 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 54.025 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 63.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(60 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 69.025 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 78.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(75 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 84.025 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 93.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(90 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 99.025 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 108.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(105 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 114.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 123.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(120 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 129.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 138.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(135 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 144.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 153.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(150 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 159.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 168.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(165 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 174.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 183.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(180 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 189.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 198.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(195 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 204.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 213.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(210 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 219.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 228.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(225 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 234.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 243.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(240 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 249.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 258.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(255 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 264.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 273.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(270 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 279.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 288.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(285 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 294.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 303.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(300 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 309.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 318.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(315 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 324.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 333.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(330 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 339.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 348.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(345 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 354.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 363.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="translate(360 -3.7151e-8)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.9 0 0 .9 369.03 8.6)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
<use xlink:href="#a" transform="matrix(.8 0 0 .8 378.05 17.2)" height="100%" width="100%" y="0" x="0" />
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
|
|
||||||
|
var boneOpen = `
|
||||||
|
<svg id="bone" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="400" viewBox="0 0 79.999993 400.00001" width="80" version="1.1" xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
`;
|
||||||
|
var boneMid = `
|
||||||
|
<path id="path4855-9" stroke-linejoin="round" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
d="m12.343 397.5-0.274-343.44c-0.066-8.49-9.569-14.59-9.569-27.05 0-12.457 7.957-24.615 21.609-24.551 7.448 0.0614 12.539 3.9094 15.891 8.055 3.352-4.1456 8.443-7.9937 15.891-8.055 13.652-0.0637 21.609 12.094 21.609 24.551s-9.5033 18.557-9.5692 27.044l-0.27382 343.41z"
|
||||||
|
stroke="#333333" stroke-linecap="round" stroke-width="5" fill="#e9ddaf" />
|
||||||
|
<g stroke-linejoin="round" stroke="#333333" stroke-linecap="round" stroke-width="5" fill="none">
|
||||||
|
<path id="path4855-2-0" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
d="m13.781 26.92a11.746 12.772 0 0 1 11.746 -12.78" />
|
||||||
|
<path id="path5025" d="m56.472 115.85v78.183" />
|
||||||
|
<path id="path5025-3-6" d="m56.472 92.06v10.609" />
|
||||||
|
<path id="path5025-0" d="m56.472 253.62v126.19" />
|
||||||
|
<path id="path5025-3-6-6" d="m56.472 212.25v24.515" />
|
||||||
|
</g>
|
||||||
|
`;
|
||||||
|
var boneClose = "</svg>";
|
||||||
|
|
||||||
|
var botBoneSVG = boneOpen + boneMid + boneClose;
|
||||||
|
var topBoneSVG =
|
||||||
|
boneOpen +
|
||||||
|
'<g transform="rotate(180) translate(-80, -400)">' +
|
||||||
|
boneMid +
|
||||||
|
"</g>" +
|
||||||
|
boneClose;
|
||||||
|
|
||||||
|
var sprite1 = `
|
||||||
|
<svg id="sprite-1" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="59.968" viewBox="0 0 100.02518 59.967859" width="100.03" version="1.1" xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<g stroke-linecap="round">
|
||||||
|
<ellipse id="body" stroke-linejoin="round" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
rx="27.792" transform="matrix(.97502 -.22210 .30061 .95375 0 0)" stroke="#333333" ry="14.864" cy="46.239"
|
||||||
|
cx="16.016" stroke-width="4.0066" fill="#d38d5f" />
|
||||||
|
<g id="head" transform="matrix(.5 0 0 .5 .011191 -.016144)">
|
||||||
|
<path id="path6767-3" stroke-linejoin="round" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
d="m196.03 86.922s-61.739-3.1063-75.355-6.8143c-14.08-3.835-25.527-11.615-25.527-25.941 0-13.335-15.956-50.135-15.956-50.135s30.525 17.767 41.481 24.195c11.784 6.9142 75.355 44.369 75.355 58.695z"
|
||||||
|
stroke="#333333" stroke-width="8" fill="#d38d5f" />
|
||||||
|
<ellipse id="eye" stroke-linejoin="round" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
rx="5.8902" ry="5.9862" stroke="#ffffff" cy="45.876" cx="120.32" stroke-width="5" fill="#333333" />
|
||||||
|
<path id="mouth" d="m194.28 84.826c-23.83-4.875-43.57-11.271-63.81-23.461" fill-rule="evenodd"
|
||||||
|
stroke="#333333" stroke-width="5" fill="#d38d5f" />
|
||||||
|
</g>
|
||||||
|
<path id="wing-top" stroke-linejoin="round" d="m10.252 43.445c0.8135-13.421 3.458-26.194-5.2065-41.445 22.742 0 34.917 19.591 38.055 31.493l0.0005-0.001"
|
||||||
|
fill-rule="evenodd" stroke="#333333" stroke-width="4" fill="#d38d5f">
|
||||||
|
</path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
|
|
||||||
|
var sprite2 = `
|
||||||
|
<svg id="sprite-2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="59.968" viewBox="0 0 100.02518 59.967859" width="100.03" version="1.1" xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<g stroke-linecap="round">
|
||||||
|
<ellipse id="body" stroke-linejoin="round" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
rx="27.792" ry="14.864" stroke="#333333" transform="matrix(.97502 -.22210 .30061 .95375 0 0)" cy="46.239"
|
||||||
|
cx="16.016" stroke-width="4.0066" fill="#d38d5f" />
|
||||||
|
<g id="head" transform="matrix(.5 0 0 .5 .011191 -.016144)">
|
||||||
|
<path id="path6767-3" stroke-linejoin="round" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
d="m196.03 86.922s-61.739-3.1063-75.355-6.8143c-14.08-3.835-25.527-11.615-25.527-25.941 0-13.335-15.956-50.135-15.956-50.135s30.525 17.767 41.481 24.195c11.784 6.9142 75.355 44.369 75.355 58.695z"
|
||||||
|
stroke="#333333" stroke-width="8" fill="#d38d5f" />
|
||||||
|
<ellipse id="eye" stroke-linejoin="round" style="color-rendering:auto;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;image-rendering:auto"
|
||||||
|
rx="5.8902" ry="5.9862" stroke="#ffffff" cy="45.876" cx="120.32" stroke-width="5" fill="#333333" />
|
||||||
|
<path id="mouth" d="m194.28 84.826c-23.83-4.875-43.57-11.271-63.81-23.461" fill-rule="evenodd"
|
||||||
|
stroke="#333333" stroke-width="5" fill="#d38d5f" />
|
||||||
|
</g>
|
||||||
|
<path id="wing-bot" stroke-linejoin="round" d="m10.252 43.445c8.7795 5.151 8.41 14.523 8.41 14.523 15.09 0 27.976-12.688 24.439-24.475l0.0005-0.0005"
|
||||||
|
fill-rule="evenodd" stroke="#333333" stroke-width="4" fill="#d38d5f">
|
||||||
|
</path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
|
|
||||||
|
var bg = new Image();
|
||||||
|
bg.src = "data:image/svg+xml," + encodeURIComponent(bgSVG);
|
||||||
|
|
||||||
|
var fg = new Image();
|
||||||
|
fg.src = "data:image/svg+xml," + encodeURIComponent(fgSVG);
|
||||||
|
|
||||||
|
var dinoGlide = new Image();
|
||||||
|
dinoGlide.src = "data:image/svg+xml," + encodeURIComponent(sprite1);
|
||||||
|
|
||||||
|
var dinoFlap = new Image();
|
||||||
|
dinoFlap.src = "data:image/svg+xml," + encodeURIComponent(sprite2);
|
||||||
|
|
||||||
|
var topBone = new Image();
|
||||||
|
topBone.src = "data:image/svg+xml," + encodeURIComponent(topBoneSVG);
|
||||||
|
|
||||||
|
var botBone = new Image();
|
||||||
|
botBone.src = "data:image/svg+xml," + encodeURIComponent(botBoneSVG);
|
||||||
|
|
||||||
|
var canvas = document.getElementById("c");
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
var hitboxWidth = 60;
|
||||||
|
var hitboxHeight = 15;
|
||||||
|
|
||||||
|
var spriteOffset_X = -10;
|
||||||
|
var spriteOffset_Y = -25;
|
||||||
|
|
||||||
|
var fgPos_X = 0;
|
||||||
|
|
||||||
|
var dinoPos_X = 100;
|
||||||
|
var dinoPos_Y = 250;
|
||||||
|
var dinoAngle = 0;
|
||||||
|
var dinoState = dinoGlide;
|
||||||
|
|
||||||
|
var minBoneHeight = -330;
|
||||||
|
var maxBoneHeight = -160;
|
||||||
|
|
||||||
|
var scrollSpeed = -3;
|
||||||
|
var gravity = 0.3;
|
||||||
|
var lift = -8;
|
||||||
|
var velocity = 0;
|
||||||
|
|
||||||
|
var start = false;
|
||||||
|
var gameOver = false;
|
||||||
|
var score = 0;
|
||||||
|
|
||||||
|
var bonePtr = 0;
|
||||||
|
var boneStart = 400;
|
||||||
|
var flyGap = 180;
|
||||||
|
var boneGap = 280;
|
||||||
|
var bones = [
|
||||||
|
{ x: boneStart, y: getRandomHeight(minBoneHeight, maxBoneHeight) },
|
||||||
|
{ x: boneStart + boneGap, y: getRandomHeight(minBoneHeight, maxBoneHeight) },
|
||||||
|
{
|
||||||
|
x: boneStart + 2 * boneGap,
|
||||||
|
y: getRandomHeight(minBoneHeight, maxBoneHeight)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function getRandomHeight(min, max) {
|
||||||
|
return Math.floor(Math.random() * (max - min) + min);
|
||||||
|
}
|
||||||
|
|
||||||
|
function playerInput() {
|
||||||
|
if (!start) {
|
||||||
|
start = true;
|
||||||
|
velocity = lift;
|
||||||
|
dinoAngle = -20;
|
||||||
|
document.getElementById("ctrl-ctn").style.opacity = 0;
|
||||||
|
} else {
|
||||||
|
if (!gameOver) {
|
||||||
|
velocity = lift;
|
||||||
|
dinoAngle = -20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCollision() {
|
||||||
|
// set upper bound
|
||||||
|
if (dinoPos_Y <= -hitboxHeight) {
|
||||||
|
velocity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dino hit the ground
|
||||||
|
if (dinoPos_Y + hitboxHeight >= canvas.height - fg.height) {
|
||||||
|
velocity = 0;
|
||||||
|
dinoPos_Y = canvas.height - fg.height - hitboxHeight;
|
||||||
|
setGameOver();
|
||||||
|
}
|
||||||
|
|
||||||
|
// dino hit bone
|
||||||
|
if (
|
||||||
|
dinoPos_X + hitboxWidth >= bones[bonePtr].x &&
|
||||||
|
dinoPos_X < bones[bonePtr].x + topBone.width &&
|
||||||
|
(dinoPos_Y <= bones[bonePtr].y + topBone.height ||
|
||||||
|
dinoPos_Y + hitboxHeight >= bones[bonePtr].y + topBone.height + flyGap)
|
||||||
|
) {
|
||||||
|
setGameOver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function replay() {
|
||||||
|
start = false;
|
||||||
|
gameOver = false;
|
||||||
|
|
||||||
|
score = 0;
|
||||||
|
velocity = 0;
|
||||||
|
|
||||||
|
dinoPos_X = 100;
|
||||||
|
dinoPos_Y = 250;
|
||||||
|
dinoAngle = 0;
|
||||||
|
dinoState = dinoGlide;
|
||||||
|
|
||||||
|
bonePtr = 0;
|
||||||
|
bones = [
|
||||||
|
{ x: boneStart, y: getRandomHeight(minBoneHeight, maxBoneHeight) },
|
||||||
|
{
|
||||||
|
x: boneStart + boneGap,
|
||||||
|
y: getRandomHeight(minBoneHeight, maxBoneHeight)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: boneStart + 2 * boneGap,
|
||||||
|
y: getRandomHeight(minBoneHeight, maxBoneHeight)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
document.getElementById("ctrl-ctn").style.opacity = 1;
|
||||||
|
|
||||||
|
document.getElementById("gameover-screen").style.visibility = "hidden";
|
||||||
|
document.getElementById("gameover-screen").style.opacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setGameOver() {
|
||||||
|
gameOver = true;
|
||||||
|
document.getElementById("gameover-screen").style.visibility = "visible";
|
||||||
|
document.getElementById("gameover-screen").style.opacity = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
// foreground scroll
|
||||||
|
if (!gameOver) {
|
||||||
|
fgPos_X += scrollSpeed;
|
||||||
|
|
||||||
|
if (fgPos_X <= -canvas.width) {
|
||||||
|
fgPos_X = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// game started
|
||||||
|
if (start) {
|
||||||
|
velocity += gravity;
|
||||||
|
dinoPos_Y += velocity;
|
||||||
|
|
||||||
|
// if velocity is negative show dino flap sprite else show dino falling
|
||||||
|
if (velocity < 0) {
|
||||||
|
dinoState = dinoFlap;
|
||||||
|
} else {
|
||||||
|
dinoState = dinoGlide;
|
||||||
|
dinoAngle = Math.min(dinoAngle + 2, 90);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkCollision();
|
||||||
|
|
||||||
|
if (!gameOver) {
|
||||||
|
for (var i = 0; i < bones.length; i++) {
|
||||||
|
// scroll bones across screen
|
||||||
|
bones[i].x += scrollSpeed;
|
||||||
|
|
||||||
|
// reassign bone object XY after it leaves screen
|
||||||
|
if (bones[i].x <= -topBone.width) {
|
||||||
|
if (i == 0) {
|
||||||
|
bones[0].x = bones[bones.length - 1].x + boneGap;
|
||||||
|
} else {
|
||||||
|
bones[i].x = bones[i - 1].x + boneGap;
|
||||||
|
}
|
||||||
|
|
||||||
|
bones[i].y = getRandomHeight(minBoneHeight, maxBoneHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if dino passed through the bone increase score
|
||||||
|
if (dinoPos_X >= bones[bonePtr].x + topBone.width) {
|
||||||
|
score++;
|
||||||
|
|
||||||
|
if (bonePtr == 2) {
|
||||||
|
bonePtr = 0;
|
||||||
|
} else {
|
||||||
|
bonePtr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
|
||||||
|
function render() {
|
||||||
|
document.getElementById("scoreboard").innerHTML = score;
|
||||||
|
|
||||||
|
ctx.drawImage(bg, 0, 0);
|
||||||
|
|
||||||
|
for (var i = 0; i < bones.length; i++) {
|
||||||
|
ctx.drawImage(topBone, bones[i].x, bones[i].y);
|
||||||
|
ctx.drawImage(botBone, bones[i].x, bones[i].y + topBone.height + flyGap);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(
|
||||||
|
dinoPos_X + hitboxWidth / 2 + spriteOffset_X,
|
||||||
|
dinoPos_Y + hitboxHeight / 2
|
||||||
|
);
|
||||||
|
ctx.rotate(dinoAngle * Math.PI / 180);
|
||||||
|
ctx.drawImage(
|
||||||
|
dinoState,
|
||||||
|
-hitboxWidth / 2,
|
||||||
|
-hitboxHeight / 2 + spriteOffset_Y
|
||||||
|
);
|
||||||
|
ctx.restore();
|
||||||
|
|
||||||
|
// Show hitbox
|
||||||
|
// ctx.fillStyle = "#ff00ff";
|
||||||
|
// ctx.fillRect(dinoPos_X, dinoPos_Y, hitboxWidth, hitboxHeight);
|
||||||
|
|
||||||
|
ctx.drawImage(fg, fgPos_X, canvas.height - fg.height);
|
||||||
|
ctx.drawImage(fg, fgPos_X + fg.width, canvas.height - fg.height);
|
||||||
|
|
||||||
|
window.requestAnimationFrame(update);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("keydown", function(e) {
|
||||||
|
var char = e.which || e.keyCode;
|
||||||
|
if (char == 32 || char == 38) {
|
||||||
|
e.preventDefault();
|
||||||
|
playerInput();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("touchstart", function() {
|
||||||
|
playerInput();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById("replay").addEventListener("click", function() {
|
||||||
|
replay();
|
||||||
|
});
|
||||||
|
|
||||||
|
update();
|
||||||
|
|
||||||
|
</script>
|
49
semag/forge/home.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
ModAPI.require("player");
|
||||||
|
ModAPI.require("ItemID");
|
||||||
|
|
||||||
|
// Define item ID for house egg
|
||||||
|
var houseEggID = ItemID.house_egg;
|
||||||
|
|
||||||
|
Item.registerUseFunction(houseEggID, function(coords, item, block){
|
||||||
|
var player = Player.get();
|
||||||
|
var pos = coords.relative;
|
||||||
|
|
||||||
|
// Check if the item is used on a solid block
|
||||||
|
if (block.id === 1) { // 1 is the block ID for stone in Minecraft, you can change it accordingly
|
||||||
|
buildHouse(pos.x, pos.y, pos.z);
|
||||||
|
Player.decreaseCarriedItem(1); // Decrease item count after usage
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function buildHouse(x, y, z) {
|
||||||
|
var world = World.getWorld();
|
||||||
|
|
||||||
|
// Build a simple house with cobblestone
|
||||||
|
// Foundation
|
||||||
|
for (var i = -2; i <= 2; i++) {
|
||||||
|
for (var j = -2; j <= 2; j++) {
|
||||||
|
world.setBlock(x + i, y - 1, z + j, 4); // Place cobblestone blocks as foundation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walls
|
||||||
|
for (var i = -2; i <= 2; i++) {
|
||||||
|
for (var j = 0; j <= 2; j++) {
|
||||||
|
world.setBlock(x + i, y + j, z - 2, 4); // Place cobblestone blocks as back wall
|
||||||
|
world.setBlock(x + i, y + j, z + 2, 4); // Place cobblestone blocks as front wall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Roof
|
||||||
|
for (var i = -2; i <= 2; i++) {
|
||||||
|
for (var j = 0; j <= 2; j++) {
|
||||||
|
if (j === 2) {
|
||||||
|
world.setBlock(x + i, y + j, z - 1, 4); // Place cobblestone blocks as roof
|
||||||
|
world.setBlock(x + i, y + j, z + 1, 4); // Place cobblestone blocks as roof
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Door
|
||||||
|
world.setBlock(x, y, z + 2, 64); // Place door
|
||||||
|
}
|
184736
semag/forge/index.html
Normal file
4
semag/fort/cover.svg
Normal file
After Width: | Height: | Size: 68 KiB |
94
semag/fort/index.html
Normal file
BIN
semag/heist/aow2.swf
Normal file
4
semag/heist/cover.svg
Normal file
After Width: | Height: | Size: 168 KiB |
2
semag/heist/index.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<embed width="100%" height="100% "src="aow2.swf"></embed>
|
||||||
|
<script src="https://unpkg.com/@ruffle-rs/ruffle"></script>
|
4995
semag/indev/index.html
Normal file
BIN
semag/karlson/.nojekyll
Normal file
146
semag/karlson/coi-serviceworker.js
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */
|
||||||
|
let coepCredentialless = false;
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
self.addEventListener("install", () => self.skipWaiting());
|
||||||
|
self.addEventListener("activate", (event) => event.waitUntil(self.clients.claim()));
|
||||||
|
|
||||||
|
self.addEventListener("message", (ev) => {
|
||||||
|
if (!ev.data) {
|
||||||
|
return;
|
||||||
|
} else if (ev.data.type === "deregister") {
|
||||||
|
self.registration
|
||||||
|
.unregister()
|
||||||
|
.then(() => {
|
||||||
|
return self.clients.matchAll();
|
||||||
|
})
|
||||||
|
.then(clients => {
|
||||||
|
clients.forEach((client) => client.navigate(client.url));
|
||||||
|
});
|
||||||
|
} else if (ev.data.type === "coepCredentialless") {
|
||||||
|
coepCredentialless = ev.data.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener("fetch", function (event) {
|
||||||
|
const r = event.request;
|
||||||
|
if (r.cache === "only-if-cached" && r.mode !== "same-origin") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const request = (coepCredentialless && r.mode === "no-cors")
|
||||||
|
? new Request(r, {
|
||||||
|
credentials: "omit",
|
||||||
|
})
|
||||||
|
: r;
|
||||||
|
event.respondWith(
|
||||||
|
fetch(request)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status === 0) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newHeaders = new Headers(response.headers);
|
||||||
|
newHeaders.set("Cross-Origin-Embedder-Policy",
|
||||||
|
coepCredentialless ? "credentialless" : "require-corp"
|
||||||
|
);
|
||||||
|
if (!coepCredentialless) {
|
||||||
|
newHeaders.set("Cross-Origin-Resource-Policy", "cross-origin");
|
||||||
|
}
|
||||||
|
newHeaders.set("Cross-Origin-Opener-Policy", "same-origin");
|
||||||
|
|
||||||
|
return new Response(response.body, {
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
headers: newHeaders,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
(() => {
|
||||||
|
const reloadedBySelf = window.sessionStorage.getItem("coiReloadedBySelf");
|
||||||
|
window.sessionStorage.removeItem("coiReloadedBySelf");
|
||||||
|
const coepDegrading = (reloadedBySelf == "coepdegrade");
|
||||||
|
|
||||||
|
// You can customize the behavior of this script through a global `coi` variable.
|
||||||
|
const coi = {
|
||||||
|
shouldRegister: () => !reloadedBySelf,
|
||||||
|
shouldDeregister: () => false,
|
||||||
|
coepCredentialless: () => true,
|
||||||
|
coepDegrade: () => true,
|
||||||
|
doReload: () => window.location.reload(),
|
||||||
|
quiet: false,
|
||||||
|
...window.coi
|
||||||
|
};
|
||||||
|
|
||||||
|
const n = navigator;
|
||||||
|
const controlling = n.serviceWorker && n.serviceWorker.controller;
|
||||||
|
|
||||||
|
// Record the failure if the page is served by serviceWorker.
|
||||||
|
if (controlling && !window.crossOriginIsolated) {
|
||||||
|
window.sessionStorage.setItem("coiCoepHasFailed", "true");
|
||||||
|
}
|
||||||
|
const coepHasFailed = window.sessionStorage.getItem("coiCoepHasFailed");
|
||||||
|
|
||||||
|
if (controlling) {
|
||||||
|
// Reload only on the first failure.
|
||||||
|
const reloadToDegrade = coi.coepDegrade() && !(
|
||||||
|
coepDegrading || window.crossOriginIsolated
|
||||||
|
);
|
||||||
|
n.serviceWorker.controller.postMessage({
|
||||||
|
type: "coepCredentialless",
|
||||||
|
value: (reloadToDegrade || coepHasFailed && coi.coepDegrade())
|
||||||
|
? false
|
||||||
|
: coi.coepCredentialless(),
|
||||||
|
});
|
||||||
|
if (reloadToDegrade) {
|
||||||
|
!coi.quiet && console.log("Reloading page to degrade COEP.");
|
||||||
|
window.sessionStorage.setItem("coiReloadedBySelf", "coepdegrade");
|
||||||
|
coi.doReload("coepdegrade");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coi.shouldDeregister()) {
|
||||||
|
n.serviceWorker.controller.postMessage({ type: "deregister" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're already coi: do nothing. Perhaps it's due to this script doing its job, or COOP/COEP are
|
||||||
|
// already set from the origin server. Also if the browser has no notion of crossOriginIsolated, just give up here.
|
||||||
|
if (window.crossOriginIsolated !== false || !coi.shouldRegister()) return;
|
||||||
|
|
||||||
|
if (!window.isSecureContext) {
|
||||||
|
!coi.quiet && console.log("COOP/COEP Service Worker not registered, a secure context is required.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In some environments (e.g. Firefox private mode) this won't be available
|
||||||
|
if (!n.serviceWorker) {
|
||||||
|
!coi.quiet && console.error("COOP/COEP Service Worker not registered, perhaps due to private mode.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
n.serviceWorker.register(window.document.currentScript.src).then(
|
||||||
|
(registration) => {
|
||||||
|
!coi.quiet && console.log("COOP/COEP Service Worker registered", registration.scope);
|
||||||
|
|
||||||
|
registration.addEventListener("updatefound", () => {
|
||||||
|
!coi.quiet && console.log("Reloading page to make use of updated COOP/COEP Service Worker.");
|
||||||
|
window.sessionStorage.setItem("coiReloadedBySelf", "updatefound");
|
||||||
|
coi.doReload();
|
||||||
|
});
|
||||||
|
|
||||||
|
// If the registration is active, but it's not controlling the page
|
||||||
|
if (registration.active && !n.serviceWorker.controller) {
|
||||||
|
!coi.quiet && console.log("Reloading page to make use of COOP/COEP Service Worker.");
|
||||||
|
window.sessionStorage.setItem("coiReloadedBySelf", "notcontrolling");
|
||||||
|
coi.doReload();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
!coi.quiet && console.error("COOP/COEP Service Worker failed to register:", err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
})();
|
||||||
|
}
|
4
semag/karlson/cover.svg
Normal file
After Width: | Height: | Size: 473 KiB |
BIN
semag/karlson/index.144x144.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
34
semag/karlson/index.144x144.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dgj5ori6dj8kb"
|
||||||
|
path="res://.godot/imported/index.144x144.png-928b0c4af947dd54463e70c9420240e9.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://build/web/index.144x144.png"
|
||||||
|
dest_files=["res://.godot/imported/index.144x144.png-928b0c4af947dd54463e70c9420240e9.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
semag/karlson/index.180x180.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
34
semag/karlson/index.180x180.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://ctip083j2oudv"
|
||||||
|
path="res://.godot/imported/index.180x180.png-e13e935b0fdf8b6dd6cfc99f0e1bebc9.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://build/web/index.180x180.png"
|
||||||
|
dest_files=["res://.godot/imported/index.180x180.png-e13e935b0fdf8b6dd6cfc99f0e1bebc9.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
semag/karlson/index.512x512.png
Normal file
After Width: | Height: | Size: 41 KiB |
34
semag/karlson/index.512x512.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bkjc4vcamkdqr"
|
||||||
|
path="res://.godot/imported/index.512x512.png-d58d36de992ce78da75957188856fdbf.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://build/web/index.512x512.png"
|
||||||
|
dest_files=["res://.godot/imported/index.512x512.png-d58d36de992ce78da75957188856fdbf.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
semag/karlson/index.apple-touch-icon.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
34
semag/karlson/index.apple-touch-icon.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dobbt2mu5luwv"
|
||||||
|
path="res://.godot/imported/index.apple-touch-icon.png-21031f526f7942c8019a62913b80e091.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://build/web/index.apple-touch-icon.png"
|
||||||
|
dest_files=["res://.godot/imported/index.apple-touch-icon.png-21031f526f7942c8019a62913b80e091.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
213
semag/karlson/index.audio.worklet.js
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
/**************************************************************************/
|
||||||
|
/* audio.worklet.js */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
class RingBuffer {
|
||||||
|
constructor(p_buffer, p_state, p_threads) {
|
||||||
|
this.buffer = p_buffer;
|
||||||
|
this.avail = p_state;
|
||||||
|
this.threads = p_threads;
|
||||||
|
this.rpos = 0;
|
||||||
|
this.wpos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_left() {
|
||||||
|
return this.threads ? Atomics.load(this.avail, 0) : this.avail;
|
||||||
|
}
|
||||||
|
|
||||||
|
space_left() {
|
||||||
|
return this.buffer.length - this.data_left();
|
||||||
|
}
|
||||||
|
|
||||||
|
read(output) {
|
||||||
|
const size = this.buffer.length;
|
||||||
|
let from = 0;
|
||||||
|
let to_write = output.length;
|
||||||
|
if (this.rpos + to_write > size) {
|
||||||
|
const high = size - this.rpos;
|
||||||
|
output.set(this.buffer.subarray(this.rpos, size));
|
||||||
|
from = high;
|
||||||
|
to_write -= high;
|
||||||
|
this.rpos = 0;
|
||||||
|
}
|
||||||
|
if (to_write) {
|
||||||
|
output.set(this.buffer.subarray(this.rpos, this.rpos + to_write), from);
|
||||||
|
}
|
||||||
|
this.rpos += to_write;
|
||||||
|
if (this.threads) {
|
||||||
|
Atomics.add(this.avail, 0, -output.length);
|
||||||
|
Atomics.notify(this.avail, 0);
|
||||||
|
} else {
|
||||||
|
this.avail -= output.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write(p_buffer) {
|
||||||
|
const to_write = p_buffer.length;
|
||||||
|
const mw = this.buffer.length - this.wpos;
|
||||||
|
if (mw >= to_write) {
|
||||||
|
this.buffer.set(p_buffer, this.wpos);
|
||||||
|
this.wpos += to_write;
|
||||||
|
if (mw === to_write) {
|
||||||
|
this.wpos = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const high = p_buffer.subarray(0, mw);
|
||||||
|
const low = p_buffer.subarray(mw);
|
||||||
|
this.buffer.set(high, this.wpos);
|
||||||
|
this.buffer.set(low);
|
||||||
|
this.wpos = low.length;
|
||||||
|
}
|
||||||
|
if (this.threads) {
|
||||||
|
Atomics.add(this.avail, 0, to_write);
|
||||||
|
Atomics.notify(this.avail, 0);
|
||||||
|
} else {
|
||||||
|
this.avail += to_write;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GodotProcessor extends AudioWorkletProcessor {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.threads = false;
|
||||||
|
this.running = true;
|
||||||
|
this.lock = null;
|
||||||
|
this.notifier = null;
|
||||||
|
this.output = null;
|
||||||
|
this.output_buffer = new Float32Array();
|
||||||
|
this.input = null;
|
||||||
|
this.input_buffer = new Float32Array();
|
||||||
|
this.port.onmessage = (event) => {
|
||||||
|
const cmd = event.data['cmd'];
|
||||||
|
const data = event.data['data'];
|
||||||
|
this.parse_message(cmd, data);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
process_notify() {
|
||||||
|
if (this.notifier) {
|
||||||
|
Atomics.add(this.notifier, 0, 1);
|
||||||
|
Atomics.notify(this.notifier, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_message(p_cmd, p_data) {
|
||||||
|
if (p_cmd === 'start' && p_data) {
|
||||||
|
const state = p_data[0];
|
||||||
|
let idx = 0;
|
||||||
|
this.threads = true;
|
||||||
|
this.lock = state.subarray(idx, ++idx);
|
||||||
|
this.notifier = state.subarray(idx, ++idx);
|
||||||
|
const avail_in = state.subarray(idx, ++idx);
|
||||||
|
const avail_out = state.subarray(idx, ++idx);
|
||||||
|
this.input = new RingBuffer(p_data[1], avail_in, true);
|
||||||
|
this.output = new RingBuffer(p_data[2], avail_out, true);
|
||||||
|
} else if (p_cmd === 'stop') {
|
||||||
|
this.running = false;
|
||||||
|
this.output = null;
|
||||||
|
this.input = null;
|
||||||
|
this.lock = null;
|
||||||
|
this.notifier = null;
|
||||||
|
} else if (p_cmd === 'start_nothreads') {
|
||||||
|
this.output = new RingBuffer(p_data[0], p_data[0].length, false);
|
||||||
|
} else if (p_cmd === 'chunk') {
|
||||||
|
this.output.write(p_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static array_has_data(arr) {
|
||||||
|
return arr.length && arr[0].length && arr[0][0].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
process(inputs, outputs, parameters) {
|
||||||
|
if (!this.running) {
|
||||||
|
return false; // Stop processing.
|
||||||
|
}
|
||||||
|
if (this.output === null) {
|
||||||
|
return true; // Not ready yet, keep processing.
|
||||||
|
}
|
||||||
|
const process_input = GodotProcessor.array_has_data(inputs);
|
||||||
|
if (process_input) {
|
||||||
|
const input = inputs[0];
|
||||||
|
const chunk = input[0].length * input.length;
|
||||||
|
if (this.input_buffer.length !== chunk) {
|
||||||
|
this.input_buffer = new Float32Array(chunk);
|
||||||
|
}
|
||||||
|
if (!this.threads) {
|
||||||
|
GodotProcessor.write_input(this.input_buffer, input);
|
||||||
|
this.port.postMessage({ 'cmd': 'input', 'data': this.input_buffer });
|
||||||
|
} else if (this.input.space_left() >= chunk) {
|
||||||
|
GodotProcessor.write_input(this.input_buffer, input);
|
||||||
|
this.input.write(this.input_buffer);
|
||||||
|
} else {
|
||||||
|
this.port.postMessage('Input buffer is full! Skipping input frame.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const process_output = GodotProcessor.array_has_data(outputs);
|
||||||
|
if (process_output) {
|
||||||
|
const output = outputs[0];
|
||||||
|
const chunk = output[0].length * output.length;
|
||||||
|
if (this.output_buffer.length !== chunk) {
|
||||||
|
this.output_buffer = new Float32Array(chunk);
|
||||||
|
}
|
||||||
|
if (this.output.data_left() >= chunk) {
|
||||||
|
this.output.read(this.output_buffer);
|
||||||
|
GodotProcessor.write_output(output, this.output_buffer);
|
||||||
|
if (!this.threads) {
|
||||||
|
this.port.postMessage({ 'cmd': 'read', 'data': chunk });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.port.postMessage('Output buffer has not enough frames! Skipping output frame.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.process_notify();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static write_output(dest, source) {
|
||||||
|
const channels = dest.length;
|
||||||
|
for (let ch = 0; ch < channels; ch++) {
|
||||||
|
for (let sample = 0; sample < dest[ch].length; sample++) {
|
||||||
|
dest[ch][sample] = source[sample * channels + ch];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static write_input(dest, source) {
|
||||||
|
const channels = source.length;
|
||||||
|
for (let ch = 0; ch < channels; ch++) {
|
||||||
|
for (let sample = 0; sample < source[ch].length; sample++) {
|
||||||
|
dest[sample * channels + ch] = source[ch][sample];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
registerProcessor('godot-processor', GodotProcessor);
|
251
semag/karlson/index.html
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<script src="./js/all.js"></script>
|
||||||
|
<script src="coi-serviceworker.js"></script>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||||
|
<title>Karlson</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
touch-action: none;
|
||||||
|
margin: 0;
|
||||||
|
border: 0 none;
|
||||||
|
padding: 0;
|
||||||
|
text-align: center;
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#canvas {
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#canvas:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.godot {
|
||||||
|
font-family: 'Noto Sans', 'Droid Sans', Arial, sans-serif;
|
||||||
|
color: #e0e0e0;
|
||||||
|
background-color: #3b3943;
|
||||||
|
background-image: linear-gradient(to bottom, #403e48, #35333c);
|
||||||
|
border: 1px solid #45434e;
|
||||||
|
box-shadow: 0 0 1px 1px #2f2d35;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Status display */
|
||||||
|
|
||||||
|
#status {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
/* don't consume click events - make children visible explicitly */
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#status-progress {
|
||||||
|
width: 366px;
|
||||||
|
height: 7px;
|
||||||
|
background-color: #38363A;
|
||||||
|
border: 1px solid #444246;
|
||||||
|
padding: 1px;
|
||||||
|
box-shadow: 0 0 2px 1px #1B1C22;
|
||||||
|
border-radius: 2px;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (orientation:portrait) {
|
||||||
|
#status-progress {
|
||||||
|
width: 61.8%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#status-progress-inner {
|
||||||
|
height: 100%;
|
||||||
|
width: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
transition: width 0.5s linear;
|
||||||
|
background-color: #202020;
|
||||||
|
border: 1px solid #222223;
|
||||||
|
box-shadow: 0 0 1px 1px #27282E;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#status-indeterminate {
|
||||||
|
height: 42px;
|
||||||
|
visibility: visible;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#status-indeterminate > div {
|
||||||
|
width: 4.5px;
|
||||||
|
height: 0;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 9px 3px 0 3px;
|
||||||
|
border-color: #2b2b2b transparent transparent transparent;
|
||||||
|
transform-origin: center 21px;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
#status-indeterminate > div:nth-child(1) { transform: rotate( 22.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(2) { transform: rotate( 67.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(3) { transform: rotate(112.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(4) { transform: rotate(157.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(5) { transform: rotate(202.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(6) { transform: rotate(247.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(7) { transform: rotate(292.5deg); }
|
||||||
|
#status-indeterminate > div:nth-child(8) { transform: rotate(337.5deg); }
|
||||||
|
|
||||||
|
#status-notice {
|
||||||
|
margin: 0 100px;
|
||||||
|
line-height: 1.3;
|
||||||
|
visibility: visible;
|
||||||
|
padding: 4px 6px;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link id='-gd-engine-icon' rel='icon' type='image/png' href='index.icon.png' />
|
||||||
|
<link rel='apple-touch-icon' href='index.apple-touch-icon.png'/>
|
||||||
|
<link rel='manifest' href='index.manifest.json'>
|
||||||
|
<script src="coi-serviceworker.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas id="canvas">
|
||||||
|
HTML5 canvas appears to be unsupported in the current browser.<br >
|
||||||
|
Please try updating or use a different browser.
|
||||||
|
</canvas>
|
||||||
|
<div id="status">
|
||||||
|
<div id="status-progress" style="display: none;" oncontextmenu="event.preventDefault();">
|
||||||
|
<div id ="status-progress-inner"></div>
|
||||||
|
</div>
|
||||||
|
<div id="status-indeterminate" style="display: none;" oncontextmenu="event.preventDefault();">
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<div id="status-notice" class="godot" style="display: none;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="index.js"></script>
|
||||||
|
<script>
|
||||||
|
const GODOT_CONFIG = {"args":[],"canvasResizePolicy":2,"executable":"index","experimentalVK":false,"fileSizes":{"index.pck":4630720,"index.wasm":35649444},"focusCanvas":true,"gdextensionLibs":[],"serviceWorker":"index.service.worker.js"};
|
||||||
|
const engine = new Engine(GODOT_CONFIG);
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
const INDETERMINATE_STATUS_STEP_MS = 100;
|
||||||
|
const statusProgress = document.getElementById('status-progress');
|
||||||
|
const statusProgressInner = document.getElementById('status-progress-inner');
|
||||||
|
const statusIndeterminate = document.getElementById('status-indeterminate');
|
||||||
|
const statusNotice = document.getElementById('status-notice');
|
||||||
|
|
||||||
|
let initializing = true;
|
||||||
|
let statusMode = 'hidden';
|
||||||
|
|
||||||
|
let animationCallbacks = [];
|
||||||
|
function animate(time) {
|
||||||
|
animationCallbacks.forEach((callback) => callback(time));
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
|
||||||
|
function animateStatusIndeterminate(ms) {
|
||||||
|
const i = Math.floor((ms / INDETERMINATE_STATUS_STEP_MS) % 8);
|
||||||
|
if (statusIndeterminate.children[i].style.borderTopColor === '') {
|
||||||
|
Array.prototype.slice.call(statusIndeterminate.children).forEach((child) => {
|
||||||
|
child.style.borderTopColor = '';
|
||||||
|
});
|
||||||
|
statusIndeterminate.children[i].style.borderTopColor = '#dfdfdf';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setStatusMode(mode) {
|
||||||
|
if (statusMode === mode || !initializing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[statusProgress, statusIndeterminate, statusNotice].forEach((elem) => {
|
||||||
|
elem.style.display = 'none';
|
||||||
|
});
|
||||||
|
animationCallbacks = animationCallbacks.filter(function (value) {
|
||||||
|
return (value !== animateStatusIndeterminate);
|
||||||
|
});
|
||||||
|
switch (mode) {
|
||||||
|
case 'progress':
|
||||||
|
statusProgress.style.display = 'block';
|
||||||
|
break;
|
||||||
|
case 'indeterminate':
|
||||||
|
statusIndeterminate.style.display = 'block';
|
||||||
|
animationCallbacks.push(animateStatusIndeterminate);
|
||||||
|
break;
|
||||||
|
case 'notice':
|
||||||
|
statusNotice.style.display = 'block';
|
||||||
|
break;
|
||||||
|
case 'hidden':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('Invalid status mode');
|
||||||
|
}
|
||||||
|
statusMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setStatusNotice(text) {
|
||||||
|
while (statusNotice.lastChild) {
|
||||||
|
statusNotice.removeChild(statusNotice.lastChild);
|
||||||
|
}
|
||||||
|
const lines = text.split('\n');
|
||||||
|
lines.forEach((line) => {
|
||||||
|
statusNotice.appendChild(document.createTextNode(line));
|
||||||
|
statusNotice.appendChild(document.createElement('br'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayFailureNotice(err) {
|
||||||
|
const msg = err.message || err;
|
||||||
|
console.error(msg);
|
||||||
|
setStatusNotice(msg);
|
||||||
|
setStatusMode('notice');
|
||||||
|
initializing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const missing = Engine.getMissingFeatures();
|
||||||
|
if (missing.length !== 0) {
|
||||||
|
const missingMsg = 'Error\nThe following features required to run Godot projects on the Web are missing:\n';
|
||||||
|
displayFailureNotice(missingMsg + missing.join('\n'));
|
||||||
|
} else {
|
||||||
|
setStatusMode('indeterminate');
|
||||||
|
engine.startGame({
|
||||||
|
'onProgress': function (current, total) {
|
||||||
|
if (total > 0) {
|
||||||
|
statusProgressInner.style.width = `${(current / total) * 100}%`;
|
||||||
|
setStatusMode('progress');
|
||||||
|
if (current === total) {
|
||||||
|
// wait for progress bar animation
|
||||||
|
setTimeout(() => {
|
||||||
|
setStatusMode('indeterminate');
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setStatusMode('indeterminate');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}).then(() => {
|
||||||
|
setStatusMode('hidden');
|
||||||
|
initializing = false;
|
||||||
|
}, displayFailureNotice);
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
BIN
semag/karlson/index.icon.png
Normal file
After Width: | Height: | Size: 15 KiB |
34
semag/karlson/index.icon.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://mf36xb5dx7ec"
|
||||||
|
path="res://.godot/imported/index.icon.png-a9d2f4f7433eeddc29dad75f5e7f8710.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://build/web/index.icon.png"
|
||||||
|
dest_files=["res://.godot/imported/index.icon.png-a9d2f4f7433eeddc29dad75f5e7f8710.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
14477
semag/karlson/index.js
Normal file
1
semag/karlson/index.manifest.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"background_color":"#000000","display":"standalone","icons":[{"sizes":"144x144","src":"index.144x144.png","type":"image/png"},{"sizes":"180x180","src":"index.180x180.png","type":"image/png"},{"sizes":"512x512","src":"index.512x512.png","type":"image/png"}],"name":"Karlson","orientation":"any","start_url":"./index.html"}
|
41
semag/karlson/index.offline.html
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>You are offline</title>
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
background-color: #000000;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
|
margin: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-block: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
display: block;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
margin: 3rem auto 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>You are offline</h1>
|
||||||
|
<p>This application requires an Internet connection to run for the first time.</p>
|
||||||
|
<p>Press the button below to try reloading:</p>
|
||||||
|
<button type="button">Reload</button>
|
||||||
|
<script>
|
||||||
|
document.querySelector('button').addEventListener('click', () => {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
semag/karlson/index.pck
Normal file
BIN
semag/karlson/index.png
Normal file
After Width: | Height: | Size: 21 KiB |
34
semag/karlson/index.png.import
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://2wb0flpiipu5"
|
||||||
|
path="res://.godot/imported/index.png-7e97af7272d6fa0065ffc53e96463470.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://build/web/index.png"
|
||||||
|
dest_files=["res://.godot/imported/index.png-7e97af7272d6fa0065ffc53e96463470.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
106
semag/karlson/index.service.worker.js
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// This service worker is required to expose an exported Godot project as a
|
||||||
|
// Progressive Web App. It provides an offline fallback page telling the user
|
||||||
|
// that they need an Internet connection to run the project if desired.
|
||||||
|
// Incrementing CACHE_VERSION will kick off the install event and force
|
||||||
|
// previously cached resources to be updated from the network.
|
||||||
|
const CACHE_VERSION = "1706872317|4593737";
|
||||||
|
const CACHE_PREFIX = "Karlson-sw-cache-";
|
||||||
|
const CACHE_NAME = CACHE_PREFIX + CACHE_VERSION;
|
||||||
|
const OFFLINE_URL = "index.offline.html";
|
||||||
|
// Files that will be cached on load.
|
||||||
|
const CACHED_FILES = ["index.html","index.js","index.offline.html","index.icon.png","index.apple-touch-icon.png","index.worker.js","index.audio.worklet.js"];
|
||||||
|
// Files that we might not want the user to preload, and will only be cached on first load.
|
||||||
|
const CACHABLE_FILES = ["index.wasm","index.pck"];
|
||||||
|
const FULL_CACHE = CACHED_FILES.concat(CACHABLE_FILES);
|
||||||
|
|
||||||
|
self.addEventListener("install", (event) => {
|
||||||
|
event.waitUntil(caches.open(CACHE_NAME).then(cache => cache.addAll(CACHED_FILES)));
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener("activate", (event) => {
|
||||||
|
event.waitUntil(caches.keys().then(
|
||||||
|
function (keys) {
|
||||||
|
// Remove old caches.
|
||||||
|
return Promise.all(keys.filter(key => key.startsWith(CACHE_PREFIX) && key != CACHE_NAME).map(key => caches.delete(key)));
|
||||||
|
}).then(function() {
|
||||||
|
// Enable navigation preload if available.
|
||||||
|
return ("navigationPreload" in self.registration) ? self.registration.navigationPreload.enable() : Promise.resolve();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
async function fetchAndCache(event, cache, isCachable) {
|
||||||
|
// Use the preloaded response, if it's there
|
||||||
|
let response = await event.preloadResponse;
|
||||||
|
if (!response) {
|
||||||
|
// Or, go over network.
|
||||||
|
response = await self.fetch(event.request);
|
||||||
|
}
|
||||||
|
if (isCachable) {
|
||||||
|
// And update the cache
|
||||||
|
cache.put(event.request, response.clone());
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.addEventListener("fetch", (event) => {
|
||||||
|
const isNavigate = event.request.mode === "navigate";
|
||||||
|
const url = event.request.url || "";
|
||||||
|
const referrer = event.request.referrer || "";
|
||||||
|
const base = referrer.slice(0, referrer.lastIndexOf("/") + 1);
|
||||||
|
const local = url.startsWith(base) ? url.replace(base, "") : "";
|
||||||
|
const isCachable = FULL_CACHE.some(v => v === local) || (base === referrer && base.endsWith(CACHED_FILES[0]));
|
||||||
|
if (isNavigate || isCachable) {
|
||||||
|
event.respondWith(async function () {
|
||||||
|
// Try to use cache first
|
||||||
|
const cache = await caches.open(CACHE_NAME);
|
||||||
|
if (event.request.mode === "navigate") {
|
||||||
|
// Check if we have full cache during HTML page request.
|
||||||
|
const fullCache = await Promise.all(FULL_CACHE.map(name => cache.match(name)));
|
||||||
|
const missing = fullCache.some(v => v === undefined);
|
||||||
|
if (missing) {
|
||||||
|
try {
|
||||||
|
// Try network if some cached file is missing (so we can display offline page in case).
|
||||||
|
return await fetchAndCache(event, cache, isCachable);
|
||||||
|
} catch (e) {
|
||||||
|
// And return the hopefully always cached offline page in case of network failure.
|
||||||
|
console.error("Network error: ", e);
|
||||||
|
return await caches.match(OFFLINE_URL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const cached = await cache.match(event.request);
|
||||||
|
if (cached) {
|
||||||
|
return cached;
|
||||||
|
} else {
|
||||||
|
// Try network if don't have it in cache.
|
||||||
|
return await fetchAndCache(event, cache, isCachable);
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener("message", (event) => {
|
||||||
|
// No cross origin
|
||||||
|
if (event.origin != self.origin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const id = event.source.id || "";
|
||||||
|
const msg = event.data || "";
|
||||||
|
// Ensure it's one of our clients.
|
||||||
|
self.clients.get(id).then(function (client) {
|
||||||
|
if (!client) {
|
||||||
|
return; // Not a valid client.
|
||||||
|
}
|
||||||
|
if (msg === "claim") {
|
||||||
|
self.skipWaiting().then(() => self.clients.claim());
|
||||||
|
} else if (msg === "clear") {
|
||||||
|
caches.delete(CACHE_NAME);
|
||||||
|
} else if (msg === "update") {
|
||||||
|
self.skipWaiting().then(() => self.clients.claim()).then(() => self.clients.matchAll()).then(all => all.forEach(c => c.navigate(c.url)));
|
||||||
|
} else {
|
||||||
|
onClientMessage(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
BIN
semag/karlson/index.wasm
Normal file
161
semag/karlson/index.worker.js
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright 2015 The Emscripten Authors
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Pthread Web Worker startup routine:
|
||||||
|
// This is the entry point file that is loaded first by each Web Worker
|
||||||
|
// that executes pthreads on the Emscripten application.
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Module = {};
|
||||||
|
|
||||||
|
// Thread-local guard variable for one-time init of the JS state
|
||||||
|
var initializedJS = false;
|
||||||
|
|
||||||
|
function assert(condition, text) {
|
||||||
|
if (!condition) abort('Assertion failed: ' + text);
|
||||||
|
}
|
||||||
|
|
||||||
|
function threadPrintErr() {
|
||||||
|
var text = Array.prototype.slice.call(arguments).join(' ');
|
||||||
|
console.error(text);
|
||||||
|
}
|
||||||
|
function threadAlert() {
|
||||||
|
var text = Array.prototype.slice.call(arguments).join(' ');
|
||||||
|
postMessage({cmd: 'alert', text: text, threadId: Module['_pthread_self']()});
|
||||||
|
}
|
||||||
|
// We don't need out() for now, but may need to add it if we want to use it
|
||||||
|
// here. Or, if this code all moves into the main JS, that problem will go
|
||||||
|
// away. (For now, adding it here increases code size for no benefit.)
|
||||||
|
var out = () => { throw 'out() is not defined in worker.js.'; }
|
||||||
|
var err = threadPrintErr;
|
||||||
|
self.alert = threadAlert;
|
||||||
|
|
||||||
|
Module['instantiateWasm'] = (info, receiveInstance) => {
|
||||||
|
// Instantiate from the module posted from the main thread.
|
||||||
|
// We can just use sync instantiation in the worker.
|
||||||
|
var module = Module['wasmModule'];
|
||||||
|
// We don't need the module anymore; new threads will be spawned from the main thread.
|
||||||
|
Module['wasmModule'] = null;
|
||||||
|
var instance = new WebAssembly.Instance(module, info);
|
||||||
|
// TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193,
|
||||||
|
// the above line no longer optimizes out down to the following line.
|
||||||
|
// When the regression is fixed, we can remove this if/else.
|
||||||
|
return receiveInstance(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turn unhandled rejected promises into errors so that the main thread will be
|
||||||
|
// notified about them.
|
||||||
|
self.onunhandledrejection = (e) => {
|
||||||
|
throw e.reason ?? e;
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleMessage(e) {
|
||||||
|
try {
|
||||||
|
if (e.data.cmd === 'load') { // Preload command that is called once per worker to parse and load the Emscripten code.
|
||||||
|
|
||||||
|
// Until we initialize the runtime, queue up any further incoming messages.
|
||||||
|
let messageQueue = [];
|
||||||
|
self.onmessage = (e) => messageQueue.push(e);
|
||||||
|
|
||||||
|
// And add a callback for when the runtime is initialized.
|
||||||
|
self.startWorker = (instance) => {
|
||||||
|
Module = instance;
|
||||||
|
// Notify the main thread that this thread has loaded.
|
||||||
|
postMessage({ 'cmd': 'loaded' });
|
||||||
|
// Process any messages that were queued before the thread was ready.
|
||||||
|
for (let msg of messageQueue) {
|
||||||
|
handleMessage(msg);
|
||||||
|
}
|
||||||
|
// Restore the real message handler.
|
||||||
|
self.onmessage = handleMessage;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Module and memory were sent from main thread
|
||||||
|
Module['wasmModule'] = e.data.wasmModule;
|
||||||
|
|
||||||
|
// Use `const` here to ensure that the variable is scoped only to
|
||||||
|
// that iteration, allowing safe reference from a closure.
|
||||||
|
for (const handler of e.data.handlers) {
|
||||||
|
Module[handler] = function() {
|
||||||
|
postMessage({ cmd: 'callHandler', handler, args: [...arguments] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Module['wasmMemory'] = e.data.wasmMemory;
|
||||||
|
|
||||||
|
Module['buffer'] = Module['wasmMemory'].buffer;
|
||||||
|
|
||||||
|
Module['workerID'] = e.data.workerID;
|
||||||
|
|
||||||
|
Module['ENVIRONMENT_IS_PTHREAD'] = true;
|
||||||
|
|
||||||
|
if (typeof e.data.urlOrBlob == 'string') {
|
||||||
|
importScripts(e.data.urlOrBlob);
|
||||||
|
} else {
|
||||||
|
var objectUrl = URL.createObjectURL(e.data.urlOrBlob);
|
||||||
|
importScripts(objectUrl);
|
||||||
|
URL.revokeObjectURL(objectUrl);
|
||||||
|
}
|
||||||
|
Godot(Module);
|
||||||
|
} else if (e.data.cmd === 'run') {
|
||||||
|
// Pass the thread address to wasm to store it for fast access.
|
||||||
|
Module['__emscripten_thread_init'](e.data.pthread_ptr, /*isMainBrowserThread=*/0, /*isMainRuntimeThread=*/0, /*canBlock=*/1);
|
||||||
|
|
||||||
|
// Await mailbox notifications with `Atomics.waitAsync` so we can start
|
||||||
|
// using the fast `Atomics.notify` notification path.
|
||||||
|
Module['__emscripten_thread_mailbox_await'](e.data.pthread_ptr);
|
||||||
|
|
||||||
|
assert(e.data.pthread_ptr);
|
||||||
|
// Also call inside JS module to set up the stack frame for this pthread in JS module scope
|
||||||
|
Module['establishStackSpace']();
|
||||||
|
Module['PThread'].receiveObjectTransfer(e.data);
|
||||||
|
Module['PThread'].threadInitTLS();
|
||||||
|
|
||||||
|
if (!initializedJS) {
|
||||||
|
initializedJS = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Module['invokeEntryPoint'](e.data.start_routine, e.data.arg);
|
||||||
|
} catch(ex) {
|
||||||
|
if (ex != 'unwind') {
|
||||||
|
// The pthread "crashed". Do not call `_emscripten_thread_exit` (which
|
||||||
|
// would make this thread joinable). Instead, re-throw the exception
|
||||||
|
// and let the top level handler propagate it back to the main thread.
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (e.data.cmd === 'cancel') { // Main thread is asking for a pthread_cancel() on this thread.
|
||||||
|
if (Module['_pthread_self']()) {
|
||||||
|
Module['__emscripten_thread_exit'](-1);
|
||||||
|
}
|
||||||
|
} else if (e.data.target === 'setimmediate') {
|
||||||
|
// no-op
|
||||||
|
} else if (e.data.cmd === 'checkMailbox') {
|
||||||
|
if (initializedJS) {
|
||||||
|
Module['checkMailbox']();
|
||||||
|
}
|
||||||
|
} else if (e.data.cmd) {
|
||||||
|
// The received message looks like something that should be handled by this message
|
||||||
|
// handler, (since there is a e.data.cmd field present), but is not one of the
|
||||||
|
// recognized commands:
|
||||||
|
err('worker.js received unknown command ' + e.data.cmd);
|
||||||
|
err(e.data);
|
||||||
|
}
|
||||||
|
} catch(ex) {
|
||||||
|
err('worker.js onmessage() captured an uncaught exception: ' + ex);
|
||||||
|
if (ex && ex.stack) err(ex.stack);
|
||||||
|
if (Module['__emscripten_thread_crashed']) {
|
||||||
|
Module['__emscripten_thread_crashed']();
|
||||||
|
}
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.onmessage = handleMessage;
|
||||||
|
|
||||||
|
|