A lightweight JavaScript game engine
git clone git://soophie.de/game-engine
1
*.css2
_*
1
MINIFY=true2
AUTO_COMPILE=true3
SOURCE_FILE=asset/less/style.less4
TARGET_FILE=asset/css/style.css
1
<!DOCTYPE html>2
<html lang="en">3
<head>4
<meta charset="utf-8">5
<meta name="viewport" content="width=device-width, initial-scale=1.0">6
<title>Universe</title>7
<style type="text/css">9
* {10
margin: 0;11
padding: 0;12
}14
html,15
body {16
overflow: hidden;17
}19
</style>20
</head>21
<body>22
<script type="module">24
import { Game, Surface, Shape, Group } from 'https://git.typable.dev/std/js/game.js';26
const width = window.innerWidth;27
const height = window.innerHeight;29
class Particle extends Surface {30
constructor(x, y) {31
super(x, y, new Shape.Circle(0));32
this.origin = {x, y};33
this.init();34
}35
init() {36
this.time = 0;37
this.angle = Math.random() * 2 * Math.PI;38
this.offset = Math.random() * width - width / 2;39
this.x = this.origin.x + Math.cos(this.angle) * this.offset;40
this.y = this.origin.y + Math.sin(this.angle) * this.offset;41
this.shape.radius = this.time;42
}43
update() {44
this.time += 0.01;45
this.x += Math.cos(this.angle) * this.time / this.offset * 50;46
this.y += Math.sin(this.angle) * this.time / this.offset * 50;47
this.shape.radius = this.time / Math.abs(this.offset) * 50;48
if(!(this.x > 0 && this.x < width && this.y > 0 && this.y < height)) {49
this.init();50
}51
}52
render(g) {53
const {x, y, shape: {radius}} = this;54
g.fillStyle = 'white';55
g.beginPath();56
g.arc(x, y, radius, 2 * Math.PI, 0);57
g.fill();58
}59
}61
class Universe extends Game {62
constructor() {63
super(width, height);64
this.group = new Group();65
for(let i = 0; i < 500; i++) {66
this.group.add(new Particle(width / 2, height / 2));67
}68
}69
update() {70
this.group.update();71
}72
render(g) {73
super.render(g);74
g.fillStyle = 'black';75
g.fillRect(0, 0, this.width, this.height);76
this.group.render(g);77
}78
}80
const game = new Universe();81
document.body.append(game.canvas);82
game.start();84
</script>85
</body>86
</html>86
\ No newline at end of file
Binary file
Binary file
1
window.onload = async function() {2
for(const rel of document.querySelectorAll('[data-rel]')) {3
rel.onclick = function() {4
const {rel: code} = rel.dataset;5
if(code === 'top') {6
window.scrollTo({ top: 0, behavior: 'smooth' });7
}8
else {9
const ref = document.querySelector(`[data-ref="${code}"]`);10
if(ref) {11
window.scrollTo({ top: ref.offsetTop - 80, behavior: 'smooth' });12
}13
}14
}15
}16
for(const ref of document.querySelectorAll('span.ref')) {17
ref.onclick = function() {18
if(ref.classList.contains('ref-link')) {19
window.open(ref.textContent, '_blank');20
}21
}22
}23
let delay;24
const snackbar = document.querySelector('.snackbar');25
for(const tone of document.querySelectorAll('.palette-tone')) {26
tone.onclick = function() {27
if(snackbar) {28
snackbar.classList.add('active');29
let time = new Date().getTime();30
setTimeout(() => {31
if(delay === time) {32
snackbar.classList.remove('active');33
}34
}, 3000);35
const value = `@color-${tone.parentNode.dataset.type}-${tone.textContent}`;36
navigator.clipboard.writeText(value);37
delay = time;38
}39
}40
}41
for(const icon of document.querySelectorAll('.icon')) {42
icon.onclick = function() {43
if(snackbar) {44
snackbar.classList.add('active');45
let time = new Date().getTime();46
setTimeout(() => {47
if(delay === time) {48
snackbar.classList.remove('active');49
}50
}, 3000);51
const value = `${icon.innerHTML}`;52
navigator.clipboard.writeText(value);53
delay = time;54
}55
}56
}57
};57
\ No newline at end of file
1
@gap: 20px;2
@full-width: 800px;4
@import '../../std/less/normalize.less';5
@import '../../std/less/color.less';6
@import '../../std/less/icons.less';8
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700');9
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,400;0,500;0,600;1,400;1,500;1,600');11
@import 'theme.less';11
\ No newline at end of file
1
@space-1x: 20px;2
@space-2x: 40px;3
@space-4x: 80px;4
@space-8x: 160px;6
@screen-xs: 576px;7
@screen-sm: 768px;8
@screen-md: 992px;9
@screen-lg: 1200px;11
.space-1 {12
width: 100%;13
height: @space-1x;14
}16
.space-2 {17
width: 100%;18
height: @space-2x;19
}21
.space-4 {22
width: 100%;23
height: @space-4x;24
}26
.space-8 {27
width: 100%;28
height: @space-8x;29
}31
* {32
color: @color-gray-900;33
font-family: 'Inter';34
-webkit-tap-highlight-color: transparent;35
}37
body,38
main,39
footer{40
overflow-x: hidden;41
}43
body {45
@media(prefers-color-scheme: dark) {46
background: @color-black;47
}48
}50
h1 {51
font-size: 36px;52
margin-top: @space-4x;54
sup {55
font-size: 18px;56
font-weight: 600;57
padding-left: 2px;58
vertical-align: top;59
}61
@media(prefers-color-scheme: dark) {62
color: @color-white;63
}64
}66
h2 {67
font-size: 28px;68
font-weight: 700;69
margin-top: @space-4x;70
margin-bottom: @space-2x;72
@media(prefers-color-scheme: dark) {73
color: @color-white;74
}76
@media(min-width: @screen-xs) {77
margin-top: @space-8x;78
}79
}81
h3 {82
font-size: 24px;83
font-weight: 600;84
margin-top: @space-2x;86
@media(prefers-color-scheme: dark) {87
color: @color-white;88
}89
}91
h4 {92
font-size: 18px;93
font-weight: 600;94
margin-top: @space-2x;96
@media(prefers-color-scheme: dark) {97
color: @color-white;98
}99
}101
p {102
color: @color-gray-700;103
font-size: 16px;104
margin-top: @space-2x;105
line-height: 26px;107
@media(prefers-color-scheme: dark) {108
color: @color-gray-400;109
}111
a {112
text-decoration: underline;113
}115
mark {116
background: @color-gray-200;117
border-radius: 2px;118
padding: 2px 4px;119
color: @color-gray-800;120
word-break: break-word;122
@media(prefers-color-scheme: dark) {123
color: @color-gray-400;124
background: darken(@color-gray-900, 8%);125
}126
}128
b {129
font-weight: 500;131
@media(prefers-color-scheme: dark) {132
color: @color-gray-100;133
}135
&.note {136
margin-bottom: calc(@space-1x / 2);137
display: inline-block;139
@media(prefers-color-scheme: dark) {140
color: @color-white;141
}142
}143
}145
span {146
color: inherit;147
display: block;148
}149
}151
.slogan {152
font-size: 44px;153
margin-bottom: @space-4x;155
@media(min-width: @screen-xs) {156
font-size: 64px;157
}158
}160
.slogan-subline {161
margin-bottom: @space-4x;162
}164
.subline {165
margin-top: @space-2x;166
font-weight: 500;167
font-size: 18px;168
line-height: 28px;169
color: @color-gray-600;171
@media(prefers-color-scheme: dark) {172
color: @color-gray-400;173
}174
}176
a {177
text-decoration: none;178
color: @color-gray-800;180
&:hover {181
text-decoration: underline;182
color: @color-gray-900;183
}185
@media(prefers-color-scheme: dark) {186
color: @color-gray-300;188
&:hover {189
color: @color-gray-100;190
}191
}192
}194
.list {195
padding-left: @space-1x;197
p {198
margin-left: calc(@space-1x / 2);199
}201
&.list-short {202
margin-top: @space-1x;204
p {205
margin-top: calc(@space-1x / 2);206
}207
}209
@media(prefers-color-scheme: dark) {211
li {212
color: @color-gray-400;213
}214
}215
}217
.link-list {219
span {220
margin-top: calc(@space-1x / 2);222
a {223
display: inline-block;224
margin-left: calc(@space-1x / 2);225
}226
}227
}229
&::-webkit-scrollbar {230
width: 10px;231
}233
&::-webkit-scrollbar-thumb {234
background: @color-gray-400;236
&:hover {237
background: @color-gray-500;238
}239
}241
.container {242
position: relative;243
}245
aside {246
position: fixed;247
transform: translate(calc(-100% - @space-2x), 0);248
width: 250px;249
padding-top: @space-4x;250
display: none;252
@media(min-width: 1500px) {253
display: block;254
}256
h4 {257
margin: 0;258
cursor: pointer;259
user-select: none;260
margin-bottom: @space-1x;261
}263
ul {264
list-style-type: none;265
margin-top: @space-2x;267
li {268
margin-top: @space-1x;269
cursor: pointer;270
user-select: none;271
font-size: 16px;272
font-weight: 500;273
color: @color-gray-700;274
line-height: 24px;276
&:hover {277
color: @color-gray-900;278
}280
@media(prefers-color-scheme: dark) {281
color: @color-gray-400;283
&:hover {284
color: @color-gray-200;285
}286
}287
}288
}289
}291
code {292
display: block;293
background: @color-gray-900;294
border-radius: 4px;295
padding: @space-1x;296
margin-top: @space-2x;297
position: relative;298
overflow-x: auto;300
&::-webkit-scrollbar {301
height: 8px;302
}304
&::-webkit-scrollbar-thumb {305
background: @color-gray-700;307
&:hover {308
background: @color-gray-800;309
}310
}312
@media(prefers-color-scheme: dark) {313
background: darken(@color-gray-900, 8%);314
}316
pre {317
color: @color-gray-400;318
line-height: 22px;319
tab-size: 40px;320
font-family: 'JetBrains Mono', monospace;321
display: inline-block;323
span {324
font-family: 'JetBrains Mono', monospace;325
color: inherit;327
&.n {328
color: @color-gray-50;329
}331
&.c {332
color: @color-blue-300;333
}335
&.s {336
color: @color-green-300;337
}339
&.p {340
color: @color-cyan-300;341
}343
&.x {344
color: @color-teal-400;345
}347
&.ref {348
cursor: pointer;350
&:hover {351
text-decoration: underline;352
}353
}354
}355
}357
.clipboard {358
position: absolute;359
top: 14px;360
right: 14px;361
width: 34px;362
height: 34px;363
padding: 5px;364
border-radius: 50%;365
cursor: pointer;366
color: @color-gray-600;368
&:hover {369
color: @color-gray-700;371
&::before,372
&::after {373
opacity: 1;374
}375
}377
&::before {378
content: '';379
opacity: 0;380
display: inline-block;381
position: absolute;382
user-select: none;383
pointer-events: none;384
left: 50%;385
top: -2px;386
transform: translate(-50%, 0);387
border: 5px solid transparent;388
border-top: 5px solid @color-gray-900;389
}391
&::after {392
content: attr(data-title);393
opacity: 0;394
display: inline-block;395
position: absolute;396
background: @color-gray-900;397
padding: 6px 8px;398
color: @color-white;399
font-family: 'Inter', sans-serif;400
font-size: 12px;401
border-radius: 3px;402
user-select: none;403
pointer-events: none;404
left: 50%;405
top: -25px;406
transform: translate(-50%, 0);407
}408
}409
}411
.logo {412
margin-top: @space-2x;413
cursor: pointer;414
}416
.banner {417
display: block;418
margin-top: @space-4x;420
img {421
width: 100%;422
height: 100%;423
object-fit: cover;424
display: block;425
border-radius: 4px;426
height: 500px;427
}429
p {430
margin-top: @space-2x;431
}432
}434
.embed {435
display: block;436
margin-top: @space-4x;438
iframe {439
border-radius: 4px;440
width: 100%;441
height: calc(100vw * 500 / 800);442
pointer-events: none;444
@media(min-width: 800px) {445
width: 100%;446
height: 500px;447
}448
}450
p {451
margin-top: @space-2x;452
}453
}455
.breadcrumb {456
display: flex;457
padding-top: @space-2x;458
list-style-type: none;460
@media(min-width: @screen-xs) {461
padding-top: @space-4x;462
}464
li {465
color: @color-gray-700;466
font-size: 16px;467
line-height: 24px;468
position: relative;469
padding-right: @space-1x;471
&:not(:last-of-type) {473
&::after {474
content: '/';475
display: inline-block;476
position: absolute;477
right: 7px;478
user-select: none;479
}480
}482
@media(prefers-color-scheme: dark) {483
color: @color-gray-400;485
a {486
color: @color-gray-400;488
&:hover {489
color: @color-gray-200;490
}491
}492
}493
}494
}496
.palette-list {497
display: flex;498
flex-wrap: wrap;499
list-style-type: none;500
margin-top: @space-4x;501
gap: @space-1x;503
.palette {504
display: flex;505
flex-direction: column;506
border-radius: 4px;507
width: calc(50% - @space-1x * 1 / 2);508
margin-bottom: @space-1x;510
@media(min-width: @screen-xs) {511
width: calc(25% - @space-1x * 3 / 4);512
}514
.palette-tone {515
width: 100%;516
color: white;517
font-size: 14px;518
display: inline-flex;519
align-items: center;520
padding: calc(@space-1x / 1.25);521
cursor: pointer;522
user-select: none;523
transition: margin ease 0.2s, width ease 0.2s, height ease 0.2s, padding ease 0.2s, border-radius ease 0.2s;525
&.dark {526
color: @color-gray-900;527
font-weight: 500;528
}530
&:hover {531
margin: -4px;532
width: calc(100% + 8px);533
height: calc(100% + 8px);534
padding: calc(@space-1x / 1.25 + 4px);535
z-index: 1;536
border-radius: 4px;537
}539
&:first-of-type {540
border-top-left-radius: 4px;541
border-top-right-radius: 4px;542
}544
&:last-of-type {545
border-bottom-left-radius: 4px;546
border-bottom-right-radius: 4px;547
}548
}549
}550
}552
.icon-list {553
display: flex;554
flex-wrap: wrap;555
list-style-type: none;556
margin-top: @space-2x;557
margin-bottom: @space-2x;558
gap: @space-1x;560
.icon {561
display: flex;562
border-radius: 4px;563
justify-content: center;564
align-items: center;565
width: calc(25% - @space-1x * 3 / 4);566
aspect-ratio: 1 / 1;567
background: @color-gray-50;568
cursor: pointer;570
@media(min-width: @screen-xs) {571
width: calc(16.666% - @space-1x * 5 / 6);572
}574
@media(min-width: @screen-sm) {575
width: calc(10% - @space-1x * 9 / 10);576
}578
.ico {579
color: @color-gray-600;580
transition: color ease 0.2s;581
}583
&:hover {584
margin: -3px;585
width: calc(10% - @space-1x * 9 / 10 + 6px);587
.ico {588
color: @color-gray-900;589
}590
}592
@media(prefers-color-scheme: dark) {593
background: darken(@color-gray-900, 8%);595
.ico {596
color: @color-gray-500;597
}599
&:hover {601
.ico {602
color: @color-gray-200;603
}604
}605
}606
}607
}609
footer {610
margin-top: @space-4x;611
margin-bottom: @space-2x;613
@media(min-width: @screen-xs) {614
margin-top: @space-8x;615
margin-bottom: @space-4x;617
a {619
&:first-of-type {620
display: flex !important;621
}622
}623
}625
.container {626
display: flex;627
justify-content: flex-end;628
gap: @space-1x;629
}631
p {632
flex: 1;633
align-self: flex-start;634
color: @color-gray-700;635
margin: 0;636
}638
a {639
font-size: 16px;640
display: flex;641
align-items: center;643
&:first-of-type {644
display: none;645
}646
}648
@media(prefers-color-scheme: dark) {650
p {651
color: @color-gray-500;652
}654
a {655
color: @color-gray-500;657
&:hover {658
color: @color-gray-300;659
}660
}661
}662
}664
.tooltip {665
position: relative;667
&:hover {669
&::before,670
&::after {671
opacity: 1;672
transition-delay: 1s;673
}675
&::before {676
bottom: -13px;677
}679
&::after {680
bottom: -40px;681
}682
}684
&::before,685
&::after {686
opacity: 0;687
content: '';688
display: inline-block;689
position: absolute;690
user-select: none;691
pointer-events: none;692
transition: opacity ease 0.1s, bottom ease 0.1s;693
transition-delay: 0s;694
z-index: 2;695
left: 50%;696
transform: translate(-50%, 0);697
}699
&::before {700
border: 3px solid transparent;701
border-bottom: 3px solid @color-gray-900;702
bottom: -10px;703
}705
&::after {706
content: attr(data-title);707
background: @color-gray-900;708
font-size: 12px;709
color: @color-white;710
white-space: nowrap;711
padding: 6px 10px;712
padding-bottom: 7px;713
border-radius: 3px;714
bottom: -37px;715
height: 15px;716
min-width: 40px;717
text-align: center;718
font-weight: 400;719
}720
}722
.snackbar {723
background: @color-gray-900;724
position: fixed;725
left: 50%;726
bottom: 0;727
border-radius: 4px;728
color: @color-white;729
padding: 18px 30px;730
pointer-events: none;731
opacity: 0;732
transition: opacity ease 0.2s, bottom ease 0.2s;733
transform: translate(-50%, 0);734
white-space: nowrap;735
z-index: 99;737
&.active {738
opacity: 1;739
bottom: @space-1x;740
}742
@media(min-width: @screen-xs) {743
left: @space-2x;744
bottom: @space-1x;745
transform: none;747
&.active {748
bottom: @space-2x;749
}750
}751
}
1
<!DOCTYPE html>2
<html lang="en" dir="ltr">3
<head>4
<meta charset="utf-8">5
<meta name="viewport" content="width=device-width, initial-scale=1.0">6
<meta name="author" content="typable">7
<meta name="keywords" content="">8
<meta name="description" content="">9
<meta name="robots" content="noindex, nofollow">10
<meta name="google" content="notranslate">11
<title>git.typable</title>12
<link href="/asset/img/favicon.png" rel="shortcut icon" type="image/png">13
<link href="/asset/css/style.css" rel="stylesheet">14
<script src="/asset/js/index.js" type="module"></script>15
</head>16
<body>17
<main class="container-fluid">18
<div class="row">19
<div class="container">20
<ul class="breadcrumb">21
<li><a href="/">Home</a></li>22
<li>Blog</li>23
</ul>24
<h1>Blog</h1>25
<p class="subline">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>26
<div class="space-1"></div>27
<p class="link-list">28
<span>--> <a href="/blog/spring-framework">Spring Framework</a></span>29
<span>--> <a href="/blog/javascript-es6-features">JavaScript ES6 Features</a></span>30
</p>31
</div>32
</div>33
</main>34
<footer class="container-fluid">35
<div class="row">36
<div class="container">37
<p>© typable 2021</p>38
<a href="https://www.buymeacoffee.com/typable">Donate</a>39
<a href="https://typable.dev/imprint">Imprint</a>40
<a href="https://typable.dev/terms">Terms</a>41
</div>42
</div>43
</footer>44
</body>45
</html>
1
<!DOCTYPE html>2
<html lang="en" dir="ltr">3
<head>4
<meta charset="utf-8">5
<meta name="viewport" content="width=device-width, initial-scale=1.0">6
<meta name="author" content="typable">7
<meta name="keywords" content="">8
<meta name="description" content="">9
<meta name="robots" content="noindex, nofollow">10
<meta name="google" content="notranslate">11
<title>git.typable</title>12
<link href="/asset/img/favicon.png" rel="shortcut icon" type="image/png">13
<link href="/asset/css/style.css" rel="stylesheet">14
<script src="/asset/js/index.js" type="module"></script>15
</head>16
<body>17
<main class="container-fluid">18
<div class="row">19
<div class="container">20
<aside>21
<h4 data-rel="top">JavaScript ES6 Features</h4>22
<ul>23
<li data-rel="introduction">Introduction</li>24
<li data-rel="scoping">Scoping</li>25
<li data-rel="constants">Constants</li>26
<li data-rel="extended-parameter-handling">Extended Parameter Handling</li>27
<li data-rel="template-literals">Template Literals</li>28
<li data-rel="enhanced-object-properties">Enhanced Object Properties</li>29
<li data-rel="destructuring-assignment">Destructuring Assignment</li>30
<li data-rel="modules">Modules</li>31
<li data-rel="classes">Classes</li>32
<li data-rel="promises">Promises</li>33
<li data-rel="internationalization-localization">Internationalization & Localization</li>34
</ul>35
</aside>36
<ul class="breadcrumb">37
<li><a href="/">Home</a></li>38
<li><a href="/blog">Blog</a></li>39
<li>JavaScript ES6 Features</li>40
</ul>41
<h1>JavaScript ES6 Features</h1>42
<p class="subline">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>43
<h2 data-ref="introduction">Introduction</h2>44
<p class="subline">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>45
<p>Source: <a href="http://es6-features.org">ES6 Features</a></p>46
<h2 data-ref="scoping">Scoping</h2>47
<code><pre><span class="c">for</span>(<span class="c">let</span> <span class="n">item</span> <span class="c">of</span> <span class="n">document</span>.<span class="p">querySelectorAll</span>(<span class="s">'.item'</span>)) {48
<span class="n">item</span>.<span class="n">onclick</span> = <span class="c">function</span>() {49
<span class="n">console</span>.<span class="p">log</span>(<span class="s">'Index: '</span> + <span class="n">item</span>.<span class="n">dataset</span>.<span class="n">index</span>);50
}51
}</pre></code>52
<h2 data-ref="constants">Constants</h2>53
<code><pre><span class="c">const</span> <span class="n">id</span> = <span class="s">'cache.custom'</span>;</pre></code>54
<h2 data-ref="extended-parameter-handling">Extended Parameter Handling</h2>55
<h4>Default Parameter Values</h4>56
<code><pre><span class="c">function</span> <span class="n">f</span>(<span class="n">x</span> = <span class="n">5</span>, <span class="n">b</span> = <span class="c">true</span>) { ... }</pre></code>57
<div class="space-1"></div>58
<h4>Rest Parameter</h4>59
<code><pre><span class="c">function</span> <span class="n">f</span>(<span class="n">x</span>, <span class="n">y</span>, ...<span class="n">a</span>) { ... }</pre></code>60
<div class="space-1"></div>61
<h4>Spread Parameter</h4>62
<code><pre><span class="c">const</span> <span class="n">a</span> = [<span class="n">1</span>, <span class="n">2</span>, ...<span class="n">params</span>];</pre></code>63
<code><pre><span class="n">f</span>(...<span class="n">a</span>);</pre></code>64
<h2 data-ref="template-literals">Template Literals</h2>65
<h4>String Interpolation</h4>66
<code><pre><span class="c">const</span> <span class="n">s</span> = <span class="s">`Hello </span><span class="c">${</span><span class="n">user</span>.<span class="n">name</span><span class="c">}</span><span class="s">!`</span>;</pre></code>67
<div class="space-1"></div>68
<h4>Custom Interpolation</h4>69
<code><pre><span class="n">foo</span><span class="s">`Hello </span><span class="c">${</span><span class="n">user</span>.<span class="n">name</span><span class="c">}</span><span class="s">!`</span>;71
<span class="c">function</span> <span class="n">foo</span>(<span class="n">strings</span>, ...<span class="n">props</span>) {72
<span class="x">// Handle interpolation</span>73
}</pre></code>74
<h2 data-ref="enhanced-object-properties">Enhanced Object Properties</h2>75
<h4>Property Shorthand</h4>76
<code><pre><span class="c">const</span> <span class="n">x</span> = <span class="n">5</span>, <span class="n">y</span> = <span class="n">0</span>;77
<span class="c">const</span> <span class="n">p</span> = { <span class="n">x</span>, <span class="n">y</span> };</pre></code>78
<h2 data-ref="destructuring-assignment">Destructuring Assignment</h2>79
<h4>Array Matching</h4>80
<code><pre><span class="c">const</span> [<span class="n">a</span>, , <span class="n">c</span>] = [<span class="n">1</span>, <span class="n">2</span>, <span class="n">3</span>];</pre></code>81
<div class="space-1"></div>82
<h4>Object Matching & Deep Matching</h4>83
<code><pre><span class="c">const</span> { <span class="n">x</span>, <span class="n">y</span> } = { <span class="n">x</span>: <span class="n">5</span>, <span class="n">y</span>: <span class="n">0</span>, <span class="n">b</span>: <span class="c">false</span> };84
<span class="c">const</span> { <span class="n">event</span>: { <span class="n">type</span> }, <span class="n">b</span>: <span class="n">valid</span> } = { <span class="n">event</span>: { <span class="n">type</span>: <span class="s">'click'</span> }, <span class="n">b</span>: <span class="c">true</span> };</pre></code>85
<div class="space-1"></div>86
<h4>Parameter Context Matching</h4>87
<code><pre><span class="c">function</span> <span class="n">f</span>({ <span class="n">name</span>, <span class="n">email</span> }) { ... }</pre></code>88
<h2 data-ref="modules">Modules</h2>89
<h4>Value Export & Import</h4>90
<div class="space-1"></div>91
<h4>Default & Wildcard</h4>92
<h2 data-ref="classes">Classes</h2>93
<h4>Static Members</h4>94
<div class="space-1"></div>95
<h4>Getter & Setter</h4>96
<h2 data-ref="promises">Promises</h2>97
<h4>async & await</h4>98
<div class="space-1"></div>99
<h4>Promise Combination</h4>100
<h2 data-ref="internationalization-localization">Internationalization & Localization</h2>101
<h4>Number Formatting</h4>102
<div class="space-1"></div>103
<h4>Currency Formatting</h4>104
<div class="space-1"></div>105
<h4>Date & Time Formatting</h4>106
</div>107
</div>108
</main>109
<footer class="container-fluid">110
<div class="row">111
<div class="container">112
<p>© typable 2021</p>113
<a href="https://www.buymeacoffee.com/typable">Donate</a>114
<a href="https://typable.dev/imprint">Imprint</a>115
<a href="https://typable.dev/terms">Terms</a>116
</div>117
</div>118
</footer>119
</body>120
</html>
1
<!DOCTYPE html>2
<html lang="en" dir="ltr">3
<head>4
<meta charset="utf-8">5
<meta name="viewport" content="width=device-width, initial-scale=1.0">6
<meta name="author" content="typable">7
<meta name="keywords" content="">8
<meta name="description" content="">9
<meta name="robots" content="noindex, nofollow">10
<meta name="google" content="notranslate">11
<title>git.typable</title>12
<link href="/asset/img/favicon.png" rel="shortcut icon" type="image/png">13
<link href="/asset/css/style.css" rel="stylesheet">14
<script src="/asset/js/index.js" type="module"></script>15
</head>16
<body>17
<main class="container-fluid">18
<div class="row">19
<div class="container">20
<aside>21
<h4 data-rel="top">Spring Framework</h4>22
<ul>23
<li data-rel="requirements">Requirements</li>24
<li data-rel="getting-started">Getting Started</li>25
<li data-rel="configurations">Configurations</li>26
<li data-rel="start-up">Start Up</li>27
</ul>28
</aside>29
<ul class="breadcrumb">30
<li><a href="/">Home</a></li>31
<li><a href="/blog">Blog</a></li>32
<li>Spring Framework</li>33
</ul>34
<h1>Spring Framework</h1>35
<p class="subline">The following article is a short introduction to the basic setup of a new Spring36
Web Project. All required dependencies for this project are managed by a37
<a href="https://stackoverflow.com/a/19516639">Build Tool</a>, in this case,38
<a href="https://gradle.org">Gradle</a>.</p>39
<h2 data-ref="requirements">Requirements</h2>40
<h4>Install Eclipse Plugins</h4>41
<p>The listed Eclipse Plugins are needed to work on Spring projects smoothly. To check if they are42
already installed and if not how to install them, check out this article:43
<a href="">Eclipse - Install Plugins</a></p>44
<ul class="list">45
<li>46
<p>Spring Tools 4 - It provides the functionality to create and launch Spring projects.<br>47
<a href="https://marketplace.eclipse.org/content/spring-tools-4-aka-spring-tool-suite-4">Eclipse Marketplace</a></p>48
</li>49
<li>50
<p>Eclipse Web Developer Tools - Deliveres HTML, CSS and JS Editors.<br>51
<a href="https://marketplace.eclipse.org/content/eclipse-web-developer-tools-0">Eclipse Marketplace</a></p>52
</li>53
</ul>54
<div class="space-2"></div>55
<h4>Prepare Eclipse Workspace</h4>56
<ul class="list">57
<li>58
<p><b>File Association</b><br><br>"JSP and Tag files has the same Syntax as HTML", in this case, we can59
now associate the default HTML Editor (delivered by the Eclipse Web Developer Tools Plugin)60
also to the file types .jsp and .tag to let Eclipse now with which Editor these files61
should be opened.<br><br>More details about the association of file types could be found62
in this article: <a href="https://help.eclipse.org/2021-03/index.jsp">Eclipse - Manage File Associations</a></p>63
</li>64
<div class="space-1"></div>65
<li>66
<p><b>Perspective and Views</b><br><br>Web Projects are typically viewed in the Resource Perspective,67
so if the Perspective is not shown by default, add it to your Eclipse Workspace.<br><br>68
The needed views for a smooth working process are the following:<br><br>69
-> Project Explorer<br>70
-> Boot Dashboard<br>71
-> Console<br>72
-> Gradle Tasks<br><br>73
More about managing Perspectives and Views can be found here:74
<a href="https://help.eclipse.org/2021-03/index.jsp">Eclipse - Manage Perspectives and Views</a></p>75
</li>76
</ul>77
<h2 data-ref="getting-started">Getting Started</h2>78
<h4>Project Setup</h4>79
<p>To create a new Spring project in Eclipse we choose the project type <mark>Spring Starter Project</mark> under80
the category <mark>Spring Boot</mark>.</p>81
<p><b>File -> New -> Project... -> Spring Boot -> Spring Starter Project</b></p>82
<p>The following properties are required to set up our project correctly:</p>83
<ul class="list list-short">84
<li>85
<p><mark>Name</mark> - The name of your project.</p>86
</li>87
<li>88
<p><mark>Type</mark> - The Build Tool to use for the project. In our case, we use Gradle (Buildship 3.x).</p>89
</li>90
<li>91
<p><mark>Java Version</mark> - The Java Version for the project. The currently preferred Version is 11.</p>92
</li>93
<li>94
<p><mark>Group</mark> - Should be the same as the Package path.</p>95
</li>96
<li>97
<p><mark>Artifact</mark> - The name of your startup Java file.</p>98
</li>99
<li>100
<p><mark>Version</mark> - The version of your project.</p>101
</li>102
<li>103
<p><mark>Description</mark> - A short description of your project.</p>104
</li>105
<li>106
<p><mark>Package</mark> - The root package of your project.<br><br>107
<b class="note">Important:</b> <span>All Java files must be found in the defined root package108
or a subpackage of them, otherwise Spring is unable to locate these files.</span></p>109
</li>110
</ul>111
<p>Complete the setup wizard by skipping the choose of dependencies and click Finish. Now Eclipse112
prepares our Spring Project, this could take some time to build up all needed resources.</p>113
<p>Then this is done the worktree should now contain the following directories and files:</p>114
<code><pre><span class="p">Tutorial</span>115
├ <span class="p">src/main</span>116
| ├ <span class="p">java</span>117
| | â”” <span class="n">de.innovate.tutorial</span>118
| | â”” <span class="n">TutorialApplication.java</span>119
| â”” <span class="p">resources</span>120
| â”” <span class="n">application.properties</span>121
├ <span class="p">gradle</span>122
| └ ∙∙∙123
├ <span class="n">build.gradle</span>124
├ <span class="n">gradlew</span>125
├ <span class="n">gradlew.bat</span>126
├ <span class="n">HELP.md</span>127
â”” <span class="n">settings.gradle</span></pre></code>128
<p><b class="note">Notice:</b> <span>All <mark>test</mark> directories and files can be deleted.129
They aren't needed in our working process with Spring.</span></p>130
<div class="space-2"></div>131
<h4>Project Building</h4>132
<p>The basic workspace setup is completed and we can now define the essential dependencies for133
Spring Web. All required dependencies for our project should be referenced in the build.gradle134
file. For that replace the content of the <mark>/build.gradle</mark> file with the following code snippet:</p>135
<code><pre><span class="p">plugins</span> {136
<span class="n">id</span> <span class="s">'org.springframework.boot'</span> <span class="n">version</span> <span class="s">'2.2.0.RELEASE'</span>137
<span class="n">id</span> <span class="s">'io.spring.dependency-management'</span> <span class="n">version</span> <span class="s">'1.0.8.RELEASE'</span>138
<span class="n">id</span> <span class="s">'java'</span>139
}140
<span class="n">group</span> = <span class="s">'de.typable.tutorial'</span>141
<span class="n">version</span> = <span class="s">'0.0.1'</span>142
<span class="n">sourceCompatibility</span> = <span class="s">'11'</span>143
<span class="p">repositories</span> {144
<span class="n">mavenCentral</span>()145
}146
<span class="p">dependencies</span> {147
<span class="x">/* Spring Web */</span>148
<span class="n">implementation</span> <span class="s">'org.springframework.boot:spring-boot-starter-web'</span>149
<span class="x">/* JSP & JSTL */</span>150
<span class="n">implementation</span> <span class="s">'org.apache.tomcat.embed:tomcat-embed-jasper:9.0.27'</span>151
<span class="n">implementation</span> <span class="s">'javax.servlet:jstl:1.2'</span>152
}</pre></code>153
<p>We have now referenced the elementary dependencies for a Spring Web project. Additional could be154
added in the dependencies section. More about dependencies and where to find them could be found155
in this article: <a href="https://docs.gradle.org/current/userguide/core_dependency_management.html">Gradle - Dependencies</a></p>156
<p>The next step is to build the project with Gradle to download all in the build.gradle defined157
dependencies. To do that go to the Gradle Tasks View and double-click on build under the build158
section.</p>159
<p><b>Gradle Tasks -> [Project] -> build -> build</b></p>160
<p>During the building process, the current progress will be displayed in the Gradle Executions View161
and the Console View. The Gradle Executions View is in most cases needless because the Console162
gives us much clearer feedback about what's happening and what went wrong if the build crashes.163
To ensure the building process is successful the Console displays the message164
<mark>BUILD SUCCESSFUL</mark>.</p>165
<p><b class="note">Tip:</b> <span>Disabling the Gradle Executions View can be done as followed:166
<b>Window -> Preferences -> Gradle -> Show Executions View</b></span></p>167
<p>The building process is finished and this has affected our project worktree, because of that, we168
need to refresh our project. For that, we right-click on the project in the Package Explorer169
View and click on <mark>Refresh Gradle Project</mark> under the Gradle section. After that, our Spring project170
is up to date.</p>171
<p><b>Project Explorer -> [Project] -> Gradle -> Refresh Gradle Project</b></p>172
<h2 data-ref="configurations">Configurations</h2>173
<p>To optimize the project to our needs, we configure some properties in the174
<mark>application.properties</mark> file. This can also be done with XML. More information about175
XML configuration can be found here:176
<a href="https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html">Spring - XML Configurations</a></p>177
<p>Add the following properties to <mark>/src/main/resources/application.properties</mark>:</p>178
<code><pre><span class="p">server.port</span>=<span class="n">8080</span>179
<span class="p">spring.mvc.view.prefix</span>=<span class="n">/WEB-INF/views/</span>180
<span class="p">spring.mvc.view.suffix</span>=<span class="n">.jsp</span>181
<span class="x"># Reload static resources (Temporary)</span>182
<span class="p">spring.resources.static-locations</span>=<span class="n">file:src/main/resources/static/</span></pre></code>183
<p>Here a short explanation of the properties from above:</p>184
<ul class="list">185
<li>186
<p><mark>server.port</mark> - Defines which <a href="https://de.wikipedia.org/wiki/Port_(Protokoll)">Port</a>187
is used to listen for incoming requests by the Browser. The default ports are 80188
(http://) and 443 (https://).<br><br><b class="note">Example:</b> <span>80 -> http://localhost, 443 ->189
https://localhost, 8080 -> http://localhost:8080</span></p>190
</li>191
<li>192
<p><mark>spring.mvc.view.prefix</mark> - Defines in which directory the server should looking193
for them to be served HTML, JSP files. The default path is <mark>/WEB-INF/views/</mark>194
which represents <mark>/src/main/resources/META-INF/resources/WEB-INF/views/</mark>.</p>195
</li>196
<li>197
<p><mark>spring.mvc.view.suffix</mark> - Defines the file type for them to be served files.198
The default file type is are .jsp and .html.</p>199
</li>200
<li>201
<p><mark>spring.resources.static-locations</mark> - Files in the defined path can be modified202
without restarting the server to see the changes. It is common to put all resources like203
CSS, JavaScript and Images in <mark>/src/main/resources/static/</mark>.<br><br>204
<b class="note">Notice:</b> <span>This is a temporary property only for development</span></p>205
</li>206
</ul>207
<h2 data-ref="start-up">Start Up</h2>208
<p>Now it's at the time to launch our Spring Web server to confirm all is configured correctly.<br><br>To209
start the <a href="http://tomcat.apache.org">Apache Tomcat</a> server that provides the basic210
functionality of a web server which is integrated in our handy Spring Tools Plugin, we go to the211
<mark>Boot Dashboard</mark> View expand the <mark>local</mark> section and select the project212
with our predefined name and click on the "Start or restart" button at the top of the View.</p>213
<p>To confirm the server is started correctly the console should show up the message:214
<mark>Started TutorialApplication ...</mark></p>215
<p>Now the Spring Web server is available under the defined port and can be viewed in the Browser of216
your choice. The page should show the message <mark>Whitelabel Error Page</mark>, this means that217
no content is currently available.</p>218
<p>Now everything is ready to build your project.</p>219
</div>220
</div>221
</main>222
<footer class="container-fluid">223
<div class="row">224
<div class="container">225
<p>© typable 2021</p>226
<a href="https://www.buymeacoffee.com/typable">Donate</a>227
<a href="https://typable.dev/imprint">Imprint</a>228
<a href="https://typable.dev/terms">Terms</a>229
</div>230
</div>231
</footer>232
</body>233
</html>
1
<!DOCTYPE html>2
<html lang="en" dir="ltr">3
<head>4
<meta charset="utf-8">5
<meta name="viewport" content="width=device-width, initial-scale=1.0">6
<meta name="author" content="typable">7
<meta name="keywords" content="">8
<meta name="description" content="">9
<meta name="robots" content="noindex, nofollow">10
<meta name="google" content="notranslate">11
<title>git.typable</title>12
<link href="/asset/img/favicon.png" rel="shortcut icon" type="image/png">13
<link href="/asset/css/style.css" rel="stylesheet">14
<script src="/asset/js/index.js" type="module"></script>15
</head>16
<body>17
<main class="container-fluid">18
<div class="row">19
<div class="container">20
<aside>21
<h4 data-rel="top">Canvas Toolkit</h4>22
<ul>23
<li data-rel="scaling">Scaling</li>24
</ul>25
</aside>26
<ul class="breadcrumb">27
<li><a href="/">Home</a></li>28
<li>Canvas Toolkit</li>29
</ul>30
<h1>Canvas Toolkit</h1>31
<p class="subline">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>32
<h2 data-ref="scaling">Scaling</h2>33
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>34
<code><pre><span class="c">import</span> { <span class="n ref">scaleCanvas</span> } <span class="c">from</span> <span class="s">'<span class="ref ref-link">https://git.typable.dev/std/js/canvas.js</span>'</span>;36
<span class="p ref">scaleCanvas</span>(<span class="n">canvas</span>, <span class="n">900</span>, <span class="n">600</span>);</pre></code>37
</div>38
</div>39
</main>40
<footer class="container-fluid">41
<div class="row">42
<div class="container">43
<p>© typable 2021</p>44
<a href="https://www.buymeacoffee.com/typable">Donate</a>45
<a href="https://typable.dev/imprint">Imprint</a>46
<a href="https://typable.dev/terms">Terms</a>47
</div>48
</div>49
</footer>50
</body>51
</html>
1
import { Shape } from './shape.js';3
export function collideRect(a, b) {4
return a.x < b.x + b.shape.width && a.x + a.shape.width > b.x5
&& a.y < b.y + b.shape.height && a.y + a.shape.height > b.y;6
}8
export function collideCircle(a, b) {9
const dx = Math.abs(a.x - b.x);10
const dy = Math.abs(a.y - b.y);11
return Math.sqrt(dx ** 2 + dy ** 2) < a.shape.radius + b.shape.radius;12
}14
export function collideRectAndCircle(a, b) {15
const [rect, circle] = a instanceof Shape.Rect ? [a, b] : [b, a];16
let x = circle.x;17
let y = circle.y;18
if(circle.x < rect.x) {19
x = rect.x;20
}21
else if(circle.x > rect.x + rect.shape.width) {22
x = rect.x + rect.shape.width;23
}24
if(circle.y < rect.y) {25
y = rect.y;26
}27
else if(circle.y > rect.y + rect.shape.height) {28
y = rect.y + rect.shape.height;29
}30
const distance = Math.sqrt((circle.x - x) ** 2 + (circle.y - y) ** 2);31
return distance <= circle.shape.radius;32
}34
export function collidePoint(object, point) {35
if(object.shape instanceof Shape.Rect) {36
const {x, y, shape: {width, height}} = object;37
return x < point.x && x + width > point.x && y < point.y && y + height > point.y;38
}39
if(object.shape instanceof Shape.Circle) {40
const {x, y, shape: {radius}} = object;41
return Math.sqrt((x - point.x) ** 2 + (y - point.y) ** 2) < radius;42
}43
}
1
<!DOCTYPE html>2
<html lang="en" dir="ltr">3
<head>4
<meta charset="utf-8">5
<meta name="viewport" content="width=device-width, initial-scale=1.0">6
<meta name="author" content="typable">7
<meta name="keywords" content="">8
<meta name="description" content="">9
<meta name="robots" content="noindex, nofollow">10
<meta name="google" content="notranslate">11
<title>git.typable</title>12
<link href="/asset/img/favicon.png" rel="shortcut icon" type="image/png">13
<link href="/asset/css/style.css" rel="stylesheet">14
<script src="/asset/js/index.js" type="module"></script>15
</head>16
<body>17
<main class="container-fluid">18
<div class="row">19
<div class="container">20
<aside>21
<h4 data-rel="top">Component Rendering</h4>22
<ul>23
<li data-rel="template">Template</li>24
</ul>25
</aside>26
<ul class="breadcrumb">27
<li><a href="/">Home</a></li>28
<li>Component Rendering</li>29
</ul>30
<h1>Component Rendering</h1>31
<p class="subline">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>32
<h2 data-ref="template">Template</h2>33
<p>Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore.</p>34
<code><pre><span class="c">import</span> { <span class="n ref">html</span> } <span class="c">from</span> <span class="s">'<span class="ref ref-link">https://git.typable.dev/std/js/render.js</span>'</span>;36
<span class="c">const</span> <span class="n">Message</span> = <span class="n">props</span> => {37
<span class="c">return</span> <span class="p ref">html</span><span class="s">`<h1>Hello </span><span class="c">${</span><span class="n">props</span>.<span class="n">text</span><span class="c">}</span><span class="s"></h1>`</span>;38
};</pre></code>39
</div>40
</div>41
</main>42
<footer class="container-fluid">43
<div class="row">44
<div class="container">45
<p>© typable 2021</p>46
<a href="https://www.buymeacoffee.com/typable">Donate</a>47
<a href="https://typable.dev/imprint">Imprint</a>48
<a href="https://typable.dev/terms">Terms</a>49
</div>50
</div>51
</footer>52
</body>53
</html>
1
<!DOCTYPE html>2
<html lang="en" dir="ltr">3
<head>4
<meta charset="utf-8">5
<meta name="viewport" content="width=device-width, initial-scale=1.0">6
<meta name="author" content="typable">7
<meta name="keywords" content="">8
<meta name="description" content="">9
<meta name="robots" content="noindex, nofollow">10
<meta name="google" content="notranslate">11
<title>git.typable</title>12
<link href="/asset/img/favicon.png" rel="shortcut icon" type="image/png">13
<link href="/asset/css/style.css" rel="stylesheet">14
<script src="/asset/js/index.js" type="module"></script>15
</head>16
<body>17
<main class="container-fluid">18
<div class="row">19
<div class="container">20
<aside>21
<h4 data-rel="top">Color</h4>22
<ul>23
<li data-rel="material-colors">Material Colors</li>24
</ul>25
</aside>26
<ul class="breadcrumb">27
<li><a href="/">Home</a></li>28
<li><a href="/design-system">Design System</a></li>29
<li>Color</li>30
</ul>31
<h1>Color</h1>32
<p class="subline">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>33
<h2 data-ref="material-colors">Material Colors</h2>34
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>35
<code><pre><span class="c">@import</span> <span class="p">url</span>(<span class="s">'<span class="ref ref-link">https://git.typable.dev/std/less/color.less</span>'</span>);</pre></code>36
<ul class="palette-list">37
<li class="palette" data-type="red">38
<div class="palette-tone dark" style="background: #FFEBEE;">50</div>39
<div class="palette-tone dark" style="background: #FFCDD2;">100</div>40
<div class="palette-tone dark" style="background: #EF9A9A;">200</div>41
<div class="palette-tone dark" style="background: #E57373;">300</div>42
<div class="palette-tone dark" style="background: #EF5350;">400</div>43
<div class="palette-tone" style="background: #F44336;">500</div>44
<div class="palette-tone" style="background: #E53935;">600</div>45
<div class="palette-tone" style="background: #D32F2F;">700</div>46
<div class="palette-tone" style="background: #C62828;">800</div>47
<div class="palette-tone" style="background: #B71C1C;">900</div>48
</li>49
<li class="palette" data-type="pink">50
<div class="palette-tone dark" style="background: #FCE4EC;">50</div>51
<div class="palette-tone dark" style="background: #F8BBD0;">100</div>52
<div class="palette-tone dark" style="background: #F48FB1;">200</div>53
<div class="palette-tone dark" style="background: #F06292;">300</div>54
<div class="palette-tone dark" style="background: #EC407A;">400</div>55
<div class="palette-tone" style="background: #E91E63;">500</div>56
<div class="palette-tone" style="background: #D81B60;">600</div>57
<div class="palette-tone" style="background: #C2185B;">700</div>58
<div class="palette-tone" style="background: #AD1457;">800</div>59
<div class="palette-tone" style="background: #880E4F;">900</div>60
</li>61
<li class="palette" data-type="purple">62
<div class="palette-tone dark" style="background: #F3E5F5;">50</div>63
<div class="palette-tone dark" style="background: #E1BEE7;">100</div>64
<div class="palette-tone dark" style="background: #CE93D8;">200</div>65
<div class="palette-tone dark" style="background: #BA68C8;">300</div>66
<div class="palette-tone dark" style="background: #AB47BC;">400</div>67
<div class="palette-tone" style="background: #9C27B0;">500</div>68
<div class="palette-tone" style="background: #8E24AA;">600</div>69
<div class="palette-tone" style="background: #7B1FA2;">700</div>70
<div class="palette-tone" style="background: #6A1B9A;">800</div>71
<div class="palette-tone" style="background: #4A148C;">900</div>72
</li>73
<li class="palette" data-type="blue">74
<div class="palette-tone dark" style="background: #E3F2FD;">50</div>75
<div class="palette-tone dark" style="background: #BBDEFB;">100</div>76
<div class="palette-tone dark" style="background: #90CAF9;">200</div>77
<div class="palette-tone dark" style="background: #64B5F6;">300</div>78
<div class="palette-tone dark" style="background: #42A5F5;">400</div>79
<div class="palette-tone" style="background: #2196F3;">500</div>80
<div class="palette-tone" style="background: #1E88E5;">600</div>81
<div class="palette-tone" style="background: #1976D2;">700</div>82
<div class="palette-tone" style="background: #1565C0;">800</div>83
<div class="palette-tone" style="background: #0D47A1;">900</div>84
</li>85
<li class="palette" data-type="cyan">86
<div class="palette-tone dark" style="background: #E0F7FA;">50</div>87
<div class="palette-tone dark" style="background: #B2EBF2;">100</div>88
<div class="palette-tone dark" style="background: #80DEEA;">200</div>89
<div class="palette-tone dark" style="background: #4DD0E1;">300</div>90
<div class="palette-tone dark" style="background: #26C6DA;">400</div>91
<div class="palette-tone" style="background: #00BCD4;">500</div>92
<div class="palette-tone" style="background: #00ACC1;">600</div>93
<div class="palette-tone" style="background: #0097A7;">700</div>94
<div class="palette-tone" style="background: #00838F;">800</div>95
<div class="palette-tone" style="background: #006064;">900</div>96
</li>97
<li class="palette" data-type="teal">98
<div class="palette-tone dark" style="background: #E0F7FA;">50</div>99
<div class="palette-tone dark" style="background: #B2DFDB;">100</div>100
<div class="palette-tone dark" style="background: #80CBC4;">200</div>101
<div class="palette-tone dark" style="background: #4DB6AC;">300</div>102
<div class="palette-tone dark" style="background: #26A69A;">400</div>103
<div class="palette-tone" style="background: #009688;">500</div>104
<div class="palette-tone" style="background: #00897B;">600</div>105
<div class="palette-tone" style="background: #00796B;">700</div>106
<div class="palette-tone" style="background: #00695C;">800</div>107
<div class="palette-tone" style="background: #004D40;">900</div>108
</li>109
<li class="palette" data-type="green">110
<div class="palette-tone dark" style="background: #E8F5E9;">50</div>111
<div class="palette-tone dark" style="background: #C8E6C9;">100</div>112
<div class="palette-tone dark" style="background: #A5D6A7;">200</div>113
<div class="palette-tone dark" style="background: #81C784;">300</div>114
<div class="palette-tone dark" style="background: #66BB6A;">400</div>115
<div class="palette-tone" style="background: #4CAF50;">500</div>116
<div class="palette-tone" style="background: #43A047;">600</div>117
<div class="palette-tone" style="background: #388E3C;">700</div>118
<div class="palette-tone" style="background: #2E7D32;">800</div>119
<div class="palette-tone" style="background: #1B5E20;">900</div>120
</li>121
<li class="palette" data-type="lime">122
<div class="palette-tone dark" style="background: #F9FBE7;">50</div>123
<div class="palette-tone dark" style="background: #F0F4C3;">100</div>124
<div class="palette-tone dark" style="background: #E6EE9C;">200</div>125
<div class="palette-tone dark" style="background: #DCE775;">300</div>126
<div class="palette-tone dark" style="background: #D4E157;">400</div>127
<div class="palette-tone" style="background: #CDDC39;">500</div>128
<div class="palette-tone" style="background: #C0CA33;">600</div>129
<div class="palette-tone" style="background: #AFB42B;">700</div>130
<div class="palette-tone" style="background: #9E9D24;">800</div>131
<div class="palette-tone" style="background: #827717;">900</div>132
</li>133
<li class="palette" data-type="yellow">134
<div class="palette-tone dark" style="background: #FFFDE7;">50</div>135
<div class="palette-tone dark" style="background: #FFF9C4;">100</div>136
<div class="palette-tone dark" style="background: #FFF59D;">200</div>137
<div class="palette-tone dark" style="background: #FFF176;">300</div>138
<div class="palette-tone dark" style="background: #FFEE58;">400</div>139
<div class="palette-tone" style="background: #FFEB3B;">500</div>140
<div class="palette-tone" style="background: #FDD835;">600</div>141
<div class="palette-tone" style="background: #FBC02D;">700</div>142
<div class="palette-tone" style="background: #F9A825;">800</div>143
<div class="palette-tone" style="background: #F57F17;">900</div>144
</li>145
<li class="palette" data-type="orange">146
<div class="palette-tone dark" style="background: #FFF3E0;">50</div>147
<div class="palette-tone dark" style="background: #FFE0B2;">100</div>148
<div class="palette-tone dark" style="background: #FFCC80;">200</div>149
<div class="palette-tone dark" style="background: #FFB74D;">300</div>150
<div class="palette-tone dark" style="background: #FFA726;">400</div>151
<div class="palette-tone" style="background: #FF9800;">500</div>152
<div class="palette-tone" style="background: #FB8C00;">600</div>153
<div class="palette-tone" style="background: #F57C00;">700</div>154
<div class="palette-tone" style="background: #EF6C00;">800</div>155
<div class="palette-tone" style="background: #E65100;">900</div>156
</li>157
<li class="palette" data-type="brown">158
<div class="palette-tone dark" style="background: #EFEBE9;">50</div>159
<div class="palette-tone dark" style="background: #D7CCC8;">100</div>160
<div class="palette-tone dark" style="background: #BCAAA4;">200</div>161
<div class="palette-tone dark" style="background: #A1887F;">300</div>162
<div class="palette-tone dark" style="background: #8D6E63;">400</div>163
<div class="palette-tone" style="background: #795548;">500</div>164
<div class="palette-tone" style="background: #6D4C41;">600</div>165
<div class="palette-tone" style="background: #5D4037;">700</div>166
<div class="palette-tone" style="background: #4E342E;">800</div>167
<div class="palette-tone" style="background: #3E2723;">900</div>168
</li>169
<li class="palette" data-type="gray">170
<div class="palette-tone dark" style="background: #FAFAFA;">50</div>171
<div class="palette-tone dark" style="background: #F5F5F5;">100</div>172
<div class="palette-tone dark" style="background: #EEEEEE;">200</div>173
<div class="palette-tone dark" style="background: #E0E0E0;">300</div>174
<div class="palette-tone dark" style="background: #BDBDBD;">400</div>175
<div class="palette-tone" style="background: #9E9E9E;">500</div>176
<div class="palette-tone" style="background: #757575;">600</div>177
<div class="palette-tone" style="background: #616161;">700</div>178
<div class="palette-tone" style="background: #424242;">800</div>179
<div class="palette-tone" style="background: #212121;">900</div>180
</li>181
</ul>182
<p>Source: <a href="https://material.io/design/color/the-color-system.html">Material Colors - Google</a></p>183
</div>184
</div>185
</main>186
<footer class="container-fluid">187
<div class="row">188
<div class="container">189
<p>© typable 2021</p>190
<a href="https://www.buymeacoffee.com/typable">Donate</a>191
<a href="https://typable.dev/imprint">Imprint</a>192
<a href="https://typable.dev/terms">Terms</a>193
</div>194
</div>195
</footer>196
<div class="snackbar">Copied to clipboard</div>197
</body>198
</html>
1
<!DOCTYPE html>2
<html lang="en" dir="ltr">3
<head>4
<meta charset="utf-8">5
<meta name="viewport" content="width=device-width, initial-scale=1.0">6
<meta name="author" content="typable">7
<meta name="keywords" content="">8
<meta name="description" content="">9
<meta name="robots" content="noindex, nofollow">10
<meta name="google" content="notranslate">11
<title>git.typable</title>12
<link href="/asset/img/favicon.png" rel="shortcut icon" type="image/png">13
<link href="/asset/css/style.css" rel="stylesheet">14
<script src="/asset/js/index.js" type="module"></script>15
</head>16
<body>17
<main class="container-fluid">18
<div class="row">19
<div class="container">20
<aside>21
<h4 data-rel="top">Icons</h4>22
<ul>23
<li data-rel="material-icons">Material Icons</li>24
</ul>25
</aside>26
<ul class="breadcrumb">27
<li><a href="/">Home</a></li>28
<li><a href="/design-system">Design System</a></li>29
<li>Icons</li>30
</ul>31
<h1>Icons</h1>32
<p class="subline">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>33
<h2 data-ref="material-icons">Material Icons</h2>34
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>35
<code><pre><span class="c">@import</span> <span class="p">url</span>(<span class="s">'<span class="ref ref-link">https://git.typable.dev/std/less/icons.less</span>'</span>);</pre></code>36
<div class="space-2"></div>37
<ul class="icon-list">38
<li class="icon tooltip" data-title="Menu"><span class="ico">menu</span></li>39
<li class="icon tooltip" data-title="Close"><span class="ico">close</span></li>40
<li class="icon tooltip" data-title="Expand"><span class="ico">expand_more</span></li>41
<li class="icon tooltip" data-title="Minimize"><span class="ico">expand_less</span></li>42
<li class="icon tooltip" data-title="Before"><span class="ico">navigate_before</span></li>43
<li class="icon tooltip" data-title="Next"><span class="ico">navigate_next</span></li>44
<li class="icon tooltip" data-title="Back"><span class="ico">arrow_back</span></li>45
<li class="icon tooltip" data-title="Foward"><span class="ico">arrow_forward</span></li>46
<li class="icon tooltip" data-title="More"><span class="ico">more_horiz</span></li>47
<li class="icon tooltip" data-title="Refresh"><span class="ico">refresh</span></li>48
<li class="icon tooltip" data-title="Fullscreen"><span class="ico">fullscreen</span></li>49
<li class="icon tooltip" data-title="Exit Fullscreen"><span class="ico">fullscreen_exit</span></li>50
<li class="icon tooltip" data-title="Search"><span class="ico">search</span></li>51
<li class="icon tooltip" data-title="Done"><span class="ico">done</span></li>52
<li class="icon tooltip" data-title="Settings"><span class="ico">settings</span></li>53
<li class="icon tooltip" data-title="Favorite"><span class="ico">favorite_outline</span></li>54
<li class="icon tooltip" data-title="Delete"><span class="ico">delete_outline</span></li>55
<li class="icon tooltip" data-title="Language"><span class="ico">language</span></li>56
<li class="icon tooltip" data-title="Schedule"><span class="ico">schedule</span></li>57
<li class="icon tooltip" data-title="Event"><span class="ico">event</span></li>58
<li class="icon tooltip" data-title="Login"><span class="ico">login</span></li>59
<li class="icon tooltip" data-title="Logout"><span class="ico">logout</span></li>60
<li class="icon tooltip" data-title="Code"><span class="ico">code</span></li>61
<li class="icon tooltip" data-title="Print"><span class="ico">print</span></li>62
<li class="icon tooltip" data-title="Bookmkar"><span class="ico">bookmark_border</span></li>63
<li class="icon tooltip" data-title="Secure"><span class="ico">https</span></li>64
<li class="icon tooltip" data-title="Inbox"><span class="ico">inbox</span></li>65
<li class="icon tooltip" data-title="Add"><span class="ico">add</span></li>66
<li class="icon tooltip" data-title="Send"><span class="ico">send</span></li>67
<li class="icon tooltip" data-title="Link"><span class="ico">link</span></li>68
<li class="icon tooltip" data-title="Edit"><span class="ico">edit</span></li>69
<li class="icon tooltip" data-title="Pin"><span class="ico">push_pin</span></li>70
<li class="icon tooltip" data-title="Block"><span class="ico">block</span></li>71
<li class="icon tooltip" data-title="Undo"><span class="ico">undo</span></li>72
<li class="icon tooltip" data-title="Redo"><span class="ico">redo</span></li>73
<li class="icon tooltip" data-title="Gesture"><span class="ico">gesture</span></li>74
<li class="icon tooltip" data-title="Tag"><span class="ico">tag</span></li>75
<li class="icon tooltip" data-title="Payl"><span class="ico">play_arrow</span></li>76
<li class="icon tooltip" data-title="Pause"><span class="ico">pause</span></li>77
<li class="icon tooltip" data-title="Mic"><span class="ico">mic</span></li>78
<li class="icon tooltip" data-title="Star"><span class="ico">star</span></li>79
<li class="icon tooltip" data-title="Photo"><span class="ico">insert_photo</span></li>80
<li class="icon tooltip" data-title="Quote"><span class="ico">format_quote</span></li>81
<li class="icon tooltip" data-title="Chart"><span class="ico">pie_chart</span></li>82
<li class="icon tooltip" data-title="Size"><span class="ico">format_size</span></li>83
<li class="icon tooltip" data-title="Bold"><span class="ico">format_bold</span></li>84
<li class="icon tooltip" data-title="Italic"><span class="ico">format_italic</span></li>85
<li class="icon tooltip" data-title="Underline"><span class="ico">format_underlined</span></li>86
<li class="icon tooltip" data-title="Bubble"><span class="ico">bubble_chart</span></li>87
<li class="icon tooltip" data-title="Border Color"><span class="ico">border_color</span></li>88
<li class="icon tooltip" data-title="Fill Color"><span class="ico">format_color_fill</span></li>89
<li class="icon tooltip" data-title="Share"><span class="ico">share</span></li>90
<li class="icon tooltip" data-title="Public"><span class="ico">public</span></li>91
<li class="icon tooltip" data-title="Person"><span class="ico">person</span></li>92
<li class="icon tooltip" data-title="Group"><span class="ico">people</span></li>93
<li class="icon tooltip" data-title="Add Person"><span class="ico">person_add</span></li>94
<li class="icon tooltip" data-title="No Notification"><span class="ico">notifications_none</span></li>95
<li class="icon tooltip" data-title="Notification"><span class="ico">notifications</span></li>96
<li class="icon tooltip" data-title="Notification Active"><span class="ico">notifications_active</span></li>97
<li class="icon tooltip" data-title="Download"><span class="ico">file_download</span></li>98
<li class="icon tooltip" data-title="Upload"><span class="ico">file_upload</span></li>99
<li class="icon tooltip" data-title="Upload File"><span class="ico">upload_file</span></li>100
<li class="icon tooltip" data-title="Help"><span class="ico">lightbulb</span></li>101
<li class="icon tooltip" data-title="Credit Card"><span class="ico">credit_card</span></li>102
<li class="icon tooltip" data-title="Folder"><span class="ico">folder</span></li>103
<li class="icon tooltip" data-title="Cloud"><span class="ico">cloud</span></li>104
<li class="icon tooltip" data-title="Mail"><span class="ico">email</span></li>105
<li class="icon tooltip" data-title="Call"><span class="ico">call</span></li>106
<li class="icon tooltip" data-title="Chat"><span class="ico">chat_bubble</span></li>107
<li class="icon tooltip" data-title="Email"><span class="ico">alternate_email</span></li>108
</ul>109
<p>Source: <a href="https://fonts.google.com/icons">Material Icons - Google</a></p>110
</div>111
</div>112
</main>113
<footer class="container-fluid">114
<div class="row">115
<div class="container">116
<p>© typable 2021</p>117
<a href="https://www.buymeacoffee.com/typable">Donate</a>118
<a href="https://typable.dev/imprint">Imprint</a>119
<a href="https://typable.dev/terms">Terms</a>120
</div>121
</div>122
</footer>123
<div class="snackbar">Copied to clipboard</div>124
</body>125
</html>
1
<!DOCTYPE html>2
<html lang="en" dir="ltr">3
<head>4
<meta charset="utf-8">5
<meta name="viewport" content="width=device-width, initial-scale=1.0">6
<meta name="author" content="typable">7
<meta name="keywords" content="">8
<meta name="description" content="">9
<meta name="robots" content="noindex, nofollow">10
<meta name="google" content="notranslate">11
<title>git.typable</title>12
<link href="/asset/img/favicon.png" rel="shortcut icon" type="image/png">13
<link href="/asset/css/style.css" rel="stylesheet">14
<script src="/asset/js/index.js" type="module"></script>15
</head>16
<body>17
<main class="container-fluid">18
<div class="row">19
<div class="container">20
<aside>21
<h4 data-rel="top">Design System</h4>22
<ul>23
<li data-rel="introduction">Introduction</li>24
<li data-rel="normalize">Normalize</li>25
</ul>26
</aside>27
<ul class="breadcrumb">28
<li><a href="/">Home</a></li>29
<li>Design System</li>30
</ul>31
<h1>Design System</h1>32
<p class="subline">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>33
<h2 data-ref="introduction">Introduction</h2>34
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>35
<div class="space-1"></div>36
<p class="link-list">37
<span>--> <a href="/design-system/color">Color</a></span>38
<span>--> <a href="/design-system/icons">Icons</a></span>39
</p>40
<h2 data-ref="normalize">Normalize</h2>41
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>42
<code><pre><span class="c">@import</span> <span class="p">url</span>(<span class="s">'<span class="ref ref-link">https://git.typable.dev/std/less/normalize.less</span>'</span>);</pre></code>43
</div>44
</div>45
</main>46
<footer class="container-fluid">47
<div class="row">48
<div class="container">49
<p>© typable 2021</p>50
<a href="https://www.buymeacoffee.com/typable">Donate</a>51
<a href="https://typable.dev/imprint">Imprint</a>52
<a href="https://typable.dev/terms">Terms</a>53
</div>54
</div>55
</footer>56
</body>57
</html>
1
<!DOCTYPE html>2
<html lang="en" dir="ltr">3
<head>4
<meta charset="utf-8">5
<meta name="viewport" content="width=device-width, initial-scale=1.0">6
<meta name="author" content="typable">7
<meta name="keywords" content="">8
<meta name="description" content="">9
<meta name="robots" content="noindex, nofollow">10
<meta name="google" content="notranslate">11
<title>git.typable</title>12
<link href="/asset/img/favicon.png" rel="shortcut icon" type="image/png">13
<link href="/asset/css/style.css" rel="stylesheet">14
<script src="/asset/js/index.js" type="module"></script>15
</head>16
<body>17
<main class="container-fluid">18
<div class="row">19
<div class="container">20
<aside>21
<h4 data-rel="top">API</h4>22
<ul>23
<li data-rel="game">Game</li>24
<li data-rel="group">Group</li>25
<li data-rel="surface">Surface</li>26
<li data-rel="shape">Shape</li>27
<li data-rel="collision">Collision</li>28
</ul>29
</aside>30
<ul class="breadcrumb">31
<li><a href="/">Home</a></li>32
<li><a href="/game-engine">Game Engine</a></li>33
<li>API</li>34
</ul>35
<h1>API</h1>36
<p class="subline">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>37
<h2 data-ref="game">Game</h2>38
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>39
<code><pre><span class="c">import</span> { <span class="n">Game</span> } <span class="c">from</span> <span class="s">'<span class="ref ref-link">https://git.typable.dev/std/js/game.js</span>'</span>;</pre></code>40
<div class="space-2"></div>41
<h4>constructor(width, height)</h4>42
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>43
<h4>update()</h4>44
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>45
<h4>render(g)</h4>46
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>47
<h4>start()</h4>48
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>49
<h4>bindEvent(element, type)</h4>50
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>51
<h4>resize(width, height)</h4>52
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>53
<h2 data-ref="group">Group</h2>54
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>55
<code><pre><span class="c">import</span> { <span class="n">Group</span> } <span class="c">from</span> <span class="s">'<span class="ref ref-link">https://git.typable.dev/std/js/game.js</span>'</span>;</pre></code>56
<div class="space-2"></div>57
<h4>constructor()</h4>58
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>59
<h4>update()</h4>60
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>61
<h4>render(g)</h4>62
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>63
<h4>causeEvent(type, events)</h4>64
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>65
<h4>collide()</h4>66
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>67
<h4>add(surface)</h4>68
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>69
<h4>remove(surface)</h4>70
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>71
<h4>[Symbol.iterator]</h4>72
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>73
<h2 data-ref="surface">Surface</h2>74
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>75
<code><pre><span class="c">import</span> { <span class="n">Surface</span> } <span class="c">from</span> <span class="s">'<span class="ref ref-link">https://git.typable.dev/std/js/game.js</span>'</span>;</pre></code>76
<div class="space-2"></div>77
<h4>constructor(x, y, shape)</h4>78
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>79
<h4>update()</h4>80
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>81
<h4>render(g)</h4>82
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>83
<h4>causeEvent(type, events)</h4>84
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>85
<h2 data-ref="shape">Shape</h2>86
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>87
<code><pre><span class="c">import</span> { <span class="n">Shape</span> } <span class="c">from</span> <span class="s">'<span class="ref ref-link">https://git.typable.dev/std/js/game.js</span>'</span>;</pre></code>88
<div class="space-2"></div>89
<h3>Rect</h3>90
<h4>constructor(width, height)</h4>91
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>92
<div class="space-1"></div>93
<h3>Circle</h3>94
<h4>constructor(radius)</h4>95
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>96
<h2 data-ref="collision">Collision</h2>97
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>98
<code><pre><span class="c">import</span> <span class="n">*</span> <span class="c">as</span> <span class="n">Collision</span> <span class="c">from</span> <span class="s">'<span class="ref ref-link">https://git.typable.dev/std/js/collision.js</span>'</span>;</pre></code>99
<div class="space-2"></div>100
<h4>collideRect(rect, rect)</h4>101
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>102
<h4>collideCircle(circle, circle)</h4>103
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>104
<h4>collideRectAndCircle(rect, circle)</h4>105
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>106
<h4>collidePoint(shape, point)</h4>107
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>108
</div>109
</div>110
</main>111
<footer class="container-fluid">112
<div class="row">113
<div class="container">114
<p>© typable 2021</p>115
<a href="https://www.buymeacoffee.com/typable">Donate</a>116
<a href="https://typable.dev/imprint">Imprint</a>117
<a href="https://typable.dev/terms">Terms</a>118
</div>119
</div>120
</footer>121
</body>122
</html>
1
<!DOCTYPE html>2
<html lang="en" dir="ltr">3
<head>4
<meta charset="utf-8">5
<meta name="viewport" content="width=device-width, initial-scale=1.0">6
<meta name="author" content="typable">7
<meta name="keywords" content="">8
<meta name="description" content="">9
<meta name="robots" content="noindex, nofollow">10
<meta name="google" content="notranslate">11
<title>git.typable</title>12
<link href="/asset/img/favicon.png" rel="shortcut icon" type="image/png">13
<link href="/asset/css/style.css" rel="stylesheet">14
<script src="/asset/js/index.js" type="module"></script>15
</head>16
<body>17
<main class="container-fluid">18
<div class="row">19
<div class="container">20
<aside>21
<h4 data-rel="top">Game Engine</h4>22
<ul>23
<li data-rel="introduction">Introduction</li>24
<li data-rel="getting-started">Getting Started</li>25
<li data-rel="rendering">Rendering</li>26
<li data-rel="collision">Collision</li>27
<li data-rel="event-handling">Event Handling</li>28
</ul>29
</aside>30
<ul class="breadcrumb">31
<li><a href="/">Home</a></li>32
<li>Game Engine</li>33
</ul>34
<h1>Game Engine</h1>35
<p class="subline">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>36
<h2 data-ref="introduction">Introduction</h2>37
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<br><br>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>38
<div class="space-2"></div>39
<p class="link-list">40
<span>--> <a href="/game-engine/api">API</a></span>41
</p>42
<div class="embed">43
<iframe src="/asset/data/embed.html" frameborder="0"></iframe>44
<p>Source: <a href="https://jsitor.com/NooIssgCT">"Universe" - typable</a></p>45
</div>46
<h2 data-ref="getting-started">Getting Started</h2>47
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>48
<code><pre><span class="c">import</span> { <span class="n ref">Game</span> } <span class="c">from</span> <span class="s">'<span class="ref ref-link">https://git.typable.dev/std/js/game.js</span>'</span>;50
<span class="c">class</span> <span class="n">Sandbox</span> <span class="c">extends</span> <span class="n ref">Game</span> {51
<span class="p">constructor</span>() {52
<span class="c">super</span>(<span class="n">900</span>, <span class="n">600</span>);53
}54
}56
<span class="c">const</span> <span class="n">game</span> = <span class="c">new</span> <span class="n">Sandbox</span>();57
<span class="n">document</span>.<span class="n">body</span>.<span class="p">append</span>(<span class="n">game</span>.<span class="n ref">canvas</span>);58
<span class="n">game</span>.<span class="p ref">start</span>();</pre></code>59
<h2 data-ref="rendering">Rendering</h2>60
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>61
<code><pre><span class="c">import</span> { <span class="n ref">Surface</span>, <span class="n ref">Shape</span> } <span class="c">from</span> <span class="s">'<span class="ref ref-link">https://git.typable.dev/std/js/game.js</span>'</span>;63
<span class="c">class</span> <span class="n">Player</span> <span class="c">extends</span> <span class="n ref">Surface</span> {64
<span class="p">constructor</span>(<span class="n">x</span>, <span class="n">y</span>) {65
<span class="c">super</span>(<span class="n">x</span>, <span class="n">y</span>, <span class="c">new</span> <span class="n ref">Shape</span>.<span class="n ref">Circle</span>(<span class="n">50</span>));66
}67
<span class="p">render</span>(<span class="n">g</span>) {68
<span class="c">const</span> { <span class="n">x</span>, <span class="n">y</span>, <span class="n">shape</span>: { <span class="n">radius</span> } } = <span class="c">this</span>;69
<span class="n">g</span>.<span class="p">beginPath</span>();70
<span class="n">g</span>.<span class="p">arc</span>(<span class="n">x</span>, <span class="n">y</span>, <span class="n">radius</span>, <span class="n">2</span> * <span class="n">Math</span>.<span class="c">PI</span>, <span class="n">0</span>);71
<span class="n">g</span>.<span class="p">stroke</span>();72
}73
}</pre></code>74
<code><pre><span class="p">render</span>(<span class="n">g</span>) {75
<span class="c ref">super</span>.<span class="p">render</span>(<span class="n">g</span>);76
<span class="n">player</span>.<span class="p ref">render</span>(<span class="n">g</span>);77
}</pre></code>78
<h2 data-ref="collision">Collision</h2>79
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>80
<code><pre><span class="c">import</span> { <span class="n ref">Group</span> } <span class="c">from</span> <span class="s">'<span class="ref ref-link">https://git.typable.dev/std/js/game.js</span>'</span>;82
<span class="c">const</span> <span class="n">group</span> = <span class="c">new</span> <span class="n ref">Group</span>();83
<span class="n">group</span>.<span class="p ref">add</span>(...);</pre></code>84
<code><pre><span class="p">update</span>() {85
<span class="n">group</span>.<span class="p ref">collide</span>();86
<span class="n">group</span>.<span class="p ref">update</span>();87
}</pre></code>88
<code><pre><span class="p">update</span>() {89
<span class="c">const</span> { <span class="n ref">collided</span>, <span class="n ref">items</span> } = <span class="c ref">this</span>;90
<span class="c">if</span>(<span class="n">collided</span>) {91
<span class="x">// handle collision</span>92
}93
}</pre></code>94
<h2 data-ref="event-handling">Event Handling</h2>95
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>96
<code><pre><span class="c">this</span>.<span class="p ref">bindEvent</span>(<span class="c">this</span>.<span class="n">canvas</span>, <span class="s">'click'</span>);</pre></code>97
<code><pre><span class="n">surface</span>.<span class="p ref">causeEvent</span>(<span class="s">'click'</span>, <span class="c">this</span><span class="n">.events</span>);</pre></code>98
<code><pre><span class="p">onclick</span>(<span class="n">event</span>) {99
<span class="x">// handle click</span>100
}</pre></code>101
</div>102
</div>103
</main>104
<footer class="container-fluid">105
<div class="row">106
<div class="container">107
<p>© typable 2021</p>108
<a href="https://www.buymeacoffee.com/typable">Donate</a>109
<a href="https://typable.dev/imprint">Imprint</a>110
<a href="https://typable.dev/terms">Terms</a>111
</div>112
</div>113
</footer>114
</body>115
</html>
1
import { scaleCanvas } from './util.js';3
export class Game {4
constructor(width, height, { fps } = {}) {5
this.width = width || 900;6
this.height = height || 600;7
this.fps = 1000 / (fps || 60);8
this.then = Date.now();9
this.canvas = document.createElement('canvas');10
scaleCanvas(this.canvas, this.width, this.height);11
this.g = this.canvas.getContext('2d');12
this.events = [];13
}14
start() {15
requestAnimationFrame(this.loop.bind(this));16
this.update();17
this.render(this.g);18
}19
loop() {20
requestAnimationFrame(this.loop.bind(this));21
this.now = Date.now();22
this.elapsed = this.now - this.then;23
if(this.elapsed > this.fps) {24
this.then = this.now - (this.elapsed % this.fps);25
for(const event of this.events) {26
if(this['on' + event.type]) {27
this['on' + event.type](event);28
}29
}30
this.update();31
this.render(this.g);32
this.events.length = 0;33
}34
}35
update() {36
// nothing37
}38
render() {39
this.g.clearRect(0, 0, this.width, this.height);40
}41
resize(width, height) {42
this.width = width;43
this.height = height;44
scaleCanvas(this.canvas, this.width, this.height);45
}46
bindEvent(element, type) {47
element['on' + type] = event => this.events.push(event);48
}49
}
1
export class Group {2
constructor() {3
this.items = [];4
}5
update() {6
for(const item of this.items) {7
item.update();8
}9
}10
render(g) {11
for(const item of this.items) {12
item.render(g);13
}14
}15
causeEvent(type, events) {16
for(const item of this.items) {17
item.causeEvent(type, events);18
}19
}20
collide() {21
for(const i of this.items) {22
i.items = [];23
i.collided = false;24
}25
const duplicate = [];26
for(const a of this.items) {27
for(const b of this.items) {28
if(!duplicate.includes(b)) {29
if(a !== b) {30
let collided = false;31
if(a.shape instanceof Shape.Rect && b.shape instanceof Shape.Rect) {32
collided = Collision.collideRect(a, b);33
}34
else if(a.shape instanceof Shape.Circle && b.shape instanceof Shape.Circle) {35
collided = Collision.collideCircle(a, b);36
}37
else {38
collided = Collision.collideRectAndCircle(a, b);39
}40
if(!a.collided) {41
a.collided = collided;42
}43
if(!b.collided) {44
b.collided = collided;45
}46
if(collided) {47
if(!a.items.includes(b)) {48
a.items.push(b);49
}50
if(!b.items.includes(a)) {51
b.items.push(a);52
}53
}54
}55
}56
}57
duplicate.push(a);58
}59
}60
add(item) {61
this.items.push(item);62
}63
remove(item) {64
const i = this.items.findIndex(n => n === item);65
if(i !== -1) {66
this.items.splice(i, 1);67
}68
}69
[Symbol.iterator]() {70
return this.items.values();71
}72
}
1
<!DOCTYPE html>2
<html lang="en" dir="ltr">3
<head>4
<meta charset="utf-8">5
<meta name="viewport" content="width=device-width, initial-scale=1.0">6
<meta name="author" content="typable">7
<meta name="keywords" content="">8
<meta name="description" content="">9
<meta name="robots" content="noindex, nofollow">10
<meta name="google" content="notranslate">11
<title>git.typable</title>12
<link href="/asset/img/favicon.png" rel="shortcut icon" type="image/png">13
<link href="/asset/css/style.css" rel="stylesheet">14
<script src="/asset/js/index.js" type="module"></script>15
</head>16
<body>17
<main class="container-fluid">18
<div class="row">19
<div class="container">20
<ul class="breadcrumb">21
<li>Home</li>22
</ul>23
<h1 class="slogan">Build for the<br>web of tomorrow</h1>24
<p class="slogan-subline subline">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>25
<p class="link-list">26
<span>--> <a href="/design-system">Design System</a></span>27
<span>--> <a href="/game-engine">Game Engine</a></span>28
<span>--> <a href="/component-rendering">Component Rendering</a></span>29
<span>--> <a href="/canvas-toolkit">Canvas Toolkit</a></span>30
<span>--> <a href="/blog">Blog</a></span>31
</p>32
</div>33
</div>34
</main>35
<footer class="container-fluid">36
<div class="row">37
<div class="container">38
<p>© typable 2021</p>39
<a href="https://www.buymeacoffee.com/typable">Donate</a>40
<a href="https://typable.dev/imprint">Imprint</a>41
<a href="https://typable.dev/terms">Terms</a>42
</div>43
</div>44
</footer>45
</body>46
</html>
1
export * from './game.js';2
export * from './group.js';3
export * from './surface.js';4
export * from './shape.js';5
export * from './collision.js';
1
class Rect {2
constructor(width, height) {3
this.width = width;4
this.height = height;5
}6
}8
class Circle {9
constructor(radius) {10
this.radius = radius;11
}12
}14
export const Shape = { Rect, Circle };14
\ No newline at end of file
1
const DEVICE_PIXEL_RATIO = window.devicePixelRatio || 1;3
export function scaleCanvas(canvas, width, height) {4
const g = canvas.getContext('2d');5
const backingStoreRatio = g.webkitBackingStorePixelRatio || 1;6
const ratio = DEVICE_PIXEL_RATIO / backingStoreRatio;7
if(DEVICE_PIXEL_RATIO != backingStoreRatio) {8
canvas.width = width * ratio;9
canvas.height = height * ratio;10
canvas.style.width = width + 'px';11
canvas.style.height = height + 'px';12
}13
else {14
canvas.width = width;15
canvas.height = height;16
canvas.style.width = '';17
canvas.style.height = '';18
}19
g.scale(ratio, ratio);20
}
1
import { Shape } from './game.js';3
export function collideRect(a, b) {4
return a.x < b.x + b.shape.width && a.x + a.shape.width > b.x5
&& a.y < b.y + b.shape.height && a.y + a.shape.height > b.y;6
}8
export function collideCircle(a, b) {9
const dx = Math.abs(a.x - b.x);10
const dy = Math.abs(a.y - b.y);11
return Math.sqrt(dx ** 2 + dy ** 2) < a.shape.radius + b.shape.radius;12
}14
export function collideRectAndCircle(a, b) {15
const [rect, circle] = a instanceof Shape.Rect ? [a, b] : [b, a];16
let x = circle.x;17
let y = circle.y;18
if(circle.x < rect.x) {19
x = rect.x;20
}21
else if(circle.x > rect.x + rect.shape.width) {22
x = rect.x + rect.shape.width;23
}24
if(circle.y < rect.y) {25
y = rect.y;26
}27
else if(circle.y > rect.y + rect.shape.height) {28
y = rect.y + rect.shape.height;29
}30
const distance = Math.sqrt((circle.x - x) ** 2 + (circle.y - y) ** 2);31
return distance <= circle.shape.radius;32
}34
export function collidePoint(object, point) {35
if(object.shape instanceof Shape.Rect) {36
const {x, y, shape: {width, height}} = object;37
return x < point.x && x + width > point.x && y < point.y && y + height > point.y;38
}39
if(object.shape instanceof Shape.Circle) {40
const {x, y, shape: {radius}} = object;41
return Math.sqrt((x - point.x) ** 2 + (y - point.y) ** 2) < radius;42
}43
}
1
import { scaleCanvas } from './canvas.js';2
import * as Collision from './collision.js';4
export class Game {5
constructor(width, height, { fps } = {}) {6
this.width = width || 900;7
this.height = height || 600;8
this.fps = 1000 / (fps || 60);9
this.then = Date.now();10
this.canvas = document.createElement('canvas');11
scaleCanvas(this.canvas, this.width, this.height);12
this.g = this.canvas.getContext('2d');13
this.events = [];14
}15
start() {16
requestAnimationFrame(this.loop.bind(this));17
this.update();18
this.render(this.g);19
}20
loop() {21
requestAnimationFrame(this.loop.bind(this));22
this.now = Date.now();23
this.elapsed = this.now - this.then;24
if(this.elapsed > this.fps) {25
this.then = this.now - (this.elapsed % this.fps);26
for(const event of this.events) {27
if(this['on' + event.type]) {28
this['on' + event.type](event);29
}30
}31
this.update();32
this.render(this.g);33
this.events.length = 0;34
}35
}36
update() {37
// nothing38
}39
render() {40
this.g.clearRect(0, 0, this.width, this.height);41
}42
resize(width, height) {43
this.width = width;44
this.height = height;45
scaleCanvas(this.canvas, this.width, this.height);46
}47
bindEvent(element, type) {48
element['on' + type] = event => this.events.push(event);49
}50
}52
export class Group {53
constructor() {54
this.items = [];55
}56
update() {57
for(let item of this.items) {58
item.update();59
}60
}61
render(g) {62
for(let item of this.items) {63
item.render(g);64
}65
}66
causeEvent(type, events) {67
for(let item of this.items) {68
item.causeEvent(type, events);69
}70
}71
collide() {72
for(const i of this.items) {73
i.items = [];74
i.collided = false;75
}76
const duplicate = [];77
for(const a of this.items) {78
for(const b of this.items) {79
if(!duplicate.includes(b)) {80
if(a !== b) {81
let collided = false;82
if(a.shape instanceof Shape.Rect && b.shape instanceof Shape.Rect) {83
collided = Collision.collideRect(a, b);84
}85
else if(a.shape instanceof Shape.Circle && b.shape instanceof Shape.Circle) {86
collided = Collision.collideCircle(a, b);87
}88
else {89
collided = Collision.collideRectAndCircle(a, b);90
}91
if(!a.collided) {92
a.collided = collided;93
}94
if(!b.collided) {95
b.collided = collided;96
}97
if(collided) {98
if(!a.items.includes(b)) {99
a.items.push(b);100
}101
if(!b.items.includes(a)) {102
b.items.push(a);103
}104
}105
}106
}107
}108
duplicate.push(a);109
}110
}111
add(item) {112
this.items.push(item);113
}114
remove(item) {115
const i = this.items.findIndex(n => n === item);116
if(i !== -1) {117
this.items.splice(i, 1);118
}119
}120
[Symbol.iterator]() {121
return this.items.values();122
}123
}125
export class Surface {126
constructor(x, y, shape) {127
this.x = x;128
this.y = y;129
this.shape = shape;130
}131
update() {132
// nothing133
}134
render(g) {135
if(this.shape instanceof Shape.Rect) {136
g.beginPath();137
g.rect(this.x, this.y, this.shape.width, this.shape.height);138
g.stroke();139
}140
if(this.shape instanceof Shape.Circle) {141
g.beginPath();142
g.arc(this.x, this.y, this.shape.radius, 2 * Math.PI, 0);143
g.stroke();144
}145
}146
causeEvent(type, events) {147
if(this['on' + type]) {148
for(const event of events) {149
if(event.type === type) {150
this['on' + type](event);151
}152
}153
}154
}155
}157
class Rect {158
constructor(width, height) {159
this.width = width;160
this.height = height;161
}162
}164
class Circle {165
constructor(radius) {166
this.radius = radius;167
}168
}170
export const Shape = { Rect, Circle };170
\ No newline at end of file
1
export function html(strings, ...props) {2
try {3
let code = '';4
let events = [];5
let children = [];6
for(let i = 0; i < strings.length; i++) {7
code += strings[i];8
if(i < props.length) {9
if(typeof props[i] === 'function') {10
const exp = new RegExp(/on(\w+)=/, 'g');11
const match = exp.exec(strings[i]);12
if(match) {13
const [, type] = match;14
code = code.slice(0, -(type.length + 3));15
code += `data-event-ref-${events.length}`;16
events.push({ type, handler: props[i] });17
}18
continue;19
}20
if(props[i] instanceof Array) {21
for(const item of props[i]) {22
if(item instanceof HTMLElement) {23
const tag = item.tagName.toLowerCase();24
code += `<${tag} data-child-ref-${children.length}></${tag}>`;25
children.push(item);26
continue;27
}28
code += item;29
}30
continue;31
}32
if(props[i] instanceof HTMLElement) {33
const tag = props[i].tagName.toLowerCase();34
code += `<${tag} data-child-ref-${children.length}></${tag}>`;35
children.push(props[i]);36
continue;37
}38
code += props[i];39
}40
}41
const template = document.createElement('template');42
template.innerHTML = code;43
const fragment = template.content.cloneNode(true);44
const element = fragment.firstElementChild;45
for(const [id, {type, handler}] of Object.entries(events)) {46
let target;47
if(element.hasAttribute(`data-event-ref-${id}`)) {48
target = element;49
}50
else {51
target = element.querySelector(`[data-event-ref-${id}]`);52
}53
if(target) {54
target.addEventListener(type, handler);55
target.removeAttribute(`data-event-ref-${id}`);56
}57
else {58
console.warn(`Unable to bind ${type} event to element with id: ${id}`);59
}60
}61
for(const [id, child] of Object.entries(children)) {62
const target = element.querySelector(`[data-child-ref-${id}]`);63
if(target) {64
target.replaceWith(child);65
}66
else {67
console.warn(`Unable to reference <${child.tagName.toLowerCase()}> tag with id: ${id}`);68
}69
}70
return element;71
}72
catch(error) {73
console.error(error);74
}75
}77
export function escape(string) {78
return string.replace(/&/g, '&')79
.replace(/</g, '<')80
.replace(/>/g, '>')81
.replace(/"/g, '"')82
.replace(/'/g, ''');83
}83
\ No newline at end of file
1
@color-red-50: #FFEBEE;2
@color-red-100: #FFCDD2;3
@color-red-200: #EF9A9A;4
@color-red-300: #E57373;5
@color-red-400: #EF5350;6
@color-red-500: #F44336;7
@color-red-600: #E53935;8
@color-red-700: #D32F2F;9
@color-red-800: #C62828;10
@color-red-900: #B71C1C;12
@color-pink-50: #FCE4EC;13
@color-pink-100: #F8BBD0;14
@color-pink-200: #F48FB1;15
@color-pink-300: #F06292;16
@color-pink-400: #EC407A;17
@color-pink-500: #E91E63;18
@color-pink-600: #D81B60;19
@color-pink-700: #C2185B;20
@color-pink-800: #AD1457;21
@color-pink-900: #880E4F;23
@color-purple-50: #F3E5F5;24
@color-purple-100: #E1BEE7;25
@color-purple-200: #CE93D8;26
@color-purple-300: #BA68C8;27
@color-purple-400: #AB47BC;28
@color-purple-500: #9C27B0;29
@color-purple-600: #8E24AA;30
@color-purple-700: #7B1FA2;31
@color-purple-800: #6A1B9A;32
@color-purple-900: #4A148C;34
@color-blue-50: #E3F2FD;35
@color-blue-100: #BBDEFB;36
@color-blue-200: #90CAF9;37
@color-blue-300: #64B5F6;38
@color-blue-400: #42A5F5;39
@color-blue-500: #2196F3;40
@color-blue-600: #1E88E5;41
@color-blue-700: #1976D2;42
@color-blue-800: #1565C0;43
@color-blue-900: #0D47A1;45
@color-cyan-50: #E0F7FA;46
@color-cyan-100: #B2EBF2;47
@color-cyan-200: #80DEEA;48
@color-cyan-300: #4DD0E1;49
@color-cyan-400: #26C6DA;50
@color-cyan-500: #00BCD4;51
@color-cyan-600: #00ACC1;52
@color-cyan-700: #0097A7;53
@color-cyan-800: #00838F;54
@color-cyan-900: #006064;56
@color-teal-50: #E0F2F1;57
@color-teal-100: #B2DFDB;58
@color-teal-200: #80CBC4;59
@color-teal-300: #4DB6AC;60
@color-teal-400: #26A69A;61
@color-teal-500: #009688;62
@color-teal-600: #00897B;63
@color-teal-700: #00796B;64
@color-teal-800: #00695C;65
@color-teal-900: #004D40;67
@color-green-50: #E8F5E9;68
@color-green-100: #C8E6C9;69
@color-green-200: #A5D6A7;70
@color-green-300: #81C784;71
@color-green-400: #66BB6A;72
@color-green-500: #4CAF50;73
@color-green-600: #43A047;74
@color-green-700: #388E3C;75
@color-green-800: #2E7D32;76
@color-green-900: #1B5E20;78
@color-lime-50: #F9FBE7;79
@color-lime-100: #F0F4C3;80
@color-lime-200: #E6EE9C;81
@color-lime-300: #DCE775;82
@color-lime-400: #D4E157;83
@color-lime-500: #CDDC39;84
@color-lime-600: #C0CA33;85
@color-lime-700: #AFB42B;86
@color-lime-800: #9E9D24;87
@color-lime-900: #827717;89
@color-yellow-50: #FFFDE7;90
@color-yellow-100: #FFF9C4;91
@color-yellow-200: #FFF59D;92
@color-yellow-300: #FFF176;93
@color-yellow-400: #FFEE58;94
@color-yellow-500: #FFEB3B;95
@color-yellow-600: #FDD835;96
@color-yellow-700: #FBC02D;97
@color-yellow-800: #F9A825;98
@color-yellow-900: #F57F17;100
@color-orange-50: #FFF3E0;101
@color-orange-100: #FFE0B2;102
@color-orange-200: #FFCC80;103
@color-orange-300: #FFB74D;104
@color-orange-400: #FFA726;105
@color-orange-500: #FF9800;106
@color-orange-600: #FB8C00;107
@color-orange-700: #F57C00;108
@color-orange-800: #EF6C00;109
@color-orange-900: #E65100;111
@color-brown-50: #EFEBE9;112
@color-brown-100: #D7CCC8;113
@color-brown-200: #BCAAA4;114
@color-brown-300: #A1887F;115
@color-brown-400: #8D6E63;116
@color-brown-500: #795548;117
@color-brown-600: #6D4C41;118
@color-brown-700: #5D4037;119
@color-brown-800: #4E342E;120
@color-brown-900: #3E2723;122
@color-gray-50: #FAFAFA;123
@color-gray-100: #F5F5F5;124
@color-gray-200: #EEEEEE;125
@color-gray-300: #E0E0E0;126
@color-gray-400: #BDBDBD;127
@color-gray-500: #9E9E9E;128
@color-gray-600: #757575;129
@color-gray-700: #616161;130
@color-gray-800: #424242;131
@color-gray-900: #212121;133
@color-black: #000000;134
@color-white: #FFFFFF;134
\ No newline at end of file
1
@import url('https://fonts.googleapis.com/icon?family=Material+Icons');3
.ico {4
font-family: 'Material Icons';5
font-weight: normal;6
font-style: normal;7
font-size: 24px;8
display: inline-block;9
line-height: 1;10
text-transform: none;11
letter-spacing: normal;12
word-wrap: normal;13
white-space: nowrap;14
direction: ltr;15
-webkit-font-smoothing: antialiased;16
text-rendering: optimizeLegibility;17
-moz-osx-font-smoothing: grayscale;18
font-feature-settings: 'liga';19
user-select: none;20
}20
\ No newline at end of file
1
* {2
margin: 0;3
padding: 0;4
font-family: sans-serif;5
box-sizing: border-box;7
&:hover,8
&:focus {9
outline: none;10
}11
}13
html {14
position: relative;15
overflow-x: hidden;16
min-height: 100vh;17
}19
body {20
width: 100%;21
font-size: 14px;22
min-height: 100vh;23
}25
img {26
pointer-events: none;27
user-select: none;28
}30
button,31
input[type="submit"] {32
user-select: none;33
cursor: pointer;34
}36
.hidden {37
display: none !important;38
}40
.col {41
padding-left: @gap;42
padding-right: @gap;43
}45
.container {46
.col;47
margin: 0 auto;48
max-width: @full-width;49
}51
.container-fluid {52
.col;53
width: 100%;54
}56
.row {57
margin-left: -@gap;58
margin-right: -@gap;59
}59
\ No newline at end of file
1
export class Surface {2
constructor(x, y, shape) {3
this.x = x;4
this.y = y;5
this.shape = shape;6
}7
update() {8
// nothing9
}10
render(g) {11
if(this.shape instanceof Shape.Rect) {12
g.beginPath();13
g.rect(this.x, this.y, this.shape.width, this.shape.height);14
g.stroke();15
}16
if(this.shape instanceof Shape.Circle) {17
g.beginPath();18
g.arc(this.x, this.y, this.shape.radius, 2 * Math.PI, 0);19
g.stroke();20
}21
}22
causeEvent(type, events) {23
if(this['on' + type]) {24
for(const event of events) {25
if(event.type === type) {26
this['on' + type](event);27
}28
}29
}30
}31
}31
\ No newline at end of file
1
const DEVICE_PIXEL_RATIO = window.devicePixelRatio || 1;3
export function scaleCanvas(canvas, width, height) {4
const g = canvas.getContext('2d');5
const backingStoreRatio = g.webkitBackingStorePixelRatio || 1;6
const ratio = DEVICE_PIXEL_RATIO / backingStoreRatio;7
if(DEVICE_PIXEL_RATIO != backingStoreRatio) {8
canvas.width = width * ratio;9
canvas.height = height * ratio;10
canvas.style.width = width + 'px';11
canvas.style.height = height + 'px';12
}13
else {14
canvas.width = width;15
canvas.height = height;16
canvas.style.width = '';17
canvas.style.height = '';18
}19
g.scale(ratio, ratio);20
}
1
import { Shape } from './game.js';3
export function collideRect(a, b) {4
return a.x < b.x + b.shape.width && a.x + a.shape.width > b.x5
&& a.y < b.y + b.shape.height && a.y + a.shape.height > b.y;6
}8
export function collideCircle(a, b) {9
const dx = Math.abs(a.x - b.x);10
const dy = Math.abs(a.y - b.y);11
return Math.sqrt(dx ** 2 + dy ** 2) < a.shape.radius + b.shape.radius;12
}14
export function collideRectAndCircle(a, b) {15
const [rect, circle] = a instanceof Shape.Rect ? [a, b] : [b, a];16
let x = circle.x;17
let y = circle.y;18
if(circle.x < rect.x) {19
x = rect.x;20
}21
else if(circle.x > rect.x + rect.shape.width) {22
x = rect.x + rect.shape.width;23
}24
if(circle.y < rect.y) {25
y = rect.y;26
}27
else if(circle.y > rect.y + rect.shape.height) {28
y = rect.y + rect.shape.height;29
}30
const distance = Math.sqrt((circle.x - x) ** 2 + (circle.y - y) ** 2);31
return distance <= circle.shape.radius;32
}34
export function collidePoint(object, point) {35
if(object.shape instanceof Shape.Rect) {36
const {x, y, shape: {width, height}} = object;37
return x < point.x && x + width > point.x && y < point.y && y + height > point.y;38
}39
if(object.shape instanceof Shape.Circle) {40
const {x, y, shape: {radius}} = object;41
return Math.sqrt((x - point.x) ** 2 + (y - point.y) ** 2) < radius;42
}43
}
1
import { scaleCanvas } from './canvas.js';2
import * as Collision from './collision.js';4
export class Game {5
constructor(width, height, { fps } = {}) {6
this.width = width || 900;7
this.height = height || 600;8
this.fps = 1000 / (fps || 60);9
this.then = Date.now();10
this.canvas = document.createElement('canvas');11
scaleCanvas(this.canvas, this.width, this.height);12
this.g = this.canvas.getContext('2d');13
this.events = [];14
}15
start() {16
requestAnimationFrame(this.loop.bind(this));17
this.update();18
this.render(this.g);19
}20
loop() {21
requestAnimationFrame(this.loop.bind(this));22
this.now = Date.now();23
this.elapsed = this.now - this.then;24
if(this.elapsed > this.fps) {25
this.then = this.now - (this.elapsed % this.fps);26
for(const event of this.events) {27
if(this['on' + event.type]) {28
this['on' + event.type](event);29
}30
}31
this.update();32
this.render(this.g);33
this.events.length = 0;34
}35
}36
update() {37
// nothing38
}39
render() {40
this.g.clearRect(0, 0, this.width, this.height);41
}42
resize(width, height) {43
this.width = width;44
this.height = height;45
scaleCanvas(this.canvas, this.width, this.height);46
}47
bindEvent(element, type) {48
element['on' + type] = event => this.events.push(event);49
}50
}52
export class Group {53
constructor() {54
this.items = [];55
}56
update() {57
for(let item of this.items) {58
item.update();59
}60
}61
render(g) {62
for(let item of this.items) {63
item.render(g);64
}65
}66
causeEvent(type, events) {67
for(let item of this.items) {68
item.causeEvent(type, events);69
}70
}71
collide() {72
const duplicate = [];73
for(const a of this.items) {74
for(const b of this.items) {75
if(!duplicate.includes(b)) {76
if(a !== b) {77
let collided = false;78
if(a.shape instanceof Shape.Rect && b.shape instanceof Shape.Rect) {79
collided = Collision.collideRect(a, b);80
}81
else if(a.shape instanceof Shape.Circle && b.shape instanceof Shape.Circle) {82
collided = Collision.collideCircle(a, b);83
}84
else {85
collided = Collision.collideRectAndCircle(a, b);86
}87
if(collided) {88
if(a.oncollide) {89
a.oncollide(b);90
}91
if(b.oncollide) {92
b.oncollide(a);93
}94
}95
}96
}97
}98
duplicate.push(a);99
}100
}101
add(item) {102
this.items.push(item);103
}104
remove(item) {105
const i = this.items.findIndex(n => n === item);106
if(i !== -1) {107
this.items.splice(i, 1);108
}109
}110
[Symbol.iterator]() {111
return this.items.values();112
}113
}115
export class Surface {116
constructor(x, y, shape) {117
this.x = x;118
this.y = y;119
this.shape = shape;120
}121
update() {122
// nothing123
}124
render(g) {125
if(this.shape instanceof Shape.Rect) {126
g.beginPath();127
g.rect(this.x, this.y, this.shape.width, this.shape.height);128
g.stroke();129
}130
if(this.shape instanceof Shape.Circle) {131
g.beginPath();132
g.arc(this.x, this.y, this.shape.radius, 2 * Math.PI, 0);133
g.stroke();134
}135
}136
causeEvent(type, events) {137
if(this['on' + type]) {138
for(const event of events) {139
if(event.type === type) {140
this['on' + type](event);141
}142
}143
}144
}145
}147
class Rect {148
constructor(width, height) {149
this.width = width;150
this.height = height;151
}152
}154
class Circle {155
constructor(radius) {156
this.radius = radius;157
}158
}160
export const Shape = { Rect, Circle };160
\ No newline at end of file
1
export function html(strings, ...props) {2
try {3
let code = '';4
let events = [];5
let children = [];6
for(let i = 0; i < strings.length; i++) {7
code += strings[i];8
if(i < props.length) {9
if(typeof props[i] === 'function') {10
const exp = new RegExp(/on(\w+)=/, 'g');11
const match = exp.exec(strings[i]);12
if(match) {13
const [, type] = match;14
code = code.slice(0, -(type.length + 3));15
code += `data-event-ref-${events.length}`;16
events.push({ type, handler: props[i] });17
}18
continue;19
}20
if(props[i] instanceof Array) {21
for(const item of props[i]) {22
if(item instanceof HTMLElement) {23
const tag = item.tagName.toLowerCase();24
code += `<${tag} data-child-ref-${children.length}></${tag}>`;25
children.push(item);26
continue;27
}28
code += item;29
}30
continue;31
}32
if(props[i] instanceof HTMLElement) {33
const tag = props[i].tagName.toLowerCase();34
code += `<${tag} data-child-ref-${children.length}></${tag}>`;35
children.push(props[i]);36
continue;37
}38
code += props[i];39
}40
}41
const template = document.createElement('template');42
template.innerHTML = code;43
const fragment = template.content.cloneNode(true);44
const element = fragment.firstElementChild;45
for(const [id, {type, handler}] of Object.entries(events)) {46
let target;47
if(element.hasAttribute(`data-event-ref-${id}`)) {48
target = element;49
}50
else {51
target = element.querySelector(`[data-event-ref-${id}]`);52
}53
if(target) {54
target.addEventListener(type, handler);55
target.removeAttribute(`data-event-ref-${id}`);56
}57
else {58
console.warn(`Unable to bind ${type} event to element with id: ${id}`);59
}60
}61
for(const [id, child] of Object.entries(children)) {62
const target = element.querySelector(`[data-child-ref-${id}]`);63
if(target) {64
target.replaceWith(child);65
}66
else {67
console.warn(`Unable to reference <${child.tagName.toLowerCase()}> tag with id: ${id}`);68
}69
}70
return element;71
}72
catch(error) {73
console.error(error);74
}75
}77
export function escape(string) {78
return string.replace(/&/g, '&')79
.replace(/</g, '<')80
.replace(/>/g, '>')81
.replace(/"/g, '"')82
.replace(/'/g, ''');83
}83
\ No newline at end of file
1
const DEVICE_PIXEL_RATIO = window.devicePixelRatio || 1;3
export function scaleCanvas(canvas, width, height) {4
const g = canvas.getContext('2d');5
const backingStoreRatio = g.webkitBackingStorePixelRatio || 1;6
const ratio = DEVICE_PIXEL_RATIO / backingStoreRatio;7
if(DEVICE_PIXEL_RATIO != backingStoreRatio) {8
canvas.width = width * ratio;9
canvas.height = height * ratio;10
canvas.style.width = width + 'px';11
canvas.style.height = height + 'px';12
}13
else {14
canvas.width = width;15
canvas.height = height;16
canvas.style.width = '';17
canvas.style.height = '';18
}19
g.scale(ratio, ratio);20
}