Add polish to the game
I added polish to the game. Hooray.
This commit is contained in:
parent
6bbfbd60d0
commit
e4584d0669
18 changed files with 651 additions and 86 deletions
|
@ -2,5 +2,3 @@
|
||||||
A sandbox game inspired by https://sandboxels.r74n.com/, with a cleaner codebase and secure/simple modding support in mind.
|
A sandbox game inspired by https://sandboxels.r74n.com/, with a cleaner codebase and secure/simple modding support in mind.
|
||||||
|
|
||||||
Some of the elements are derived from other games in the falling sand genre, especially Sandboxels. However, the physics engine and other backend code are custom and independently developed.
|
Some of the elements are derived from other games in the falling sand genre, especially Sandboxels. However, the physics engine and other backend code are custom and independently developed.
|
||||||
|
|
||||||
Recreated to remove private information from commit logs.
|
|
257
css/core.css
257
css/core.css
|
@ -1,10 +1,13 @@
|
||||||
|
@import url("./fonts.css");
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: monospace;
|
font-family: "Ubuntu Mono";
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background: rgb(21, 21, 22);
|
background: rgb(21, 21, 22);
|
||||||
color: white;
|
color: white;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#no-overflow {
|
#no-overflow {
|
||||||
|
@ -16,6 +19,7 @@ canvas {
|
||||||
display: block;
|
display: block;
|
||||||
background: rgb(181, 204, 253);
|
background: rgb(181, 204, 253);
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#main2 {
|
#main2 {
|
||||||
|
@ -27,7 +31,7 @@ canvas {
|
||||||
}
|
}
|
||||||
|
|
||||||
button, a, textarea {
|
button, a, textarea {
|
||||||
padding: 5px;
|
padding: 5px 10px;
|
||||||
border: none;
|
border: none;
|
||||||
margin: 6px 3px 0px 3px;
|
margin: 6px 3px 0px 3px;
|
||||||
|
|
||||||
|
@ -36,9 +40,254 @@ button, a, textarea {
|
||||||
background: rgb(44, 142, 255);
|
background: rgb(44, 142, 255);
|
||||||
color: white;
|
color: white;
|
||||||
|
|
||||||
font-family: monospace;
|
font-family: inherit;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 17px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
section:target button, .menu2 button, a, textarea {
|
section.selected-group button, .menu2 button, a, textarea {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
div#header-title {
|
||||||
|
font-size: 23px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header-links a {
|
||||||
|
margin-top: 0;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header {
|
||||||
|
padding: 0 8px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
#header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu, .menu2, .buttons > .selected-group {
|
||||||
|
position: relative;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: var(--canvasWidth);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
background: #7b7b7b;
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.buttons > .selected-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
height: 100px;
|
||||||
|
padding: 10px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu a,
|
||||||
|
.menu2 a {
|
||||||
|
width: 100%;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.buttons button {
|
||||||
|
width: calc(25% - 6px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-bar > * {
|
||||||
|
background: #616161;
|
||||||
|
margin: 0;
|
||||||
|
margin-top: 8px;
|
||||||
|
border-radius: 10px 10px 0 0;
|
||||||
|
padding: 8px 10px;
|
||||||
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.tab-bar > .selected-group {
|
||||||
|
background: #7b7b7b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#game {
|
||||||
|
position: relative;
|
||||||
|
left: 50vw;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
.info {
|
||||||
|
height: 20px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Mod Loader */
|
||||||
|
|
||||||
|
#mod-loader-modal {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
background: #000a;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
z-index: 100;
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.25s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mod-loader-modal-box {
|
||||||
|
position: fixed;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: min(800px, 75vw);
|
||||||
|
background: #7b7b7b;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 0;
|
||||||
|
transition: transform 0.25s ease-in-out;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
#mod-loader-modal:not(.opened) {
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
#mod-loader-modal:not(.opened) #mod-loader-modal-box {
|
||||||
|
transform: translate(-50%, -50%) scaleY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#mod-loader-modal-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px;
|
||||||
|
height: 28px;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
background: #3b3b3b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-bar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mod-loader-modal-title {
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
#mod-loader-modal-close-button {
|
||||||
|
background: gray;
|
||||||
|
padding: 6px;
|
||||||
|
border-radius: 7px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-loader-tab-content:not(.selected-group) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mod-form {
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
width: 100%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#mod-loader-modal-content {
|
||||||
|
height: min(500px, 75vh);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mod-loader-modal-box > * > * {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mod-loader-modal-tabs {
|
||||||
|
/* margin: 0 29px; */
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Mods */
|
||||||
|
|
||||||
|
.mods-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-content: flex-start;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod {
|
||||||
|
display: inline-flex;
|
||||||
|
--margin: 10px;
|
||||||
|
width: calc(50% - (var(--margin) * 2));
|
||||||
|
height: 96px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 5px solid darkgray;
|
||||||
|
background: lightgray;
|
||||||
|
color: #555;
|
||||||
|
padding: 8px;
|
||||||
|
margin: 10px;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-icon {
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
flex: none;
|
||||||
|
height: 100%;
|
||||||
|
image-rendering: pixelated;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-details > * {
|
||||||
|
text-align: left;
|
||||||
|
margin: 0 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
-webkit-line-clamp: 3;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
display: -webkit-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-loader-tab-content {
|
||||||
|
/* padding: 10px; */
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-details {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 68%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-name {
|
||||||
|
color: #111;
|
||||||
|
font-size: 20px;
|
||||||
|
/* white-space: nowrap; */
|
||||||
|
max-width: 100%;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-options {
|
||||||
|
flex: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
40
css/fonts.css
Normal file
40
css/fonts.css
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Ubuntu Mono';
|
||||||
|
src: local('Ubuntu Mono'), local('UbuntuMono-Regular'),
|
||||||
|
url('fonts/UbuntuMono-Regular.woff2') format('woff2'),
|
||||||
|
url('fonts/UbuntuMono-Regular.woff') format('woff');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Ubuntu Mono';
|
||||||
|
src: local('Ubuntu Mono Italic'), local('UbuntuMono-Italic'),
|
||||||
|
url('fonts/UbuntuMono-Italic.woff2') format('woff2'),
|
||||||
|
url('fonts/UbuntuMono-Italic.woff') format('woff');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: italic;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Ubuntu Mono';
|
||||||
|
src: local('Ubuntu Mono Bold Italic'), local('UbuntuMono-BoldItalic'),
|
||||||
|
url('fonts/UbuntuMono-BoldItalic.woff2') format('woff2'),
|
||||||
|
url('fonts/UbuntuMono-BoldItalic.woff') format('woff');
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Ubuntu Mono';
|
||||||
|
src: local('Ubuntu Mono Bold'), local('UbuntuMono-Bold'),
|
||||||
|
url('fonts/UbuntuMono-Bold.woff2') format('woff2'),
|
||||||
|
url('fonts/UbuntuMono-Bold.woff') format('woff');
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
96
css/fonts/UFL.txt
Normal file
96
css/fonts/UFL.txt
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
-------------------------------
|
||||||
|
UBUNTU FONT LICENCE Version 1.0
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
This licence allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely. The fonts, including any derivative works, can be
|
||||||
|
bundled, embedded, and redistributed provided the terms of this licence
|
||||||
|
are met. The fonts and derivatives, however, cannot be released under
|
||||||
|
any other licence. The requirement for fonts to remain under this
|
||||||
|
licence does not require any document created using the fonts or their
|
||||||
|
derivatives to be published under this licence, as long as the primary
|
||||||
|
purpose of the document is not to be a vehicle for the distribution of
|
||||||
|
the fonts.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this licence and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components
|
||||||
|
as received under this licence.
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to
|
||||||
|
a new environment.
|
||||||
|
|
||||||
|
"Copyright Holder(s)" refers to all individuals and companies who have a
|
||||||
|
copyright ownership of the Font Software.
|
||||||
|
|
||||||
|
"Substantially Changed" refers to Modified Versions which can be easily
|
||||||
|
identified as dissimilar to the Font Software by users of the Font
|
||||||
|
Software comparing the Original Version with the Modified Version.
|
||||||
|
|
||||||
|
To "Propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification and with or without charging
|
||||||
|
a redistribution fee), making available to the public, and in some
|
||||||
|
countries other activities as well.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
This licence does not grant any rights under trademark law and all such
|
||||||
|
rights are reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of the Font Software, to propagate the Font Software, subject to
|
||||||
|
the below conditions:
|
||||||
|
|
||||||
|
1) Each copy of the Font Software must contain the above copyright
|
||||||
|
notice and this licence. These can be included either as stand-alone
|
||||||
|
text files, human-readable headers or in the appropriate machine-
|
||||||
|
readable metadata fields within text or binary files as long as those
|
||||||
|
fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
2) The font name complies with the following:
|
||||||
|
(a) The Original Version must retain its name, unmodified.
|
||||||
|
(b) Modified Versions which are Substantially Changed must be renamed to
|
||||||
|
avoid use of the name of the Original Version or similar names entirely.
|
||||||
|
(c) Modified Versions which are not Substantially Changed must be
|
||||||
|
renamed to both (i) retain the name of the Original Version and (ii) add
|
||||||
|
additional naming elements to distinguish the Modified Version from the
|
||||||
|
Original Version. The name of such Modified Versions must be the name of
|
||||||
|
the Original Version, with "derivative X" where X represents the name of
|
||||||
|
the new work, appended to that name.
|
||||||
|
|
||||||
|
3) The name(s) of the Copyright Holder(s) and any contributor to the
|
||||||
|
Font Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except (i) as required by this licence, (ii) to
|
||||||
|
acknowledge the contribution(s) of the Copyright Holder(s) or (iii) with
|
||||||
|
their explicit written permission.
|
||||||
|
|
||||||
|
4) The Font Software, modified or unmodified, in part or in whole, must
|
||||||
|
be distributed entirely under this licence, and must not be distributed
|
||||||
|
under any other licence. The requirement for fonts to remain under this
|
||||||
|
licence does not affect any document created using the Font Software,
|
||||||
|
except any version of the Font Software extracted from a document
|
||||||
|
created using the Font Software may only be distributed under this
|
||||||
|
licence.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This licence becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||||
|
COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
|
||||||
|
DEALINGS IN THE FONT SOFTWARE.
|
BIN
css/fonts/UbuntuMono-Bold.woff
Normal file
BIN
css/fonts/UbuntuMono-Bold.woff
Normal file
Binary file not shown.
BIN
css/fonts/UbuntuMono-Bold.woff2
Normal file
BIN
css/fonts/UbuntuMono-Bold.woff2
Normal file
Binary file not shown.
BIN
css/fonts/UbuntuMono-BoldItalic.woff
Normal file
BIN
css/fonts/UbuntuMono-BoldItalic.woff
Normal file
Binary file not shown.
BIN
css/fonts/UbuntuMono-BoldItalic.woff2
Normal file
BIN
css/fonts/UbuntuMono-BoldItalic.woff2
Normal file
Binary file not shown.
BIN
css/fonts/UbuntuMono-Italic.woff
Normal file
BIN
css/fonts/UbuntuMono-Italic.woff
Normal file
Binary file not shown.
BIN
css/fonts/UbuntuMono-Italic.woff2
Normal file
BIN
css/fonts/UbuntuMono-Italic.woff2
Normal file
Binary file not shown.
BIN
css/fonts/UbuntuMono-Regular.woff
Normal file
BIN
css/fonts/UbuntuMono-Regular.woff
Normal file
Binary file not shown.
BIN
css/fonts/UbuntuMono-Regular.woff2
Normal file
BIN
css/fonts/UbuntuMono-Regular.woff2
Normal file
Binary file not shown.
16
css/icons/open-link.svg
Normal file
16
css/icons/open-link.svg
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg height="800px" width="800px" version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
viewBox="0 0 512 512" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#000000;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M96,0v416h416V0H96z M472,376H136V40h336V376z"/>
|
||||||
|
<polygon class="st0" points="40,472 40,296 40,136 40,96 0,96 0,512 416,512 416,472 376,472 "/>
|
||||||
|
<polygon class="st0" points="232.812,312.829 350.671,194.969 350.671,279.766 390.671,279.766 390.671,126.688 237.594,126.688
|
||||||
|
237.594,166.688 322.39,166.688 204.531,284.547 "/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 837 B |
98
index.html
98
index.html
|
@ -15,41 +15,85 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1>Altboxels</h1>
|
<div id="header">
|
||||||
<canvas id='main' style=""></canvas>
|
<div id="header-title">Altboxels</div>
|
||||||
<canvas id='alt' style='display: none;'></canvas>
|
|
||||||
|
|
||||||
<span class='info'>
|
<div id="header-links">
|
||||||
N/A
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<div class='menu2'>
|
|
||||||
<section>
|
|
||||||
<a href='https://discord.gg/wtBVte4Syu'>Chat</a>
|
<a href='https://discord.gg/wtBVte4Syu'>Chat</a>
|
||||||
<a href='https://github.com/qazox/altboxels'>Source</a>
|
<a href='https://github.com/qazox/altboxels'>Source</a>
|
||||||
<a href='https://altboxels.qazox.dev/'>Website</a>
|
<a href='https://altboxels.qazox.dev/'>Website</a>
|
||||||
<a href='https://abc.qazox.dev/'>Community</a>
|
<a href='https://abc.qazox.dev/'>Community</a>
|
||||||
</section>
|
</div>
|
||||||
<section>
|
</div>
|
||||||
<button onclick="handler.noTick = !handler.noTick">Pause</button>
|
<div id="mod-loader-modal">
|
||||||
<button onclick="openMods()">Mods</button>
|
<div id="mod-loader-modal-box">
|
||||||
<button onclick="save()">Save</button>
|
<div id="mod-loader-modal-header">
|
||||||
<button onclick="load()">Load</button>
|
<div id="mod-loader-modal-title">Mods (Alpha!)</div>
|
||||||
<button onclick="canvas.radius++;">+Rad</button>
|
<div id="mod-loader-modal-tabs" class="tab-bar">
|
||||||
<button onclick="canvas.radius = Math.max(canvas.radius - 1,0);">-Rad</button>
|
<div class="mod-loader-tab">Load Online</div>
|
||||||
</section>
|
<div class="mod-loader-tab selected-group">Load from URL</div>
|
||||||
|
<div class="mod-loader-tab">Manage</div>
|
||||||
|
</div>
|
||||||
|
<div id="mod-loader-modal-close-button" onclick="closeMods()">X</div>
|
||||||
|
</div>
|
||||||
|
<div id="mod-loader-modal-content">
|
||||||
|
<div class="mod-loader-tab-content">uploaded mods go here</div>
|
||||||
|
<div class="mod-loader-tab-content selected-group">
|
||||||
|
<form id="mod-form" onsubmit="loadModFromForm(); return false">
|
||||||
|
<p>Paste a link to a mod you've found, and put it here!</p>
|
||||||
|
<input type="url" />
|
||||||
|
<input type="submit" value="Load" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="mod-loader-tab-content mods-list">
|
||||||
|
<div class="mod example-mod">
|
||||||
|
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAYJJREFUOE9NU9thwjAMlPYgMwAfCbMl+W6zCizQzkD4iFkC/toR1N6dZciH48f5JJ3Obt8/4eFmFoafG+ZYvq9DWxx0rhtm7l+/gVUIowMPA6kI8yLhucJNzv3y7CICHI4cuE+yiiWOCQmhKPUwzPz83DHXllKCKjwzUnFBcmcUVePnx07cTLuyC6UaoUULqrKwwcRw5/LYqXztvAkkQkbR0ITUtGp0fnQx3w72OWxEM5MmeSqd6lOlqpZIqMG0gqBoI8LG9ai1ajKcL/0m8SJsQsC+iIwE16N9ngojj+velqHYiL2h2LTu6x+YzYBdho0kH/0dInYxVxDikX0oNldSEd5tRJa9LiL6dDva0heI2AWihLvSDpHgME2JEuAVEOFjyadNgqcPZAS1j21ytU+Dv0hlt1cbQUDbymPpx7oIm68HZoe609tvL0MaMBrslI3nw0JHKiujZhOAq+1tVk4czaU3kZ6XE+uDyOSbw0wi8jXS3NWN7SG1FNKSkimL/Z/8AVDdA77BS/1YAAAAAElFTkSuQmCC" class="mod-icon">
|
||||||
|
<div class="mod-details">
|
||||||
|
<div class="mod-name">Sample Mod</div>
|
||||||
|
<div class="mod-description">This mod has a 16x16 icon. It's just a sample mod, this menu isn't finished yet.</div>
|
||||||
|
</div>
|
||||||
|
<div class="mod-options">
|
||||||
|
<input type="checkbox" class="mod-check" disabled checked />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='menu'>
|
|
||||||
|
<div id="game">
|
||||||
|
<span class='info'>
|
||||||
|
N/A
|
||||||
|
</span>
|
||||||
|
<canvas id='main' style=""></canvas>
|
||||||
|
<canvas id='alt' style='display: none;'></canvas> <!-- why -->
|
||||||
|
|
||||||
|
|
||||||
|
<div class='menu2'>
|
||||||
|
<section>
|
||||||
|
<button onclick="handler.noTick = !handler.noTick">Pause/Play</button>
|
||||||
|
<button onclick="openMods()">Mods</button>
|
||||||
|
<button onclick="save()">Save</button>
|
||||||
|
<button onclick="load()">Load</button>
|
||||||
|
<!-- <button onclick="upload()">Upload (TODO)</button> - HEY! Please add this. Prompt() for title, I dunno. For a site like this, I feel like allowing anonymous posting is a good idea. -->
|
||||||
|
<label for="tile-radius">Radius:</label>
|
||||||
|
<input type="range" min="1" max="20"
|
||||||
|
oninput="canvas.radius = Number(this.value);"
|
||||||
|
onmousedown="canvas.forceShowTilePlacement = true; canvas.radius = Number(this.value)"
|
||||||
|
onmouseup="canvas.forceShowTilePlacement = false"/> <!-- TODO: automatically change range value -->
|
||||||
|
|
||||||
|
<button onclick="clearEverything()">Clear</button> <!-- TODO: add clear function (i do not know how to do that) -->
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='menu tab-bar'>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='buttons'>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='buttons'>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<textarea id='code'>
|
|
||||||
(save data here)
|
|
||||||
</textarea>
|
|
||||||
|
|
||||||
<!-- Core code -->
|
<!-- Core code -->
|
||||||
<script src="js/tile.js"></script>
|
<script src="js/tile.js"></script>
|
||||||
<script src="js/event.js"></script>
|
<script src="js/event.js"></script>
|
||||||
|
|
33
js/core.js
33
js/core.js
|
@ -35,10 +35,17 @@ function Canvas(width, height, upscale) {
|
||||||
that.pageX = e.pageX;
|
that.pageX = e.pageX;
|
||||||
that.pageY = e.pageY;
|
that.pageY = e.pageY;
|
||||||
})
|
})
|
||||||
|
this.elem.addEventListener('mouseover', function (e) {
|
||||||
|
that.isMouseOver = true;
|
||||||
|
})
|
||||||
|
this.elem.addEventListener('mouseout', function (e) {
|
||||||
|
that.isMouseOver = false;
|
||||||
|
})
|
||||||
|
|
||||||
this.elem.addEventListener('wheel', function (e) {
|
this.elem.addEventListener('wheel', function (e) {
|
||||||
that.radius += Math.sign(e.deltaY);
|
that.radius += Math.sign(e.deltaY);
|
||||||
if (that.radius < 0) that.radius = 0;
|
if (that.radius < 0) that.radius = 0;
|
||||||
|
e.preventDefault();
|
||||||
})
|
})
|
||||||
|
|
||||||
this.elem.addEventListener('mouseup', function (e) {
|
this.elem.addEventListener('mouseup', function (e) {
|
||||||
|
@ -76,6 +83,12 @@ Canvas.prototype.resize = function () {
|
||||||
this.elem.width = this.width;
|
this.elem.width = this.width;
|
||||||
this.elem.height = this.height;
|
this.elem.height = this.height;
|
||||||
|
|
||||||
|
if(document.querySelector("#game") !== null)
|
||||||
|
document.querySelector("#game").setAttribute("style", `
|
||||||
|
width: ${this.width * this.upscale}px;
|
||||||
|
height: ${this.height * this.upscale}px;
|
||||||
|
`);
|
||||||
|
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,15 +144,20 @@ Canvas.prototype.render = function () {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let x = (this.pageX - this.elem.getBoundingClientRect().x - scrollX + this.x) - 0.5 - this.radius * this.upscale;
|
if(this.forceShowTilePlacement == true) {
|
||||||
let y = (this.pageY - this.elem.getBoundingClientRect().y - scrollY + this.y) - 0.5 - this.radius * this.upscale;
|
var x = (this.width / 2 - this.radius) * this.upscale;
|
||||||
|
var y = (this.height / 2 - this.radius) * this.upscale;
|
||||||
|
} else {
|
||||||
|
var x = (this.pageX - this.elem.getBoundingClientRect().x - scrollX + this.x) - 0.5 - this.radius * this.upscale;
|
||||||
|
var y = (this.pageY - this.elem.getBoundingClientRect().y - scrollY + this.y) - 0.5 - this.radius * this.upscale;
|
||||||
|
}
|
||||||
|
|
||||||
this.ctx.globalAlpha = 1;
|
this.ctx.globalAlpha = 1;
|
||||||
|
|
||||||
this.ctx.strokeStyle = 'rgb(255,255,255)';
|
this.ctx.strokeStyle = 'rgb(255,255,255)';
|
||||||
this.ctx.lineWidth = 2;
|
this.ctx.lineWidth = 2;
|
||||||
this.ctx.strokeRect(x / this.upscale, y / this.upscale, this.radius * 2 + 2, this.radius * 2 + 2);
|
if(this.isMouseOver || this.forceShowTilePlacement)
|
||||||
|
this.ctx.strokeRect(x / this.upscale, y / this.upscale, this.radius * 2 + 2, this.radius * 2 + 2);
|
||||||
|
|
||||||
let theX = Math.floor(x/this.upscale + this.radius + 1);
|
let theX = Math.floor(x/this.upscale + this.radius + 1);
|
||||||
let theY = Math.floor(y/this.upscale + this.radius + 1);
|
let theY = Math.floor(y/this.upscale + this.radius + 1);
|
||||||
|
@ -149,10 +167,11 @@ Canvas.prototype.render = function () {
|
||||||
let blok = mainTiles.tiles[this.getBlock(theX, theY)];
|
let blok = mainTiles.tiles[this.getBlock(theX, theY)];
|
||||||
let temp = this.getBlock(theX,theY, true);
|
let temp = this.getBlock(theX,theY, true);
|
||||||
|
|
||||||
if (blok) {
|
if (blok && this.isMouseOver) {
|
||||||
document.querySelector('.info').textContent = `${blok.namespace}; ${blok.id}; ${Math.round(temp+23)}deg Celsius`
|
document.querySelector('.info').textContent = `
|
||||||
|
Looking at ${blok.id} from ${blok.namespace}. Temperature at tile: ${Math.round(temp+23)}deg Celsius`
|
||||||
} else {
|
} else {
|
||||||
document.querySelector('.info').textContent = `Unknown`
|
document.querySelector('.info').textContent = ``
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
48
js/loader.js
48
js/loader.js
|
@ -13,6 +13,8 @@
|
||||||
decent basis for modding in the future.
|
decent basis for modding in the future.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
mods = [];
|
||||||
|
|
||||||
legalFuncs = [
|
legalFuncs = [
|
||||||
"gravity",
|
"gravity",
|
||||||
"cohesion",
|
"cohesion",
|
||||||
|
@ -47,9 +49,53 @@ function loadMod(stuff) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
async function openMods(stuff) {
|
async function openMods(stuff) {
|
||||||
// TODO: don't use prompt
|
// TODO: don't use prompt
|
||||||
let url = prompt('Type in the URL to the JSON of the mod you want to load.');
|
let url = prompt('Type in the URL to the JSON of the mod you want to load.');
|
||||||
loadMod(await (await fetch(url)).json())
|
loadMod(await (await fetch(url)).json())
|
||||||
|
}*/
|
||||||
|
|
||||||
|
function openMods() {
|
||||||
|
|
||||||
|
document.querySelector("#mod-loader-modal").classList.add("opened")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
function closeMods() {
|
||||||
|
|
||||||
|
document.querySelector("#mod-loader-modal").classList.remove("opened")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async function loadModFromForm() {
|
||||||
|
|
||||||
|
document.querySelector("#mod-form input").disabled = true;
|
||||||
|
let url = document.querySelector("#mod-form input").value;
|
||||||
|
try {
|
||||||
|
var mod = await fetch(url).then(e => e.json());
|
||||||
|
// do stuff here, check if mod is ok, etc...
|
||||||
|
alert("Mod loaded!")
|
||||||
|
|
||||||
|
mods.push(mod)
|
||||||
|
} catch(err) {
|
||||||
|
alert("That mod isn't valid. Check the mod, and try again.")
|
||||||
|
}
|
||||||
|
document.querySelector("#mod-form input").disabled = false;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
document.querySelectorAll(".mod-loader-tab").forEach(function(element, index){
|
||||||
|
|
||||||
|
element.onclick = function() {
|
||||||
|
|
||||||
|
document.querySelectorAll("#mod-loader-modal .selected-group").forEach(function(e) {e.classList.remove("selected-group")})
|
||||||
|
element.classList.add("selected-group");
|
||||||
|
document.querySelector(".mod-loader-tab-content:nth-child("+(index+1)+")").classList.add("selected-group");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
111
js/save_load.js
111
js/save_load.js
|
@ -4,6 +4,47 @@
|
||||||
Features a somewhat efficient compression algorithm.
|
Features a somewhat efficient compression algorithm.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
function download_file(data, filename) {
|
||||||
|
// ONLY works with ascii/latin1 characters. if you'd like to be able to download UTF-16 data (for compression, etc), please find a base64-encoding library for UTF-16, and replace "btoa".
|
||||||
|
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = "data:text/plain;base64,"+(btoa(data));
|
||||||
|
a.setAttribute("download", filename);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function upload_file(options = {}) {
|
||||||
|
base64_output = Boolean(options.useBase64);
|
||||||
|
textEncoding = options.textEncoding ? options.textEncoding : "UTF-8";
|
||||||
|
|
||||||
|
return new Promise(function(res) {
|
||||||
|
var input = document.createElement('input');
|
||||||
|
input.type = 'file';
|
||||||
|
|
||||||
|
input.onchange = e => {
|
||||||
|
var file = e.target.files[0];
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = readerEvent => {
|
||||||
|
|
||||||
|
res(readerEvent.target.result); // this is the content!
|
||||||
|
input.remove();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(base64_output)
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
else
|
||||||
|
reader.readAsText(file, textEncoding);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
input.click();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
let jason = {
|
let jason = {
|
||||||
'pal': [],
|
'pal': [],
|
||||||
|
@ -49,52 +90,58 @@ function save() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelector('#code').value = JSON.stringify(jason);
|
download_file(JSON.stringify(jason), "game-data.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
function load() {
|
function load() {
|
||||||
let jason = JSON.parse(document.querySelector('#code').value);
|
upload_file().then((text_data) => {
|
||||||
|
try {
|
||||||
|
let jason = JSON.parse(text_data);
|
||||||
|
|
||||||
let json = jason.data;
|
let json = jason.data;
|
||||||
|
|
||||||
canvas.width = jason.width;
|
canvas.width = jason.width;
|
||||||
canvas.height = jason.height;
|
canvas.height = jason.height;
|
||||||
canvas.resize();
|
canvas.resize();
|
||||||
|
|
||||||
let mainPal = jason.pal.map(x => mainTiles.resolveID(x[0],x[1]));
|
let mainPal = jason.pal.map(x => mainTiles.resolveID(x[0],x[1]));
|
||||||
|
|
||||||
console.log(mainPal);
|
console.log(mainPal);
|
||||||
|
|
||||||
for (let i in json) {
|
for (let i in json) {
|
||||||
let data = json[i];
|
let data = json[i];
|
||||||
let pal = data.pal;
|
let pal = data.pal;
|
||||||
let dat = new TextEncoder('ascii').encode(data.dat);
|
let dat = new TextEncoder('ascii').encode(data.dat);
|
||||||
|
|
||||||
let otherArray = new Uint16Array(128);
|
let otherArray = new Uint16Array(128);
|
||||||
|
|
||||||
if (pal.length < 2) {
|
if (pal.length < 2) {
|
||||||
for (let i in otherArray) {
|
for (let i in otherArray) {
|
||||||
otherArray[i] = mainPal[(pal[0])];
|
otherArray[i] = mainPal[(pal[0])];
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (pal.length < 9) {
|
||||||
|
for (let i in dat) {
|
||||||
|
otherArray[i*2] = mainPal[pal[((dat[i] - 'A'.charCodeAt()) & 0x38) / 8]];
|
||||||
|
otherArray[i*2+1] = mainPal[pal[(dat[i] - 'A'.charCodeAt()) & 0x7]];
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for (let i in dat) {
|
||||||
|
otherArray[i] = mainPal[pal[(dat[i] - 'A'.charCodeAt()) & 0x7F]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.blocks.set(otherArray,Math.min(i*128,canvas.blocks.length - 128));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (pal.length < 9) {
|
for (let i in canvas.temp) {
|
||||||
for (let i in dat) {
|
canvas.temp[i] = mainTiles.tiles[canvas.blocks[i]].attributes.temperature;
|
||||||
otherArray[i*2] = mainPal[pal[((dat[i] - 'A'.charCodeAt()) & 0x38) / 8]];
|
|
||||||
otherArray[i*2+1] = mainPal[pal[(dat[i] - 'A'.charCodeAt()) & 0x7]];
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
for (let i in dat) {
|
|
||||||
otherArray[i] = mainPal[pal[(dat[i] - 'A'.charCodeAt()) & 0x7F]];
|
|
||||||
}
|
}
|
||||||
|
} catch(err) {
|
||||||
|
alert("This save file is invalid! Please provide a JSON file, with Altboxels save data.")
|
||||||
}
|
}
|
||||||
|
})
|
||||||
canvas.blocks.set(otherArray,Math.min(i*128,canvas.blocks.length - 128));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i in canvas.temp) {
|
|
||||||
canvas.temp[i] = mainTiles.tiles[canvas.blocks[i]].attributes.temperature;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var loc3 = new URL(window.location).searchParams;
|
var loc3 = new URL(window.location).searchParams;
|
||||||
|
|
12
js/tile.js
12
js/tile.js
|
@ -55,13 +55,23 @@ TileManager.prototype.loadSet = function (namespace, tiles) {
|
||||||
|
|
||||||
let elem = document.createElement('a');
|
let elem = document.createElement('a');
|
||||||
elem.textContent = namespace;
|
elem.textContent = namespace;
|
||||||
elem.href = `#${namespace}`
|
//elem.href = `#${namespace}`
|
||||||
|
//elem.id = namespace
|
||||||
|
|
||||||
this.row.appendChild(elem);
|
this.row.appendChild(elem);
|
||||||
|
|
||||||
let elem2 = document.createElement('section');
|
let elem2 = document.createElement('section');
|
||||||
elem2.id = namespace
|
elem2.id = namespace
|
||||||
this.row2.appendChild(elem2);
|
this.row2.appendChild(elem2);
|
||||||
|
|
||||||
|
elem.onclick = function(e) {
|
||||||
|
|
||||||
|
document.querySelectorAll("#game .selected-group").forEach(function(e) {e.classList.remove("selected-group")})
|
||||||
|
e.target.classList.add("selected-group");
|
||||||
|
elem2.classList.add("selected-group");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (let tile of tiles) {
|
for (let tile of tiles) {
|
||||||
tile.namespace = namespace;
|
tile.namespace = namespace;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue