mirror of
https://github.com/pyscript/pyscript.git
synced 2026-02-21 11:01:26 -05:00
Apply prettier to css, html, js, md, ts, and yml (#1249)
* Apply prettier to css, js, html, md, ts, and yml As a followup I will add prettier to the .pre-commit config. This patch is 100% generated by prettier. I used a forked version of prettier that understands the py-script tag. See https://github.com/hoodmane/pyscript-prettier-precommit for more info. * Apply old pre-commit * Revert some problems * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Revert some changes * More changes * Fix pre-commit * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1,78 +1,78 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Altair</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Altair</a>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
<div id="altair"></div>
|
||||
<py-tutor>
|
||||
<py-config>
|
||||
packages = [
|
||||
"altair",
|
||||
"pandas",
|
||||
"vega_datasets"
|
||||
]
|
||||
plugins = [
|
||||
"../build/plugins/python/py_tutor.py"
|
||||
]
|
||||
</py-config>
|
||||
<py-script>
|
||||
import altair as alt
|
||||
from vega_datasets import data
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c">Altair</a>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
<div id="altair"></div>
|
||||
<py-tutor>
|
||||
<py-config>
|
||||
packages = [
|
||||
"altair",
|
||||
"pandas",
|
||||
"vega_datasets"
|
||||
]
|
||||
plugins = [
|
||||
"../build/plugins/python/py_tutor.py"
|
||||
]
|
||||
</py-config>
|
||||
<py-script>
|
||||
import altair as alt
|
||||
from vega_datasets import data
|
||||
|
||||
source = data.movies.url
|
||||
source = data.movies.url
|
||||
|
||||
pts = alt.selection(type="single", encodings=['x'])
|
||||
pts = alt.selection(type="single", encodings=['x'])
|
||||
|
||||
rect = alt.Chart(data.movies.url).mark_rect().encode(
|
||||
alt.X('IMDB_Rating:Q', bin=True),
|
||||
alt.Y('Rotten_Tomatoes_Rating:Q', bin=True),
|
||||
alt.Color('count()',
|
||||
scale=alt.Scale(scheme='greenblue'),
|
||||
legend=alt.Legend(title='Total Records')
|
||||
)
|
||||
)
|
||||
rect = alt.Chart(data.movies.url).mark_rect().encode(
|
||||
alt.X('IMDB_Rating:Q', bin=True),
|
||||
alt.Y('Rotten_Tomatoes_Rating:Q', bin=True),
|
||||
alt.Color('count()',
|
||||
scale=alt.Scale(scheme='greenblue'),
|
||||
legend=alt.Legend(title='Total Records')
|
||||
)
|
||||
)
|
||||
|
||||
circ = rect.mark_point().encode(
|
||||
alt.ColorValue('grey'),
|
||||
alt.Size('count()',
|
||||
legend=alt.Legend(title='Records in Selection')
|
||||
)
|
||||
).transform_filter(
|
||||
pts
|
||||
)
|
||||
circ = rect.mark_point().encode(
|
||||
alt.ColorValue('grey'),
|
||||
alt.Size('count()',
|
||||
legend=alt.Legend(title='Records in Selection')
|
||||
)
|
||||
).transform_filter(
|
||||
pts
|
||||
)
|
||||
|
||||
bar = alt.Chart(source).mark_bar().encode(
|
||||
x='Major_Genre:N',
|
||||
y='count()',
|
||||
color=alt.condition(pts, alt.ColorValue("steelblue"), alt.ColorValue("grey"))
|
||||
).properties(
|
||||
width=550,
|
||||
height=200
|
||||
).add_selection(pts)
|
||||
bar = alt.Chart(source).mark_bar().encode(
|
||||
x='Major_Genre:N',
|
||||
y='count()',
|
||||
color=alt.condition(pts, alt.ColorValue("steelblue"), alt.ColorValue("grey"))
|
||||
).properties(
|
||||
width=550,
|
||||
height=200
|
||||
).add_selection(pts)
|
||||
|
||||
display(alt.vconcat(
|
||||
rect + circ,
|
||||
bar
|
||||
).resolve_legend(
|
||||
color="independent",
|
||||
size="independent"
|
||||
), target="altair")
|
||||
</py-script>
|
||||
</py-tutor>
|
||||
</section>
|
||||
display(alt.vconcat(
|
||||
rect + circ,
|
||||
bar
|
||||
).resolve_legend(
|
||||
color="independent",
|
||||
size="independent"
|
||||
), target="altair")
|
||||
</py-script>
|
||||
</py-tutor>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Antigravity</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Antigravity</a>
|
||||
<a class="title" href="" style="color: #f0ab3c">Antigravity</a>
|
||||
</div>
|
||||
</nav>
|
||||
<py-tutor modules="antigravity.py">
|
||||
<section class="pyscript">
|
||||
<py-config>
|
||||
plugins = [
|
||||
"../build/plugins/python/py_tutor.py"
|
||||
]
|
||||
[[fetch]]
|
||||
files = ["./antigravity.py"]
|
||||
</py-config>
|
||||
<b>Based on xkcd: antigravity https://xkcd.com/353/.</b>
|
||||
<py-script>
|
||||
import antigravity
|
||||
antigravity.fly()
|
||||
</py-script>
|
||||
<py-config>
|
||||
plugins = [
|
||||
"../build/plugins/python/py_tutor.py"
|
||||
]
|
||||
[[fetch]]
|
||||
files = ["./antigravity.py"]
|
||||
</py-config>
|
||||
<b>Based on xkcd: antigravity https://xkcd.com/353/.</b>
|
||||
<py-script>
|
||||
import antigravity
|
||||
antigravity.fly()
|
||||
</py-script>
|
||||
</section>
|
||||
</py-tutor>
|
||||
</body>
|
||||
|
||||
@@ -1,90 +1,91 @@
|
||||
body {
|
||||
margin: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pyscript {
|
||||
margin: 0.5rem;
|
||||
margin: 0.5rem;
|
||||
}
|
||||
|
||||
.code {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
z-index: 9998;
|
||||
top: 7rem;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
z-index: 9998;
|
||||
top: 7rem;
|
||||
}
|
||||
|
||||
@media (max-width: 1300px) {
|
||||
.code:has(> .code-section-visible) {
|
||||
width: 90%;
|
||||
/* Absolute position is messing up the layout on small screens */
|
||||
right: 70px;
|
||||
}
|
||||
.code:has(> .code-section-visible) {
|
||||
width: 90%;
|
||||
/* Absolute position is messing up the layout on small screens */
|
||||
right: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
.code-section-hidden {
|
||||
width: 0px;
|
||||
display: none;
|
||||
width: 0px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.code-section-visible {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
background-color: rgb(45 46 53 / 90%);
|
||||
padding: 1rem;
|
||||
border-radius: 10px 0px 0px 10px;
|
||||
color: #c6c6c8;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
background-color: rgb(45 46 53 / 90%);
|
||||
padding: 1rem;
|
||||
border-radius: 10px 0px 0px 10px;
|
||||
color: #c6c6c8;
|
||||
}
|
||||
.code-section-visible p{
|
||||
margin: 0;
|
||||
font-style: italic;
|
||||
font-size: small;
|
||||
.code-section-visible p {
|
||||
margin: 0;
|
||||
font-style: italic;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.language-html, .language-python {
|
||||
float: left;
|
||||
.language-html,
|
||||
.language-python {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#view-code-button {
|
||||
writing-mode: tb-rl;
|
||||
text-orientation: sideways-right;
|
||||
background-color: #1D1D22;
|
||||
color: white;
|
||||
padding: 0.5rem;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
height: 81px;
|
||||
writing-mode: tb-rl;
|
||||
text-orientation: sideways-right;
|
||||
background-color: #1d1d22;
|
||||
color: white;
|
||||
padding: 0.5rem;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
height: 81px;
|
||||
}
|
||||
|
||||
nav {
|
||||
position: sticky;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9999;
|
||||
position: sticky;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.logo {
|
||||
padding-right: 10px;
|
||||
font-size: 28px;
|
||||
height: 30px;
|
||||
max-width: inherit;
|
||||
padding-right: 10px;
|
||||
font-size: 28px;
|
||||
height: 30px;
|
||||
max-width: inherit;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-decoration: none;
|
||||
text-decoration-line: none;
|
||||
text-decoration-style: initial;
|
||||
text-decoration-color: initial;
|
||||
font-weight: 400;
|
||||
font-size: 1.5em;
|
||||
line-height: 2em;
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
text-decoration-line: none;
|
||||
text-decoration-style: initial;
|
||||
text-decoration-color: initial;
|
||||
font-weight: 400;
|
||||
font-size: 1.5em;
|
||||
line-height: 2em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.app-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
@@ -1,70 +1,74 @@
|
||||
.example {
|
||||
margin-bottom: 5rem;
|
||||
margin-bottom: 5rem;
|
||||
}
|
||||
|
||||
.example h2{
|
||||
/* color: #000000; */
|
||||
font-family: "Inconsolata", monospace;
|
||||
font-size: 2.25rem;
|
||||
margin-bottom: 1rem;
|
||||
.example h2 {
|
||||
/* color: #000000; */
|
||||
font-family: "Inconsolata", monospace;
|
||||
font-size: 2.25rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
height: 15rem;
|
||||
background-color: var(--color-secondary);
|
||||
padding: 1rem;
|
||||
border-radius: 10px;
|
||||
height: 15rem;
|
||||
background-color: var(--color-secondary);
|
||||
padding: 1rem;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.card:hover, .card:hover a, .card:hover a:visited, .card:hover h2 {
|
||||
background-color: var(--color-primary);
|
||||
color: #1D1D22
|
||||
.card:hover,
|
||||
.card:hover a,
|
||||
.card:hover a:visited,
|
||||
.card:hover h2 {
|
||||
background-color: var(--color-primary);
|
||||
color: #1d1d22;
|
||||
}
|
||||
|
||||
.card a h2 {
|
||||
color: var(--color-primary);
|
||||
margin: 0;
|
||||
font-family: "Inconsolata", monospace;
|
||||
font-size: 2.25rem;
|
||||
color: var(--color-primary);
|
||||
margin: 0;
|
||||
font-family: "Inconsolata", monospace;
|
||||
font-size: 2.25rem;
|
||||
}
|
||||
|
||||
.card a p {
|
||||
color: var(--text-color);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
a .card {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card-content a, .card-content a:visited {
|
||||
color: var(--color-primary);
|
||||
.card-content a,
|
||||
.card-content a:visited {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.container-card {
|
||||
max-width: 1500px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
max-width: 1500px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 600px) {
|
||||
.container-card {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
.container-card {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 900px) {
|
||||
.container-card {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
.container-card {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,23 +2,24 @@
|
||||
@import "./variables.css";
|
||||
@import "./reset.css";
|
||||
|
||||
|
||||
body {
|
||||
background: #2D2E35 url('https://assets.anaconda.com/production/Content/1650828148240.png?w=3240&auto=compress%2Cformat&fit=crop&dm=1650828161&s=c558dc55e0ed1f8419a892e842a5728f') repeat-x center bottom / 250px;
|
||||
background-attachment: fixed;
|
||||
overflow-x: hidden;
|
||||
color: var(--text-color)
|
||||
background: #2d2e35
|
||||
url("https://assets.anaconda.com/production/Content/1650828148240.png?w=3240&auto=compress%2Cformat&fit=crop&dm=1650828161&s=c558dc55e0ed1f8419a892e842a5728f")
|
||||
repeat-x center bottom / 250px;
|
||||
background-attachment: fixed;
|
||||
overflow-x: hidden;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1510px;
|
||||
margin: auto;
|
||||
padding: 0 2rem;
|
||||
max-width: 1510px;
|
||||
margin: auto;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
|
||||
.title-main {
|
||||
font-size: 4.25rem;
|
||||
font-family: "Inconsolata", monospace;
|
||||
text-align: center;
|
||||
margin: 2rem 0;
|
||||
font-size: 4.25rem;
|
||||
font-family: "Inconsolata", monospace;
|
||||
text-align: center;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
*,
|
||||
*:after,
|
||||
*:before {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
text-decoration: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 100%;
|
||||
list-style-type: none;
|
||||
font-size: 100%;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: "Inconsolata", monospace;
|
||||
font-weight: 400;
|
||||
font-family: "Inconsolata", monospace;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
:root {
|
||||
--color-primary: #FDA703;
|
||||
--color-secondary: #1D1D22;
|
||||
--text-color: white;
|
||||
--card-shadow: 0px 5px 11px 0px rgb(0 0 0 / 15%);
|
||||
--color-primary: #fda703;
|
||||
--color-secondary: #1d1d22;
|
||||
--text-color: white;
|
||||
--card-shadow: 0px 5px 11px 0px rgb(0 0 0 / 15%);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@@ -9,18 +9,18 @@
|
||||
</head>
|
||||
<body>
|
||||
<py-script>
|
||||
import js
|
||||
import asyncio
|
||||
for i in range(3):
|
||||
js.console.log('A', i)
|
||||
await asyncio.sleep(0.1)
|
||||
import js
|
||||
import asyncio
|
||||
for i in range(3):
|
||||
js.console.log('A', i)
|
||||
await asyncio.sleep(0.1)
|
||||
</py-script>
|
||||
<py-script>
|
||||
import js
|
||||
import asyncio
|
||||
for i in range(3):
|
||||
js.console.log('B', i)
|
||||
await asyncio.sleep(0.1)
|
||||
import js
|
||||
import asyncio
|
||||
for i in range(3):
|
||||
js.console.log('B', i)
|
||||
await asyncio.sleep(0.1)
|
||||
</py-script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@@ -9,7 +9,8 @@
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
Pyscript - FIRST ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME LEVEL AS LOOP Pyscript writing to console.log:
|
||||
Pyscript - FIRST ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME LEVEL AS
|
||||
LOOP Pyscript writing to console.log:
|
||||
<py-script>
|
||||
import js
|
||||
import asyncio
|
||||
@@ -23,7 +24,8 @@
|
||||
</py-script>
|
||||
</div>
|
||||
<div>
|
||||
Pyscript - SECOND ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME LEVEL AS LOOP Pyscript writing to console.log:
|
||||
Pyscript - SECOND ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME LEVEL AS
|
||||
LOOP Pyscript writing to console.log:
|
||||
<py-script>
|
||||
import js
|
||||
import asyncio
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@@ -9,7 +9,8 @@
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
Pyscript - FIRST ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME LEVEL AS LOOP Pyscript writing to console.log:
|
||||
Pyscript - FIRST ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME LEVEL AS
|
||||
LOOP Pyscript writing to console.log:
|
||||
<py-script>
|
||||
import js
|
||||
import asyncio
|
||||
@@ -23,7 +24,8 @@
|
||||
</py-script>
|
||||
</div>
|
||||
<div>
|
||||
Pyscript - SECOND ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME LEVEL AS LOOP Pyscript writing to console.log:
|
||||
Pyscript - SECOND ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME LEVEL
|
||||
AS LOOP Pyscript writing to console.log:
|
||||
<py-script>
|
||||
import js
|
||||
import asyncio
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@@ -9,7 +9,8 @@
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
Pyscript - FIRST ASYNC WITH NON-BLOCKING AWAIT AT ONE LEVEL LOWER THAN LOOP Pyscript writing to console.log:
|
||||
Pyscript - FIRST ASYNC WITH NON-BLOCKING AWAIT AT ONE LEVEL LOWER THAN
|
||||
LOOP Pyscript writing to console.log:
|
||||
<py-script>
|
||||
import js
|
||||
import asyncio
|
||||
@@ -23,7 +24,8 @@
|
||||
</py-script>
|
||||
</div>
|
||||
<div>
|
||||
Pyscript - SECOND ASYNC WITH NON-BLOCKING AWAIT AT ONE LEVEL LOWER THAN LOOP Pyscript writing to console.log:
|
||||
Pyscript - SECOND ASYNC WITH NON-BLOCKING AWAIT AT ONE LEVEL LOWER THAN
|
||||
LOOP Pyscript writing to console.log:
|
||||
<py-script>
|
||||
import js
|
||||
import asyncio
|
||||
|
||||
@@ -1,34 +1,36 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>Async Await BLOCKING LOOP Pyscript Twice</title>
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
Pyscript - FIRST ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME LEVEL AS LOOP Pyscript writing to console.log:
|
||||
<py-script>
|
||||
import js
|
||||
import asyncio
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>Async Await BLOCKING LOOP Pyscript Twice</title>
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
Pyscript - FIRST ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME LEVEL AS
|
||||
LOOP Pyscript writing to console.log:
|
||||
<py-script>
|
||||
import js
|
||||
import asyncio
|
||||
|
||||
for i in range(3):
|
||||
js.console.log('A', i)
|
||||
await asyncio.sleep(2)
|
||||
</py-script>
|
||||
</div>
|
||||
<div>
|
||||
Pyscript - SECOND ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME LEVEL AS LOOP Pyscript writing to console.log:
|
||||
<py-script>
|
||||
import js
|
||||
import asyncio
|
||||
for i in range(3):
|
||||
js.console.log('A', i)
|
||||
await asyncio.sleep(2)
|
||||
</py-script>
|
||||
</div>
|
||||
<div>
|
||||
Pyscript - SECOND ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME LEVEL
|
||||
AS LOOP Pyscript writing to console.log:
|
||||
<py-script>
|
||||
import js
|
||||
import asyncio
|
||||
|
||||
for i in range(3):
|
||||
js.console.log('B', i)
|
||||
await asyncio.sleep(2)
|
||||
</py-script>
|
||||
</div>
|
||||
</body>
|
||||
for i in range(3):
|
||||
js.console.log('B', i)
|
||||
await asyncio.sleep(2)
|
||||
</py-script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>Async Await BLOCKING LOOP Pyscript Twice</title>
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</head>
|
||||
<body>
|
||||
<py-script>
|
||||
import asyncio
|
||||
from itertools import count
|
||||
for i in count():
|
||||
print(f"Count: {i}")
|
||||
await asyncio.sleep(1)
|
||||
import asyncio
|
||||
from itertools import count
|
||||
for i in count():
|
||||
print(f"Count: {i}")
|
||||
await asyncio.sleep(1)
|
||||
</py-script>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,63 +1,79 @@
|
||||
<html><head>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bokeh Example</title>
|
||||
<meta charset="iso-8859-1">
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-3.0.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.0.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.0.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.0.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.0.3.min.js"></script>
|
||||
<meta charset="iso-8859-1" />
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-3.0.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.0.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.0.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.0.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.0.3.min.js"
|
||||
></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
Bokeh.set_log_level("info");
|
||||
Bokeh.set_log_level("info");
|
||||
</script>
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Bokeh Example</a>
|
||||
</div>
|
||||
</nav>
|
||||
<py-tutor>
|
||||
<section class="pyscript">
|
||||
<div id="myplot"></div>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c">Bokeh Example</a>
|
||||
</div>
|
||||
</nav>
|
||||
<py-tutor>
|
||||
<section class="pyscript">
|
||||
<div id="myplot"></div>
|
||||
|
||||
<py-config>
|
||||
packages = [
|
||||
"pandas",
|
||||
"bokeh",
|
||||
"xyzservices"
|
||||
]
|
||||
plugins = [
|
||||
"../build/plugins/python/py_tutor.py"
|
||||
]
|
||||
</py-config>
|
||||
<py-config>
|
||||
packages = [
|
||||
"pandas",
|
||||
"bokeh",
|
||||
"xyzservices"
|
||||
]
|
||||
plugins = [
|
||||
"../build/plugins/python/py_tutor.py"
|
||||
]
|
||||
</py-config>
|
||||
|
||||
<py-script id="main">
|
||||
import json
|
||||
import pyodide
|
||||
import json
|
||||
import pyodide
|
||||
|
||||
from js import Bokeh, console, JSON
|
||||
from js import Bokeh, console, JSON
|
||||
|
||||
from bokeh.embed import json_item
|
||||
from bokeh.plotting import figure
|
||||
from bokeh.resources import CDN
|
||||
from bokeh.embed import json_item
|
||||
from bokeh.plotting import figure
|
||||
from bokeh.resources import CDN
|
||||
|
||||
# create a new plot with default tools, using figure
|
||||
p = figure(width=400, height=400)
|
||||
# create a new plot with default tools, using figure
|
||||
p = figure(width=400, height=400)
|
||||
|
||||
# add a circle renderer with x and y coordinates, size, color, and alpha
|
||||
p.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=15, line_color="navy", fill_color="orange", fill_alpha=0.5)
|
||||
p_json = json.dumps(json_item(p, "myplot"))
|
||||
# add a circle renderer with x and y coordinates, size, color, and alpha
|
||||
p.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=15, line_color="navy", fill_color="orange", fill_alpha=0.5)
|
||||
p_json = json.dumps(json_item(p, "myplot"))
|
||||
|
||||
Bokeh.embed.embed_item(JSON.parse(p_json))
|
||||
Bokeh.embed.embed_item(JSON.parse(p_json))
|
||||
</py-script>
|
||||
</section>
|
||||
</py-tutor>
|
||||
|
||||
@@ -1,114 +1,130 @@
|
||||
<html><head>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bokeh Example</title>
|
||||
<meta charset="iso-8859-1">
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js"></script>
|
||||
<meta charset="iso-8859-1" />
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js"
|
||||
></script>
|
||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
Bokeh.set_log_level("info");
|
||||
Bokeh.set_log_level("info");
|
||||
</script>
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Bokeh Example</a>
|
||||
<a class="title" href="" style="color: #f0ab3c">Bokeh Example</a>
|
||||
</div>
|
||||
</nav>
|
||||
<py-tutor>
|
||||
<section class="pyscript">
|
||||
<h1>Bokeh Example</h1>
|
||||
<div id="myplot"></div>
|
||||
<h1>Bokeh Example</h1>
|
||||
<div id="myplot"></div>
|
||||
|
||||
<py-config>
|
||||
packages = [
|
||||
"https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
|
||||
"numpy",
|
||||
]
|
||||
plugins = [
|
||||
"../build/plugins/python/py_tutor.py"
|
||||
]
|
||||
</py-config>
|
||||
<py-config>
|
||||
packages = [
|
||||
"https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
|
||||
"numpy",
|
||||
]
|
||||
plugins = [
|
||||
"../build/plugins/python/py_tutor.py"
|
||||
]
|
||||
</py-config>
|
||||
|
||||
<py-script id="main">
|
||||
import asyncio
|
||||
import json
|
||||
import pyodide
|
||||
<py-script id="main">
|
||||
import asyncio
|
||||
import json
|
||||
import pyodide
|
||||
|
||||
from js import Bokeh, console, JSON
|
||||
from js import Bokeh, console, JSON
|
||||
|
||||
from bokeh import __version__
|
||||
from bokeh.document import Document
|
||||
from bokeh.embed.util import OutputDocumentFor, standalone_docs_json_and_render_items
|
||||
from bokeh.models import Slider, Div
|
||||
from bokeh.layouts import Row
|
||||
from bokeh.protocol.messages.patch_doc import process_document_events
|
||||
from bokeh import __version__
|
||||
from bokeh.document import Document
|
||||
from bokeh.embed.util import OutputDocumentFor, standalone_docs_json_and_render_items
|
||||
from bokeh.models import Slider, Div
|
||||
from bokeh.layouts import Row
|
||||
from bokeh.protocol.messages.patch_doc import process_document_events
|
||||
|
||||
# create a new plot with default tools, using figure
|
||||
p = Slider(start=0.1, end=10, value=1, step=.1, title="Amplitude")
|
||||
div = Div(text=f'Amplitude is: {p.value}')
|
||||
# create a new plot with default tools, using figure
|
||||
p = Slider(start=0.1, end=10, value=1, step=.1, title="Amplitude")
|
||||
div = Div(text=f'Amplitude is: {p.value}')
|
||||
|
||||
def callback(attr, old, new):
|
||||
div.text = f'Amplitude is: {new}'
|
||||
def callback(attr, old, new):
|
||||
div.text = f'Amplitude is: {new}'
|
||||
|
||||
p.on_change('value', callback)
|
||||
p.on_change('value', callback)
|
||||
|
||||
row = Row(children=[p, div])
|
||||
row = Row(children=[p, div])
|
||||
|
||||
def doc_json(model, target):
|
||||
with OutputDocumentFor([model]) as doc:
|
||||
doc.title = ""
|
||||
docs_json, _ = standalone_docs_json_and_render_items(
|
||||
[model], suppress_callback_warning=True
|
||||
)
|
||||
def doc_json(model, target):
|
||||
with OutputDocumentFor([model]) as doc:
|
||||
doc.title = ""
|
||||
docs_json, _ = standalone_docs_json_and_render_items(
|
||||
[model], suppress_callback_warning=True
|
||||
)
|
||||
|
||||
doc_json = list(docs_json.values())[0]
|
||||
root_id = doc_json['roots']['root_ids'][0]
|
||||
doc_json = list(docs_json.values())[0]
|
||||
root_id = doc_json['roots']['root_ids'][0]
|
||||
|
||||
return doc, json.dumps(dict(
|
||||
target_id = target,
|
||||
root_id = root_id,
|
||||
doc = doc_json,
|
||||
version = __version__,
|
||||
))
|
||||
return doc, json.dumps(dict(
|
||||
target_id = target,
|
||||
root_id = root_id,
|
||||
doc = doc_json,
|
||||
version = __version__,
|
||||
))
|
||||
|
||||
def _link_docs(pydoc, jsdoc):
|
||||
def jssync(event):
|
||||
if getattr(event, 'setter_id', None) is not None:
|
||||
return
|
||||
events = [event]
|
||||
json_patch = jsdoc.create_json_patch_string(pyodide.ffi.to_js(events))
|
||||
pydoc.apply_json_patch(json.loads(json_patch))
|
||||
def _link_docs(pydoc, jsdoc):
|
||||
def jssync(event):
|
||||
if getattr(event, 'setter_id', None) is not None:
|
||||
return
|
||||
events = [event]
|
||||
json_patch = jsdoc.create_json_patch_string(pyodide.ffi.to_js(events))
|
||||
pydoc.apply_json_patch(json.loads(json_patch))
|
||||
|
||||
jsdoc.on_change(pyodide.ffi.create_proxy(jssync), pyodide.ffi.to_js(False))
|
||||
jsdoc.on_change(pyodide.ffi.create_proxy(jssync), pyodide.ffi.to_js(False))
|
||||
|
||||
def pysync(event):
|
||||
json_patch, buffers = process_document_events([event], use_buffers=True)
|
||||
buffer_map = {}
|
||||
for (ref, buffer) in buffers:
|
||||
buffer_map[ref['id']] = buffer
|
||||
jsdoc.apply_json_patch(JSON.parse(json_patch), pyodide.ffi.to_js(buffer_map), setter_id='js')
|
||||
def pysync(event):
|
||||
json_patch, buffers = process_document_events([event], use_buffers=True)
|
||||
buffer_map = {}
|
||||
for (ref, buffer) in buffers:
|
||||
buffer_map[ref['id']] = buffer
|
||||
jsdoc.apply_json_patch(JSON.parse(json_patch), pyodide.ffi.to_js(buffer_map), setter_id='js')
|
||||
|
||||
pydoc.on_change(pysync)
|
||||
pydoc.on_change(pysync)
|
||||
|
||||
async def show(plot, target):
|
||||
pydoc, model_json = doc_json(plot, target)
|
||||
views = await Bokeh.embed.embed_item(JSON.parse(model_json))
|
||||
jsdoc = views[0].model.document
|
||||
_link_docs(pydoc, jsdoc)
|
||||
async def show(plot, target):
|
||||
pydoc, model_json = doc_json(plot, target)
|
||||
views = await Bokeh.embed.embed_item(JSON.parse(model_json))
|
||||
jsdoc = views[0].model.document
|
||||
_link_docs(pydoc, jsdoc)
|
||||
|
||||
asyncio.ensure_future(show(row, 'myplot'))
|
||||
</py-script>
|
||||
asyncio.ensure_future(show(row, 'myplot'))
|
||||
</py-script>
|
||||
</section>
|
||||
</py-tutor>
|
||||
</body>
|
||||
|
||||
182
examples/d3.html
182
examples/d3.html
@@ -1,44 +1,45 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>d3: JavaScript & PyScript visualizations side-by-side</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||
<style>
|
||||
.loading {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border: 3px solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 50%;
|
||||
border-top-color: black;
|
||||
animation: spin 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
.loading {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border: 3px solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 50%;
|
||||
border-top-color: black;
|
||||
animation: spin 1s ease-in-out infinite;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Simple d3 visualization</a>
|
||||
<a class="title" href="" style="color: #f0ab3c"
|
||||
>Simple d3 visualization</a
|
||||
>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<section class="pyscript">
|
||||
<py-tutor modules="d3.py">
|
||||
<section class="pyscript">
|
||||
<py-tutor modules="d3.py">
|
||||
<py-config>
|
||||
plugins = [
|
||||
"../build/plugins/python/py_tutor.py"
|
||||
@@ -46,79 +47,88 @@
|
||||
[[fetch]]
|
||||
files = ["./d3.py"]
|
||||
</py-config>
|
||||
</py-tutor>
|
||||
<b>
|
||||
Based on <i><a href="https://observablehq.com/@d3/learn-d3-shapes?collection=@d3/learn-d3>">Learn D3: Shapes</a></i> tutorial.
|
||||
</b>
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<div>
|
||||
<div style="text-align: center">JavaScript version</div>
|
||||
<div id="js" style="width: 400px; height: 400px">
|
||||
<div class="loading"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="text-align: center">PyScript version</div>
|
||||
<div id="py" style="width: 400px; height: 400px">
|
||||
<div class="loading"></div>
|
||||
</div>
|
||||
</py-tutor>
|
||||
<b>
|
||||
Based on
|
||||
<i
|
||||
><a
|
||||
href="https://observablehq.com/@d3/learn-d3-shapes?collection=@d3/learn-d3>"
|
||||
>Learn D3: Shapes</a
|
||||
></i
|
||||
>
|
||||
tutorial.
|
||||
</b>
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<div>
|
||||
<div style="text-align: center">JavaScript version</div>
|
||||
<div id="js" style="width: 400px; height: 400px">
|
||||
<div class="loading"></div>
|
||||
</div>
|
||||
</div>
|
||||
<py-script src="d3.py"></py-script>
|
||||
</section>
|
||||
<div>
|
||||
<div style="text-align: center">PyScript version</div>
|
||||
<div id="py" style="width: 400px; height: 400px">
|
||||
<div class="loading"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<py-script src="d3.py"></py-script>
|
||||
</section>
|
||||
|
||||
<script type="module">
|
||||
<script type="module">
|
||||
const fruits = [
|
||||
{ name: "🍊", count: 21 },
|
||||
{ name: "🍇", count: 13 },
|
||||
{ name: "🍏", count: 8 },
|
||||
{ name: "🍌", count: 5 },
|
||||
{ name: "🍐", count: 3 },
|
||||
{ name: "🍋", count: 2 },
|
||||
{ name: "🍎", count: 1 },
|
||||
{ name: "🍉", count: 1 },
|
||||
];
|
||||
|
||||
const fruits = [
|
||||
{name: "🍊", count: 21},
|
||||
{name: "🍇", count: 13},
|
||||
{name: "🍏", count: 8},
|
||||
{name: "🍌", count: 5},
|
||||
{name: "🍐", count: 3},
|
||||
{name: "🍋", count: 2},
|
||||
{name: "🍎", count: 1},
|
||||
{name: "🍉", count: 1},
|
||||
]
|
||||
const fn = (d) => d.count;
|
||||
const data = d3.pie().value(fn)(fruits);
|
||||
|
||||
const fn = (d) => d.count
|
||||
const data = d3.pie().value(fn)(fruits)
|
||||
const arc = d3
|
||||
.arc()
|
||||
.innerRadius(210)
|
||||
.outerRadius(310)
|
||||
.padRadius(300)
|
||||
.padAngle(2 / 300)
|
||||
.cornerRadius(8);
|
||||
|
||||
const arc = d3.arc()
|
||||
.innerRadius(210)
|
||||
.outerRadius(310)
|
||||
.padRadius(300)
|
||||
.padAngle(2 / 300)
|
||||
.cornerRadius(8)
|
||||
const js = d3.select("#js");
|
||||
js.select(".loading").remove();
|
||||
|
||||
const js = d3.select("#js")
|
||||
js.select(".loading").remove()
|
||||
const svg = js
|
||||
.append("svg")
|
||||
.attr("viewBox", "-320 -320 640 640")
|
||||
.attr("width", "400")
|
||||
.attr("height", "400");
|
||||
|
||||
const svg = js
|
||||
.append("svg")
|
||||
.attr("viewBox", "-320 -320 640 640")
|
||||
.attr("width", "400")
|
||||
.attr("height", "400")
|
||||
for (const d of data) {
|
||||
svg.append("path").style("fill", "steelblue").attr("d", arc(d));
|
||||
|
||||
for (const d of data) {
|
||||
svg.append("path")
|
||||
.style("fill", "steelblue")
|
||||
.attr("d", arc(d))
|
||||
const text = svg
|
||||
.append("text")
|
||||
.style("fill", "white")
|
||||
.attr("transform", `translate(${arc.centroid(d).join(",")})`)
|
||||
.attr("text-anchor", "middle");
|
||||
|
||||
const text = svg.append("text")
|
||||
.style("fill", "white")
|
||||
.attr("transform", `translate(${arc.centroid(d).join(",")})`)
|
||||
.attr("text-anchor", "middle")
|
||||
text
|
||||
.append("tspan")
|
||||
.style("font-size", "24")
|
||||
.attr("x", "0")
|
||||
.text(d.data.name);
|
||||
|
||||
text.append("tspan")
|
||||
.style("font-size", "24")
|
||||
.attr("x", "0").text(d.data.name)
|
||||
|
||||
text.append("tspan")
|
||||
.style("font-size", "18")
|
||||
.attr("x", "0")
|
||||
.attr("dy", "1.3em")
|
||||
.text(d.value)
|
||||
}
|
||||
text
|
||||
.append("tspan")
|
||||
.style("font-size", "18")
|
||||
.attr("x", "0")
|
||||
.attr("dy", "1.3em")
|
||||
.text(d.value);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Folium</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Folium</a>
|
||||
<a class="title" href="" style="color: #f0ab3c">Folium</a>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
@@ -31,40 +31,39 @@
|
||||
</py-config>
|
||||
|
||||
<py-script>
|
||||
import folium
|
||||
import json
|
||||
import pandas as pd
|
||||
import folium
|
||||
import json
|
||||
import pandas as pd
|
||||
|
||||
from pyodide.http import open_url
|
||||
from pyodide.http import open_url
|
||||
|
||||
url = (
|
||||
"https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
|
||||
)
|
||||
state_geo = f"{url}/us-states.json"
|
||||
state_unemployment = f"{url}/US_Unemployment_Oct2012.csv"
|
||||
state_data = pd.read_csv(open_url(state_unemployment))
|
||||
geo_json = json.loads(open_url(state_geo).read())
|
||||
url = (
|
||||
"https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
|
||||
)
|
||||
state_geo = f"{url}/us-states.json"
|
||||
state_unemployment = f"{url}/US_Unemployment_Oct2012.csv"
|
||||
state_data = pd.read_csv(open_url(state_unemployment))
|
||||
geo_json = json.loads(open_url(state_geo).read())
|
||||
|
||||
m = folium.Map(location=[48, -102], zoom_start=3)
|
||||
m = folium.Map(location=[48, -102], zoom_start=3)
|
||||
|
||||
folium.Choropleth(
|
||||
geo_data=geo_json,
|
||||
name="choropleth",
|
||||
data=state_data,
|
||||
columns=["State", "Unemployment"],
|
||||
key_on="feature.id",
|
||||
fill_color="YlGn",
|
||||
fill_opacity=0.7,
|
||||
line_opacity=0.2,
|
||||
legend_name="Unemployment Rate (%)",
|
||||
).add_to(m)
|
||||
folium.Choropleth(
|
||||
geo_data=geo_json,
|
||||
name="choropleth",
|
||||
data=state_data,
|
||||
columns=["State", "Unemployment"],
|
||||
key_on="feature.id",
|
||||
fill_color="YlGn",
|
||||
fill_opacity=0.7,
|
||||
line_opacity=0.2,
|
||||
legend_name="Unemployment Rate (%)",
|
||||
).add_to(m)
|
||||
|
||||
folium.LayerControl().add_to(m)
|
||||
folium.LayerControl().add_to(m)
|
||||
|
||||
display(m, target="folium")
|
||||
display(m, target="folium")
|
||||
</py-script>
|
||||
|
||||
</py-tutor>
|
||||
</section>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@@ -13,12 +13,12 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Hello World</a>
|
||||
<a class="title" href="" style="color: #f0ab3c">Hello World</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
</py-config>
|
||||
|
||||
<section class="pyscript">
|
||||
Hello world! <br>
|
||||
Hello world! <br />
|
||||
This is the current date and time, as computed by Python:
|
||||
<py-script>
|
||||
from datetime import datetime
|
||||
|
||||
@@ -1,173 +1,167 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>PyScript demo</title>
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
<link rel="stylesheet" href="./assets/css/main.css" />
|
||||
<link rel="stylesheet" href="./assets/css/index.css" />
|
||||
</head>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>PyScript demo</title>
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
<link rel="stylesheet" href="./assets/css/main.css" />
|
||||
<link rel="stylesheet" href="./assets/css/index.css" />
|
||||
</head>
|
||||
|
||||
<body class="container">
|
||||
<h1 class="title-main">PyScript demos</h1>
|
||||
<section class="example">
|
||||
<h2>Basic examples</h2>
|
||||
<div class="container-card">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./hello_world.html" target="_blank">
|
||||
<h2>Hello world</h2>
|
||||
</a>
|
||||
<p>
|
||||
A static demo of the <code><py-script></code> tag
|
||||
</p>
|
||||
<body class="container">
|
||||
<h1 class="title-main">PyScript demos</h1>
|
||||
<section class="example">
|
||||
<h2>Basic examples</h2>
|
||||
<div class="container-card">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./hello_world.html" target="_blank">
|
||||
<h2>Hello world</h2>
|
||||
</a>
|
||||
<p>A static demo of the <code><py-script></code> tag</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./simple_clock.html" target="_blank">
|
||||
<h2>Simple clock</h2>
|
||||
</a>
|
||||
<p>
|
||||
A dynamic demo of the <code><py-script></code> tag
|
||||
</p>
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./simple_clock.html" target="_blank">
|
||||
<h2>Simple clock</h2>
|
||||
</a>
|
||||
<p>A dynamic demo of the <code><py-script></code> tag</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./repl.html" target="_blank">
|
||||
<h2>REPL</h2>
|
||||
</a>
|
||||
<p>
|
||||
A Python REPL (Read Eval Print Loop)
|
||||
</p>
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./repl.html" target="_blank">
|
||||
<h2>REPL</h2>
|
||||
</a>
|
||||
<p>A Python REPL (Read Eval Print Loop)</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./repl2.html" target="_blank">
|
||||
<h2>REPL2</h2>
|
||||
</a>
|
||||
</a>
|
||||
<p>
|
||||
A Python REPL (Read Eval Print Loop) with slightly better formatting
|
||||
A Python REPL (Read Eval Print Loop) with slightly better
|
||||
formatting
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./todo.html" target="_blank">
|
||||
<h2>TODO App</h2>
|
||||
</a>
|
||||
<p>
|
||||
Simple TODO App
|
||||
</p>
|
||||
<p>Simple TODO App</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./todo-pylist.html" target="_blank">
|
||||
<h2>PyScript Native TODO App</h2>
|
||||
</a>
|
||||
<p>
|
||||
Simple TODO App using <code><py-list></code>
|
||||
</p>
|
||||
<p>Simple TODO App using <code><py-list></code></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section class="example">
|
||||
<h2>MIME Rendering</h2>
|
||||
<div class="container-card">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<section class="example">
|
||||
<h2>MIME Rendering</h2>
|
||||
<div class="container-card">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./matplotlib.html" target="_blank">
|
||||
<h2>Matplotlib</h2>
|
||||
</a>
|
||||
<p>
|
||||
Demonstrates rendering a <a href="https://matplotlib.org/" target="_blank">Matplotlib</a> figure as output of the py-script tag
|
||||
Demonstrates rendering a
|
||||
<a href="https://matplotlib.org/" target="_blank">Matplotlib</a>
|
||||
figure as output of the py-script tag
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./altair.html" target="_blank">
|
||||
<h2>
|
||||
Altair
|
||||
</h2>
|
||||
<h2>Altair</h2>
|
||||
</a>
|
||||
<p>
|
||||
Demonstrates rendering a <a href="https://altair-viz.github.io/" target="_blank">Altair</a> plot as output of the py-script tag
|
||||
Demonstrates rendering a
|
||||
<a href="https://altair-viz.github.io/" target="_blank">Altair</a>
|
||||
plot as output of the py-script tag
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./folium.html" target="_blank">
|
||||
<h2>Folium</h2>
|
||||
</a>
|
||||
<p>
|
||||
Demonstrates rendering a
|
||||
<a
|
||||
href="https://python-visualization.github.io/folium/"
|
||||
target="_blank"
|
||||
>Folium</a
|
||||
>
|
||||
map as output of the py-script tag
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./folium.html" target="_blank">
|
||||
<h2>
|
||||
Folium
|
||||
</h2>
|
||||
</a>
|
||||
<p>
|
||||
Demonstrates rendering a
|
||||
<a href="https://python-visualization.github.io/folium/" target="_blank">Folium</a>
|
||||
map as output of the py-script tag
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="example">
|
||||
<h2>JS Interaction</h2>
|
||||
<div class="container-card">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<section class="example">
|
||||
<h2>JS Interaction</h2>
|
||||
<div class="container-card">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./d3.html" target="_blank">
|
||||
<h2>
|
||||
Simple d3 visualization
|
||||
</h2>
|
||||
<h2>Simple d3 visualization</h2>
|
||||
</a>
|
||||
<p>
|
||||
Minimal <a href="https://d3js.org/" target="_blank">D3</a>
|
||||
demo demonstrating how to create a visualization
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./webgl/raycaster/index.html" target="_blank">
|
||||
<h2>
|
||||
Webgl Icosahedron Example
|
||||
</h2>
|
||||
<h2>Webgl Icosahedron Example</h2>
|
||||
</a>
|
||||
<p>
|
||||
Demo showing how a Simple <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API" target="_blank">WebGL</a>
|
||||
Demo showing how a Simple
|
||||
<a
|
||||
href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API"
|
||||
target="_blank"
|
||||
>WebGL</a
|
||||
>
|
||||
scene would work in the <code><py-script></code> tag
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section class="example">
|
||||
<h2>Visualizations & Dashboards</h2>
|
||||
<div class="container-card">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<section class="example">
|
||||
<h2>Visualizations & Dashboards</h2>
|
||||
<div class="container-card">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./bokeh.html" target="_blank">
|
||||
<h2>
|
||||
Simple Static Bokeh Plot
|
||||
</h2>
|
||||
<h2>Simple Static Bokeh Plot</h2>
|
||||
</a>
|
||||
<p>
|
||||
Minimal Bokeh demo demonstrating how to create a simple
|
||||
@@ -175,10 +169,10 @@
|
||||
plot from code
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./bokeh_interactive.html" target="_blank">
|
||||
<h2 class="text-2xl font-bold text-blue-600">
|
||||
Bokeh Interactive
|
||||
@@ -187,14 +181,14 @@
|
||||
<p>
|
||||
Interactive demo using a
|
||||
<a href="https://bokeh.org/" target="_blank">Bokeh</a>
|
||||
slider widget to dynamically change a value in the page
|
||||
WARNING: This examples takes a little longer to load. So be patient :)
|
||||
slider widget to dynamically change a value in the page WARNING:
|
||||
This examples takes a little longer to load. So be patient :)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./panel_kmeans.html" target="_blank">
|
||||
<h2 class="text-2xl font-bold text-blue-600">
|
||||
KMeans Demo in Panel
|
||||
@@ -203,13 +197,14 @@
|
||||
<p>
|
||||
Interactive KMeans Chart using
|
||||
<a href="https://panel.holoviz.org/" target="_blank">Panel</a>
|
||||
WARNING: This examples takes a little longer to load. So be patient :)
|
||||
WARNING: This examples takes a little longer to load. So be
|
||||
patient :)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./panel_stream.html" target="_blank">
|
||||
<h2 class="text-2xl font-bold text-blue-600">
|
||||
Streaming Demo in Panel
|
||||
@@ -218,13 +213,14 @@
|
||||
<p>
|
||||
Interactive Streaming Table and Bokeh plot using
|
||||
<a href="https://panel.holoviz.org/" target="_blank">Panel</a>
|
||||
WARNING: This examples takes a little longer to load. So be patient :)
|
||||
WARNING: This examples takes a little longer to load. So be
|
||||
patient :)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./panel.html" target="_blank">
|
||||
<h2 class="text-3xl font-bold text-blue-600">
|
||||
Simple Panel Demo
|
||||
@@ -233,14 +229,14 @@
|
||||
<p>
|
||||
Simple demo showing
|
||||
<a href="https://panel.holoviz.org/" target="_blank">Panel</a>
|
||||
widgets interacting with parts of the page
|
||||
WARNING: This examples takes a little longer to load. So be patient :)
|
||||
widgets interacting with parts of the page WARNING: This examples
|
||||
takes a little longer to load. So be patient :)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./panel_deckgl.html" target="_blank">
|
||||
<h2 class="text-2xl font-bold text-blue-600">
|
||||
NYC Taxi Data Panel DeckGL Demo
|
||||
@@ -248,14 +244,16 @@
|
||||
</a>
|
||||
<p>
|
||||
Interactive application exploring the NYC Taxi dataset using
|
||||
<a href="https://panel.holoviz.org/" target="_blank">Panel</a> and <a href="https://deck.gl/" target="_blank">DeckGL</a>
|
||||
WARNING: This examples takes a little longer to load. So be patient :)
|
||||
<a href="https://panel.holoviz.org/" target="_blank">Panel</a> and
|
||||
<a href="https://deck.gl/" target="_blank">DeckGL</a>
|
||||
WARNING: This examples takes a little longer to load. So be
|
||||
patient :)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<a href="./numpy_canvas_fractals.html" target="_blank">
|
||||
<h2 class="text-2xl font-bold text-blue-600">
|
||||
Fractals with NumPy and canvas
|
||||
@@ -264,13 +262,16 @@
|
||||
<p>
|
||||
Visualization of Mandelbrot and Julia sets with
|
||||
<a href="https://numpy.org/" target="_blank">Numpy</a> and
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API" target="_blank">
|
||||
<a
|
||||
href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API"
|
||||
target="_blank"
|
||||
>
|
||||
HTML5 canvas
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
html, body, ul, li {
|
||||
html,
|
||||
body,
|
||||
ul,
|
||||
li {
|
||||
margin: 0;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
var Bcoin = Mario.Bcoin = function(pos) {
|
||||
var Bcoin = (Mario.Bcoin = function (pos) {
|
||||
Mario.Entity.call(this, {
|
||||
pos: pos,
|
||||
sprite: level.bcoinSprite(),
|
||||
hitbox: [0,0,16,16]
|
||||
hitbox: [0, 0, 16, 16],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Mario.Util.inherits(Bcoin, Mario.Entity);
|
||||
|
||||
//I'm not sure whether it makes sense to use an array for vel and acc here
|
||||
//in order to keep with convention, or to just use a single value, since
|
||||
//it's literally impossible for these to move left or right.
|
||||
Bcoin.prototype.spawn = function() {
|
||||
Bcoin.prototype.spawn = function () {
|
||||
sounds.coin.currentTime = 0.05;
|
||||
sounds.coin.play();
|
||||
this.idx = level.items.length;
|
||||
@@ -23,9 +22,9 @@
|
||||
this.active = true;
|
||||
this.vel = -12;
|
||||
this.targetpos = this.pos[1] - 32;
|
||||
}
|
||||
};
|
||||
|
||||
Bcoin.prototype.update = function(dt) {
|
||||
Bcoin.prototype.update = function (dt) {
|
||||
if (!this.active) return;
|
||||
|
||||
if (this.vel > 0 && this.pos[1] >= this.targetpos) {
|
||||
@@ -38,8 +37,7 @@
|
||||
this.vel += this.acc;
|
||||
this.pos[1] += this.vel;
|
||||
this.sprite.update(dt);
|
||||
}
|
||||
|
||||
Bcoin.prototype.checkCollisions = function() {;}
|
||||
};
|
||||
|
||||
Bcoin.prototype.checkCollisions = function () {};
|
||||
})();
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
//TODO: clean up the logic for sprite switching.
|
||||
//TODO: There's a weird bug with the collision logic. Look into it.
|
||||
|
||||
var Block = Mario.Block = function(options) {
|
||||
var Block = (Mario.Block = function (options) {
|
||||
this.item = options.item;
|
||||
this.usedSprite = options.usedSprite;
|
||||
this.bounceSprite = options.bounceSprite;
|
||||
@@ -14,26 +13,27 @@
|
||||
Mario.Entity.call(this, {
|
||||
pos: options.pos,
|
||||
sprite: options.sprite,
|
||||
hitbox: [0,0,16,16]
|
||||
hitbox: [0, 0, 16, 16],
|
||||
});
|
||||
|
||||
this.standing = true;
|
||||
}
|
||||
});
|
||||
|
||||
Mario.Util.inherits(Block, Mario.Floor);
|
||||
|
||||
Block.prototype.break = function() {
|
||||
Block.prototype.break = function () {
|
||||
sounds.breakBlock.play();
|
||||
(new Mario.Rubble()).spawn(this.pos);
|
||||
var x = this.pos[0] / 16, y = this.pos[1] / 16;
|
||||
new Mario.Rubble().spawn(this.pos);
|
||||
var x = this.pos[0] / 16,
|
||||
y = this.pos[1] / 16;
|
||||
delete level.blocks[y][x];
|
||||
}
|
||||
};
|
||||
|
||||
Block.prototype.bonk = function(power) {
|
||||
Block.prototype.bonk = function (power) {
|
||||
sounds.bump.play();
|
||||
if (power > 0 && this.breakable) {
|
||||
this.break();
|
||||
} else if (this.standing){
|
||||
} else if (this.standing) {
|
||||
this.standing = false;
|
||||
if (this.item) {
|
||||
this.item.spawn();
|
||||
@@ -51,9 +51,9 @@
|
||||
|
||||
this.vel[1] = -2;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Block.prototype.update = function(dt, gameTime) {
|
||||
Block.prototype.update = function (dt, gameTime) {
|
||||
if (!this.standing) {
|
||||
if (this.pos[1] < this.opos[1] - 8) {
|
||||
this.vel[1] = 2;
|
||||
@@ -68,7 +68,8 @@
|
||||
}
|
||||
} else {
|
||||
if (this.sprite === this.usedSprite) {
|
||||
var x = this.pos[0] / 16, y = this.pos[1] / 16;
|
||||
var x = this.pos[0] / 16,
|
||||
y = this.pos[1] / 16;
|
||||
level.statics[y][x] = new Mario.Floor(this.pos, this.usedSprite);
|
||||
delete level.blocks[y][x];
|
||||
}
|
||||
@@ -76,6 +77,5 @@
|
||||
|
||||
this.pos[1] += this.vel[1];
|
||||
this.sprite.update(dt, gameTime);
|
||||
}
|
||||
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,47 +1,59 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
var Coin = Mario.Coin = function(pos, sprite) {
|
||||
var Coin = (Mario.Coin = function (pos, sprite) {
|
||||
Mario.Entity.call(this, {
|
||||
pos: pos,
|
||||
sprite: sprite,
|
||||
hitbox: [0,0,16,16]
|
||||
hitbox: [0, 0, 16, 16],
|
||||
});
|
||||
this.idx = level.items.length
|
||||
}
|
||||
this.idx = level.items.length;
|
||||
});
|
||||
|
||||
Mario.Util.inherits(Coin, Mario.Entity);
|
||||
|
||||
Coin.prototype.isPlayerCollided = function() {
|
||||
Coin.prototype.isPlayerCollided = function () {
|
||||
//the first two elements of the hitbox array are an offset, so let's do this now.
|
||||
var hpos1 = [this.pos[0] + this.hitbox[0], this.pos[1] + this.hitbox[1]];
|
||||
var hpos2 = [player.pos[0] + player.hitbox[0], player.pos[1] + player.hitbox[1]];
|
||||
var hpos2 = [
|
||||
player.pos[0] + player.hitbox[0],
|
||||
player.pos[1] + player.hitbox[1],
|
||||
];
|
||||
|
||||
//if the hitboxes actually overlap
|
||||
if (!(hpos1[0] > hpos2[0]+player.hitbox[2] || (hpos1[0]+this.hitbox[2] < hpos2[0]))) {
|
||||
if (!(hpos1[1] > hpos2[1]+player.hitbox[3] || (hpos1[1]+this.hitbox[3] < hpos2[1]))) {
|
||||
if (
|
||||
!(
|
||||
hpos1[0] > hpos2[0] + player.hitbox[2] ||
|
||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
||||
)
|
||||
) {
|
||||
if (
|
||||
!(
|
||||
hpos1[1] > hpos2[1] + player.hitbox[3] ||
|
||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
||||
)
|
||||
) {
|
||||
this.collect();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Coin.prototype.render = function(ctx, vX, vY) {
|
||||
Coin.prototype.render = function (ctx, vX, vY) {
|
||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||
}
|
||||
};
|
||||
|
||||
//money is not affected by gravity, you see.
|
||||
Coin.prototype.update = function(dt) {
|
||||
Coin.prototype.update = function (dt) {
|
||||
this.sprite.update(dt);
|
||||
}
|
||||
Coin.prototype.checkCollisions = function() {
|
||||
};
|
||||
Coin.prototype.checkCollisions = function () {
|
||||
this.isPlayerCollided();
|
||||
}
|
||||
};
|
||||
|
||||
Coin.prototype.collect = function() {
|
||||
Coin.prototype.collect = function () {
|
||||
sounds.coin.currentTime = 0.05;
|
||||
sounds.coin.play();
|
||||
player.coins += 1;
|
||||
delete level.items[this.idx]
|
||||
}
|
||||
delete level.items[this.idx];
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
var Entity = Mario.Entity = function(options) {
|
||||
this.vel = [0,0];
|
||||
this.acc = [0,0];
|
||||
this.standing = true;
|
||||
this.pos = options.pos;
|
||||
this.sprite = options.sprite;
|
||||
this.hitbox = options.hitbox;
|
||||
this.left = false;
|
||||
}
|
||||
var Entity = (Mario.Entity = function (options) {
|
||||
this.vel = [0, 0];
|
||||
this.acc = [0, 0];
|
||||
this.standing = true;
|
||||
this.pos = options.pos;
|
||||
this.sprite = options.sprite;
|
||||
this.hitbox = options.hitbox;
|
||||
this.left = false;
|
||||
});
|
||||
|
||||
Entity.prototype.render = function(ctx, vX, vY) {
|
||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY)
|
||||
}
|
||||
Entity.prototype.render = function (ctx, vX, vY) {
|
||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||
};
|
||||
|
||||
Entity.prototype.collideWall = function(wall) {
|
||||
//the wall will always be a 16x16 block with hitbox = [0,0,16,16].
|
||||
if (this.pos[0] > wall.pos[0]) {
|
||||
//from the right
|
||||
this.pos[0] = wall.pos[0] + wall.hitbox[2] - this.hitbox[0];
|
||||
this.vel[0] = Math.max(0, this.vel[0]);
|
||||
this.acc[0] = Math.max(0, this.acc[0]);
|
||||
} else {
|
||||
this.pos[0] = wall.pos[0] + wall.hitbox[0] - this.hitbox[2] - this.hitbox[0];
|
||||
this.vel[0] = Math.min(0, this.vel[0]);
|
||||
this.acc[0] = Math.min(0, this.acc[0]);
|
||||
}
|
||||
}
|
||||
Entity.prototype.collideWall = function (wall) {
|
||||
//the wall will always be a 16x16 block with hitbox = [0,0,16,16].
|
||||
if (this.pos[0] > wall.pos[0]) {
|
||||
//from the right
|
||||
this.pos[0] = wall.pos[0] + wall.hitbox[2] - this.hitbox[0];
|
||||
this.vel[0] = Math.max(0, this.vel[0]);
|
||||
this.acc[0] = Math.max(0, this.acc[0]);
|
||||
} else {
|
||||
this.pos[0] =
|
||||
wall.pos[0] + wall.hitbox[0] - this.hitbox[2] - this.hitbox[0];
|
||||
this.vel[0] = Math.min(0, this.vel[0]);
|
||||
this.acc[0] = Math.min(0, this.acc[0]);
|
||||
}
|
||||
};
|
||||
|
||||
Entity.prototype.bump = function() {;}
|
||||
Entity.prototype.bump = function () {};
|
||||
})();
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
var Fireball = Mario.Fireball = function(pos) {
|
||||
var Fireball = (Mario.Fireball = function (pos) {
|
||||
this.hit = 0;
|
||||
this.standing = false;
|
||||
|
||||
Mario.Entity.call(this, {
|
||||
pos: pos,
|
||||
sprite: new Mario.Sprite('sprites/items.png', [96, 144], [8,8], 5, [0,1,2,3]),
|
||||
hitbox: [0,0,8,8]
|
||||
sprite: new Mario.Sprite(
|
||||
"sprites/items.png",
|
||||
[96, 144],
|
||||
[8, 8],
|
||||
5,
|
||||
[0, 1, 2, 3],
|
||||
),
|
||||
hitbox: [0, 0, 8, 8],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Mario.Util.inherits(Fireball, Mario.Entity);
|
||||
|
||||
Fireball.prototype.spawn = function(left) {
|
||||
Fireball.prototype.spawn = function (left) {
|
||||
sounds.fireball.currentTime = 0;
|
||||
sounds.fireball.play();
|
||||
if (fireballs[0]) {
|
||||
@@ -25,20 +30,20 @@
|
||||
this.idx = 0;
|
||||
fireballs[0] = this;
|
||||
}
|
||||
this.vel[0] = (left ? -5 : 5);
|
||||
this.vel[0] = left ? -5 : 5;
|
||||
this.standing = false;
|
||||
this.vel[1] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
Fireball.prototype.render = function(ctx, vX, vY) {
|
||||
Fireball.prototype.render = function (ctx, vX, vY) {
|
||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||
}
|
||||
};
|
||||
|
||||
Fireball.prototype.update = function(dt) {
|
||||
Fireball.prototype.update = function (dt) {
|
||||
if (this.hit == 1) {
|
||||
this.sprite.pos = [96, 160];
|
||||
this.sprite.size = [16,16];
|
||||
this.sprite.frames = [0,1,2];
|
||||
this.sprite.size = [16, 16];
|
||||
this.sprite.frames = [0, 1, 2];
|
||||
this.sprite.speed = 8;
|
||||
this.hit += 1;
|
||||
return;
|
||||
@@ -67,13 +72,13 @@
|
||||
this.hit = 1;
|
||||
}
|
||||
this.sprite.update(dt);
|
||||
}
|
||||
};
|
||||
|
||||
Fireball.prototype.collideWall = function() {
|
||||
Fireball.prototype.collideWall = function () {
|
||||
if (!this.hit) this.hit = 1;
|
||||
}
|
||||
};
|
||||
|
||||
Fireball.prototype.checkCollisions = function() {
|
||||
Fireball.prototype.checkCollisions = function () {
|
||||
if (this.hit) return;
|
||||
var h = this.pos[1] % 16 < 8 ? 1 : 2;
|
||||
var w = this.pos[0] % 16 < 8 ? 1 : 2;
|
||||
@@ -99,28 +104,39 @@
|
||||
}
|
||||
|
||||
var that = this;
|
||||
level.enemies.forEach(function(enemy){
|
||||
if (enemy.flipping || enemy.pos[0] - vX > 336){ //stop checking once we get to far away dudes.
|
||||
level.enemies.forEach(function (enemy) {
|
||||
if (enemy.flipping || enemy.pos[0] - vX > 336) {
|
||||
//stop checking once we get to far away dudes.
|
||||
return;
|
||||
} else {
|
||||
that.isCollideWith(enemy);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Fireball.prototype.isCollideWith = function(ent) {
|
||||
Fireball.prototype.isCollideWith = function (ent) {
|
||||
//the first two elements of the hitbox array are an offset, so let's do this now.
|
||||
var hpos1 = [this.pos[0] + this.hitbox[0], this.pos[1] + this.hitbox[1]];
|
||||
var hpos2 = [ent.pos[0] + ent.hitbox[0], ent.pos[1] + ent.hitbox[1]];
|
||||
|
||||
//if the hitboxes actually overlap
|
||||
if (!(hpos1[0] > hpos2[0]+ent.hitbox[2] || (hpos1[0]+this.hitbox[2] < hpos2[0]))) {
|
||||
if (!(hpos1[1] > hpos2[1]+ent.hitbox[3] || (hpos1[1]+this.hitbox[3] < hpos2[1]))) {
|
||||
if (
|
||||
!(
|
||||
hpos1[0] > hpos2[0] + ent.hitbox[2] ||
|
||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
||||
)
|
||||
) {
|
||||
if (
|
||||
!(
|
||||
hpos1[1] > hpos2[1] + ent.hitbox[3] ||
|
||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
||||
)
|
||||
) {
|
||||
this.hit = 1;
|
||||
ent.bump();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Fireball.prototype.bump = function() {;}
|
||||
Fireball.prototype.bump = function () {};
|
||||
})();
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
var Fireflower = Mario.Fireflower = function(pos) {
|
||||
var Fireflower = (Mario.Fireflower = function (pos) {
|
||||
this.spawning = false;
|
||||
this.waiting = 0;
|
||||
|
||||
Mario.Entity.call(this, {
|
||||
pos: pos,
|
||||
sprite: level.fireFlowerSprite,
|
||||
hitbox: [0,0,16,16]
|
||||
hitbox: [0, 0, 16, 16],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Mario.Util.inherits(Fireflower, Mario.Entity);
|
||||
|
||||
Fireflower.prototype.render = function(ctx, vX, vY) {
|
||||
Fireflower.prototype.render = function (ctx, vX, vY) {
|
||||
if (this.spawning > 1) return;
|
||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||
}
|
||||
};
|
||||
|
||||
Fireflower.prototype.spawn = function() {
|
||||
Fireflower.prototype.spawn = function () {
|
||||
sounds.itemAppear.play();
|
||||
this.idx = level.items.length;
|
||||
level.items.push(this);
|
||||
@@ -28,12 +27,12 @@
|
||||
this.targetpos = [];
|
||||
this.targetpos[0] = this.pos[0];
|
||||
this.targetpos[1] = this.pos[1] - 16;
|
||||
}
|
||||
};
|
||||
|
||||
Fireflower.prototype.update = function(dt) {
|
||||
Fireflower.prototype.update = function (dt) {
|
||||
if (this.spawning > 1) {
|
||||
this.spawning -= 1;
|
||||
if (this.spawning == 1) this.vel[1] = -.5;
|
||||
if (this.spawning == 1) this.vel[1] = -0.5;
|
||||
return;
|
||||
}
|
||||
if (this.spawning) {
|
||||
@@ -44,31 +43,45 @@
|
||||
}
|
||||
}
|
||||
|
||||
this.vel[1] += this.acc[1];
|
||||
this.pos[0] += this.vel[0];
|
||||
this.pos[1] += this.vel[1];
|
||||
this.sprite.update(dt);
|
||||
}
|
||||
this.vel[1] += this.acc[1];
|
||||
this.pos[0] += this.vel[0];
|
||||
this.pos[1] += this.vel[1];
|
||||
this.sprite.update(dt);
|
||||
};
|
||||
|
||||
Fireflower.prototype.checkCollisions = function() {
|
||||
if (this.spawning) {return;}
|
||||
Fireflower.prototype.checkCollisions = function () {
|
||||
if (this.spawning) {
|
||||
return;
|
||||
}
|
||||
this.isPlayerCollided();
|
||||
}
|
||||
};
|
||||
|
||||
Fireflower.prototype.isPlayerCollided = function() {
|
||||
Fireflower.prototype.isPlayerCollided = function () {
|
||||
//the first two elements of the hitbox array are an offset, so let's do this now.
|
||||
var hpos1 = [this.pos[0] + this.hitbox[0], this.pos[1] + this.hitbox[1]];
|
||||
var hpos2 = [player.pos[0] + player.hitbox[0], player.pos[1] + player.hitbox[1]];
|
||||
var hpos2 = [
|
||||
player.pos[0] + player.hitbox[0],
|
||||
player.pos[1] + player.hitbox[1],
|
||||
];
|
||||
|
||||
//if the hitboxes actually overlap
|
||||
if (!(hpos1[0] > hpos2[0]+player.hitbox[2] || (hpos1[0]+this.hitbox[2] < hpos2[0]))) {
|
||||
if (!(hpos1[1] > hpos2[1]+player.hitbox[3] || (hpos1[1]+this.hitbox[3] < hpos2[1]))) {
|
||||
if (
|
||||
!(
|
||||
hpos1[0] > hpos2[0] + player.hitbox[2] ||
|
||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
||||
)
|
||||
) {
|
||||
if (
|
||||
!(
|
||||
hpos1[1] > hpos2[1] + player.hitbox[3] ||
|
||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
||||
)
|
||||
) {
|
||||
player.powerUp(this.idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//This should never be called, but just in case.
|
||||
Fireflower.prototype.bump = function() {;}
|
||||
|
||||
Fireflower.prototype.bump = function () {};
|
||||
})();
|
||||
|
||||
@@ -1,47 +1,45 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
Flag = Mario.Flag = function(pos) {
|
||||
Flag = Mario.Flag = function (pos) {
|
||||
//afaik flags always have the same height and Y-position
|
||||
this.pos = [pos, 49];
|
||||
this.hitbox = [0,0,0,0];
|
||||
this.vel = [0,0];
|
||||
this.acc = [0,0];
|
||||
}
|
||||
this.hitbox = [0, 0, 0, 0];
|
||||
this.vel = [0, 0];
|
||||
this.acc = [0, 0];
|
||||
};
|
||||
|
||||
Flag.prototype.collideWall = function() {;
|
||||
}
|
||||
Flag.prototype.collideWall = function () {};
|
||||
|
||||
Flag.prototype.update = function(dt){
|
||||
Flag.prototype.update = function (dt) {
|
||||
if (!this.done && this.pos[1] >= 170) {
|
||||
this.vel = [0,0];
|
||||
this.vel = [0, 0];
|
||||
this.pos[1] = 170;
|
||||
player.exit();
|
||||
this.done = true;
|
||||
}
|
||||
this.pos[1] += this.vel[1];
|
||||
}
|
||||
};
|
||||
|
||||
Flag.prototype.checkCollisions = function() {
|
||||
Flag.prototype.checkCollisions = function () {
|
||||
this.isPlayerCollided();
|
||||
}
|
||||
};
|
||||
|
||||
Flag.prototype.isPlayerCollided = function() {
|
||||
Flag.prototype.isPlayerCollided = function () {
|
||||
if (this.hit) return;
|
||||
if (player.pos[0] + 8 >= this.pos[0]) {
|
||||
music.overworld.pause();
|
||||
sounds.flagpole.play();
|
||||
setTimeout(function() {
|
||||
setTimeout(function () {
|
||||
music.clear.play();
|
||||
}, 2000);
|
||||
this.hit = true;
|
||||
player.flag();
|
||||
this.vel = [0, 2];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Flag.prototype.render = function() {
|
||||
level.flagpoleSprites[2].render(ctx, this.pos[0]-8, this.pos[1], vX, vY);
|
||||
}
|
||||
Flag.prototype.render = function () {
|
||||
level.flagpoleSprites[2].render(ctx, this.pos[0] - 8, this.pos[1], vX, vY);
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,56 +1,75 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
var Floor = Mario.Floor = function(pos, sprite) {
|
||||
var Floor = (Mario.Floor = function (pos, sprite) {
|
||||
Mario.Entity.call(this, {
|
||||
pos: pos,
|
||||
sprite: sprite,
|
||||
hitbox: [0, 0, 16, 16],
|
||||
});
|
||||
});
|
||||
|
||||
Mario.Entity.call(this, {
|
||||
pos: pos,
|
||||
sprite: sprite,
|
||||
hitbox: [0,0,16,16]
|
||||
});
|
||||
}
|
||||
Mario.Util.inherits(Floor, Mario.Entity);
|
||||
|
||||
Mario.Util.inherits(Floor, Mario.Entity);
|
||||
Floor.prototype.isCollideWith = function (ent) {
|
||||
//the first two elements of the hitbox array are an offset, so let's do this now.
|
||||
var hpos1 = [
|
||||
Math.floor(this.pos[0] + this.hitbox[0]),
|
||||
Math.floor(this.pos[1] + this.hitbox[1]),
|
||||
];
|
||||
var hpos2 = [
|
||||
Math.floor(ent.pos[0] + ent.hitbox[0]),
|
||||
Math.floor(ent.pos[1] + ent.hitbox[1]),
|
||||
];
|
||||
|
||||
Floor.prototype.isCollideWith = function (ent) {
|
||||
//the first two elements of the hitbox array are an offset, so let's do this now.
|
||||
var hpos1 = [Math.floor(this.pos[0] + this.hitbox[0]), Math.floor(this.pos[1] + this.hitbox[1])];
|
||||
var hpos2 = [Math.floor(ent.pos[0] + ent.hitbox[0]), Math.floor(ent.pos[1] + ent.hitbox[1])];
|
||||
//if the hitboxes actually overlap
|
||||
if (
|
||||
!(
|
||||
hpos1[0] > hpos2[0] + ent.hitbox[2] ||
|
||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
||||
)
|
||||
) {
|
||||
if (
|
||||
!(
|
||||
hpos1[1] > hpos2[1] + ent.hitbox[3] ||
|
||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
||||
)
|
||||
) {
|
||||
if (!this.standing) {
|
||||
ent.bump();
|
||||
} else {
|
||||
//if the entity is over the block, it's basically floor
|
||||
var center = hpos2[0] + ent.hitbox[2] / 2;
|
||||
if (Math.abs(hpos2[1] + ent.hitbox[3] - hpos1[1]) <= ent.vel[1]) {
|
||||
if (level.statics[this.pos[1] / 16 - 1][this.pos[0] / 16]) {
|
||||
return;
|
||||
}
|
||||
ent.vel[1] = 0;
|
||||
ent.pos[1] = hpos1[1] - ent.hitbox[3] - ent.hitbox[1];
|
||||
ent.standing = true;
|
||||
if (ent instanceof Mario.Player) {
|
||||
ent.jumping = 0;
|
||||
}
|
||||
} else if (
|
||||
Math.abs(hpos2[1] - hpos1[1] - this.hitbox[3]) > ent.vel[1] &&
|
||||
center + 2 >= hpos1[0] &&
|
||||
center - 2 <= hpos1[0] + this.hitbox[2]
|
||||
) {
|
||||
//ent is under the block.
|
||||
ent.vel[1] = 0;
|
||||
ent.pos[1] = hpos1[1] + this.hitbox[3];
|
||||
if (ent instanceof Mario.Player) {
|
||||
this.bonk(ent.power);
|
||||
ent.jumping = 0;
|
||||
}
|
||||
} else {
|
||||
//entity is hitting it from the side, we're a wall
|
||||
ent.collideWall(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//if the hitboxes actually overlap
|
||||
if (!(hpos1[0] > hpos2[0]+ent.hitbox[2] || (hpos1[0]+this.hitbox[2] < hpos2[0]))) {
|
||||
if (!(hpos1[1] > hpos2[1]+ent.hitbox[3] || (hpos1[1]+this.hitbox[3] < hpos2[1]))) {
|
||||
if (!this.standing) {
|
||||
ent.bump();
|
||||
} else {
|
||||
//if the entity is over the block, it's basically floor
|
||||
var center = hpos2[0] + ent.hitbox[2] / 2;
|
||||
if (Math.abs(hpos2[1] + ent.hitbox[3] - hpos1[1]) <= ent.vel[1]) {
|
||||
if (level.statics[(this.pos[1] / 16) - 1][this.pos[0] / 16]) {return};
|
||||
ent.vel[1] = 0;
|
||||
ent.pos[1] = hpos1[1] - ent.hitbox[3] - ent.hitbox[1];
|
||||
ent.standing = true;
|
||||
if (ent instanceof Mario.Player) {
|
||||
ent.jumping = 0;
|
||||
}
|
||||
} else if (Math.abs(hpos2[1] - hpos1[1] - this.hitbox[3]) > ent.vel[1] &&
|
||||
center + 2 >= hpos1[0] && center - 2 <= hpos1[0] + this.hitbox[2]) {
|
||||
//ent is under the block.
|
||||
ent.vel[1] = 0;
|
||||
ent.pos[1] = hpos1[1] + this.hitbox[3];
|
||||
if (ent instanceof Mario.Player) {
|
||||
this.bonk(ent.power);
|
||||
ent.jumping = 0;
|
||||
}
|
||||
} else {
|
||||
//entity is hitting it from the side, we're a wall
|
||||
ent.collideWall(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Floor.prototype.bonk = function() {;}
|
||||
Floor.prototype.bonk = function () {};
|
||||
})();
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
var requestAnimFrame = (function(){
|
||||
return window.requestAnimationFrame ||
|
||||
var requestAnimFrame = (function () {
|
||||
return (
|
||||
window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.oRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function(callback){
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.oRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function (callback) {
|
||||
window.setTimeout(callback, 1000 / 60);
|
||||
};
|
||||
}
|
||||
);
|
||||
})();
|
||||
|
||||
//create the canvas
|
||||
var canvas = document.createElement("canvas");
|
||||
var ctx = canvas.getContext('2d');
|
||||
var ctx = canvas.getContext("2d");
|
||||
var updateables = [];
|
||||
var fireballs = [];
|
||||
var player = new Mario.Player([0,0]);
|
||||
var player = new Mario.Player([0, 0]);
|
||||
|
||||
//we might have to get the size and calculate the scaling
|
||||
//but this method should let us make it however big.
|
||||
@@ -23,23 +25,23 @@ var player = new Mario.Player([0,0]);
|
||||
//TODO: fiddling with scaled sprites looks BETTER, but not perfect. Hmm.
|
||||
canvas.width = 762;
|
||||
canvas.height = 720;
|
||||
ctx.scale(3,3);
|
||||
ctx.scale(3, 3);
|
||||
document.body.appendChild(canvas);
|
||||
|
||||
//viewport
|
||||
var vX = 0,
|
||||
vY = 0,
|
||||
vWidth = 256,
|
||||
vHeight = 240;
|
||||
vY = 0,
|
||||
vWidth = 256,
|
||||
vHeight = 240;
|
||||
|
||||
//load our images
|
||||
resources.load([
|
||||
'sprites/player.png',
|
||||
'sprites/enemy.png',
|
||||
'sprites/tiles.png',
|
||||
'sprites/playerl.png',
|
||||
'sprites/items.png',
|
||||
'sprites/enemyr.png',
|
||||
"sprites/player.png",
|
||||
"sprites/enemy.png",
|
||||
"sprites/tiles.png",
|
||||
"sprites/playerl.png",
|
||||
"sprites/items.png",
|
||||
"sprites/enemyr.png",
|
||||
]);
|
||||
|
||||
resources.onReady(init);
|
||||
@@ -51,24 +53,24 @@ var music;
|
||||
var lastTime;
|
||||
function init() {
|
||||
music = {
|
||||
overworld: new Audio('sounds/aboveground_bgm.ogg'),
|
||||
underground: new Audio('sounds/underground_bgm.ogg'),
|
||||
clear: new Audio('sounds/stage_clear.wav'),
|
||||
death: new Audio('sounds/mariodie.wav')
|
||||
overworld: new Audio("sounds/aboveground_bgm.ogg"),
|
||||
underground: new Audio("sounds/underground_bgm.ogg"),
|
||||
clear: new Audio("sounds/stage_clear.wav"),
|
||||
death: new Audio("sounds/mariodie.wav"),
|
||||
};
|
||||
sounds = {
|
||||
smallJump: new Audio('sounds/jump-small.wav'),
|
||||
bigJump: new Audio('sounds/jump-super.wav'),
|
||||
breakBlock: new Audio('sounds/breakblock.wav'),
|
||||
bump: new Audio('sounds/bump.wav'),
|
||||
coin: new Audio('sounds/coin.wav'),
|
||||
fireball: new Audio('sounds/fireball.wav'),
|
||||
flagpole: new Audio('sounds/flagpole.wav'),
|
||||
kick: new Audio('sounds/kick.wav'),
|
||||
pipe: new Audio('sounds/pipe.wav'),
|
||||
itemAppear: new Audio('sounds/itemAppear.wav'),
|
||||
powerup: new Audio('sounds/powerup.wav'),
|
||||
stomp: new Audio('sounds/stomp.wav')
|
||||
smallJump: new Audio("sounds/jump-small.wav"),
|
||||
bigJump: new Audio("sounds/jump-super.wav"),
|
||||
breakBlock: new Audio("sounds/breakblock.wav"),
|
||||
bump: new Audio("sounds/bump.wav"),
|
||||
coin: new Audio("sounds/coin.wav"),
|
||||
fireball: new Audio("sounds/fireball.wav"),
|
||||
flagpole: new Audio("sounds/flagpole.wav"),
|
||||
kick: new Audio("sounds/kick.wav"),
|
||||
pipe: new Audio("sounds/pipe.wav"),
|
||||
itemAppear: new Audio("sounds/itemAppear.wav"),
|
||||
powerup: new Audio("sounds/powerup.wav"),
|
||||
stomp: new Audio("sounds/stomp.wav"),
|
||||
};
|
||||
Mario.oneone();
|
||||
lastTime = Date.now();
|
||||
@@ -101,28 +103,29 @@ function update(dt) {
|
||||
function handleInput(dt) {
|
||||
if (player.piping || player.dying || player.noInput) return; //don't accept input
|
||||
|
||||
if (input.isDown('RUN')){
|
||||
if (input.isDown("RUN")) {
|
||||
player.run();
|
||||
} else {
|
||||
player.noRun();
|
||||
}
|
||||
if (input.isDown('JUMP')) {
|
||||
if (input.isDown("JUMP")) {
|
||||
player.jump();
|
||||
} else {
|
||||
//we need this to handle the timing for how long you hold it
|
||||
player.noJump();
|
||||
}
|
||||
|
||||
if (input.isDown('DOWN')) {
|
||||
if (input.isDown("DOWN")) {
|
||||
player.crouch();
|
||||
} else {
|
||||
player.noCrouch();
|
||||
}
|
||||
|
||||
if (input.isDown('LEFT')) { // 'd' or left arrow
|
||||
if (input.isDown("LEFT")) {
|
||||
// 'd' or left arrow
|
||||
player.moveLeft();
|
||||
}
|
||||
else if (input.isDown('RIGHT')) { // 'k' or right arrow
|
||||
} else if (input.isDown("RIGHT")) {
|
||||
// 'k' or right arrow
|
||||
player.moveRight();
|
||||
} else {
|
||||
player.noWalk();
|
||||
@@ -132,51 +135,54 @@ function handleInput(dt) {
|
||||
//update all the moving stuff
|
||||
function updateEntities(dt, gameTime) {
|
||||
player.update(dt, vX);
|
||||
updateables.forEach (function(ent) {
|
||||
updateables.forEach(function (ent) {
|
||||
ent.update(dt, gameTime);
|
||||
});
|
||||
|
||||
//This should stop the jump when he switches sides on the flag.
|
||||
if (player.exiting) {
|
||||
if (player.pos[0] > vX + 96)
|
||||
vX = player.pos[0] - 96
|
||||
}else if (level.scrolling && player.pos[0] > vX + 80) {
|
||||
if (player.pos[0] > vX + 96) vX = player.pos[0] - 96;
|
||||
} else if (level.scrolling && player.pos[0] > vX + 80) {
|
||||
vX = player.pos[0] - 80;
|
||||
}
|
||||
|
||||
if (player.powering.length !== 0 || player.dying) { return; }
|
||||
level.items.forEach (function(ent) {
|
||||
if (player.powering.length !== 0 || player.dying) {
|
||||
return;
|
||||
}
|
||||
level.items.forEach(function (ent) {
|
||||
ent.update(dt);
|
||||
});
|
||||
|
||||
level.enemies.forEach (function(ent) {
|
||||
level.enemies.forEach(function (ent) {
|
||||
ent.update(dt, vX);
|
||||
});
|
||||
|
||||
fireballs.forEach(function(fireball) {
|
||||
fireballs.forEach(function (fireball) {
|
||||
fireball.update(dt);
|
||||
});
|
||||
level.pipes.forEach (function(pipe) {
|
||||
level.pipes.forEach(function (pipe) {
|
||||
pipe.update(dt);
|
||||
});
|
||||
}
|
||||
|
||||
//scan for collisions
|
||||
function checkCollisions() {
|
||||
if (player.powering.length !== 0 || player.dying) { return; }
|
||||
if (player.powering.length !== 0 || player.dying) {
|
||||
return;
|
||||
}
|
||||
player.checkCollisions();
|
||||
|
||||
//Apparently for each will just skip indices where things were deleted.
|
||||
level.items.forEach(function(item) {
|
||||
level.items.forEach(function (item) {
|
||||
item.checkCollisions();
|
||||
});
|
||||
level.enemies.forEach (function(ent) {
|
||||
level.enemies.forEach(function (ent) {
|
||||
ent.checkCollisions();
|
||||
});
|
||||
fireballs.forEach(function(fireball){
|
||||
fireballs.forEach(function (fireball) {
|
||||
fireball.checkCollisions();
|
||||
});
|
||||
level.pipes.forEach (function(pipe) {
|
||||
level.pipes.forEach(function (pipe) {
|
||||
pipe.checkCollisions();
|
||||
});
|
||||
}
|
||||
@@ -189,8 +195,8 @@ function render() {
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
//scenery gets drawn first to get layering right.
|
||||
for(var i = 0; i < 15; i++) {
|
||||
for (var j = Math.floor(vX / 16) - 1; j < Math.floor(vX / 16) + 20; j++){
|
||||
for (var i = 0; i < 15; i++) {
|
||||
for (var j = Math.floor(vX / 16) - 1; j < Math.floor(vX / 16) + 20; j++) {
|
||||
if (level.scenery[i][j]) {
|
||||
renderEntity(level.scenery[i][j]);
|
||||
}
|
||||
@@ -198,23 +204,21 @@ function render() {
|
||||
}
|
||||
|
||||
//then items
|
||||
level.items.forEach (function (item) {
|
||||
level.items.forEach(function (item) {
|
||||
renderEntity(item);
|
||||
});
|
||||
|
||||
level.enemies.forEach (function(enemy) {
|
||||
level.enemies.forEach(function (enemy) {
|
||||
renderEntity(enemy);
|
||||
});
|
||||
|
||||
|
||||
|
||||
fireballs.forEach(function(fireball) {
|
||||
fireballs.forEach(function (fireball) {
|
||||
renderEntity(fireball);
|
||||
})
|
||||
});
|
||||
|
||||
//then we draw every static object.
|
||||
for(var i = 0; i < 15; i++) {
|
||||
for (var j = Math.floor(vX / 16) - 1; j < Math.floor(vX / 16) + 20; j++){
|
||||
for (var i = 0; i < 15; i++) {
|
||||
for (var j = Math.floor(vX / 16) - 1; j < Math.floor(vX / 16) + 20; j++) {
|
||||
if (level.statics[i][j]) {
|
||||
renderEntity(level.statics[i][j]);
|
||||
}
|
||||
@@ -231,7 +235,7 @@ function render() {
|
||||
}
|
||||
|
||||
//Mario goes INTO pipes, so naturally they go after.
|
||||
level.pipes.forEach (function(pipe) {
|
||||
level.pipes.forEach(function (pipe) {
|
||||
renderEntity(pipe);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
//TODO: On console the hitbox is smaller. Measure it and edit this.
|
||||
|
||||
var Goomba = Mario.Goomba = function(pos, sprite) {
|
||||
var Goomba = (Mario.Goomba = function (pos, sprite) {
|
||||
this.dying = false;
|
||||
Mario.Entity.call(this, {
|
||||
pos: pos,
|
||||
sprite: sprite,
|
||||
hitbox: [0,0,16,16]
|
||||
hitbox: [0, 0, 16, 16],
|
||||
});
|
||||
this.vel[0] = -0.5;
|
||||
this.idx = level.enemies.length;
|
||||
};
|
||||
});
|
||||
|
||||
Goomba.prototype.render = function(ctx, vX, vY) {
|
||||
Goomba.prototype.render = function (ctx, vX, vY) {
|
||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||
};
|
||||
|
||||
Goomba.prototype.update = function(dt, vX) {
|
||||
if (this.pos[0] - vX > 336) { //if we're too far away, do nothing.
|
||||
Goomba.prototype.update = function (dt, vX) {
|
||||
if (this.pos[0] - vX > 336) {
|
||||
//if we're too far away, do nothing.
|
||||
return;
|
||||
} else if (this.pos[0] - vX < -32) {
|
||||
delete level.enemies[this.idx];
|
||||
@@ -39,11 +39,11 @@
|
||||
this.sprite.update(dt);
|
||||
};
|
||||
|
||||
Goomba.prototype.collideWall = function() {
|
||||
Goomba.prototype.collideWall = function () {
|
||||
this.vel[0] = -this.vel[0];
|
||||
};
|
||||
|
||||
Goomba.prototype.checkCollisions = function() {
|
||||
Goomba.prototype.checkCollisions = function () {
|
||||
if (this.flipping) {
|
||||
return;
|
||||
}
|
||||
@@ -70,10 +70,12 @@
|
||||
}
|
||||
}
|
||||
var that = this;
|
||||
level.enemies.forEach(function(enemy){
|
||||
if (enemy === that) { //don't check collisions with ourselves.
|
||||
level.enemies.forEach(function (enemy) {
|
||||
if (enemy === that) {
|
||||
//don't check collisions with ourselves.
|
||||
return;
|
||||
} else if (enemy.pos[0] - vX > 336){ //stop checking once we get to far away dudes.
|
||||
} else if (enemy.pos[0] - vX > 336) {
|
||||
//stop checking once we get to far away dudes.
|
||||
return;
|
||||
} else {
|
||||
that.isCollideWith(enemy);
|
||||
@@ -82,7 +84,7 @@
|
||||
this.isCollideWith(player);
|
||||
};
|
||||
|
||||
Goomba.prototype.isCollideWith = function(ent) {
|
||||
Goomba.prototype.isCollideWith = function (ent) {
|
||||
if (ent instanceof Mario.Player && (this.dying || ent.invincibility)) {
|
||||
return;
|
||||
}
|
||||
@@ -92,14 +94,27 @@
|
||||
var hpos2 = [ent.pos[0] + ent.hitbox[0], ent.pos[1] + ent.hitbox[1]];
|
||||
|
||||
//if the hitboxes actually overlap
|
||||
if (!(hpos1[0] > hpos2[0]+ent.hitbox[2] || (hpos1[0]+this.hitbox[2] < hpos2[0]))) {
|
||||
if (!(hpos1[1] > hpos2[1]+ent.hitbox[3] || (hpos1[1]+this.hitbox[3] < hpos2[1]))) {
|
||||
if (ent instanceof Mario.Player) { //if we hit the player
|
||||
if (ent.vel[1] > 0) { //then the goomba dies
|
||||
if (
|
||||
!(
|
||||
hpos1[0] > hpos2[0] + ent.hitbox[2] ||
|
||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
||||
)
|
||||
) {
|
||||
if (
|
||||
!(
|
||||
hpos1[1] > hpos2[1] + ent.hitbox[3] ||
|
||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
||||
)
|
||||
) {
|
||||
if (ent instanceof Mario.Player) {
|
||||
//if we hit the player
|
||||
if (ent.vel[1] > 0) {
|
||||
//then the goomba dies
|
||||
this.stomp();
|
||||
} else if (ent.starTime) {
|
||||
this.bump();
|
||||
} else { //or the player gets hit
|
||||
} else {
|
||||
//or the player gets hit
|
||||
ent.damage();
|
||||
}
|
||||
} else {
|
||||
@@ -109,7 +124,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
Goomba.prototype.stomp = function() {
|
||||
Goomba.prototype.stomp = function () {
|
||||
sounds.stomp.play();
|
||||
player.bounce = true;
|
||||
this.sprite.pos[0] = 32;
|
||||
@@ -118,9 +133,9 @@
|
||||
this.dying = 10;
|
||||
};
|
||||
|
||||
Goomba.prototype.bump = function() {
|
||||
Goomba.prototype.bump = function () {
|
||||
sounds.kick.play();
|
||||
this.sprite.img = 'sprites/enemyr.png';
|
||||
this.sprite.img = "sprites/enemyr.png";
|
||||
this.flipping = true;
|
||||
this.pos[1] -= 1;
|
||||
this.vel[0] = 0;
|
||||
|
||||
@@ -1,54 +1,61 @@
|
||||
(function() {
|
||||
var pressedKeys = {};
|
||||
(function () {
|
||||
var pressedKeys = {};
|
||||
|
||||
function setKey(event, status) {
|
||||
var code = event.keyCode;
|
||||
var key;
|
||||
function setKey(event, status) {
|
||||
var code = event.keyCode;
|
||||
var key;
|
||||
|
||||
switch(code) {
|
||||
case 32:
|
||||
key = 'SPACE'; break;
|
||||
case 37:
|
||||
key = 'LEFT'; break;
|
||||
case 38:
|
||||
key = 'UP'; break;
|
||||
case 39:
|
||||
key = 'RIGHT'; break;
|
||||
case 40:
|
||||
key = 'DOWN'; break;
|
||||
case 88:
|
||||
key = 'JUMP'; break;
|
||||
case 90:
|
||||
key = 'RUN'; break;
|
||||
default:
|
||||
key = String.fromCharCode(code);
|
||||
}
|
||||
|
||||
pressedKeys[key] = status;
|
||||
switch (code) {
|
||||
case 32:
|
||||
key = "SPACE";
|
||||
break;
|
||||
case 37:
|
||||
key = "LEFT";
|
||||
break;
|
||||
case 38:
|
||||
key = "UP";
|
||||
break;
|
||||
case 39:
|
||||
key = "RIGHT";
|
||||
break;
|
||||
case 40:
|
||||
key = "DOWN";
|
||||
break;
|
||||
case 88:
|
||||
key = "JUMP";
|
||||
break;
|
||||
case 90:
|
||||
key = "RUN";
|
||||
break;
|
||||
default:
|
||||
key = String.fromCharCode(code);
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', function(e) {
|
||||
setKey(e, true);
|
||||
});
|
||||
pressedKeys[key] = status;
|
||||
}
|
||||
|
||||
document.addEventListener('keyup', function(e) {
|
||||
setKey(e, false);
|
||||
});
|
||||
document.addEventListener("keydown", function (e) {
|
||||
setKey(e, true);
|
||||
});
|
||||
|
||||
window.addEventListener('blur', function() {
|
||||
pressedKeys = {};
|
||||
});
|
||||
document.addEventListener("keyup", function (e) {
|
||||
setKey(e, false);
|
||||
});
|
||||
|
||||
window.input = {
|
||||
isDown: function(key) {
|
||||
return pressedKeys[key.toUpperCase()];
|
||||
},
|
||||
reset: function() {
|
||||
pressedKeys['RUN'] = false;
|
||||
pressedKeys['LEFT'] = false;
|
||||
pressedKeys['RIGHT'] = false;
|
||||
pressedKeys['DOWN'] = false;
|
||||
pressedKeys['JUMP'] = false;
|
||||
}
|
||||
};
|
||||
window.addEventListener("blur", function () {
|
||||
pressedKeys = {};
|
||||
});
|
||||
|
||||
window.input = {
|
||||
isDown: function (key) {
|
||||
return pressedKeys[key.toUpperCase()];
|
||||
},
|
||||
reset: function () {
|
||||
pressedKeys["RUN"] = false;
|
||||
pressedKeys["LEFT"] = false;
|
||||
pressedKeys["RIGHT"] = false;
|
||||
pressedKeys["DOWN"] = false;
|
||||
pressedKeys["JUMP"] = false;
|
||||
},
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
var Koopa = Mario.Koopa = function(pos, sprite, para) {
|
||||
var Koopa = (Mario.Koopa = function (pos, sprite, para) {
|
||||
this.dying = false;
|
||||
this.shell = false;
|
||||
|
||||
@@ -14,33 +13,34 @@
|
||||
Mario.Entity.call(this, {
|
||||
pos: pos,
|
||||
sprite: sprite,
|
||||
hitbox: [2,8,12,24]
|
||||
hitbox: [2, 8, 12, 24],
|
||||
});
|
||||
this.vel[0] = -0.5;
|
||||
this.idx = level.enemies.length;
|
||||
};
|
||||
});
|
||||
|
||||
Koopa.prototype.render = function(ctx, vX, vY) {
|
||||
Koopa.prototype.render = function (ctx, vX, vY) {
|
||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||
};
|
||||
|
||||
Koopa.prototype.update = function(dt, vX) {
|
||||
Koopa.prototype.update = function (dt, vX) {
|
||||
if (this.turn) {
|
||||
this.vel[0] = -this.vel[0];
|
||||
if (this.shell) sounds.bump.play();
|
||||
this.turn = false;
|
||||
}
|
||||
if (this.vel[0] != 0) {
|
||||
this.left = (this.vel[0] < 0);
|
||||
this.left = this.vel[0] < 0;
|
||||
}
|
||||
|
||||
if (this.left) {
|
||||
this.sprite.img = 'sprites/enemy.png';
|
||||
this.sprite.img = "sprites/enemy.png";
|
||||
} else {
|
||||
this.sprite.img = 'sprites/enemyr.png';
|
||||
this.sprite.img = "sprites/enemyr.png";
|
||||
}
|
||||
|
||||
if (this.pos[0] - vX > 336) { //if we're too far away, do nothing.
|
||||
if (this.pos[0] - vX > 336) {
|
||||
//if we're too far away, do nothing.
|
||||
return;
|
||||
} else if (this.pos[0] - vX < -32) {
|
||||
delete level.enemies[this.idx];
|
||||
@@ -61,9 +61,9 @@
|
||||
}
|
||||
if (this.shell == 0) {
|
||||
this.sprite = level.koopaSprite();
|
||||
this.hitbox = [2,8,12,24]
|
||||
this.hitbox = [2, 8, 12, 24];
|
||||
if (this.left) {
|
||||
this.sprite.img = 'sprites/enemyr.png';
|
||||
this.sprite.img = "sprites/enemyr.png";
|
||||
this.vel[0] = 0.5;
|
||||
this.left = false;
|
||||
} else {
|
||||
@@ -85,13 +85,13 @@
|
||||
this.sprite.update(dt);
|
||||
};
|
||||
|
||||
Koopa.prototype.collideWall = function() {
|
||||
Koopa.prototype.collideWall = function () {
|
||||
//This stops us from flipping twice on the same frame if we collide
|
||||
//with multiple wall tiles simultaneously.
|
||||
this.turn = true;
|
||||
};
|
||||
|
||||
Koopa.prototype.checkCollisions = function() {
|
||||
Koopa.prototype.checkCollisions = function () {
|
||||
var h = this.shell ? 1 : 2;
|
||||
if (this.pos[1] % 16 !== 0) {
|
||||
h += 1;
|
||||
@@ -121,10 +121,12 @@
|
||||
}
|
||||
}
|
||||
var that = this;
|
||||
level.enemies.forEach(function(enemy){
|
||||
if (enemy === that) { //don't check collisions with ourselves.
|
||||
level.enemies.forEach(function (enemy) {
|
||||
if (enemy === that) {
|
||||
//don't check collisions with ourselves.
|
||||
return;
|
||||
} else if (enemy.pos[0] - vX > 336){ //stop checking once we get to far away dudes.
|
||||
} else if (enemy.pos[0] - vX > 336) {
|
||||
//stop checking once we get to far away dudes.
|
||||
return;
|
||||
} else {
|
||||
that.isCollideWith(enemy);
|
||||
@@ -133,7 +135,7 @@
|
||||
this.isCollideWith(player);
|
||||
};
|
||||
|
||||
Koopa.prototype.isCollideWith = function(ent) {
|
||||
Koopa.prototype.isCollideWith = function (ent) {
|
||||
if (ent instanceof Mario.Player && (this.dying || ent.invincibility)) {
|
||||
return;
|
||||
}
|
||||
@@ -143,8 +145,18 @@
|
||||
var hpos2 = [ent.pos[0] + ent.hitbox[0], ent.pos[1] + ent.hitbox[1]];
|
||||
|
||||
//if the hitboxes actually overlap
|
||||
if (!(hpos1[0] > hpos2[0]+ent.hitbox[2] || (hpos1[0]+this.hitbox[2] < hpos2[0]))) {
|
||||
if (!(hpos1[1] > hpos2[1]+ent.hitbox[3] || (hpos1[1]+this.hitbox[3] < hpos2[1]))) {
|
||||
if (
|
||||
!(
|
||||
hpos1[0] > hpos2[0] + ent.hitbox[2] ||
|
||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
||||
)
|
||||
) {
|
||||
if (
|
||||
!(
|
||||
hpos1[1] > hpos2[1] + ent.hitbox[3] ||
|
||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
||||
)
|
||||
) {
|
||||
if (ent instanceof Mario.Player) {
|
||||
if (ent.vel[1] > 0) {
|
||||
player.bounce = true;
|
||||
@@ -152,7 +164,8 @@
|
||||
if (this.shell) {
|
||||
sounds.kick.play();
|
||||
if (this.vel[0] === 0) {
|
||||
if (ent.left) { //I'm pretty sure this isn't the real logic.
|
||||
if (ent.left) {
|
||||
//I'm pretty sure this isn't the real logic.
|
||||
this.vel[0] = -4;
|
||||
} else {
|
||||
this.vel[0] = 4;
|
||||
@@ -162,13 +175,15 @@
|
||||
this.vel[0] = 0;
|
||||
} else ent.damage();
|
||||
}
|
||||
} else if (ent.vel[1] > 0) { //then we get BOPPED.
|
||||
} else if (ent.vel[1] > 0) {
|
||||
//then we get BOPPED.
|
||||
this.stomp();
|
||||
} else { //or the player gets hit
|
||||
} else {
|
||||
//or the player gets hit
|
||||
ent.damage();
|
||||
}
|
||||
} else {
|
||||
if (this.shell && (ent instanceof Mario.Goomba)) {
|
||||
if (this.shell && ent instanceof Mario.Goomba) {
|
||||
ent.bump();
|
||||
} else this.collideWall();
|
||||
}
|
||||
@@ -176,7 +191,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
Koopa.prototype.stomp = function() {
|
||||
Koopa.prototype.stomp = function () {
|
||||
//Turn this thing into a shell if it isn't already. Kick it if it is.
|
||||
player.bounce = true;
|
||||
if (this.para) {
|
||||
@@ -187,22 +202,21 @@
|
||||
this.shell = 360;
|
||||
this.sprite.pos[0] += 64;
|
||||
this.sprite.pos[1] += 16;
|
||||
this.sprite.size = [16,16];
|
||||
this.hitbox = [2,0,12,16];
|
||||
this.sprite.size = [16, 16];
|
||||
this.hitbox = [2, 0, 12, 16];
|
||||
this.sprite.speed = 0;
|
||||
this.frames = [0,1];
|
||||
this.vel = [0,0];
|
||||
this.frames = [0, 1];
|
||||
this.vel = [0, 0];
|
||||
this.pos[1] += 16;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Koopa.prototype.bump = function() {
|
||||
Koopa.prototype.bump = function () {
|
||||
sounds.kick.play();
|
||||
if (this.flipping) return;
|
||||
this.flipping = true;
|
||||
this.sprite.pos = [160, 0];
|
||||
this.sprite.size = [16,16];
|
||||
this.sprite.size = [16, 16];
|
||||
this.hitbox = [2, 0, 12, 16];
|
||||
this.sprite.speed = 0;
|
||||
this.vel[0] = 0;
|
||||
|
||||
@@ -1,117 +1,208 @@
|
||||
var oneone = Mario.oneone = function() {
|
||||
var oneone = (Mario.oneone = function () {
|
||||
//The things that need to be passed in are basically just dependent on what
|
||||
//tileset we're in, so it makes more sense to just make one variable for that, so
|
||||
//TODO: put as much of this in the Level object definition as possible.
|
||||
level = new Mario.Level({
|
||||
playerPos: [56,192],
|
||||
playerPos: [56, 192],
|
||||
loader: Mario.oneone,
|
||||
background: "#7974FF",
|
||||
scrolling: true,
|
||||
invincibility: [144, 192, 240],
|
||||
exit: 204,
|
||||
floorSprite: new Mario.Sprite('sprites/tiles.png', [0,0],[16,16],0),
|
||||
cloudSprite: new Mario.Sprite('sprites/tiles.png', [0,320],[48,32],0),
|
||||
wallSprite: new Mario.Sprite('sprites/tiles.png', [0, 16],[16,16],0),
|
||||
brickSprite: new Mario.Sprite('sprites/tiles.png', [16, 0], [16,16], 0),
|
||||
brickBounceSprite: new Mario.Sprite('sprites/tiles.png',[32,0],[16,16],0),
|
||||
floorSprite: new Mario.Sprite("sprites/tiles.png", [0, 0], [16, 16], 0),
|
||||
cloudSprite: new Mario.Sprite("sprites/tiles.png", [0, 320], [48, 32], 0),
|
||||
wallSprite: new Mario.Sprite("sprites/tiles.png", [0, 16], [16, 16], 0),
|
||||
brickSprite: new Mario.Sprite("sprites/tiles.png", [16, 0], [16, 16], 0),
|
||||
brickBounceSprite: new Mario.Sprite(
|
||||
"sprites/tiles.png",
|
||||
[32, 0],
|
||||
[16, 16],
|
||||
0,
|
||||
),
|
||||
rubbleSprite: function () {
|
||||
return new Mario.Sprite('sprites/items.png', [64,0], [8,8], 3, [0,1])
|
||||
return new Mario.Sprite("sprites/items.png", [64, 0], [8, 8], 3, [0, 1]);
|
||||
},
|
||||
ublockSprite: new Mario.Sprite('sprites/tiles.png', [48, 0], [16,16],0),
|
||||
superShroomSprite: new Mario.Sprite('sprites/items.png', [0,0], [16,16], 0),
|
||||
fireFlowerSprite: new Mario.Sprite('sprites/items.png', [0,32], [16,16], 20, [0,1,2,3]),
|
||||
starSprite: new Mario.Sprite('sprites/items.png', [0,48], [16,16], 20, [0,1,2,3]),
|
||||
pipeLEndSprite: new Mario.Sprite('sprites/tiles.png', [0, 128], [16,16], 0),
|
||||
pipeREndSprite: new Mario.Sprite('sprites/tiles.png', [16, 128], [16,16], 0),
|
||||
pipeLMidSprite: new Mario.Sprite('sprites/tiles.png', [0, 144], [16,16], 0),
|
||||
pipeRMidSprite: new Mario.Sprite('sprites/tiles.png', [16, 144], [16,16], 0),
|
||||
ublockSprite: new Mario.Sprite("sprites/tiles.png", [48, 0], [16, 16], 0),
|
||||
superShroomSprite: new Mario.Sprite(
|
||||
"sprites/items.png",
|
||||
[0, 0],
|
||||
[16, 16],
|
||||
0,
|
||||
),
|
||||
fireFlowerSprite: new Mario.Sprite(
|
||||
"sprites/items.png",
|
||||
[0, 32],
|
||||
[16, 16],
|
||||
20,
|
||||
[0, 1, 2, 3],
|
||||
),
|
||||
starSprite: new Mario.Sprite(
|
||||
"sprites/items.png",
|
||||
[0, 48],
|
||||
[16, 16],
|
||||
20,
|
||||
[0, 1, 2, 3],
|
||||
),
|
||||
pipeLEndSprite: new Mario.Sprite(
|
||||
"sprites/tiles.png",
|
||||
[0, 128],
|
||||
[16, 16],
|
||||
0,
|
||||
),
|
||||
pipeREndSprite: new Mario.Sprite(
|
||||
"sprites/tiles.png",
|
||||
[16, 128],
|
||||
[16, 16],
|
||||
0,
|
||||
),
|
||||
pipeLMidSprite: new Mario.Sprite(
|
||||
"sprites/tiles.png",
|
||||
[0, 144],
|
||||
[16, 16],
|
||||
0,
|
||||
),
|
||||
pipeRMidSprite: new Mario.Sprite(
|
||||
"sprites/tiles.png",
|
||||
[16, 144],
|
||||
[16, 16],
|
||||
0,
|
||||
),
|
||||
|
||||
pipeUpMid: new Mario.Sprite('sprites/tiles.png', [0, 144], [32,16], 0),
|
||||
pipeSideMid: new Mario.Sprite('sprites/tiles.png', [48, 128], [16,32], 0),
|
||||
pipeLeft: new Mario.Sprite('sprites/tiles.png', [32, 128], [16,32], 0),
|
||||
pipeTop: new Mario.Sprite('sprites/tiles.png', [0, 128], [32,16], 0),
|
||||
qblockSprite: new Mario.Sprite('sprites/tiles.png', [384, 0], [16,16], 8, [0,0,0,0,1,2,1]),
|
||||
bcoinSprite: function() {
|
||||
return new Mario.Sprite('sprites/items.png', [0,112],[16,16], 20,[0,1,2,3]);
|
||||
pipeUpMid: new Mario.Sprite("sprites/tiles.png", [0, 144], [32, 16], 0),
|
||||
pipeSideMid: new Mario.Sprite("sprites/tiles.png", [48, 128], [16, 32], 0),
|
||||
pipeLeft: new Mario.Sprite("sprites/tiles.png", [32, 128], [16, 32], 0),
|
||||
pipeTop: new Mario.Sprite("sprites/tiles.png", [0, 128], [32, 16], 0),
|
||||
qblockSprite: new Mario.Sprite(
|
||||
"sprites/tiles.png",
|
||||
[384, 0],
|
||||
[16, 16],
|
||||
8,
|
||||
[0, 0, 0, 0, 1, 2, 1],
|
||||
),
|
||||
bcoinSprite: function () {
|
||||
return new Mario.Sprite(
|
||||
"sprites/items.png",
|
||||
[0, 112],
|
||||
[16, 16],
|
||||
20,
|
||||
[0, 1, 2, 3],
|
||||
);
|
||||
},
|
||||
cloudSprites:[
|
||||
new Mario.Sprite('sprites/tiles.png', [0,320],[16,32],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [16,320],[16,32],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [32,320],[16,32],0)
|
||||
cloudSprites: [
|
||||
new Mario.Sprite("sprites/tiles.png", [0, 320], [16, 32], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [16, 320], [16, 32], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [32, 320], [16, 32], 0),
|
||||
],
|
||||
hillSprites: [
|
||||
new Mario.Sprite('sprites/tiles.png', [128,128],[16,16],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [144,128],[16,16],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [160,128],[16,16],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [128,144],[16,16],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [144,144],[16,16],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [160,144],[16,16],0)
|
||||
new Mario.Sprite("sprites/tiles.png", [128, 128], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [144, 128], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [160, 128], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [128, 144], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [144, 144], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [160, 144], [16, 16], 0),
|
||||
],
|
||||
bushSprite: new Mario.Sprite('sprites/tiles.png', [176, 144], [48, 16], 0),
|
||||
bushSprite: new Mario.Sprite("sprites/tiles.png", [176, 144], [48, 16], 0),
|
||||
bushSprites: [
|
||||
new Mario.Sprite('sprites/tiles.png', [176,144], [16,16],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [192,144], [16,16],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [208,144], [16,16],0)],
|
||||
goombaSprite: function() {
|
||||
return new Mario.Sprite('sprites/enemy.png', [0, 16], [16,16], 3, [0,1]);
|
||||
},
|
||||
koopaSprite: function() {
|
||||
return new Mario.Sprite('sprites/enemy.png', [96,0], [16,32], 2, [0,1]);
|
||||
},
|
||||
flagPoleSprites: [
|
||||
new Mario.Sprite('sprites/tiles.png', [256, 128], [16,16], 0),
|
||||
new Mario.Sprite('sprites/tiles.png', [256, 144], [16,16], 0),
|
||||
new Mario.Sprite('sprites/items.png', [128, 32], [16,16], 0)
|
||||
]
|
||||
});
|
||||
ground = [[0,69],[71,86],[89,153],[155,212]];
|
||||
new Mario.Sprite("sprites/tiles.png", [176, 144], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [192, 144], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [208, 144], [16, 16], 0),
|
||||
],
|
||||
goombaSprite: function () {
|
||||
return new Mario.Sprite(
|
||||
"sprites/enemy.png",
|
||||
[0, 16],
|
||||
[16, 16],
|
||||
3,
|
||||
[0, 1],
|
||||
);
|
||||
},
|
||||
koopaSprite: function () {
|
||||
return new Mario.Sprite(
|
||||
"sprites/enemy.png",
|
||||
[96, 0],
|
||||
[16, 32],
|
||||
2,
|
||||
[0, 1],
|
||||
);
|
||||
},
|
||||
flagPoleSprites: [
|
||||
new Mario.Sprite("sprites/tiles.png", [256, 128], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [256, 144], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/items.png", [128, 32], [16, 16], 0),
|
||||
],
|
||||
});
|
||||
ground = [
|
||||
[0, 69],
|
||||
[71, 86],
|
||||
[89, 153],
|
||||
[155, 212],
|
||||
];
|
||||
player.pos[0] = level.playerPos[0];
|
||||
player.pos[1] = level.playerPos[1];
|
||||
vX = 0;
|
||||
|
||||
//build THE GROUND
|
||||
ground.forEach(function(loc) {
|
||||
level.putFloor(loc[0],loc[1]);
|
||||
ground.forEach(function (loc) {
|
||||
level.putFloor(loc[0], loc[1]);
|
||||
});
|
||||
|
||||
//build scenery
|
||||
clouds = [[7,3],[19, 2],[56, 3],[67, 2],[87, 2],[103, 2],[152, 3],[163, 2],[200, 3]];
|
||||
clouds.forEach(function(cloud){
|
||||
level.putCloud(cloud[0],cloud[1]);
|
||||
clouds = [
|
||||
[7, 3],
|
||||
[19, 2],
|
||||
[56, 3],
|
||||
[67, 2],
|
||||
[87, 2],
|
||||
[103, 2],
|
||||
[152, 3],
|
||||
[163, 2],
|
||||
[200, 3],
|
||||
];
|
||||
clouds.forEach(function (cloud) {
|
||||
level.putCloud(cloud[0], cloud[1]);
|
||||
});
|
||||
|
||||
twoClouds = [[36,2],[132,2],[180,2]];
|
||||
twoClouds.forEach(function(cloud){
|
||||
level.putTwoCloud(cloud[0],cloud[1]);
|
||||
twoClouds = [
|
||||
[36, 2],
|
||||
[132, 2],
|
||||
[180, 2],
|
||||
];
|
||||
twoClouds.forEach(function (cloud) {
|
||||
level.putTwoCloud(cloud[0], cloud[1]);
|
||||
});
|
||||
|
||||
threeClouds = [[27,3],[75,3],[123,3],[171,3]];
|
||||
threeClouds.forEach(function(cloud){
|
||||
level.putThreeCloud(cloud[0],cloud[1]);
|
||||
threeClouds = [
|
||||
[27, 3],
|
||||
[75, 3],
|
||||
[123, 3],
|
||||
[171, 3],
|
||||
];
|
||||
threeClouds.forEach(function (cloud) {
|
||||
level.putThreeCloud(cloud[0], cloud[1]);
|
||||
});
|
||||
|
||||
bHills = [0,48,96,144,192]
|
||||
bHills.forEach(function(hill) {
|
||||
bHills = [0, 48, 96, 144, 192];
|
||||
bHills.forEach(function (hill) {
|
||||
level.putBigHill(hill, 12);
|
||||
});
|
||||
|
||||
sHills = [16,64,111,160];
|
||||
sHills.forEach(function(hill) {
|
||||
sHills = [16, 64, 111, 160];
|
||||
sHills.forEach(function (hill) {
|
||||
level.putSmallHill(hill, 12);
|
||||
});
|
||||
|
||||
bushes = [23,71,118,167];
|
||||
bushes.forEach(function(bush) {
|
||||
bushes = [23, 71, 118, 167];
|
||||
bushes.forEach(function (bush) {
|
||||
level.putBush(bush, 12);
|
||||
});
|
||||
|
||||
twoBushes = [41,89,137];
|
||||
twoBushes.forEach(function(bush) {
|
||||
twoBushes = [41, 89, 137];
|
||||
twoBushes.forEach(function (bush) {
|
||||
level.putTwoBush(bush, 12);
|
||||
});
|
||||
|
||||
threeBushes = [11,59,106];
|
||||
threeBushes.forEach(function(bush) {
|
||||
threeBushes = [11, 59, 106];
|
||||
threeBushes.forEach(function (bush) {
|
||||
level.putThreeBush(bush, 12);
|
||||
});
|
||||
|
||||
@@ -216,4 +307,4 @@ var oneone = Mario.oneone = function() {
|
||||
music.underground.pause();
|
||||
// music.overworld.currentTime = 0;
|
||||
music.overworld.play();
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,65 +1,113 @@
|
||||
var oneonetunnel = Mario.oneonetunnel = function() {
|
||||
var oneonetunnel = (Mario.oneonetunnel = function () {
|
||||
level = new Mario.Level({
|
||||
playerPos: [40,16],
|
||||
playerPos: [40, 16],
|
||||
loader: Mario.oneonetunnel,
|
||||
background: "#000000",
|
||||
scrolling: false,
|
||||
coinSprite: function() {
|
||||
return new Mario.Sprite('sprites/items.png', [0,96],[16,16], 6,[0,0,0,0,1,2,1]);
|
||||
coinSprite: function () {
|
||||
return new Mario.Sprite(
|
||||
"sprites/items.png",
|
||||
[0, 96],
|
||||
[16, 16],
|
||||
6,
|
||||
[0, 0, 0, 0, 1, 2, 1],
|
||||
);
|
||||
},
|
||||
floorSprite: new Mario.Sprite('sprites/tiles.png', [0,32],[16,16],0),
|
||||
wallSprite: new Mario.Sprite('sprites/tiles.png', [32, 32],[16,16],0),
|
||||
brickSprite: new Mario.Sprite('sprites/tiles.png', [16, 0], [16,16], 0),
|
||||
brickBounceSprite: new Mario.Sprite('sprites/tiles.png',[32,0],[16,16],0),
|
||||
ublockSprite: new Mario.Sprite('sprites/tiles.png', [48, 0], [16,16],0),
|
||||
pipeLMidSprite: new Mario.Sprite('sprites/tiles.png', [0, 144], [16,16], 0),
|
||||
pipeRMidSprite: new Mario.Sprite('sprites/tiles.png', [16, 144], [16,16], 0),
|
||||
pipeLEndSprite: new Mario.Sprite('sprites/tiles.png', [0, 128], [16,16], 0),
|
||||
pipeREndSprite: new Mario.Sprite('sprites/tiles.png', [16, 128], [16,16], 0),
|
||||
pipeUpMid: new Mario.Sprite('sprites/tiles.png', [0, 144], [32,16], 0),
|
||||
pipeSideMid: new Mario.Sprite('sprites/tiles.png', [48, 128], [16,32], 0),
|
||||
pipeLeft: new Mario.Sprite('sprites/tiles.png', [32, 128], [16,32], 0),
|
||||
pipeTop: new Mario.Sprite('sprites/tiles.png', [0, 128], [32,16], 0),
|
||||
|
||||
LPipeSprites:[
|
||||
new Mario.Sprite('sprites/tiles.png', [32,128],[16,16],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [32,144],[16,16],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [48,128],[16,16],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [48,144],[16,16],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [64,128],[16,16],0),
|
||||
new Mario.Sprite('sprites/tiles.png', [64,144],[16,16],0),
|
||||
]
|
||||
floorSprite: new Mario.Sprite("sprites/tiles.png", [0, 32], [16, 16], 0),
|
||||
wallSprite: new Mario.Sprite("sprites/tiles.png", [32, 32], [16, 16], 0),
|
||||
brickSprite: new Mario.Sprite("sprites/tiles.png", [16, 0], [16, 16], 0),
|
||||
brickBounceSprite: new Mario.Sprite(
|
||||
"sprites/tiles.png",
|
||||
[32, 0],
|
||||
[16, 16],
|
||||
0,
|
||||
),
|
||||
ublockSprite: new Mario.Sprite("sprites/tiles.png", [48, 0], [16, 16], 0),
|
||||
pipeLMidSprite: new Mario.Sprite(
|
||||
"sprites/tiles.png",
|
||||
[0, 144],
|
||||
[16, 16],
|
||||
0,
|
||||
),
|
||||
pipeRMidSprite: new Mario.Sprite(
|
||||
"sprites/tiles.png",
|
||||
[16, 144],
|
||||
[16, 16],
|
||||
0,
|
||||
),
|
||||
pipeLEndSprite: new Mario.Sprite(
|
||||
"sprites/tiles.png",
|
||||
[0, 128],
|
||||
[16, 16],
|
||||
0,
|
||||
),
|
||||
pipeREndSprite: new Mario.Sprite(
|
||||
"sprites/tiles.png",
|
||||
[16, 128],
|
||||
[16, 16],
|
||||
0,
|
||||
),
|
||||
pipeUpMid: new Mario.Sprite("sprites/tiles.png", [0, 144], [32, 16], 0),
|
||||
pipeSideMid: new Mario.Sprite("sprites/tiles.png", [48, 128], [16, 32], 0),
|
||||
pipeLeft: new Mario.Sprite("sprites/tiles.png", [32, 128], [16, 32], 0),
|
||||
pipeTop: new Mario.Sprite("sprites/tiles.png", [0, 128], [32, 16], 0),
|
||||
|
||||
LPipeSprites: [
|
||||
new Mario.Sprite("sprites/tiles.png", [32, 128], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [32, 144], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [48, 128], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [48, 144], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [64, 128], [16, 16], 0),
|
||||
new Mario.Sprite("sprites/tiles.png", [64, 144], [16, 16], 0),
|
||||
],
|
||||
});
|
||||
|
||||
player.pos[0] = level.playerPos[0];
|
||||
player.pos[1] = level.playerPos[1];
|
||||
vX = 0;
|
||||
level.putFloor(0,16);
|
||||
level.putWall(0,13,11);
|
||||
walls = [4,5,6,7,8,9,10];
|
||||
walls.forEach(function(loc){
|
||||
level.putWall(loc,13,3);
|
||||
level.putWall(loc,3,1);
|
||||
level.putFloor(0, 16);
|
||||
level.putWall(0, 13, 11);
|
||||
walls = [4, 5, 6, 7, 8, 9, 10];
|
||||
walls.forEach(function (loc) {
|
||||
level.putWall(loc, 13, 3);
|
||||
level.putWall(loc, 3, 1);
|
||||
});
|
||||
|
||||
coins = [[5,5], [6,5], [7,5], [8,5], [9,5],
|
||||
[4,7], [5,7], [6,7], [7,7], [8,7], [9,7], [10,7],
|
||||
[4,9], [5,9], [6,9], [7,9], [8,9], [9,9], [10,9]];
|
||||
coins.forEach(function(pos){
|
||||
level.putCoin(pos[0],pos[1]);
|
||||
coins = [
|
||||
[5, 5],
|
||||
[6, 5],
|
||||
[7, 5],
|
||||
[8, 5],
|
||||
[9, 5],
|
||||
[4, 7],
|
||||
[5, 7],
|
||||
[6, 7],
|
||||
[7, 7],
|
||||
[8, 7],
|
||||
[9, 7],
|
||||
[10, 7],
|
||||
[4, 9],
|
||||
[5, 9],
|
||||
[6, 9],
|
||||
[7, 9],
|
||||
[8, 9],
|
||||
[9, 9],
|
||||
[10, 9],
|
||||
];
|
||||
coins.forEach(function (pos) {
|
||||
level.putCoin(pos[0], pos[1]);
|
||||
});
|
||||
|
||||
//level.putLeftPipe(13,11);
|
||||
level.putRealPipe(13,11,3,"RIGHT", function() {
|
||||
level.putRealPipe(13, 11, 3, "RIGHT", function () {
|
||||
Mario.oneone.call();
|
||||
player.pos = [2616, 177]
|
||||
player.pipe("UP", function() {;});
|
||||
player.pos = [2616, 177];
|
||||
player.pipe("UP", function () {});
|
||||
});
|
||||
|
||||
level.putPipe(15,13,13);
|
||||
level.putPipe(15, 13, 13);
|
||||
|
||||
music.overworld.pause();
|
||||
music.underground.currentTime = 0;
|
||||
music.underground.play();
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
var Level = Mario.Level = function(options) {
|
||||
(function () {
|
||||
var Level = (Mario.Level = function (options) {
|
||||
this.playerPos = options.playerPos;
|
||||
this.scrolling = options.scrolling;
|
||||
this.loader = options.loader;
|
||||
@@ -55,164 +55,241 @@
|
||||
this.scenery[i] = [];
|
||||
this.blocks[i] = [];
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
Level.prototype.putFloor = function(start, end) {
|
||||
Level.prototype.putFloor = function (start, end) {
|
||||
for (var i = start; i < end; i++) {
|
||||
this.statics[13][i] = new Mario.Floor([16*i,208], this.floorSprite);
|
||||
this.statics[14][i] = new Mario.Floor([16*i,224], this.floorSprite);
|
||||
this.statics[13][i] = new Mario.Floor([16 * i, 208], this.floorSprite);
|
||||
this.statics[14][i] = new Mario.Floor([16 * i, 224], this.floorSprite);
|
||||
}
|
||||
};
|
||||
|
||||
Level.prototype.putGoomba = function(x, y) {
|
||||
this.enemies.push(new Mario.Goomba([16*x, 16*y], this.goombaSprite() ));
|
||||
Level.prototype.putGoomba = function (x, y) {
|
||||
this.enemies.push(new Mario.Goomba([16 * x, 16 * y], this.goombaSprite()));
|
||||
};
|
||||
|
||||
Level.prototype.putKoopa = function(x, y) {
|
||||
this.enemies.push(new Mario.Koopa([16*x, 16*y], this.koopaSprite(), false));
|
||||
Level.prototype.putKoopa = function (x, y) {
|
||||
this.enemies.push(
|
||||
new Mario.Koopa([16 * x, 16 * y], this.koopaSprite(), false),
|
||||
);
|
||||
};
|
||||
|
||||
Level.prototype.putWall = function(x, y, height) {
|
||||
Level.prototype.putWall = function (x, y, height) {
|
||||
//y is the bottom of the wall in this case.
|
||||
for (var i = y-height; i < y; i++) {
|
||||
this.statics[i][x] = new Mario.Floor([16*x, 16*i], this.wallSprite);
|
||||
for (var i = y - height; i < y; i++) {
|
||||
this.statics[i][x] = new Mario.Floor([16 * x, 16 * i], this.wallSprite);
|
||||
}
|
||||
};
|
||||
|
||||
Level.prototype.putPipe = function(x, y, height) {
|
||||
Level.prototype.putPipe = function (x, y, height) {
|
||||
for (var i = y - height; i < y; i++) {
|
||||
if (i === y - height) {
|
||||
this.statics[i][x] = new Mario.Floor([16*x, 16*i], this.pipeLEndSprite);
|
||||
this.statics[i][x+1] = new Mario.Floor([16*x+16, 16*i], this.pipeREndSprite);
|
||||
this.statics[i][x] = new Mario.Floor(
|
||||
[16 * x, 16 * i],
|
||||
this.pipeLEndSprite,
|
||||
);
|
||||
this.statics[i][x + 1] = new Mario.Floor(
|
||||
[16 * x + 16, 16 * i],
|
||||
this.pipeREndSprite,
|
||||
);
|
||||
} else {
|
||||
this.statics[i][x] = new Mario.Floor([16*x, 16*i], this.pipeLMidSprite);
|
||||
this.statics[i][x+1] = new Mario.Floor([16*x+16, 16*i], this.pipeRMidSprite);
|
||||
this.statics[i][x] = new Mario.Floor(
|
||||
[16 * x, 16 * i],
|
||||
this.pipeLMidSprite,
|
||||
);
|
||||
this.statics[i][x + 1] = new Mario.Floor(
|
||||
[16 * x + 16, 16 * i],
|
||||
this.pipeRMidSprite,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//sometimes, pipes don't go straight up and down.
|
||||
Level.prototype.putLeftPipe = function(x,y) {
|
||||
this.statics[y][x] = new Mario.Floor([16*x, 16*y], this.LPipeSprites[0]);
|
||||
this.statics[y+1][x] = new Mario.Floor([16*x,16*(y+1)], this.LPipeSprites[1]);
|
||||
this.statics[y][x+1] = new Mario.Floor([16*(x+1),16*y], this.LPipeSprites[2]);
|
||||
this.statics[y+1][x+1] = new Mario.Floor([16*(x+1),16*(y+1)], this.LPipeSprites[3]);
|
||||
this.statics[y][x+2] = new Mario.Floor([16*(x+2),16*y], this.LPipeSprites[4]);
|
||||
this.statics[y+1][x+2] = new Mario.Floor([16*(x+2),16*(y+1)], this.LPipeSprites[5]);
|
||||
Level.prototype.putLeftPipe = function (x, y) {
|
||||
this.statics[y][x] = new Mario.Floor(
|
||||
[16 * x, 16 * y],
|
||||
this.LPipeSprites[0],
|
||||
);
|
||||
this.statics[y + 1][x] = new Mario.Floor(
|
||||
[16 * x, 16 * (y + 1)],
|
||||
this.LPipeSprites[1],
|
||||
);
|
||||
this.statics[y][x + 1] = new Mario.Floor(
|
||||
[16 * (x + 1), 16 * y],
|
||||
this.LPipeSprites[2],
|
||||
);
|
||||
this.statics[y + 1][x + 1] = new Mario.Floor(
|
||||
[16 * (x + 1), 16 * (y + 1)],
|
||||
this.LPipeSprites[3],
|
||||
);
|
||||
this.statics[y][x + 2] = new Mario.Floor(
|
||||
[16 * (x + 2), 16 * y],
|
||||
this.LPipeSprites[4],
|
||||
);
|
||||
this.statics[y + 1][x + 2] = new Mario.Floor(
|
||||
[16 * (x + 2), 16 * (y + 1)],
|
||||
this.LPipeSprites[5],
|
||||
);
|
||||
};
|
||||
|
||||
Level.prototype.putCoin = function(x, y) {
|
||||
this.items.push(new Mario.Coin(
|
||||
[x*16, y*16],
|
||||
this.coinSprite()
|
||||
));
|
||||
Level.prototype.putCoin = function (x, y) {
|
||||
this.items.push(new Mario.Coin([x * 16, y * 16], this.coinSprite()));
|
||||
};
|
||||
|
||||
Level.prototype.putCloud = function(x, y) {
|
||||
this.scenery[y][x] = new Mario.Prop([x*16, y*16], this.cloudSprite);
|
||||
Level.prototype.putCloud = function (x, y) {
|
||||
this.scenery[y][x] = new Mario.Prop([x * 16, y * 16], this.cloudSprite);
|
||||
};
|
||||
|
||||
Level.prototype.putQBlock = function(x, y, item) {
|
||||
this.blocks[y][x] = new Mario.Block( {
|
||||
pos: [x*16, y*16],
|
||||
Level.prototype.putQBlock = function (x, y, item) {
|
||||
this.blocks[y][x] = new Mario.Block({
|
||||
pos: [x * 16, y * 16],
|
||||
item: item,
|
||||
sprite: this.qblockSprite,
|
||||
usedSprite: this.ublockSprite
|
||||
usedSprite: this.ublockSprite,
|
||||
});
|
||||
};
|
||||
|
||||
Level.prototype.putBrick = function(x,y,item) {
|
||||
Level.prototype.putBrick = function (x, y, item) {
|
||||
this.blocks[y][x] = new Mario.Block({
|
||||
pos: [x*16, y*16],
|
||||
pos: [x * 16, y * 16],
|
||||
item: item,
|
||||
sprite: this.brickSprite,
|
||||
bounceSprite: this.brickBounceSprite,
|
||||
usedSprite: this.ublockSprite,
|
||||
breakable: !item
|
||||
breakable: !item,
|
||||
});
|
||||
};
|
||||
|
||||
Level.prototype.putBigHill = function(x, y) {
|
||||
var px = x*16, py = y*16;
|
||||
Level.prototype.putBigHill = function (x, y) {
|
||||
var px = x * 16,
|
||||
py = y * 16;
|
||||
this.scenery[y][x] = new Mario.Prop([px, py], this.hillSprites[0]);
|
||||
this.scenery[y][x+1] = new Mario.Prop([px+16, py], this.hillSprites[3]);
|
||||
this.scenery[y-1][x+1] = new Mario.Prop([px+16, py-16], this.hillSprites[0]);
|
||||
this.scenery[y][x+2] = new Mario.Prop([px+32, py], this.hillSprites[4]);
|
||||
this.scenery[y-1][x+2] = new Mario.Prop([px+32, py-16], this.hillSprites[3]);
|
||||
this.scenery[y-2][x+2] = new Mario.Prop([px+32, py-32], this.hillSprites[1]);
|
||||
this.scenery[y][x+3] = new Mario.Prop([px+48, py], this.hillSprites[5]);
|
||||
this.scenery[y-1][x+3] = new Mario.Prop([px+48, py-16], this.hillSprites[2]);
|
||||
this.scenery[y][x+4] = new Mario.Prop([px+64, py], this.hillSprites[2]);
|
||||
this.scenery[y][x + 1] = new Mario.Prop([px + 16, py], this.hillSprites[3]);
|
||||
this.scenery[y - 1][x + 1] = new Mario.Prop(
|
||||
[px + 16, py - 16],
|
||||
this.hillSprites[0],
|
||||
);
|
||||
this.scenery[y][x + 2] = new Mario.Prop([px + 32, py], this.hillSprites[4]);
|
||||
this.scenery[y - 1][x + 2] = new Mario.Prop(
|
||||
[px + 32, py - 16],
|
||||
this.hillSprites[3],
|
||||
);
|
||||
this.scenery[y - 2][x + 2] = new Mario.Prop(
|
||||
[px + 32, py - 32],
|
||||
this.hillSprites[1],
|
||||
);
|
||||
this.scenery[y][x + 3] = new Mario.Prop([px + 48, py], this.hillSprites[5]);
|
||||
this.scenery[y - 1][x + 3] = new Mario.Prop(
|
||||
[px + 48, py - 16],
|
||||
this.hillSprites[2],
|
||||
);
|
||||
this.scenery[y][x + 4] = new Mario.Prop([px + 64, py], this.hillSprites[2]);
|
||||
};
|
||||
|
||||
Level.prototype.putBush = function(x, y) {
|
||||
this.scenery[y][x] = new Mario.Prop([x*16, y*16], this.bushSprite);
|
||||
Level.prototype.putBush = function (x, y) {
|
||||
this.scenery[y][x] = new Mario.Prop([x * 16, y * 16], this.bushSprite);
|
||||
};
|
||||
|
||||
Level.prototype.putThreeBush = function(x,y) {
|
||||
px = x*16;
|
||||
py = y*16;
|
||||
Level.prototype.putThreeBush = function (x, y) {
|
||||
px = x * 16;
|
||||
py = y * 16;
|
||||
this.scenery[y][x] = new Mario.Prop([px, py], this.bushSprites[0]);
|
||||
this.scenery[y][x+1] = new Mario.Prop([px+16, py], this.bushSprites[1]);
|
||||
this.scenery[y][x+2] = new Mario.Prop([px+32, py], this.bushSprites[1]);
|
||||
this.scenery[y][x+3] = new Mario.Prop([px+48, py], this.bushSprites[1]);
|
||||
this.scenery[y][x+4] = new Mario.Prop([px+64, py], this.bushSprites[2]);
|
||||
this.scenery[y][x + 1] = new Mario.Prop([px + 16, py], this.bushSprites[1]);
|
||||
this.scenery[y][x + 2] = new Mario.Prop([px + 32, py], this.bushSprites[1]);
|
||||
this.scenery[y][x + 3] = new Mario.Prop([px + 48, py], this.bushSprites[1]);
|
||||
this.scenery[y][x + 4] = new Mario.Prop([px + 64, py], this.bushSprites[2]);
|
||||
};
|
||||
|
||||
Level.prototype.putTwoBush = function(x,y) {
|
||||
px = x*16;
|
||||
py = y*16;
|
||||
Level.prototype.putTwoBush = function (x, y) {
|
||||
px = x * 16;
|
||||
py = y * 16;
|
||||
this.scenery[y][x] = new Mario.Prop([px, py], this.bushSprites[0]);
|
||||
this.scenery[y][x+1] = new Mario.Prop([px+16, py], this.bushSprites[1]);
|
||||
this.scenery[y][x+2] = new Mario.Prop([px+32, py], this.bushSprites[1]);
|
||||
this.scenery[y][x+3] = new Mario.Prop([px+48, py], this.bushSprites[2]);
|
||||
this.scenery[y][x + 1] = new Mario.Prop([px + 16, py], this.bushSprites[1]);
|
||||
this.scenery[y][x + 2] = new Mario.Prop([px + 32, py], this.bushSprites[1]);
|
||||
this.scenery[y][x + 3] = new Mario.Prop([px + 48, py], this.bushSprites[2]);
|
||||
};
|
||||
|
||||
Level.prototype.putSmallHill = function(x, y) {
|
||||
var px = x*16, py = y*16;
|
||||
Level.prototype.putSmallHill = function (x, y) {
|
||||
var px = x * 16,
|
||||
py = y * 16;
|
||||
this.scenery[y][x] = new Mario.Prop([px, py], this.hillSprites[0]);
|
||||
this.scenery[y][x+1] = new Mario.Prop([px+16, py], this.hillSprites[3]);
|
||||
this.scenery[y-1][x+1] = new Mario.Prop([px+16, py-16], this.hillSprites[1]);
|
||||
this.scenery[y][x+2] = new Mario.Prop([px+32, py], this.hillSprites[2]);
|
||||
this.scenery[y][x + 1] = new Mario.Prop([px + 16, py], this.hillSprites[3]);
|
||||
this.scenery[y - 1][x + 1] = new Mario.Prop(
|
||||
[px + 16, py - 16],
|
||||
this.hillSprites[1],
|
||||
);
|
||||
this.scenery[y][x + 2] = new Mario.Prop([px + 32, py], this.hillSprites[2]);
|
||||
};
|
||||
|
||||
Level.prototype.putTwoCloud = function(x,y) {
|
||||
px = x*16;
|
||||
py = y*16;
|
||||
Level.prototype.putTwoCloud = function (x, y) {
|
||||
px = x * 16;
|
||||
py = y * 16;
|
||||
this.scenery[y][x] = new Mario.Prop([px, py], this.cloudSprites[0]);
|
||||
this.scenery[y][x+1] = new Mario.Prop([px+16, py], this.cloudSprites[1]);
|
||||
this.scenery[y][x+2] = new Mario.Prop([px+32, py], this.cloudSprites[1]);
|
||||
this.scenery[y][x+3] = new Mario.Prop([px+48, py], this.cloudSprites[2]);
|
||||
this.scenery[y][x + 1] = new Mario.Prop(
|
||||
[px + 16, py],
|
||||
this.cloudSprites[1],
|
||||
);
|
||||
this.scenery[y][x + 2] = new Mario.Prop(
|
||||
[px + 32, py],
|
||||
this.cloudSprites[1],
|
||||
);
|
||||
this.scenery[y][x + 3] = new Mario.Prop(
|
||||
[px + 48, py],
|
||||
this.cloudSprites[2],
|
||||
);
|
||||
};
|
||||
|
||||
Level.prototype.putThreeCloud = function(x,y) {
|
||||
px = x*16;
|
||||
py = y*16;
|
||||
Level.prototype.putThreeCloud = function (x, y) {
|
||||
px = x * 16;
|
||||
py = y * 16;
|
||||
this.scenery[y][x] = new Mario.Prop([px, py], this.cloudSprites[0]);
|
||||
this.scenery[y][x+1] = new Mario.Prop([px+16, py], this.cloudSprites[1]);
|
||||
this.scenery[y][x+2] = new Mario.Prop([px+32, py], this.cloudSprites[1]);
|
||||
this.scenery[y][x+3] = new Mario.Prop([px+48, py], this.cloudSprites[1]);
|
||||
this.scenery[y][x+4] = new Mario.Prop([px+64, py], this.cloudSprites[2]);
|
||||
this.scenery[y][x + 1] = new Mario.Prop(
|
||||
[px + 16, py],
|
||||
this.cloudSprites[1],
|
||||
);
|
||||
this.scenery[y][x + 2] = new Mario.Prop(
|
||||
[px + 32, py],
|
||||
this.cloudSprites[1],
|
||||
);
|
||||
this.scenery[y][x + 3] = new Mario.Prop(
|
||||
[px + 48, py],
|
||||
this.cloudSprites[1],
|
||||
);
|
||||
this.scenery[y][x + 4] = new Mario.Prop(
|
||||
[px + 64, py],
|
||||
this.cloudSprites[2],
|
||||
);
|
||||
};
|
||||
|
||||
Level.prototype.putRealPipe = function(x, y, length, direction, destination) {
|
||||
px = x*16;
|
||||
py = y*16;
|
||||
this.pipes.push(new Mario.Pipe({
|
||||
pos: [px, py],
|
||||
length: length,
|
||||
direction: direction,
|
||||
destination: destination
|
||||
}));
|
||||
}
|
||||
Level.prototype.putRealPipe = function (
|
||||
x,
|
||||
y,
|
||||
length,
|
||||
direction,
|
||||
destination,
|
||||
) {
|
||||
px = x * 16;
|
||||
py = y * 16;
|
||||
this.pipes.push(
|
||||
new Mario.Pipe({
|
||||
pos: [px, py],
|
||||
length: length,
|
||||
direction: direction,
|
||||
destination: destination,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
Level.prototype.putFlagpole = function(x) {
|
||||
this.statics[12][x] = new Mario.Floor([16*x, 192], this.wallSprite);
|
||||
for (i=3; i < 12; i++) {
|
||||
this.scenery[i][x] = new Mario.Prop([16*x, 16*i], this.flagpoleSprites[1])
|
||||
Level.prototype.putFlagpole = function (x) {
|
||||
this.statics[12][x] = new Mario.Floor([16 * x, 192], this.wallSprite);
|
||||
for (i = 3; i < 12; i++) {
|
||||
this.scenery[i][x] = new Mario.Prop(
|
||||
[16 * x, 16 * i],
|
||||
this.flagpoleSprites[1],
|
||||
);
|
||||
}
|
||||
this.scenery[2][x] = new Mario.Prop([16*x, 32], this.flagpoleSprites[0]);
|
||||
this.items.push(new Mario.Flag(16*x));
|
||||
}
|
||||
this.scenery[2][x] = new Mario.Prop([16 * x, 32], this.flagpoleSprites[0]);
|
||||
this.items.push(new Mario.Flag(16 * x));
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,29 +1,28 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
var Mushroom = Mario.Mushroom = function(pos) {
|
||||
var Mushroom = (Mario.Mushroom = function (pos) {
|
||||
this.spawning = false;
|
||||
this.waiting = 0;
|
||||
|
||||
Mario.Entity.call(this, {
|
||||
pos: pos,
|
||||
sprite: level.superShroomSprite,
|
||||
hitbox: [0,0,16,16]
|
||||
hitbox: [0, 0, 16, 16],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Mario.Util.inherits(Mushroom, Mario.Entity);
|
||||
|
||||
Mushroom.prototype.render = function(ctx, vX, vY) {
|
||||
Mushroom.prototype.render = function (ctx, vX, vY) {
|
||||
if (this.spawning > 1) return;
|
||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||
}
|
||||
};
|
||||
|
||||
Mushroom.prototype.spawn = function() {
|
||||
Mushroom.prototype.spawn = function () {
|
||||
if (player.power > 0) {
|
||||
//replace this with a fire flower
|
||||
var ff = new Mario.Fireflower(this.pos)
|
||||
var ff = new Mario.Fireflower(this.pos);
|
||||
ff.spawn();
|
||||
return;
|
||||
}
|
||||
@@ -34,12 +33,12 @@
|
||||
this.targetpos = [];
|
||||
this.targetpos[0] = this.pos[0];
|
||||
this.targetpos[1] = this.pos[1] - 16;
|
||||
}
|
||||
};
|
||||
|
||||
Mushroom.prototype.update = function(dt) {
|
||||
Mushroom.prototype.update = function (dt) {
|
||||
if (this.spawning > 1) {
|
||||
this.spawning -= 1;
|
||||
if (this.spawning == 1) this.vel[1] = -.5;
|
||||
if (this.spawning == 1) this.vel[1] = -0.5;
|
||||
return;
|
||||
}
|
||||
if (this.spawning) {
|
||||
@@ -62,14 +61,14 @@
|
||||
this.pos[1] += this.vel[1];
|
||||
this.sprite.update(dt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Mushroom.prototype.collideWall = function() {
|
||||
Mushroom.prototype.collideWall = function () {
|
||||
this.vel[0] = -this.vel[0];
|
||||
}
|
||||
};
|
||||
|
||||
Mushroom.prototype.checkCollisions = function() {
|
||||
if(this.spawning) {
|
||||
Mushroom.prototype.checkCollisions = function () {
|
||||
if (this.spawning) {
|
||||
return;
|
||||
}
|
||||
var h = this.pos[1] % 16 == 0 ? 1 : 2;
|
||||
@@ -95,24 +94,36 @@
|
||||
}
|
||||
|
||||
this.isPlayerCollided();
|
||||
}
|
||||
};
|
||||
|
||||
//we have access to player everywhere, so let's just do this.
|
||||
Mushroom.prototype.isPlayerCollided = function() {
|
||||
Mushroom.prototype.isPlayerCollided = function () {
|
||||
//the first two elements of the hitbox array are an offset, so let's do this now.
|
||||
var hpos1 = [this.pos[0] + this.hitbox[0], this.pos[1] + this.hitbox[1]];
|
||||
var hpos2 = [player.pos[0] + player.hitbox[0], player.pos[1] + player.hitbox[1]];
|
||||
var hpos2 = [
|
||||
player.pos[0] + player.hitbox[0],
|
||||
player.pos[1] + player.hitbox[1],
|
||||
];
|
||||
|
||||
//if the hitboxes actually overlap
|
||||
if (!(hpos1[0] > hpos2[0]+player.hitbox[2] || (hpos1[0]+this.hitbox[2] < hpos2[0]))) {
|
||||
if (!(hpos1[1] > hpos2[1]+player.hitbox[3] || (hpos1[1]+this.hitbox[3] < hpos2[1]))) {
|
||||
if (
|
||||
!(
|
||||
hpos1[0] > hpos2[0] + player.hitbox[2] ||
|
||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
||||
)
|
||||
) {
|
||||
if (
|
||||
!(
|
||||
hpos1[1] > hpos2[1] + player.hitbox[3] ||
|
||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
||||
)
|
||||
) {
|
||||
player.powerUp(this.idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Mushroom.prototype.bump = function() {
|
||||
Mushroom.prototype.bump = function () {
|
||||
this.vel[1] = -2;
|
||||
}
|
||||
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,97 +1,122 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
//there are too many possible configurations of pipe to capture in a reasonable
|
||||
//set of simple variables. Joints, etc. are just too much.
|
||||
//To that end, the pipe class handles simple pipes, and we'll put together
|
||||
//anything more complex with individual props. OK? OK.
|
||||
Pipe = Mario.Pipe = function(options) {
|
||||
this.pos = options.pos
|
||||
Pipe = Mario.Pipe = function (options) {
|
||||
this.pos = options.pos;
|
||||
|
||||
//NOTE: direction is the direction you move INTO the pipe.
|
||||
this.direction = options.direction
|
||||
this.destination = options.destination
|
||||
this.direction = options.direction;
|
||||
this.destination = options.destination;
|
||||
this.length = options.length;
|
||||
|
||||
if (this.direction === "UP" || this.direction === "DOWN") {
|
||||
this.hitbox = [0,0, 32, this.length * 16];
|
||||
this.hitbox = [0, 0, 32, this.length * 16];
|
||||
this.midsection = level.pipeUpMid;
|
||||
this.endsection = level.pipeTop;
|
||||
} else {
|
||||
this.hitbox = [0,0, 16*this.length, 32];
|
||||
this.hitbox = [0, 0, 16 * this.length, 32];
|
||||
this.midsection = level.pipeSideMid;
|
||||
this.endsection = level.pipeLeft;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Pipe.prototype.checkPipe = function() {
|
||||
Pipe.prototype.checkPipe = function () {
|
||||
if (this.destination === undefined || !input.isDown(this.direction)) return;
|
||||
|
||||
var h = player.power===0 ? 16 : 32;
|
||||
var h = player.power === 0 ? 16 : 32;
|
||||
var x = Math.floor(player.pos[0]);
|
||||
var y = Math.floor(player.pos[1]);
|
||||
switch (this.direction) {
|
||||
case 'RIGHT': if (x === this.pos[0]-16 &&
|
||||
y >= this.pos[1] &&
|
||||
y+h <= this.pos[1]+32) {
|
||||
player.pipe(this.direction, this.destination)
|
||||
}
|
||||
case "RIGHT":
|
||||
if (
|
||||
x === this.pos[0] - 16 &&
|
||||
y >= this.pos[1] &&
|
||||
y + h <= this.pos[1] + 32
|
||||
) {
|
||||
player.pipe(this.direction, this.destination);
|
||||
}
|
||||
break;
|
||||
case 'LEFT': if (x === this.pos[0]+16*this.length &&
|
||||
y >= this.pos[1] &&
|
||||
y+h <= this.pos[1]+32) {
|
||||
player.pipe(this.direction, this.destination)
|
||||
}
|
||||
case "LEFT":
|
||||
if (
|
||||
x === this.pos[0] + 16 * this.length &&
|
||||
y >= this.pos[1] &&
|
||||
y + h <= this.pos[1] + 32
|
||||
) {
|
||||
player.pipe(this.direction, this.destination);
|
||||
}
|
||||
break;
|
||||
case 'UP': if (y === this.pos[1] + 16*this.length &&
|
||||
x >= this.pos[0] &&
|
||||
x+16 <= this.pos[0]+32) {
|
||||
player.pipe(this.direction, this.destination)
|
||||
}
|
||||
case "UP":
|
||||
if (
|
||||
y === this.pos[1] + 16 * this.length &&
|
||||
x >= this.pos[0] &&
|
||||
x + 16 <= this.pos[0] + 32
|
||||
) {
|
||||
player.pipe(this.direction, this.destination);
|
||||
}
|
||||
break;
|
||||
case 'DOWN': if (y+h === this.pos[1] &&
|
||||
x >= this.pos[0] &&
|
||||
x+16 <= this.pos[0]+32) {
|
||||
player.pipe(this.direction, this.destination);
|
||||
}
|
||||
case "DOWN":
|
||||
if (
|
||||
y + h === this.pos[1] &&
|
||||
x >= this.pos[0] &&
|
||||
x + 16 <= this.pos[0] + 32
|
||||
) {
|
||||
player.pipe(this.direction, this.destination);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Note to self: next time, decide on a convention for which thing checks for collisions
|
||||
//and stick to it. This is a pain.
|
||||
Pipe.prototype.checkCollisions = function() {
|
||||
Pipe.prototype.checkCollisions = function () {
|
||||
var that = this;
|
||||
level.enemies.forEach (function(ent) {
|
||||
level.enemies.forEach(function (ent) {
|
||||
that.isCollideWith(ent);
|
||||
});
|
||||
|
||||
level.items.forEach (function(ent) {
|
||||
level.items.forEach(function (ent) {
|
||||
that.isCollideWith(ent);
|
||||
});
|
||||
|
||||
fireballs.forEach(function(ent){
|
||||
that.isCollideWith(ent)
|
||||
fireballs.forEach(function (ent) {
|
||||
that.isCollideWith(ent);
|
||||
});
|
||||
|
||||
if (!player.piping) this.isCollideWith(player);
|
||||
}
|
||||
};
|
||||
|
||||
Pipe.prototype.isCollideWith = function (ent) {
|
||||
//long story short: because we scan every item, and and one 'rubble' item is four things with separate positions
|
||||
//we'll crash without this line as soon as we destroy a block. OOPS.
|
||||
if (ent.pos === undefined) return;
|
||||
|
||||
|
||||
//the first two elements of the hitbox array are an offset, so let's do this now.
|
||||
var hpos1 = [Math.floor(this.pos[0] + this.hitbox[0]), Math.floor(this.pos[1] + this.hitbox[1])];
|
||||
var hpos2 = [Math.floor(ent.pos[0] + ent.hitbox[0]), Math.floor(ent.pos[1] + ent.hitbox[1])];
|
||||
var hpos1 = [
|
||||
Math.floor(this.pos[0] + this.hitbox[0]),
|
||||
Math.floor(this.pos[1] + this.hitbox[1]),
|
||||
];
|
||||
var hpos2 = [
|
||||
Math.floor(ent.pos[0] + ent.hitbox[0]),
|
||||
Math.floor(ent.pos[1] + ent.hitbox[1]),
|
||||
];
|
||||
|
||||
//if the hitboxes actually overlap
|
||||
if (!(hpos1[0] > hpos2[0]+ent.hitbox[2] || (hpos1[0]+this.hitbox[2] < hpos2[0]))) {
|
||||
if (!(hpos1[1] > hpos2[1]+ent.hitbox[3] || (hpos1[1]+this.hitbox[3] < hpos2[1]))) {
|
||||
if (
|
||||
!(
|
||||
hpos1[0] > hpos2[0] + ent.hitbox[2] ||
|
||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
||||
)
|
||||
) {
|
||||
if (
|
||||
!(
|
||||
hpos1[1] > hpos2[1] + ent.hitbox[3] ||
|
||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
||||
)
|
||||
) {
|
||||
//if the entity is over the block, it's basically floor
|
||||
var center = hpos2[0] + ent.hitbox[2] / 2;
|
||||
if (Math.abs(hpos2[1] + ent.hitbox[3] - hpos1[1]) <= ent.vel[1]) {
|
||||
@@ -101,8 +126,11 @@
|
||||
if (ent instanceof Mario.Player) {
|
||||
ent.jumping = 0;
|
||||
}
|
||||
} else if (Math.abs(hpos2[1] - hpos1[1] - this.hitbox[3]) > ent.vel[1] &&
|
||||
center + 2 >= hpos1[0] && center - 2 <= hpos1[0] + this.hitbox[2]) {
|
||||
} else if (
|
||||
Math.abs(hpos2[1] - hpos1[1] - this.hitbox[3]) > ent.vel[1] &&
|
||||
center + 2 >= hpos1[0] &&
|
||||
center - 2 <= hpos1[0] + this.hitbox[2]
|
||||
) {
|
||||
//ent is under the block.
|
||||
ent.vel[1] = 0;
|
||||
ent.pos[1] = hpos1[1] + this.hitbox[3];
|
||||
@@ -115,46 +143,82 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//we COULD try to write some shenanigans so that the check gets put into the
|
||||
//collision code, but there won't ever be more than a handful of pipes in a level
|
||||
//so the performance hit of scanning all of them is miniscule.
|
||||
Pipe.prototype.update = function(dt) {
|
||||
Pipe.prototype.update = function (dt) {
|
||||
if (this.destination) this.checkPipe();
|
||||
}
|
||||
};
|
||||
|
||||
//http://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-an-unsorted-array
|
||||
//I honestly have no idea if javascript does this, but I feel like it makes sense
|
||||
//stylistically to prefer branching outside of loops when possible as convention
|
||||
|
||||
//TODO: edit the spritesheet so UP and LEFT pipes aren't backwards.
|
||||
Pipe.prototype.render = function(ctx, vX, vY) {
|
||||
Pipe.prototype.render = function (ctx, vX, vY) {
|
||||
switch (this.direction) {
|
||||
case "DOWN":
|
||||
this.endsection.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||
for (var i = 1; i < this.length; i++) {
|
||||
this.midsection.render(ctx, this.pos[0], this.pos[1]+i*16, vX, vY)
|
||||
this.midsection.render(
|
||||
ctx,
|
||||
this.pos[0],
|
||||
this.pos[1] + i * 16,
|
||||
vX,
|
||||
vY,
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "UP":
|
||||
this.endsection.render(ctx, this.pos[0], this.pos[1]+16*(this.length-1), vX, vY)
|
||||
for (var i=0; i < this.length - 1; i++) {
|
||||
this.midsection.render(ctx, this.pos[0], this.pos[1]+i*16, vX, vY)
|
||||
this.endsection.render(
|
||||
ctx,
|
||||
this.pos[0],
|
||||
this.pos[1] + 16 * (this.length - 1),
|
||||
vX,
|
||||
vY,
|
||||
);
|
||||
for (var i = 0; i < this.length - 1; i++) {
|
||||
this.midsection.render(
|
||||
ctx,
|
||||
this.pos[0],
|
||||
this.pos[1] + i * 16,
|
||||
vX,
|
||||
vY,
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "RIGHT":
|
||||
this.endsection.render(ctx, this.pos[0], this.pos[1], vX, vY)
|
||||
this.endsection.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||
for (var i = 1; i < this.length; i++) {
|
||||
this.midsection.render(ctx, this.pos[0]+16*i, this.pos[1], vX, vY)
|
||||
this.midsection.render(
|
||||
ctx,
|
||||
this.pos[0] + 16 * i,
|
||||
this.pos[1],
|
||||
vX,
|
||||
vY,
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "LEFT":
|
||||
this.endsection.render(ctx, this.pos[0]+16*(this.length-1), this.pos[1], vX, vY)
|
||||
for (var i = 0; i < this.legth-1; i++) {
|
||||
this.midsection.render(ctx, this.pos[0], this.pos[1]+i*16, vX, vY)
|
||||
this.endsection.render(
|
||||
ctx,
|
||||
this.pos[0] + 16 * (this.length - 1),
|
||||
this.pos[1],
|
||||
vX,
|
||||
vY,
|
||||
);
|
||||
for (var i = 0; i < this.legth - 1; i++) {
|
||||
this.midsection.render(
|
||||
ctx,
|
||||
this.pos[0],
|
||||
this.pos[1] + i * 16,
|
||||
vX,
|
||||
vY,
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,446 +1,498 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
var Player = Mario.Player = function(pos) {
|
||||
//I know, I know, there are a lot of variables tracking Mario's state.
|
||||
//Maybe these can be consolidated some way? We'll see once they're all in.
|
||||
this.power = 0;
|
||||
this.coins = 0;
|
||||
this.powering = [];
|
||||
this.bounce = false;
|
||||
this.jumping = 0;
|
||||
this.canJump = true;
|
||||
this.invincibility = 0;
|
||||
this.crouching = false;
|
||||
this.fireballs = 0;
|
||||
this.runheld = false;
|
||||
this.noInput = false;
|
||||
this.targetPos = [];
|
||||
var Player = (Mario.Player = function (pos) {
|
||||
//I know, I know, there are a lot of variables tracking Mario's state.
|
||||
//Maybe these can be consolidated some way? We'll see once they're all in.
|
||||
this.power = 0;
|
||||
this.coins = 0;
|
||||
this.powering = [];
|
||||
this.bounce = false;
|
||||
this.jumping = 0;
|
||||
this.canJump = true;
|
||||
this.invincibility = 0;
|
||||
this.crouching = false;
|
||||
this.fireballs = 0;
|
||||
this.runheld = false;
|
||||
this.noInput = false;
|
||||
this.targetPos = [];
|
||||
|
||||
Mario.Entity.call(this, {
|
||||
pos: pos,
|
||||
sprite: new Mario.Sprite('sprites/player.png', [80,32],[16,16],0),
|
||||
hitbox: [0,0,16,16]
|
||||
});
|
||||
};
|
||||
Mario.Entity.call(this, {
|
||||
pos: pos,
|
||||
sprite: new Mario.Sprite("sprites/player.png", [80, 32], [16, 16], 0),
|
||||
hitbox: [0, 0, 16, 16],
|
||||
});
|
||||
});
|
||||
|
||||
Mario.Util.inherits(Player, Mario.Entity);
|
||||
Mario.Util.inherits(Player, Mario.Entity);
|
||||
|
||||
Player.prototype.run = function() {
|
||||
this.maxSpeed = 2.5;
|
||||
if (this.power == 2 && !this.runheld) {
|
||||
this.shoot();
|
||||
}
|
||||
this.runheld = true;
|
||||
}
|
||||
|
||||
Player.prototype.shoot = function() {
|
||||
if (this.fireballs >= 2) return; //Projectile limit!
|
||||
this.fireballs += 1;
|
||||
var fb = new Mario.Fireball([this.pos[0]+8,this.pos[1]]); //I hate you, Javascript.
|
||||
fb.spawn(this.left);
|
||||
this.shooting = 2;
|
||||
}
|
||||
|
||||
Player.prototype.noRun = function() {
|
||||
this.maxSpeed = 1.5;
|
||||
this.moveAcc = 0.07;
|
||||
this.runheld = false;
|
||||
}
|
||||
|
||||
Player.prototype.moveRight = function() {
|
||||
//we're on the ground
|
||||
if (this.vel[1] === 0 && this.standing) {
|
||||
if (this.crouching) {
|
||||
this.noWalk();
|
||||
return;
|
||||
}
|
||||
this.acc[0] = this.moveAcc;
|
||||
this.left = false;
|
||||
} else {
|
||||
this.acc[0] = this.moveAcc;
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.moveLeft = function() {
|
||||
if (this.vel[1] === 0 && this.standing) {
|
||||
if (this.crouching) {
|
||||
this.noWalk();
|
||||
return;
|
||||
}
|
||||
this.acc[0] = -this.moveAcc;
|
||||
this.left = true;
|
||||
} else {
|
||||
this.acc[0] = -this.moveAcc;
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.noWalk = function() {
|
||||
this.maxSpeed = 0;
|
||||
if (this.vel[0] === 0) return;
|
||||
|
||||
if (Math.abs(this.vel[0]) <= 0.1) {
|
||||
this.vel[0] = 0;
|
||||
this.acc[0] = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Player.prototype.crouch = function() {
|
||||
if (this.power === 0) {
|
||||
this.crouching = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.standing) this.crouching = true;
|
||||
}
|
||||
|
||||
Player.prototype.noCrouch = function() {
|
||||
this.crouching = false;
|
||||
}
|
||||
|
||||
Player.prototype.jump = function() {
|
||||
if (this.vel[1] > 0) {
|
||||
return;
|
||||
}
|
||||
if (this.jumping) {
|
||||
this.jumping -= 1;
|
||||
} else if (this.standing && this.canJump) {
|
||||
this.jumping = 20;
|
||||
this.canJump = false;
|
||||
this.standing = false;
|
||||
this.vel[1] = -6;
|
||||
if (this.power === 0) {
|
||||
sounds.smallJump.currentTime = 0;
|
||||
sounds.smallJump.play();
|
||||
} else {
|
||||
sounds.bigJump.currentTime = 0;
|
||||
sounds.bigJump.play();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.noJump = function() {
|
||||
this.canJump = true;
|
||||
if (this.jumping) {
|
||||
if (this.jumping <= 16) {
|
||||
this.vel[1] = 0;
|
||||
this.jumping = 0;
|
||||
} else this.jumping -= 1;
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.setAnimation = function() {
|
||||
if (this.dying) return;
|
||||
|
||||
if (this.starTime) {
|
||||
var index;
|
||||
if (this.starTime > 60)
|
||||
index = Math.floor(this.starTime / 2) % 3;
|
||||
else index = Math.floor(this.starTime / 8) % 3;
|
||||
|
||||
this.sprite.pos[1] = level.invincibility[index];
|
||||
if (this.power == 0) {
|
||||
this.sprite.pos[1] += 32;
|
||||
}
|
||||
this.starTime -= 1;
|
||||
if (this.starTime == 0) {
|
||||
switch(this.power) {
|
||||
case 0: this.sprite.pos[1] = 32; break;
|
||||
case 1: this.sprite.pos[1] = 0; break;
|
||||
case 2: this.sprite.pos[1] = 96; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//okay cool, now set the sprite
|
||||
if (this.crouching) {
|
||||
this.sprite.pos[0] = 176;
|
||||
this.sprite.speed = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.jumping) {
|
||||
this.sprite.pos[0] = 160;
|
||||
this.sprite.speed = 0;
|
||||
} else if (this.standing) {
|
||||
if (Math.abs(this.vel[0]) > 0) {
|
||||
if (this.vel[0] * this.acc[0] >= 0) {
|
||||
this.sprite.pos[0] = 96;
|
||||
this.sprite.frames = [0,1,2];
|
||||
if (this.vel[0] < 0.2) {
|
||||
this.sprite.speed = 5;
|
||||
} else {
|
||||
this.sprite.speed = Math.abs(this.vel[0]) * 8;
|
||||
}
|
||||
} else if ((this.vel[0] > 0 && this.left) || (this.vel[0] < 0 && !this.left)){
|
||||
this.sprite.pos[0] = 144;
|
||||
this.sprite.speed = 0;
|
||||
}
|
||||
} else {
|
||||
this.sprite.pos[0] = 80;
|
||||
this.sprite.speed = 0;
|
||||
}
|
||||
if (this.shooting) {
|
||||
this.sprite.pos[0] += 160;
|
||||
this.shooting -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.flagging) {
|
||||
this.sprite.pos[0] = 192;
|
||||
this.sprite.frames = [0,1];
|
||||
this.sprite.speed = 10;
|
||||
if (this.vel[1] === 0) this.sprite.frames = [0];
|
||||
}
|
||||
|
||||
//which way are we facing?
|
||||
if (this.left) {
|
||||
this.sprite.img = 'sprites/playerl.png';
|
||||
} else {
|
||||
this.sprite.img = 'sprites/player.png';
|
||||
}
|
||||
Player.prototype.run = function () {
|
||||
this.maxSpeed = 2.5;
|
||||
if (this.power == 2 && !this.runheld) {
|
||||
this.shoot();
|
||||
}
|
||||
this.runheld = true;
|
||||
};
|
||||
|
||||
Player.prototype.update = function(dt, vX) {
|
||||
if (this.powering.length !== 0) {
|
||||
var next = this.powering.shift();
|
||||
if (next == 5) return;
|
||||
this.sprite.pos = this.powerSprites[next];
|
||||
this.sprite.size = this.powerSizes[next];
|
||||
this.pos[1] += this.shift[next];
|
||||
if (this.powering.length === 0) {
|
||||
delete level.items[this.touchedItem];
|
||||
}
|
||||
return;
|
||||
}
|
||||
Player.prototype.shoot = function () {
|
||||
if (this.fireballs >= 2) return; //Projectile limit!
|
||||
this.fireballs += 1;
|
||||
var fb = new Mario.Fireball([this.pos[0] + 8, this.pos[1]]); //I hate you, Javascript.
|
||||
fb.spawn(this.left);
|
||||
this.shooting = 2;
|
||||
};
|
||||
|
||||
if (this.invincibility) {
|
||||
this.invincibility -= Math.round(dt * 60);
|
||||
}
|
||||
Player.prototype.noRun = function () {
|
||||
this.maxSpeed = 1.5;
|
||||
this.moveAcc = 0.07;
|
||||
this.runheld = false;
|
||||
};
|
||||
|
||||
if (this.waiting) {
|
||||
this.waiting -= dt;
|
||||
if (this.waiting <= 0) {
|
||||
this.waiting = 0;
|
||||
} else return;
|
||||
}
|
||||
Player.prototype.moveRight = function () {
|
||||
//we're on the ground
|
||||
if (this.vel[1] === 0 && this.standing) {
|
||||
if (this.crouching) {
|
||||
this.noWalk();
|
||||
return;
|
||||
}
|
||||
this.acc[0] = this.moveAcc;
|
||||
this.left = false;
|
||||
} else {
|
||||
this.acc[0] = this.moveAcc;
|
||||
}
|
||||
};
|
||||
|
||||
if (this.bounce) {
|
||||
this.bounce = false;
|
||||
this.standing = false;
|
||||
this.vel[1] = -3;
|
||||
}
|
||||
Player.prototype.moveLeft = function () {
|
||||
if (this.vel[1] === 0 && this.standing) {
|
||||
if (this.crouching) {
|
||||
this.noWalk();
|
||||
return;
|
||||
}
|
||||
this.acc[0] = -this.moveAcc;
|
||||
this.left = true;
|
||||
} else {
|
||||
this.acc[0] = -this.moveAcc;
|
||||
}
|
||||
};
|
||||
|
||||
if (this.pos[0] <= vX) {
|
||||
this.pos[0] = vX;
|
||||
this.vel[0] = Math.max(this.vel[0], 0);
|
||||
}
|
||||
Player.prototype.noWalk = function () {
|
||||
this.maxSpeed = 0;
|
||||
if (this.vel[0] === 0) return;
|
||||
|
||||
if (Math.abs(this.vel[0]) > this.maxSpeed) {
|
||||
this.vel[0] -= 0.05 * this.vel[0] / Math.abs(this.vel[0]);
|
||||
this.acc[0] = 0;
|
||||
}
|
||||
if (Math.abs(this.vel[0]) <= 0.1) {
|
||||
this.vel[0] = 0;
|
||||
this.acc[0] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
if (this.dying){
|
||||
if (this.pos[1] < this.targetPos[1]) {
|
||||
this.vel[1] = 1;
|
||||
}
|
||||
this.dying -= 1 * dt;
|
||||
if (this.dying <= 0) {
|
||||
player = new Mario.Player(level.playerPos);
|
||||
level.loader.call();
|
||||
input.reset();
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.acc[1] = 0.25
|
||||
if (this.pos[1] > 240) {
|
||||
this.die();
|
||||
}
|
||||
}
|
||||
Player.prototype.crouch = function () {
|
||||
if (this.power === 0) {
|
||||
this.crouching = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.piping) {
|
||||
this.acc = [0,0];
|
||||
var pos = [Math.round(this.pos[0]), Math.round(this.pos[1])]
|
||||
if (pos[0] === this.targetPos[0] && pos[1] === this.targetPos[1]) {
|
||||
this.piping = false;
|
||||
this.pipeLoc.call();
|
||||
}
|
||||
}
|
||||
if (this.standing) this.crouching = true;
|
||||
};
|
||||
|
||||
if (this.flagging) {
|
||||
this.acc = [0,0];
|
||||
}
|
||||
Player.prototype.noCrouch = function () {
|
||||
this.crouching = false;
|
||||
};
|
||||
|
||||
if (this.exiting) {
|
||||
this.left = false;
|
||||
this.flagging = false;
|
||||
this.vel[0] = 1.5;
|
||||
if (this.pos[0] >= this.targetPos[0]) {
|
||||
this.sprite.size = [0,0];
|
||||
this.vel = [0,0];
|
||||
window.setTimeout(function() {
|
||||
player.sprite.size = player.power===0 ? [16,16] : [16,32];
|
||||
player.exiting = false;
|
||||
player.noInput = false;
|
||||
level.loader();
|
||||
if (player.power !== 0) player.pos[1] -= 16;
|
||||
music.overworld.currentTime = 0;
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
Player.prototype.jump = function () {
|
||||
if (this.vel[1] > 0) {
|
||||
return;
|
||||
}
|
||||
if (this.jumping) {
|
||||
this.jumping -= 1;
|
||||
} else if (this.standing && this.canJump) {
|
||||
this.jumping = 20;
|
||||
this.canJump = false;
|
||||
this.standing = false;
|
||||
this.vel[1] = -6;
|
||||
if (this.power === 0) {
|
||||
sounds.smallJump.currentTime = 0;
|
||||
sounds.smallJump.play();
|
||||
} else {
|
||||
sounds.bigJump.currentTime = 0;
|
||||
sounds.bigJump.play();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//approximate acceleration
|
||||
this.vel[0] += this.acc[0];
|
||||
this.vel[1] += this.acc[1];
|
||||
this.pos[0] += this.vel[0];
|
||||
this.pos[1] += this.vel[1];
|
||||
Player.prototype.noJump = function () {
|
||||
this.canJump = true;
|
||||
if (this.jumping) {
|
||||
if (this.jumping <= 16) {
|
||||
this.vel[1] = 0;
|
||||
this.jumping = 0;
|
||||
} else this.jumping -= 1;
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.setAnimation = function () {
|
||||
if (this.dying) return;
|
||||
|
||||
if (this.starTime) {
|
||||
var index;
|
||||
if (this.starTime > 60) index = Math.floor(this.starTime / 2) % 3;
|
||||
else index = Math.floor(this.starTime / 8) % 3;
|
||||
|
||||
this.sprite.pos[1] = level.invincibility[index];
|
||||
if (this.power == 0) {
|
||||
this.sprite.pos[1] += 32;
|
||||
}
|
||||
this.starTime -= 1;
|
||||
if (this.starTime == 0) {
|
||||
switch (this.power) {
|
||||
case 0:
|
||||
this.sprite.pos[1] = 32;
|
||||
break;
|
||||
case 1:
|
||||
this.sprite.pos[1] = 0;
|
||||
break;
|
||||
case 2:
|
||||
this.sprite.pos[1] = 96;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//okay cool, now set the sprite
|
||||
if (this.crouching) {
|
||||
this.sprite.pos[0] = 176;
|
||||
this.sprite.speed = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.jumping) {
|
||||
this.sprite.pos[0] = 160;
|
||||
this.sprite.speed = 0;
|
||||
} else if (this.standing) {
|
||||
if (Math.abs(this.vel[0]) > 0) {
|
||||
if (this.vel[0] * this.acc[0] >= 0) {
|
||||
this.sprite.pos[0] = 96;
|
||||
this.sprite.frames = [0, 1, 2];
|
||||
if (this.vel[0] < 0.2) {
|
||||
this.sprite.speed = 5;
|
||||
} else {
|
||||
this.sprite.speed = Math.abs(this.vel[0]) * 8;
|
||||
}
|
||||
} else if (
|
||||
(this.vel[0] > 0 && this.left) ||
|
||||
(this.vel[0] < 0 && !this.left)
|
||||
) {
|
||||
this.sprite.pos[0] = 144;
|
||||
this.sprite.speed = 0;
|
||||
}
|
||||
} else {
|
||||
this.sprite.pos[0] = 80;
|
||||
this.sprite.speed = 0;
|
||||
}
|
||||
if (this.shooting) {
|
||||
this.sprite.pos[0] += 160;
|
||||
this.shooting -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.flagging) {
|
||||
this.sprite.pos[0] = 192;
|
||||
this.sprite.frames = [0, 1];
|
||||
this.sprite.speed = 10;
|
||||
if (this.vel[1] === 0) this.sprite.frames = [0];
|
||||
}
|
||||
|
||||
//which way are we facing?
|
||||
if (this.left) {
|
||||
this.sprite.img = "sprites/playerl.png";
|
||||
} else {
|
||||
this.sprite.img = "sprites/player.png";
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.update = function (dt, vX) {
|
||||
if (this.powering.length !== 0) {
|
||||
var next = this.powering.shift();
|
||||
if (next == 5) return;
|
||||
this.sprite.pos = this.powerSprites[next];
|
||||
this.sprite.size = this.powerSizes[next];
|
||||
this.pos[1] += this.shift[next];
|
||||
if (this.powering.length === 0) {
|
||||
delete level.items[this.touchedItem];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.invincibility) {
|
||||
this.invincibility -= Math.round(dt * 60);
|
||||
}
|
||||
|
||||
if (this.waiting) {
|
||||
this.waiting -= dt;
|
||||
if (this.waiting <= 0) {
|
||||
this.waiting = 0;
|
||||
} else return;
|
||||
}
|
||||
|
||||
if (this.bounce) {
|
||||
this.bounce = false;
|
||||
this.standing = false;
|
||||
this.vel[1] = -3;
|
||||
}
|
||||
|
||||
if (this.pos[0] <= vX) {
|
||||
this.pos[0] = vX;
|
||||
this.vel[0] = Math.max(this.vel[0], 0);
|
||||
}
|
||||
|
||||
if (Math.abs(this.vel[0]) > this.maxSpeed) {
|
||||
this.vel[0] -= (0.05 * this.vel[0]) / Math.abs(this.vel[0]);
|
||||
this.acc[0] = 0;
|
||||
}
|
||||
|
||||
if (this.dying) {
|
||||
if (this.pos[1] < this.targetPos[1]) {
|
||||
this.vel[1] = 1;
|
||||
}
|
||||
this.dying -= 1 * dt;
|
||||
if (this.dying <= 0) {
|
||||
player = new Mario.Player(level.playerPos);
|
||||
level.loader.call();
|
||||
input.reset();
|
||||
}
|
||||
} else {
|
||||
this.acc[1] = 0.25;
|
||||
if (this.pos[1] > 240) {
|
||||
this.die();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.piping) {
|
||||
this.acc = [0, 0];
|
||||
var pos = [Math.round(this.pos[0]), Math.round(this.pos[1])];
|
||||
if (pos[0] === this.targetPos[0] && pos[1] === this.targetPos[1]) {
|
||||
this.piping = false;
|
||||
this.pipeLoc.call();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.flagging) {
|
||||
this.acc = [0, 0];
|
||||
}
|
||||
|
||||
if (this.exiting) {
|
||||
this.left = false;
|
||||
this.flagging = false;
|
||||
this.vel[0] = 1.5;
|
||||
if (this.pos[0] >= this.targetPos[0]) {
|
||||
this.sprite.size = [0, 0];
|
||||
this.vel = [0, 0];
|
||||
window.setTimeout(function () {
|
||||
player.sprite.size = player.power === 0 ? [16, 16] : [16, 32];
|
||||
player.exiting = false;
|
||||
player.noInput = false;
|
||||
level.loader();
|
||||
if (player.power !== 0) player.pos[1] -= 16;
|
||||
music.overworld.currentTime = 0;
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
//approximate acceleration
|
||||
this.vel[0] += this.acc[0];
|
||||
this.vel[1] += this.acc[1];
|
||||
this.pos[0] += this.vel[0];
|
||||
this.pos[1] += this.vel[1];
|
||||
|
||||
this.setAnimation();
|
||||
this.sprite.update(dt);
|
||||
};
|
||||
this.sprite.update(dt);
|
||||
};
|
||||
|
||||
Player.prototype.checkCollisions = function() {
|
||||
if (this.piping || this.dying) return;
|
||||
//x-axis first!
|
||||
var h = this.power > 0 ? 2 : 1;
|
||||
var w = 1;
|
||||
if (this.pos[1] % 16 !== 0) {
|
||||
h += 1;
|
||||
}
|
||||
if (this.pos[0] % 16 !== 0) {
|
||||
w += 1;
|
||||
}
|
||||
var baseX = Math.floor(this.pos[0] / 16);
|
||||
var baseY = Math.floor(this.pos[1] / 16);
|
||||
Player.prototype.checkCollisions = function () {
|
||||
if (this.piping || this.dying) return;
|
||||
//x-axis first!
|
||||
var h = this.power > 0 ? 2 : 1;
|
||||
var w = 1;
|
||||
if (this.pos[1] % 16 !== 0) {
|
||||
h += 1;
|
||||
}
|
||||
if (this.pos[0] % 16 !== 0) {
|
||||
w += 1;
|
||||
}
|
||||
var baseX = Math.floor(this.pos[0] / 16);
|
||||
var baseY = Math.floor(this.pos[1] / 16);
|
||||
|
||||
for (var i = 0; i < h; i++) {
|
||||
if (baseY + i < 0 || baseY + i >= 15) continue;
|
||||
for (var j = 0; j < w; j++) {
|
||||
if (baseY < 0) { i++;}
|
||||
if (level.statics[baseY + i][baseX + j]) {
|
||||
level.statics[baseY + i][baseX + j].isCollideWith(this);
|
||||
}
|
||||
if (level.blocks[baseY + i][baseX + j]) {
|
||||
level.blocks[baseY + i][baseX + j].isCollideWith(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
for (var i = 0; i < h; i++) {
|
||||
if (baseY + i < 0 || baseY + i >= 15) continue;
|
||||
for (var j = 0; j < w; j++) {
|
||||
if (baseY < 0) {
|
||||
i++;
|
||||
}
|
||||
if (level.statics[baseY + i][baseX + j]) {
|
||||
level.statics[baseY + i][baseX + j].isCollideWith(this);
|
||||
}
|
||||
if (level.blocks[baseY + i][baseX + j]) {
|
||||
level.blocks[baseY + i][baseX + j].isCollideWith(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.powerUp = function(idx) {
|
||||
sounds.powerup.play();
|
||||
this.powering = [0,5,2,5,1,5,2,5,1,5,2,5,3,5,1,5,2,5,3,5,1,5,4];
|
||||
this.touchedItem = idx;
|
||||
Player.prototype.powerUp = function (idx) {
|
||||
sounds.powerup.play();
|
||||
this.powering = [
|
||||
0, 5, 2, 5, 1, 5, 2, 5, 1, 5, 2, 5, 3, 5, 1, 5, 2, 5, 3, 5, 1, 5, 4,
|
||||
];
|
||||
this.touchedItem = idx;
|
||||
|
||||
if (this.power === 0) {
|
||||
this.sprite.pos[0] = 80;
|
||||
var newy = this.sprite.pos[1] - 32;
|
||||
this.powerSprites = [[80, newy+32], [80, newy+32], [320, newy], [80, newy], [128, newy]];
|
||||
this.powerSizes = [[16,16],[16,16],[16,32],[16,32],[16,32]];
|
||||
this.shift = [0,16,-16,0,-16];
|
||||
this.power = 1;
|
||||
this.hitbox = [0,0,16,32];
|
||||
} else if (this.power == 1) {
|
||||
var curx = this.sprite.pos[0];
|
||||
this.powerSprites = [[curx, 96], [curx, level.invincibility[0]],
|
||||
[curx, level.invincibility[1]], [curx, level.invincibility[2]],
|
||||
[curx, 96]];
|
||||
this.powerSizes[[16,32],[16,32],[16,32],[16,32],[16,32]];
|
||||
this.shift = [0,0,0,0,0];
|
||||
this.power = 2;
|
||||
} else {
|
||||
this.powering = [];
|
||||
delete level.items[idx];
|
||||
//no animation, but we play the sound and you get 5000 points.
|
||||
}
|
||||
};
|
||||
if (this.power === 0) {
|
||||
this.sprite.pos[0] = 80;
|
||||
var newy = this.sprite.pos[1] - 32;
|
||||
this.powerSprites = [
|
||||
[80, newy + 32],
|
||||
[80, newy + 32],
|
||||
[320, newy],
|
||||
[80, newy],
|
||||
[128, newy],
|
||||
];
|
||||
this.powerSizes = [
|
||||
[16, 16],
|
||||
[16, 16],
|
||||
[16, 32],
|
||||
[16, 32],
|
||||
[16, 32],
|
||||
];
|
||||
this.shift = [0, 16, -16, 0, -16];
|
||||
this.power = 1;
|
||||
this.hitbox = [0, 0, 16, 32];
|
||||
} else if (this.power == 1) {
|
||||
var curx = this.sprite.pos[0];
|
||||
this.powerSprites = [
|
||||
[curx, 96],
|
||||
[curx, level.invincibility[0]],
|
||||
[curx, level.invincibility[1]],
|
||||
[curx, level.invincibility[2]],
|
||||
[curx, 96],
|
||||
];
|
||||
this.powerSizes[([16, 32], [16, 32], [16, 32], [16, 32], [16, 32])];
|
||||
this.shift = [0, 0, 0, 0, 0];
|
||||
this.power = 2;
|
||||
} else {
|
||||
this.powering = [];
|
||||
delete level.items[idx];
|
||||
//no animation, but we play the sound and you get 5000 points.
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.damage = function() {
|
||||
if (this.power === 0) { //if you're already small, you dead!
|
||||
this.die();
|
||||
} else { //otherwise, you get turned into small mario
|
||||
sounds.pipe.play();
|
||||
this.powering = [0,5,1,5,2,5,1,5,2,5,1,5,2,5,1,5,2,5,1,5,2,5,3];
|
||||
this.shift = [0,16,-16,16];
|
||||
this.sprite.pos = [160, 0];
|
||||
this.powerSprites = [[160,0], [240, 32], [240, 0], [160, 32]];
|
||||
this.powerSizes = [[16, 32], [16,16], [16,32], [16,16]];
|
||||
this.invincibility = 120;
|
||||
this.power = 0;
|
||||
this.hitbox = [0,0,16,16];
|
||||
}
|
||||
};
|
||||
Player.prototype.damage = function () {
|
||||
if (this.power === 0) {
|
||||
//if you're already small, you dead!
|
||||
this.die();
|
||||
} else {
|
||||
//otherwise, you get turned into small mario
|
||||
sounds.pipe.play();
|
||||
this.powering = [
|
||||
0, 5, 1, 5, 2, 5, 1, 5, 2, 5, 1, 5, 2, 5, 1, 5, 2, 5, 1, 5, 2, 5, 3,
|
||||
];
|
||||
this.shift = [0, 16, -16, 16];
|
||||
this.sprite.pos = [160, 0];
|
||||
this.powerSprites = [
|
||||
[160, 0],
|
||||
[240, 32],
|
||||
[240, 0],
|
||||
[160, 32],
|
||||
];
|
||||
this.powerSizes = [
|
||||
[16, 32],
|
||||
[16, 16],
|
||||
[16, 32],
|
||||
[16, 16],
|
||||
];
|
||||
this.invincibility = 120;
|
||||
this.power = 0;
|
||||
this.hitbox = [0, 0, 16, 16];
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.die = function () {
|
||||
//TODO: rewrite the way sounds work to emulate the channels of an NES.
|
||||
music.overworld.pause();
|
||||
music.underground.pause();
|
||||
music.overworld.currentTime = 0;
|
||||
music.death.play();
|
||||
this.noWalk();
|
||||
this.noRun();
|
||||
this.noJump();
|
||||
Player.prototype.die = function () {
|
||||
//TODO: rewrite the way sounds work to emulate the channels of an NES.
|
||||
music.overworld.pause();
|
||||
music.underground.pause();
|
||||
music.overworld.currentTime = 0;
|
||||
music.death.play();
|
||||
this.noWalk();
|
||||
this.noRun();
|
||||
this.noJump();
|
||||
|
||||
this.acc[0] = 0;
|
||||
this.sprite.pos = [176, 32];
|
||||
this.sprite.speed = 0;
|
||||
this.power = 0;
|
||||
this.waiting = 0.5;
|
||||
this.dying = 2;
|
||||
this.acc[0] = 0;
|
||||
this.sprite.pos = [176, 32];
|
||||
this.sprite.speed = 0;
|
||||
this.power = 0;
|
||||
this.waiting = 0.5;
|
||||
this.dying = 2;
|
||||
|
||||
if (this.pos[1] < 240) { //falling into a pit doesn't do the animation.
|
||||
this.targetPos = [this.pos[0], this.pos[1]-128];
|
||||
this.vel = [0,-5];
|
||||
} else {
|
||||
this.vel = [0,0];
|
||||
this.targetPos = [this.pos[0], this.pos[1] - 16];
|
||||
}
|
||||
};
|
||||
if (this.pos[1] < 240) {
|
||||
//falling into a pit doesn't do the animation.
|
||||
this.targetPos = [this.pos[0], this.pos[1] - 128];
|
||||
this.vel = [0, -5];
|
||||
} else {
|
||||
this.vel = [0, 0];
|
||||
this.targetPos = [this.pos[0], this.pos[1] - 16];
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.star = function(idx) {
|
||||
delete level.items[idx];
|
||||
this.starTime = 660;
|
||||
}
|
||||
Player.prototype.star = function (idx) {
|
||||
delete level.items[idx];
|
||||
this.starTime = 660;
|
||||
};
|
||||
|
||||
Player.prototype.pipe = function(direction, destination) {
|
||||
sounds.pipe.play();
|
||||
this.piping = true;
|
||||
this.pipeLoc = destination;
|
||||
switch(direction) {
|
||||
case "LEFT":
|
||||
this.vel = [-1,0];
|
||||
this.targetPos = [Math.round(this.pos[0]-16), Math.round(this.pos[1])]
|
||||
break;
|
||||
case "RIGHT":
|
||||
this.vel = [1,0];
|
||||
this.targetPos = [Math.round(this.pos[0]+16), Math.round(this.pos[1])]
|
||||
break;
|
||||
case "DOWN":
|
||||
this.vel = [0,1];
|
||||
this.targetPos = [Math.round(this.pos[0]), Math.round(this.pos[1]+this.hitbox[3])]
|
||||
break;
|
||||
case "UP":
|
||||
this.vel = [0,-1];
|
||||
this.targetPos = [Math.round(this.pos[0]), Math.round(this.pos[1]-this.hitbox[3])]
|
||||
break;
|
||||
}
|
||||
}
|
||||
Player.prototype.pipe = function (direction, destination) {
|
||||
sounds.pipe.play();
|
||||
this.piping = true;
|
||||
this.pipeLoc = destination;
|
||||
switch (direction) {
|
||||
case "LEFT":
|
||||
this.vel = [-1, 0];
|
||||
this.targetPos = [
|
||||
Math.round(this.pos[0] - 16),
|
||||
Math.round(this.pos[1]),
|
||||
];
|
||||
break;
|
||||
case "RIGHT":
|
||||
this.vel = [1, 0];
|
||||
this.targetPos = [
|
||||
Math.round(this.pos[0] + 16),
|
||||
Math.round(this.pos[1]),
|
||||
];
|
||||
break;
|
||||
case "DOWN":
|
||||
this.vel = [0, 1];
|
||||
this.targetPos = [
|
||||
Math.round(this.pos[0]),
|
||||
Math.round(this.pos[1] + this.hitbox[3]),
|
||||
];
|
||||
break;
|
||||
case "UP":
|
||||
this.vel = [0, -1];
|
||||
this.targetPos = [
|
||||
Math.round(this.pos[0]),
|
||||
Math.round(this.pos[1] - this.hitbox[3]),
|
||||
];
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.flag = function() {
|
||||
this.noInput = true;
|
||||
this.flagging = true;
|
||||
this.vel = [0, 2];
|
||||
this.acc = [0, 0];
|
||||
}
|
||||
Player.prototype.flag = function () {
|
||||
this.noInput = true;
|
||||
this.flagging = true;
|
||||
this.vel = [0, 2];
|
||||
this.acc = [0, 0];
|
||||
};
|
||||
|
||||
Player.prototype.exit = function() {
|
||||
this.pos[0] += 16;
|
||||
this.targetPos[0] = level.exit * 16;
|
||||
this.left = true;
|
||||
this.setAnimation();
|
||||
this.waiting = 1;
|
||||
this.exiting = true;
|
||||
}
|
||||
Player.prototype.exit = function () {
|
||||
this.pos[0] += 16;
|
||||
this.targetPos[0] = level.exit * 16;
|
||||
this.left = true;
|
||||
this.setAnimation();
|
||||
this.waiting = 1;
|
||||
this.exiting = true;
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
//props do even less than entities, so they don't need to inherit really
|
||||
var Prop = Mario.Prop = function(pos, sprite) {
|
||||
var Prop = (Mario.Prop = function (pos, sprite) {
|
||||
this.pos = pos;
|
||||
this.sprite = sprite;
|
||||
}
|
||||
});
|
||||
|
||||
//but we will be using the same Render, more or less.
|
||||
Prop.prototype.render = function(ctx, vX, vY) {
|
||||
Prop.prototype.render = function (ctx, vX, vY) {
|
||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,62 +1,61 @@
|
||||
//simple resource loader
|
||||
(function() {
|
||||
var resourceCache = {};
|
||||
var loading = [];
|
||||
var readyCallbacks = [];
|
||||
(function () {
|
||||
var resourceCache = {};
|
||||
var loading = [];
|
||||
var readyCallbacks = [];
|
||||
|
||||
// Load an image url or an array of image urls
|
||||
function load(urlOrArr) {
|
||||
if(urlOrArr instanceof Array) {
|
||||
urlOrArr.forEach(function(url) {
|
||||
_load(url);
|
||||
});
|
||||
}
|
||||
else {
|
||||
_load(urlOrArr);
|
||||
}
|
||||
// Load an image url or an array of image urls
|
||||
function load(urlOrArr) {
|
||||
if (urlOrArr instanceof Array) {
|
||||
urlOrArr.forEach(function (url) {
|
||||
_load(url);
|
||||
});
|
||||
} else {
|
||||
_load(urlOrArr);
|
||||
}
|
||||
}
|
||||
|
||||
function _load(url) {
|
||||
if(resourceCache[url]) {
|
||||
return resourceCache[url];
|
||||
}
|
||||
else {
|
||||
var img = new Image();
|
||||
img.onload = function() {
|
||||
resourceCache[url] = img;
|
||||
|
||||
if(isReady()) {
|
||||
readyCallbacks.forEach(function(func) { func(); });
|
||||
}
|
||||
};
|
||||
resourceCache[url] = false;
|
||||
img.src = url;
|
||||
function _load(url) {
|
||||
if (resourceCache[url]) {
|
||||
return resourceCache[url];
|
||||
} else {
|
||||
var img = new Image();
|
||||
img.onload = function () {
|
||||
resourceCache[url] = img;
|
||||
|
||||
if (isReady()) {
|
||||
readyCallbacks.forEach(function (func) {
|
||||
func();
|
||||
});
|
||||
}
|
||||
};
|
||||
resourceCache[url] = false;
|
||||
img.src = url;
|
||||
}
|
||||
}
|
||||
|
||||
function get(url) {
|
||||
return resourceCache[url];
|
||||
function get(url) {
|
||||
return resourceCache[url];
|
||||
}
|
||||
|
||||
function isReady() {
|
||||
var ready = true;
|
||||
for (var k in resourceCache) {
|
||||
if (resourceCache.hasOwnProperty(k) && !resourceCache[k]) {
|
||||
ready = false;
|
||||
}
|
||||
}
|
||||
return ready;
|
||||
}
|
||||
|
||||
function isReady() {
|
||||
var ready = true;
|
||||
for(var k in resourceCache) {
|
||||
if(resourceCache.hasOwnProperty(k) &&
|
||||
!resourceCache[k]) {
|
||||
ready = false;
|
||||
}
|
||||
}
|
||||
return ready;
|
||||
}
|
||||
function onReady(func) {
|
||||
readyCallbacks.push(func);
|
||||
}
|
||||
|
||||
function onReady(func) {
|
||||
readyCallbacks.push(func);
|
||||
}
|
||||
|
||||
window.resources = {
|
||||
load: load,
|
||||
get: get,
|
||||
onReady: onReady,
|
||||
isReady: isReady
|
||||
};
|
||||
window.resources = {
|
||||
load: load,
|
||||
get: get,
|
||||
onReady: onReady,
|
||||
isReady: isReady,
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
//TODO: make each rubble an entity, use that render and write in Entity.update
|
||||
var Rubble = Mario.Rubble = function() {
|
||||
var Rubble = (Mario.Rubble = function () {
|
||||
this.sprites = [];
|
||||
this.poss = [];
|
||||
this.vels = [];
|
||||
}
|
||||
});
|
||||
|
||||
Rubble.prototype.spawn = function(pos) {
|
||||
Rubble.prototype.spawn = function (pos) {
|
||||
this.idx = level.items.length;
|
||||
level.items.push(this);
|
||||
this.sprites[0] = level.rubbleSprite();
|
||||
@@ -17,19 +16,19 @@
|
||||
this.sprites[2] = level.rubbleSprite();
|
||||
this.sprites[3] = level.rubbleSprite();
|
||||
this.poss[0] = pos;
|
||||
this.poss[1] = [ pos[0] + 8, pos[1] ];
|
||||
this.poss[2] = [ pos[0], pos[1] + 8 ];
|
||||
this.poss[3] = [ pos[0] + 8, pos[1] + 8 ];
|
||||
this.poss[1] = [pos[0] + 8, pos[1]];
|
||||
this.poss[2] = [pos[0], pos[1] + 8];
|
||||
this.poss[3] = [pos[0] + 8, pos[1] + 8];
|
||||
this.vels[0] = [-1.25, -5];
|
||||
this.vels[1] = [1.25, -5];
|
||||
this.vels[2] = [-1.25, -3];
|
||||
this.vels[3] = [1.25, -3];
|
||||
}
|
||||
};
|
||||
|
||||
Rubble.prototype.update = function(dt) {
|
||||
for(var i = 0; i < 4; i++) {
|
||||
if (this.sprites[i]===undefined) continue;
|
||||
this.vels[i][1] += .3;
|
||||
Rubble.prototype.update = function (dt) {
|
||||
for (var i = 0; i < 4; i++) {
|
||||
if (this.sprites[i] === undefined) continue;
|
||||
this.vels[i][1] += 0.3;
|
||||
this.poss[i][0] += this.vels[i][0];
|
||||
this.poss[i][1] += this.vels[i][1];
|
||||
this.sprites[i].update(dt);
|
||||
@@ -37,19 +36,23 @@
|
||||
delete this.sprites[i];
|
||||
}
|
||||
}
|
||||
if (this.sprites.every(function (el) {return !el})) {
|
||||
if (
|
||||
this.sprites.every(function (el) {
|
||||
return !el;
|
||||
})
|
||||
) {
|
||||
delete level.items[this.idx];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//You might argue that things that can't collide are more like scenery
|
||||
//but these move and need to be deleted, and i'd rather deal with the 1d array.
|
||||
Rubble.prototype.checkCollisions = function() {;}
|
||||
Rubble.prototype.checkCollisions = function () {};
|
||||
|
||||
Rubble.prototype.render = function() {
|
||||
for(var i = 0; i < 4; i++) {
|
||||
Rubble.prototype.render = function () {
|
||||
for (var i = 0; i < 4; i++) {
|
||||
if (this.sprites[i] === undefined) continue;
|
||||
this.sprites[i].render(ctx, this.poss[i][0], this.poss[i][1], vX, vY);
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
var Sprite = Mario.Sprite = function(img, pos, size, speed, frames, once) {
|
||||
var Sprite = (Mario.Sprite = function (img, pos, size, speed, frames, once) {
|
||||
this.pos = pos;
|
||||
this.size = size;
|
||||
this.speed = speed;
|
||||
@@ -10,19 +9,19 @@
|
||||
this.img = img;
|
||||
this.once = once;
|
||||
this.frames = frames;
|
||||
}
|
||||
});
|
||||
|
||||
Sprite.prototype.update = function(dt, gameTime) {
|
||||
Sprite.prototype.update = function (dt, gameTime) {
|
||||
if (gameTime && gameTime == this.lastUpdated) return;
|
||||
this._index += this.speed*dt;
|
||||
this._index += this.speed * dt;
|
||||
if (gameTime) this.lastUpdated = gameTime;
|
||||
}
|
||||
};
|
||||
|
||||
Sprite.prototype.setFrame = function(frame) {
|
||||
Sprite.prototype.setFrame = function (frame) {
|
||||
this._index = frame;
|
||||
}
|
||||
};
|
||||
|
||||
Sprite.prototype.render = function(ctx, posx, posy, vX, vY) {
|
||||
Sprite.prototype.render = function (ctx, posx, posy, vX, vY) {
|
||||
var frame;
|
||||
|
||||
if (this.speed > 0) {
|
||||
@@ -41,7 +40,17 @@
|
||||
var x = this.pos[0];
|
||||
var y = this.pos[1];
|
||||
|
||||
x += frame*this.size[0];
|
||||
ctx.drawImage(resources.get(this.img), x + (1/3),y + (1/3), this.size[0] - (2/3), this.size[1] - (2/3), Math.round(posx - vX), Math.round(posy - vY), this.size[0],this.size[1]);
|
||||
}
|
||||
x += frame * this.size[0];
|
||||
ctx.drawImage(
|
||||
resources.get(this.img),
|
||||
x + 1 / 3,
|
||||
y + 1 / 3,
|
||||
this.size[0] - 2 / 3,
|
||||
this.size[1] - 2 / 3,
|
||||
Math.round(posx - vX),
|
||||
Math.round(posy - vY),
|
||||
this.size[0],
|
||||
this.size[1],
|
||||
);
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,38 +1,37 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined')
|
||||
window.Mario = {};
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") window.Mario = {};
|
||||
|
||||
var Star = Mario.Star = function(pos) {
|
||||
var Star = (Mario.Star = function (pos) {
|
||||
this.spawning = false;
|
||||
this.waiting = 0;
|
||||
|
||||
Mario.Entity.call(this, {
|
||||
pos: pos,
|
||||
sprite: level.starSprite,
|
||||
hitbox: [0,0,16,16]
|
||||
hitbox: [0, 0, 16, 16],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Mario.Util.inherits(Star, Mario.Entity);
|
||||
|
||||
Star.prototype.render = function(ctx, vX, vY) {
|
||||
Star.prototype.render = function (ctx, vX, vY) {
|
||||
if (this.spawning > 1) return;
|
||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||
}
|
||||
};
|
||||
|
||||
Star.prototype.spawn = function() {
|
||||
Star.prototype.spawn = function () {
|
||||
this.idx = level.items.length;
|
||||
level.items.push(this);
|
||||
this.spawning = 12;
|
||||
this.targetpos = [];
|
||||
this.targetpos[0] = this.pos[0];
|
||||
this.targetpos[1] = this.pos[1] - 16;
|
||||
}
|
||||
};
|
||||
|
||||
Star.prototype.update = function(dt) {
|
||||
Star.prototype.update = function (dt) {
|
||||
if (this.spawning > 1) {
|
||||
this.spawning -= 1;
|
||||
if (this.spawning == 1) this.vel[1] = -.5;
|
||||
if (this.spawning == 1) this.vel[1] = -0.5;
|
||||
return;
|
||||
}
|
||||
if (this.spawning) {
|
||||
@@ -60,14 +59,14 @@
|
||||
this.pos[1] += this.vel[1];
|
||||
this.sprite.update(dt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Star.prototype.collideWall = function() {
|
||||
Star.prototype.collideWall = function () {
|
||||
this.vel[0] = -this.vel[0];
|
||||
}
|
||||
};
|
||||
|
||||
Star.prototype.checkCollisions = function() {
|
||||
if(this.spawning) {
|
||||
Star.prototype.checkCollisions = function () {
|
||||
if (this.spawning) {
|
||||
return;
|
||||
}
|
||||
var h = this.pos[1] % 16 == 0 ? 1 : 2;
|
||||
@@ -93,24 +92,36 @@
|
||||
}
|
||||
|
||||
this.isPlayerCollided();
|
||||
}
|
||||
};
|
||||
|
||||
//we have access to player everywhere, so let's just do this.
|
||||
Star.prototype.isPlayerCollided = function() {
|
||||
Star.prototype.isPlayerCollided = function () {
|
||||
//the first two elements of the hitbox array are an offset, so let's do this now.
|
||||
var hpos1 = [this.pos[0] + this.hitbox[0], this.pos[1] + this.hitbox[1]];
|
||||
var hpos2 = [player.pos[0] + player.hitbox[0], player.pos[1] + player.hitbox[1]];
|
||||
var hpos2 = [
|
||||
player.pos[0] + player.hitbox[0],
|
||||
player.pos[1] + player.hitbox[1],
|
||||
];
|
||||
|
||||
//if the hitboxes actually overlap
|
||||
if (!(hpos1[0] > hpos2[0]+player.hitbox[2] || (hpos1[0]+this.hitbox[2] < hpos2[0]))) {
|
||||
if (!(hpos1[1] > hpos2[1]+player.hitbox[3] || (hpos1[1]+this.hitbox[3] < hpos2[1]))) {
|
||||
if (
|
||||
!(
|
||||
hpos1[0] > hpos2[0] + player.hitbox[2] ||
|
||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
||||
)
|
||||
) {
|
||||
if (
|
||||
!(
|
||||
hpos1[1] > hpos2[1] + player.hitbox[3] ||
|
||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
||||
)
|
||||
) {
|
||||
player.star(this.idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Star.prototype.bump = function() {
|
||||
Star.prototype.bump = function () {
|
||||
this.vel[1] = -2;
|
||||
}
|
||||
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
(function() {
|
||||
if (typeof Mario === 'undefined') {
|
||||
window.Mario = {};
|
||||
}
|
||||
(function () {
|
||||
if (typeof Mario === "undefined") {
|
||||
window.Mario = {};
|
||||
}
|
||||
|
||||
var Util = Mario.Util = {};
|
||||
var Util = (Mario.Util = {});
|
||||
|
||||
Util.inherits = function(subclass, superclass) {
|
||||
function Surrogate() {};
|
||||
Util.inherits = function (subclass, superclass) {
|
||||
function Surrogate() {}
|
||||
|
||||
Surrogate.prototype = superclass.prototype;
|
||||
subclass.prototype = new Surrogate();
|
||||
}
|
||||
})()
|
||||
Surrogate.prototype = superclass.prototype;
|
||||
subclass.prototype = new Surrogate();
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Matplotlib</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Matplotlib</a>
|
||||
<a class="title" href="" style="color: #f0ab3c">Matplotlib</a>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
@@ -30,39 +30,39 @@
|
||||
</py-config>
|
||||
|
||||
<py-script>
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.tri as tri
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.tri as tri
|
||||
import numpy as np
|
||||
|
||||
# First create the x and y coordinates of the points.
|
||||
n_angles = 36
|
||||
n_radii = 8
|
||||
min_radius = 0.25
|
||||
radii = np.linspace(min_radius, 0.95, n_radii)
|
||||
# First create the x and y coordinates of the points.
|
||||
n_angles = 36
|
||||
n_radii = 8
|
||||
min_radius = 0.25
|
||||
radii = np.linspace(min_radius, 0.95, n_radii)
|
||||
|
||||
angles = np.linspace(0, 2 * np.pi, n_angles, endpoint=False)
|
||||
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)
|
||||
angles[:, 1::2] += np.pi / n_angles
|
||||
angles = np.linspace(0, 2 * np.pi, n_angles, endpoint=False)
|
||||
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)
|
||||
angles[:, 1::2] += np.pi / n_angles
|
||||
|
||||
x = (radii * np.cos(angles)).flatten()
|
||||
y = (radii * np.sin(angles)).flatten()
|
||||
z = (np.cos(radii) * np.cos(3 * angles)).flatten()
|
||||
x = (radii * np.cos(angles)).flatten()
|
||||
y = (radii * np.sin(angles)).flatten()
|
||||
z = (np.cos(radii) * np.cos(3 * angles)).flatten()
|
||||
|
||||
# Create the Triangulation; no triangles so Delaunay triangulation created.
|
||||
triang = tri.Triangulation(x, y)
|
||||
# Create the Triangulation; no triangles so Delaunay triangulation created.
|
||||
triang = tri.Triangulation(x, y)
|
||||
|
||||
# Mask off unwanted triangles.
|
||||
triang.set_mask(np.hypot(x[triang.triangles].mean(axis=1),
|
||||
y[triang.triangles].mean(axis=1))
|
||||
< min_radius)
|
||||
# Mask off unwanted triangles.
|
||||
triang.set_mask(np.hypot(x[triang.triangles].mean(axis=1),
|
||||
y[triang.triangles].mean(axis=1))
|
||||
< min_radius)
|
||||
|
||||
fig1, ax1 = plt.subplots()
|
||||
ax1.set_aspect('equal')
|
||||
tpc = ax1.tripcolor(triang, z, shading='flat')
|
||||
fig1.colorbar(tpc)
|
||||
ax1.set_title('tripcolor of Delaunay triangulation, flat shading')
|
||||
fig1, ax1 = plt.subplots()
|
||||
ax1.set_aspect('equal')
|
||||
tpc = ax1.tripcolor(triang, z, shading='flat')
|
||||
fig1.colorbar(tpc)
|
||||
ax1.set_title('tripcolor of Delaunay triangulation, flat shading')
|
||||
|
||||
display(fig1, target="mpl")
|
||||
display(fig1, target="mpl")
|
||||
</py-script>
|
||||
</py-tutor>
|
||||
</section>
|
||||
|
||||
@@ -1,37 +1,35 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<head>
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<py-tutor>
|
||||
<py-config>
|
||||
packages = [
|
||||
"numpy",
|
||||
"networkx",
|
||||
"matplotlib"
|
||||
]
|
||||
plugins = [
|
||||
"../build/plugins/python/py_tutor.py"
|
||||
]
|
||||
</py-config>
|
||||
<py-config>
|
||||
packages = [
|
||||
"numpy",
|
||||
"networkx",
|
||||
"matplotlib"
|
||||
]
|
||||
plugins = [
|
||||
"../build/plugins/python/py_tutor.py"
|
||||
]
|
||||
</py-config>
|
||||
|
||||
<py-script>
|
||||
import numpy as np
|
||||
import networkx as nx
|
||||
</py-script>
|
||||
<py-script>
|
||||
import numpy as np
|
||||
import networkx as nx
|
||||
</py-script>
|
||||
|
||||
<p>Message passing with linear algebra: a demo.</p>
|
||||
<p>Imagine we have a chain graph that looks like this:</p>
|
||||
<pre><code>O --> 1 --> 2 --> 3</code></pre>
|
||||
<p>In NetworkX this graph would look like the following:</p>
|
||||
<pre>
|
||||
<p>Message passing with linear algebra: a demo.</p>
|
||||
<p>Imagine we have a chain graph that looks like this:</p>
|
||||
<pre><code>O --> 1 --> 2 --> 3</code></pre>
|
||||
<p>In NetworkX this graph would look like the following:</p>
|
||||
<pre>
|
||||
<py-script>
|
||||
G = nx.Graph()
|
||||
nodes = list(range(4))
|
||||
@@ -39,28 +37,29 @@ G.add_edges_from(zip(nodes[0:-1], nodes[1:]))
|
||||
print(G.edges())
|
||||
</py-script>
|
||||
</pre>
|
||||
<p>This chain graph has the following adjacency matrix:</p>
|
||||
<pre>
|
||||
<p>This chain graph has the following adjacency matrix:</p>
|
||||
<pre>
|
||||
<py-script>
|
||||
adj_mat = np.eye(4, k=1)
|
||||
print(f"A: {adj_mat}")
|
||||
</py-script>
|
||||
</pre>
|
||||
<p>And imagine that we have a message that lives on the graph:</p>
|
||||
<pre>
|
||||
<p>And imagine that we have a message that lives on the graph:</p>
|
||||
<pre>
|
||||
<py-script>
|
||||
message = np.array([1.0, 0.0, 0.0, 0.0])
|
||||
print(f"message: {message}")
|
||||
</py-script>
|
||||
</pre>
|
||||
<p>Try out message passing below by doing any one of the following steps:</p>
|
||||
<pre><code>message @ adj_mat</code></pre>
|
||||
<pre><code>message @ adj_mat @ adj_mat</code></pre>
|
||||
<pre><code>message @ adj_mat @ adj_mat @ adj_mat</code></pre>
|
||||
<div>
|
||||
<p>
|
||||
Try out message passing below by doing any one of the following steps:
|
||||
</p>
|
||||
<pre><code>message @ adj_mat</code></pre>
|
||||
<pre><code>message @ adj_mat @ adj_mat</code></pre>
|
||||
<pre><code>message @ adj_mat @ adj_mat @ adj_mat</code></pre>
|
||||
<div>
|
||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||
</div>
|
||||
</div>
|
||||
</py-tutor>
|
||||
</body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,191 +1,186 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
|
||||
<title>micrograd</title>
|
||||
<title>micrograd</title>
|
||||
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
|
||||
</head>
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
</head>
|
||||
|
||||
<body style="padding-top: 20px; padding-right: 20px; padding-bottom: 20px; padding-left: 20px">
|
||||
<h1>Micrograd - A tiny Autograd engine (with a bite! :))</h1><br>
|
||||
<body
|
||||
style="
|
||||
padding-top: 20px;
|
||||
padding-right: 20px;
|
||||
padding-bottom: 20px;
|
||||
padding-left: 20px;
|
||||
"
|
||||
>
|
||||
<h1>Micrograd - A tiny Autograd engine (with a bite! :))</h1>
|
||||
<br />
|
||||
|
||||
<py-config>
|
||||
packages = [
|
||||
"micrograd",
|
||||
"numpy",
|
||||
"matplotlib"
|
||||
]
|
||||
</py-config>
|
||||
<py-config>
|
||||
packages = [
|
||||
"micrograd",
|
||||
"numpy",
|
||||
"matplotlib"
|
||||
]
|
||||
</py-config>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
<a href="https://github.com/karpathy/micrograd">Micrograd</a> is a tiny Autograd engine created
|
||||
by <a href="https://twitter.com/karpathy">Andrej Karpathy</a>. This app recreates the
|
||||
<a href="https://github.com/karpathy/micrograd/blob/master/demo.ipynb">demo</a>
|
||||
he prepared for this package using pyscript to train a basic model, written in Python, natively in
|
||||
the browser. <br>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
You may run each Python REPL cell interactively by pressing (Shift + Enter) or (Ctrl + Enter).
|
||||
You can also modify the code directly as you wish. If you want to run all the code at once,
|
||||
not each cell individually, you may instead click the 'Run All' button. Training the model
|
||||
takes between 1-2 min if you decide to 'Run All' at once. 'Run All' is your only option if
|
||||
you are running this on a mobile device where you cannot press (Shift + Enter). After the
|
||||
model is trained, a plot image should be displayed depicting the model's ability to
|
||||
classify the data. <br>
|
||||
</p>
|
||||
<p>
|
||||
Currently the <code>></code> symbol is being imported incorrectly as <code>&gt;</code> into the REPL's.
|
||||
In this app the <code>></code> symbol has been replaced with <code>().__gt__()</code> so you can run the code
|
||||
without issue. Ex: instead of <code>a > b</code>, you will see <code>(a).__gt__(b)</code> instead. <br>
|
||||
</p>
|
||||
<py-script>import js; js.document.getElementById('python-status').innerHTML = 'Python is now ready. You may proceed.'</py-script>
|
||||
<div id="python-status">Python is currently starting. Please wait...</div>
|
||||
<button id="run-all-button" class="btn btn-primary" type="submit" py-onClick="run_all_micrograd_demo()">Run All</button><br>
|
||||
<py-script src="/micrograd_ai.py"></py-script>
|
||||
<div id="micrograd-run-all-print-div"></div><br>
|
||||
<div id="micrograd-run-all-fig1-div"></div>
|
||||
<div id="micrograd-run-all-fig2-div"></div><br>
|
||||
</div>
|
||||
<py-repl auto-generate="false">
|
||||
import random
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
</py-repl><br>
|
||||
<py-repl auto-generate="false">
|
||||
from micrograd.engine import Value
|
||||
from micrograd.nn import Neuron, Layer, MLP
|
||||
</py-repl><br>
|
||||
<py-repl auto-generate="true">
|
||||
np.random.seed(1337)
|
||||
random.seed(1337)
|
||||
</py-repl><br>
|
||||
<py-repl auto-generate="true">
|
||||
#An adaptation of sklearn's make_moons function https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_moons.html
|
||||
def make_moons(n_samples=100, noise=None):
|
||||
n_samples_out, n_samples_in = n_samples, n_samples
|
||||
<div>
|
||||
<p>
|
||||
<a href="https://github.com/karpathy/micrograd">Micrograd</a> is a tiny
|
||||
Autograd engine created by
|
||||
<a href="https://twitter.com/karpathy">Andrej Karpathy</a>. This app
|
||||
recreates the
|
||||
<a href="https://github.com/karpathy/micrograd/blob/master/demo.ipynb"
|
||||
>demo</a
|
||||
>
|
||||
he prepared for this package using pyscript to train a basic model,
|
||||
written in Python, natively in the browser. <br />
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
You may run each Python REPL cell interactively by pressing (Shift +
|
||||
Enter) or (Ctrl + Enter). You can also modify the code directly as you
|
||||
wish. If you want to run all the code at once, not each cell
|
||||
individually, you may instead click the 'Run All' button. Training the
|
||||
model takes between 1-2 min if you decide to 'Run All' at once. 'Run
|
||||
All' is your only option if you are running this on a mobile device
|
||||
where you cannot press (Shift + Enter). After the model is trained, a
|
||||
plot image should be displayed depicting the model's ability to classify
|
||||
the data. <br />
|
||||
</p>
|
||||
<p>
|
||||
Currently the <code>></code> symbol is being imported incorrectly as
|
||||
<code>&gt;</code> into the REPL's. In this app the
|
||||
<code>></code> symbol has been replaced with
|
||||
<code>().__gt__()</code> so you can run the code without issue. Ex:
|
||||
instead of <code>a > b</code>, you will see
|
||||
<code>(a).__gt__(b)</code> instead. <br />
|
||||
</p>
|
||||
<py-script>
|
||||
import js; js.document.getElementById('python-status').innerHTML = 'Python is now ready. You may proceed.'
|
||||
</py-script>
|
||||
<div id="python-status">Python is currently starting. Please wait...</div>
|
||||
<button
|
||||
id="run-all-button"
|
||||
class="btn btn-primary"
|
||||
type="submit"
|
||||
py-onClick="run_all_micrograd_demo()"
|
||||
>
|
||||
Run All</button
|
||||
><br />
|
||||
<py-script src="/micrograd_ai.py"></py-script>
|
||||
<div id="micrograd-run-all-print-div"></div>
|
||||
<br />
|
||||
<div id="micrograd-run-all-fig1-div"></div>
|
||||
<div id="micrograd-run-all-fig2-div"></div>
|
||||
<br />
|
||||
</div>
|
||||
<py-repl auto-generate="false">
|
||||
import random import numpy as np import matplotlib.pyplot as plt </py-repl
|
||||
><br />
|
||||
<py-repl auto-generate="false">
|
||||
from micrograd.engine import Value from micrograd.nn import Neuron, Layer,
|
||||
MLP </py-repl
|
||||
><br />
|
||||
<py-repl auto-generate="true">
|
||||
np.random.seed(1337) random.seed(1337) </py-repl
|
||||
><br />
|
||||
<py-repl auto-generate="true">
|
||||
#An adaptation of sklearn's make_moons function
|
||||
https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_moons.html
|
||||
def make_moons(n_samples=100, noise=None): n_samples_out, n_samples_in =
|
||||
n_samples, n_samples outer_circ_x = np.cos(np.linspace(0, np.pi,
|
||||
n_samples_out)) outer_circ_y = np.sin(np.linspace(0, np.pi,
|
||||
n_samples_out)) inner_circ_x = 1 - np.cos(np.linspace(0, np.pi,
|
||||
n_samples_in)) inner_circ_y = 1 - np.sin(np.linspace(0, np.pi,
|
||||
n_samples_in)) - 0.5 X = np.vstack([np.append(outer_circ_x, inner_circ_x),
|
||||
np.append(outer_circ_y, inner_circ_y)]).T y =
|
||||
np.hstack([np.zeros(n_samples_out, dtype=np.intp), np.ones(n_samples_in,
|
||||
dtype=np.intp)]) if noise is not None: X += np.random.normal(loc=0.0,
|
||||
scale=noise, size=X.shape) return X, y X, y = make_moons(n_samples=100,
|
||||
noise=0.1) </py-repl
|
||||
><br />
|
||||
<py-repl auto-generate="true">
|
||||
y = y*2 - 1 # make y be -1 or 1 # visualize in 2D
|
||||
plt.figure(figsize=(5,5)) plt.scatter(X[:,0], X[:,1], c=y, s=20,
|
||||
cmap='jet') plt </py-repl
|
||||
><br />
|
||||
<py-repl auto-generate="true">
|
||||
model = MLP(2, [16, 16, 1]) # 2-layer neural network print(model)
|
||||
print("number of parameters", len(model.parameters())) </py-repl
|
||||
><br />
|
||||
|
||||
outer_circ_x = np.cos(np.linspace(0, np.pi, n_samples_out))
|
||||
outer_circ_y = np.sin(np.linspace(0, np.pi, n_samples_out))
|
||||
inner_circ_x = 1 - np.cos(np.linspace(0, np.pi, n_samples_in))
|
||||
inner_circ_y = 1 - np.sin(np.linspace(0, np.pi, n_samples_in)) - 0.5
|
||||
<div>
|
||||
Line 24 has been changed from: <br />
|
||||
<code
|
||||
>accuracy = [(yi > 0) == (scorei.data > 0) for yi, scorei in
|
||||
zip(yb, scores)]</code
|
||||
><br />
|
||||
to: <br />
|
||||
<code
|
||||
>accuracy = [((yi).__gt__(0)) == ((scorei.data).__gt__(0)) for yi,
|
||||
scorei in zip(yb, scores)]</code
|
||||
><br />
|
||||
</div>
|
||||
|
||||
X = np.vstack([np.append(outer_circ_x, inner_circ_x), np.append(outer_circ_y, inner_circ_y)]).T
|
||||
y = np.hstack([np.zeros(n_samples_out, dtype=np.intp), np.ones(n_samples_in, dtype=np.intp)])
|
||||
if noise is not None: X += np.random.normal(loc=0.0, scale=noise, size=X.shape)
|
||||
return X, y
|
||||
X, y = make_moons(n_samples=100, noise=0.1)
|
||||
</py-repl><br>
|
||||
<py-repl auto-generate="true">
|
||||
y = y*2 - 1 # make y be -1 or 1
|
||||
# visualize in 2D
|
||||
plt.figure(figsize=(5,5))
|
||||
plt.scatter(X[:,0], X[:,1], c=y, s=20, cmap='jet')
|
||||
plt
|
||||
</py-repl><br>
|
||||
<py-repl auto-generate="true">
|
||||
model = MLP(2, [16, 16, 1]) # 2-layer neural network
|
||||
print(model)
|
||||
print("number of parameters", len(model.parameters()))
|
||||
</py-repl><br>
|
||||
<py-repl auto-generate="true">
|
||||
# loss function def loss(batch_size=None): # inline DataLoader :) if
|
||||
batch_size is None: Xb, yb = X, y else: ri =
|
||||
np.random.permutation(X.shape[0])[:batch_size] Xb, yb = X[ri], y[ri]
|
||||
inputs = [list(map(Value, xrow)) for xrow in Xb] # forward the model to
|
||||
get scores scores = list(map(model, inputs)) # svm "max-margin" loss
|
||||
losses = [(1 + -yi*scorei).relu() for yi, scorei in zip(yb, scores)]
|
||||
data_loss = sum(losses) * (1.0 / len(losses)) # L2 regularization alpha =
|
||||
1e-4 reg_loss = alpha * sum((p*p for p in model.parameters())) total_loss
|
||||
= data_loss + reg_loss # also get accuracy accuracy = [((yi).__gt__(0)) ==
|
||||
((scorei.data).__gt__(0)) for yi, scorei in zip(yb, scores)] return
|
||||
total_loss, sum(accuracy) / len(accuracy) total_loss, acc = loss()
|
||||
print(total_loss, acc) </py-repl
|
||||
><br />
|
||||
<py-repl auto-generate="true">
|
||||
# optimization for k in range(20): #was 100. Accuracy can be further
|
||||
improved w/ more epochs (to 100%). # forward total_loss, acc = loss() #
|
||||
backward model.zero_grad() total_loss.backward() # update (sgd)
|
||||
learning_rate = 1.0 - 0.9*k/100 for p in model.parameters(): p.data -=
|
||||
learning_rate * p.grad if k % 1 == 0: print(f"step {k} loss
|
||||
{total_loss.data}, accuracy {acc*100}%") </py-repl
|
||||
><br />
|
||||
<div>
|
||||
<p>
|
||||
Please wait for the training loop above to complete. It will not print
|
||||
out stats until it has completely finished. This typically takes 1-2
|
||||
min. <br /><br />
|
||||
|
||||
<div>
|
||||
Line 24 has been changed from: <br>
|
||||
<code>accuracy = [(yi > 0) == (scorei.data > 0) for yi, scorei in zip(yb, scores)]</code><br>
|
||||
to: <br>
|
||||
<code>accuracy = [((yi).__gt__(0)) == ((scorei.data).__gt__(0)) for yi, scorei in zip(yb, scores)]</code><br>
|
||||
</div>
|
||||
|
||||
<py-repl auto-generate="true">
|
||||
# loss function
|
||||
def loss(batch_size=None):
|
||||
|
||||
# inline DataLoader :)
|
||||
if batch_size is None:
|
||||
Xb, yb = X, y
|
||||
else:
|
||||
ri = np.random.permutation(X.shape[0])[:batch_size]
|
||||
Xb, yb = X[ri], y[ri]
|
||||
inputs = [list(map(Value, xrow)) for xrow in Xb]
|
||||
|
||||
# forward the model to get scores
|
||||
scores = list(map(model, inputs))
|
||||
|
||||
# svm "max-margin" loss
|
||||
losses = [(1 + -yi*scorei).relu() for yi, scorei in zip(yb, scores)]
|
||||
data_loss = sum(losses) * (1.0 / len(losses))
|
||||
# L2 regularization
|
||||
alpha = 1e-4
|
||||
reg_loss = alpha * sum((p*p for p in model.parameters()))
|
||||
total_loss = data_loss + reg_loss
|
||||
|
||||
# also get accuracy
|
||||
accuracy = [((yi).__gt__(0)) == ((scorei.data).__gt__(0)) for yi, scorei in zip(yb, scores)]
|
||||
return total_loss, sum(accuracy) / len(accuracy)
|
||||
|
||||
total_loss, acc = loss()
|
||||
print(total_loss, acc)
|
||||
</py-repl><br>
|
||||
<py-repl auto-generate="true">
|
||||
# optimization
|
||||
for k in range(20): #was 100. Accuracy can be further improved w/ more epochs (to 100%).
|
||||
|
||||
# forward
|
||||
total_loss, acc = loss()
|
||||
|
||||
# backward
|
||||
model.zero_grad()
|
||||
total_loss.backward()
|
||||
|
||||
# update (sgd)
|
||||
learning_rate = 1.0 - 0.9*k/100
|
||||
for p in model.parameters():
|
||||
p.data -= learning_rate * p.grad
|
||||
|
||||
if k % 1 == 0:
|
||||
print(f"step {k} loss {total_loss.data}, accuracy {acc*100}%")
|
||||
</py-repl><br>
|
||||
<div>
|
||||
<p>
|
||||
Please wait for the training loop above to complete. It will not print out stats until it
|
||||
has completely finished. This typically takes 1-2 min. <br><br>
|
||||
|
||||
Line 9 has been changed from: <br>
|
||||
<code>Z = np.array([s.data > 0 for s in scores])</code><br>
|
||||
to: <br>
|
||||
<code>Z = np.array([(s.data).__gt__(0) for s in scores])</code><br>
|
||||
</p>
|
||||
</div>
|
||||
<py-repl auto-generate="true">
|
||||
h = 0.25
|
||||
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
|
||||
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
|
||||
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
|
||||
np.arange(y_min, y_max, h))
|
||||
Xmesh = np.c_[xx.ravel(), yy.ravel()]
|
||||
inputs = [list(map(Value, xrow)) for xrow in Xmesh]
|
||||
scores = list(map(model, inputs))
|
||||
Z = np.array([(s.data).__gt__(0) for s in scores])
|
||||
Z = Z.reshape(xx.shape)
|
||||
|
||||
fig = plt.figure()
|
||||
plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral, alpha=0.8)
|
||||
plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.Spectral)
|
||||
plt.xlim(xx.min(), xx.max())
|
||||
plt.ylim(yy.min(), yy.max())
|
||||
plt
|
||||
</py-repl><br>
|
||||
<py-repl auto-generate="true">
|
||||
1+1
|
||||
</py-repl><br>
|
||||
</body>
|
||||
Line 9 has been changed from: <br />
|
||||
<code>Z = np.array([s.data > 0 for s in scores])</code><br />
|
||||
to: <br />
|
||||
<code>Z = np.array([(s.data).__gt__(0) for s in scores])</code><br />
|
||||
</p>
|
||||
</div>
|
||||
<py-repl auto-generate="true">
|
||||
h = 0.25 x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1 y_min, y_max
|
||||
= X[:, 1].min() - 1, X[:, 1].max() + 1 xx, yy =
|
||||
np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) Xmesh
|
||||
= np.c_[xx.ravel(), yy.ravel()] inputs = [list(map(Value, xrow)) for xrow
|
||||
in Xmesh] scores = list(map(model, inputs)) Z =
|
||||
np.array([(s.data).__gt__(0) for s in scores]) Z = Z.reshape(xx.shape) fig
|
||||
= plt.figure() plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral, alpha=0.8)
|
||||
plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.Spectral)
|
||||
plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) plt </py-repl
|
||||
><br />
|
||||
<py-repl auto-generate="true"> 1+1 </py-repl><br />
|
||||
</body>
|
||||
</html>
|
||||
<!-- Adapted by Mat Miller -->
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Visualization of Mandelbrot, Julia and Newton sets with NumPy and HTML5 canvas</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<title>
|
||||
Visualization of Mandelbrot, Julia and Newton sets with NumPy and HTML5
|
||||
canvas
|
||||
</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||
@@ -27,19 +30,22 @@
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Fractals with NumPy and canvas</a>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
<div style="display: flex; flex-direction: column; gap: 1em; width: 600px">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c"
|
||||
>Fractals with NumPy and canvas</a
|
||||
>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
<div
|
||||
style="display: flex; flex-direction: column; gap: 1em; width: 600px"
|
||||
>
|
||||
<div id="mandelbrot">
|
||||
<div style="text-align: center">Mandelbrot set</div>
|
||||
<div>
|
||||
@@ -57,25 +63,63 @@
|
||||
<div id="newton">
|
||||
<div style="text-align: center">Newton set</div>
|
||||
<fieldset style="display: flex; flex-direction: row; gap: 1em">
|
||||
<div><span style="white-space: pre">p(z) = </span><input id="poly" type="text" value="z**3 - 2*z + 2"></div>
|
||||
<div><span style="white-space: pre">a = </span><input id="coef" type="text" value="1" style="width: 40px"></div>
|
||||
<div>
|
||||
<span style="white-space: pre">p(z) = </span
|
||||
><input id="poly" type="text" value="z**3 - 2*z + 2" />
|
||||
</div>
|
||||
<div>
|
||||
<span style="white-space: pre">a = </span
|
||||
><input id="coef" type="text" value="1" style="width: 40px" />
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<span style="white-space: pre">x = [</span>
|
||||
<input id="x0" type="text" value="-2.5" style="width: 80px; text-align: right">
|
||||
<input
|
||||
id="x0"
|
||||
type="text"
|
||||
value="-2.5"
|
||||
style="width: 80px; text-align: right"
|
||||
/>
|
||||
<span style="white-space: pre">, </span>
|
||||
<input id="x1" type="text" value="2.5" style="width: 80px; text-align: right">
|
||||
<input
|
||||
id="x1"
|
||||
type="text"
|
||||
value="2.5"
|
||||
style="width: 80px; text-align: right"
|
||||
/>
|
||||
<span style="white-space: pre">]</span>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<span style="white-space: pre">y = [</span>
|
||||
<input id="y0" type="text" value="-5.0" style="width: 80px; text-align: right">
|
||||
<input
|
||||
id="y0"
|
||||
type="text"
|
||||
value="-5.0"
|
||||
style="width: 80px; text-align: right"
|
||||
/>
|
||||
<span style="white-space: pre">, </span>
|
||||
<input id="y1" type="text" value="5.0" style="width: 80px; text-align: right">
|
||||
<input
|
||||
id="y1"
|
||||
type="text"
|
||||
value="5.0"
|
||||
style="width: 80px; text-align: right"
|
||||
/>
|
||||
<span style="white-space: pre">]</span>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: row; gap: 1em">
|
||||
<div style="white-space: pre"><input type="radio" id="conv" name="type" value="convergence" checked> convergence</div>
|
||||
<div style="white-space: pre"><input type="radio" id="iter" name="type" value="iterations"> iterations</div>
|
||||
<div style="white-space: pre">
|
||||
<input
|
||||
type="radio"
|
||||
id="conv"
|
||||
name="type"
|
||||
value="convergence"
|
||||
checked
|
||||
/>
|
||||
convergence
|
||||
</div>
|
||||
<div style="white-space: pre">
|
||||
<input type="radio" id="iter" name="type" value="iterations" />
|
||||
iterations
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div>
|
||||
@@ -106,236 +150,236 @@
|
||||
</py-config>
|
||||
|
||||
<py-script>
|
||||
from pyodide.ffi import to_js, create_proxy
|
||||
from pyodide.ffi import to_js, create_proxy
|
||||
|
||||
import numpy as np
|
||||
import sympy
|
||||
import numpy as np
|
||||
import sympy
|
||||
|
||||
from palettes import Magma256
|
||||
from fractals import mandelbrot, julia, newton
|
||||
from palettes import Magma256
|
||||
from fractals import mandelbrot, julia, newton
|
||||
|
||||
from js import (
|
||||
console,
|
||||
document,
|
||||
devicePixelRatio,
|
||||
ImageData,
|
||||
Uint8ClampedArray,
|
||||
CanvasRenderingContext2D as Context2d,
|
||||
requestAnimationFrame,
|
||||
)
|
||||
from js import (
|
||||
console,
|
||||
document,
|
||||
devicePixelRatio,
|
||||
ImageData,
|
||||
Uint8ClampedArray,
|
||||
CanvasRenderingContext2D as Context2d,
|
||||
requestAnimationFrame,
|
||||
)
|
||||
|
||||
def prepare_canvas(width: int, height: int, canvas: Element) -> Context2d:
|
||||
ctx = canvas.getContext("2d")
|
||||
def prepare_canvas(width: int, height: int, canvas: Element) -> Context2d:
|
||||
ctx = canvas.getContext("2d")
|
||||
|
||||
canvas.style.width = f"{width}px"
|
||||
canvas.style.height = f"{height}px"
|
||||
canvas.style.width = f"{width}px"
|
||||
canvas.style.height = f"{height}px"
|
||||
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
|
||||
ctx.clearRect(0, 0, width, height)
|
||||
ctx.clearRect(0, 0, width, height)
|
||||
|
||||
return ctx
|
||||
return ctx
|
||||
|
||||
def color_map(array: np.array, palette: np.array) -> np.array:
|
||||
size, _ = palette.shape
|
||||
index = (array/array.max()*(size - 1)).round().astype("uint8")
|
||||
def color_map(array: np.array, palette: np.array) -> np.array:
|
||||
size, _ = palette.shape
|
||||
index = (array/array.max()*(size - 1)).round().astype("uint8")
|
||||
|
||||
width, height = array.shape
|
||||
image = np.full((width, height, 4), 0xff, dtype=np.uint8)
|
||||
image[:, :, :3] = palette[index]
|
||||
width, height = array.shape
|
||||
image = np.full((width, height, 4), 0xff, dtype=np.uint8)
|
||||
image[:, :, :3] = palette[index]
|
||||
|
||||
return image
|
||||
return image
|
||||
|
||||
def draw_image(ctx: Context2d, image: np.array) -> None:
|
||||
data = Uint8ClampedArray.new(to_js(image.tobytes()))
|
||||
width, height, _ = image.shape
|
||||
image_data = ImageData.new(data, width, height)
|
||||
ctx.putImageData(image_data, 0, 0)
|
||||
def draw_image(ctx: Context2d, image: np.array) -> None:
|
||||
data = Uint8ClampedArray.new(to_js(image.tobytes()))
|
||||
width, height, _ = image.shape
|
||||
image_data = ImageData.new(data, width, height)
|
||||
ctx.putImageData(image_data, 0, 0)
|
||||
|
||||
width, height = 600, 600
|
||||
width, height = 600, 600
|
||||
|
||||
async def draw_mandelbrot() -> None:
|
||||
spinner = document.querySelector("#mandelbrot .loading")
|
||||
canvas = document.querySelector("#mandelbrot canvas")
|
||||
async def draw_mandelbrot() -> None:
|
||||
spinner = document.querySelector("#mandelbrot .loading")
|
||||
canvas = document.querySelector("#mandelbrot canvas")
|
||||
|
||||
spinner.style.display = ""
|
||||
canvas.style.display = "none"
|
||||
spinner.style.display = ""
|
||||
canvas.style.display = "none"
|
||||
|
||||
ctx = prepare_canvas(width, height, canvas)
|
||||
ctx = prepare_canvas(width, height, canvas)
|
||||
|
||||
console.log("Computing Mandelbrot set ...")
|
||||
console.time("mandelbrot")
|
||||
iters = mandelbrot(width, height)
|
||||
console.timeEnd("mandelbrot")
|
||||
console.log("Computing Mandelbrot set ...")
|
||||
console.time("mandelbrot")
|
||||
iters = mandelbrot(width, height)
|
||||
console.timeEnd("mandelbrot")
|
||||
|
||||
image = color_map(iters, Magma256)
|
||||
draw_image(ctx, image)
|
||||
image = color_map(iters, Magma256)
|
||||
draw_image(ctx, image)
|
||||
|
||||
spinner.style.display = "none"
|
||||
canvas.style.display = "block"
|
||||
spinner.style.display = "none"
|
||||
canvas.style.display = "block"
|
||||
|
||||
async def draw_julia() -> None:
|
||||
spinner = document.querySelector("#julia .loading")
|
||||
canvas = document.querySelector("#julia canvas")
|
||||
async def draw_julia() -> None:
|
||||
spinner = document.querySelector("#julia .loading")
|
||||
canvas = document.querySelector("#julia canvas")
|
||||
|
||||
spinner.style.display = ""
|
||||
canvas.style.display = "none"
|
||||
spinner.style.display = ""
|
||||
canvas.style.display = "none"
|
||||
|
||||
ctx = prepare_canvas(width, height, canvas)
|
||||
ctx = prepare_canvas(width, height, canvas)
|
||||
|
||||
console.log("Computing Julia set ...")
|
||||
console.time("julia")
|
||||
iters = julia(width, height)
|
||||
console.timeEnd("julia")
|
||||
console.log("Computing Julia set ...")
|
||||
console.time("julia")
|
||||
iters = julia(width, height)
|
||||
console.timeEnd("julia")
|
||||
|
||||
image = color_map(iters, Magma256)
|
||||
draw_image(ctx, image)
|
||||
image = color_map(iters, Magma256)
|
||||
draw_image(ctx, image)
|
||||
|
||||
spinner.style.display = "none"
|
||||
canvas.style.display = "block"
|
||||
spinner.style.display = "none"
|
||||
canvas.style.display = "block"
|
||||
|
||||
def ranges():
|
||||
x0_in = document.querySelector("#x0")
|
||||
x1_in = document.querySelector("#x1")
|
||||
y0_in = document.querySelector("#y0")
|
||||
y1_in = document.querySelector("#y1")
|
||||
def ranges():
|
||||
x0_in = document.querySelector("#x0")
|
||||
x1_in = document.querySelector("#x1")
|
||||
y0_in = document.querySelector("#y0")
|
||||
y1_in = document.querySelector("#y1")
|
||||
|
||||
xr = (float(x0_in.value), float(x1_in.value))
|
||||
yr = (float(y0_in.value), float(y1_in.value))
|
||||
xr = (float(x0_in.value), float(x1_in.value))
|
||||
yr = (float(y0_in.value), float(y1_in.value))
|
||||
|
||||
return xr, yr
|
||||
return xr, yr
|
||||
|
||||
current_image = None
|
||||
async def draw_newton() -> None:
|
||||
spinner = document.querySelector("#newton .loading")
|
||||
canvas = document.querySelector("#newton canvas")
|
||||
current_image = None
|
||||
async def draw_newton() -> None:
|
||||
spinner = document.querySelector("#newton .loading")
|
||||
canvas = document.querySelector("#newton canvas")
|
||||
|
||||
spinner.style.display = ""
|
||||
canvas.style.display = "none"
|
||||
spinner.style.display = ""
|
||||
canvas.style.display = "none"
|
||||
|
||||
ctx = prepare_canvas(width, height, canvas)
|
||||
ctx = prepare_canvas(width, height, canvas)
|
||||
|
||||
console.log("Computing Newton set ...")
|
||||
console.log("Computing Newton set ...")
|
||||
|
||||
poly_in = document.querySelector("#poly")
|
||||
coef_in = document.querySelector("#coef")
|
||||
conv_in = document.querySelector("#conv")
|
||||
iter_in = document.querySelector("#iter")
|
||||
poly_in = document.querySelector("#poly")
|
||||
coef_in = document.querySelector("#coef")
|
||||
conv_in = document.querySelector("#conv")
|
||||
iter_in = document.querySelector("#iter")
|
||||
|
||||
xr, yr = ranges()
|
||||
xr, yr = ranges()
|
||||
|
||||
# z**3 - 1
|
||||
# z**8 + 15*z**4 - 16
|
||||
# z**3 - 2*z + 2
|
||||
# z**3 - 1
|
||||
# z**8 + 15*z**4 - 16
|
||||
# z**3 - 2*z + 2
|
||||
|
||||
expr = sympy.parse_expr(poly_in.value)
|
||||
coeffs = [ complex(c) for c in reversed(sympy.Poly(expr, sympy.Symbol("z")).all_coeffs()) ]
|
||||
poly = np.polynomial.Polynomial(coeffs)
|
||||
expr = sympy.parse_expr(poly_in.value)
|
||||
coeffs = [ complex(c) for c in reversed(sympy.Poly(expr, sympy.Symbol("z")).all_coeffs()) ]
|
||||
poly = np.polynomial.Polynomial(coeffs)
|
||||
|
||||
coef = complex(sympy.parse_expr(coef_in.value))
|
||||
coef = complex(sympy.parse_expr(coef_in.value))
|
||||
|
||||
console.time("newton")
|
||||
iters, roots = newton(width, height, p=poly, a=coef, xr=xr, yr=yr)
|
||||
console.timeEnd("newton")
|
||||
console.time("newton")
|
||||
iters, roots = newton(width, height, p=poly, a=coef, xr=xr, yr=yr)
|
||||
console.timeEnd("newton")
|
||||
|
||||
if conv_in.checked:
|
||||
n = poly.degree() + 1
|
||||
k = int(len(Magma256)/n)
|
||||
if conv_in.checked:
|
||||
n = poly.degree() + 1
|
||||
k = int(len(Magma256)/n)
|
||||
|
||||
colors = Magma256[::k, :][:n]
|
||||
colors[0, :] = [255, 0, 0] # red: no convergence
|
||||
colors = Magma256[::k, :][:n]
|
||||
colors[0, :] = [255, 0, 0] # red: no convergence
|
||||
|
||||
image = color_map(roots, colors)
|
||||
else:
|
||||
image = color_map(iters, Magma256)
|
||||
image = color_map(roots, colors)
|
||||
else:
|
||||
image = color_map(iters, Magma256)
|
||||
|
||||
global current_image
|
||||
current_image = image
|
||||
draw_image(ctx, image)
|
||||
global current_image
|
||||
current_image = image
|
||||
draw_image(ctx, image)
|
||||
|
||||
spinner.style.display = "none"
|
||||
canvas.style.display = "block"
|
||||
spinner.style.display = "none"
|
||||
canvas.style.display = "block"
|
||||
|
||||
handler = create_proxy(lambda _event: draw_newton())
|
||||
document.querySelector("#newton fieldset").addEventListener("change", handler)
|
||||
handler = create_proxy(lambda _event: draw_newton())
|
||||
document.querySelector("#newton fieldset").addEventListener("change", handler)
|
||||
|
||||
canvas = document.querySelector("#newton canvas")
|
||||
canvas = document.querySelector("#newton canvas")
|
||||
|
||||
is_selecting = False
|
||||
init_sx, init_sy = None, None
|
||||
sx, sy = None, None
|
||||
async def mousemove(event):
|
||||
global is_selecting
|
||||
global init_sx
|
||||
global init_sy
|
||||
global sx
|
||||
global sy
|
||||
is_selecting = False
|
||||
init_sx, init_sy = None, None
|
||||
sx, sy = None, None
|
||||
async def mousemove(event):
|
||||
global is_selecting
|
||||
global init_sx
|
||||
global init_sy
|
||||
global sx
|
||||
global sy
|
||||
|
||||
def invert(sx, source_range, target_range):
|
||||
source_start, source_end = source_range
|
||||
target_start, target_end = target_range
|
||||
factor = (target_end - target_start)/(source_end - source_start)
|
||||
offset = -(factor * source_start) + target_start
|
||||
return (sx - offset) / factor
|
||||
def invert(sx, source_range, target_range):
|
||||
source_start, source_end = source_range
|
||||
target_start, target_end = target_range
|
||||
factor = (target_end - target_start)/(source_end - source_start)
|
||||
offset = -(factor * source_start) + target_start
|
||||
return (sx - offset) / factor
|
||||
|
||||
bds = canvas.getBoundingClientRect()
|
||||
event_sx, event_sy = event.clientX - bds.x, event.clientY - bds.y
|
||||
bds = canvas.getBoundingClientRect()
|
||||
event_sx, event_sy = event.clientX - bds.x, event.clientY - bds.y
|
||||
|
||||
ctx = canvas.getContext("2d")
|
||||
ctx = canvas.getContext("2d")
|
||||
|
||||
pressed = event.buttons == 1
|
||||
if is_selecting:
|
||||
if not pressed:
|
||||
xr, yr = ranges()
|
||||
pressed = event.buttons == 1
|
||||
if is_selecting:
|
||||
if not pressed:
|
||||
xr, yr = ranges()
|
||||
|
||||
x0 = invert(init_sx, xr, (0, width))
|
||||
x1 = invert(sx, xr, (0, width))
|
||||
y0 = invert(init_sy, yr, (0, height))
|
||||
y1 = invert(sy, yr, (0, height))
|
||||
x0 = invert(init_sx, xr, (0, width))
|
||||
x1 = invert(sx, xr, (0, width))
|
||||
y0 = invert(init_sy, yr, (0, height))
|
||||
y1 = invert(sy, yr, (0, height))
|
||||
|
||||
document.querySelector("#x0").value = x0
|
||||
document.querySelector("#x1").value = x1
|
||||
document.querySelector("#y0").value = y0
|
||||
document.querySelector("#y1").value = y1
|
||||
document.querySelector("#x0").value = x0
|
||||
document.querySelector("#x1").value = x1
|
||||
document.querySelector("#y0").value = y0
|
||||
document.querySelector("#y1").value = y1
|
||||
|
||||
is_selecting = False
|
||||
init_sx, init_sy = None, None
|
||||
sx, sy = init_sx, init_sy
|
||||
is_selecting = False
|
||||
init_sx, init_sy = None, None
|
||||
sx, sy = init_sx, init_sy
|
||||
|
||||
await draw_newton()
|
||||
else:
|
||||
ctx.save()
|
||||
ctx.clearRect(0, 0, width, height)
|
||||
draw_image(ctx, current_image)
|
||||
sx, sy = event_sx, event_sy
|
||||
ctx.beginPath()
|
||||
ctx.rect(init_sx, init_sy, sx - init_sx, sy - init_sy)
|
||||
ctx.fillStyle = "rgba(255, 255, 255, 0.4)"
|
||||
ctx.strokeStyle = "rgba(255, 255, 255, 1.0)"
|
||||
ctx.fill()
|
||||
ctx.stroke()
|
||||
ctx.restore()
|
||||
else:
|
||||
if pressed:
|
||||
is_selecting = True
|
||||
init_sx, init_sy = event_sx, event_sy
|
||||
sx, sy = init_sx, init_sy
|
||||
await draw_newton()
|
||||
else:
|
||||
ctx.save()
|
||||
ctx.clearRect(0, 0, width, height)
|
||||
draw_image(ctx, current_image)
|
||||
sx, sy = event_sx, event_sy
|
||||
ctx.beginPath()
|
||||
ctx.rect(init_sx, init_sy, sx - init_sx, sy - init_sy)
|
||||
ctx.fillStyle = "rgba(255, 255, 255, 0.4)"
|
||||
ctx.strokeStyle = "rgba(255, 255, 255, 1.0)"
|
||||
ctx.fill()
|
||||
ctx.stroke()
|
||||
ctx.restore()
|
||||
else:
|
||||
if pressed:
|
||||
is_selecting = True
|
||||
init_sx, init_sy = event_sx, event_sy
|
||||
sx, sy = init_sx, init_sy
|
||||
|
||||
canvas.addEventListener("mousemove", create_proxy(mousemove))
|
||||
canvas.addEventListener("mousemove", create_proxy(mousemove))
|
||||
|
||||
import asyncio
|
||||
import asyncio
|
||||
|
||||
async def main():
|
||||
_ = await asyncio.gather(
|
||||
draw_mandelbrot(),
|
||||
draw_julia(),
|
||||
draw_newton(),
|
||||
)
|
||||
async def main():
|
||||
_ = await asyncio.gather(
|
||||
draw_mandelbrot(),
|
||||
draw_julia(),
|
||||
draw_newton(),
|
||||
)
|
||||
|
||||
asyncio.ensure_future(main())
|
||||
asyncio.ensure_future(main())
|
||||
</py-script>
|
||||
</py-tutor>
|
||||
</section>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,120 +1,124 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title id="header-title"></title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
<head>
|
||||
<title id="header-title"></title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||
</head>
|
||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
</a>
|
||||
<a class="title" id="page-title" href="" style="color: #f0ab3c;"></a>
|
||||
</div>
|
||||
</nav>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" id="page-title" href="" style="color: #f0ab3c"></a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<br />
|
||||
<div id="page-message"></div>
|
||||
<br />
|
||||
<div id="page-message"></div>
|
||||
|
||||
<div id="pandas-source">
|
||||
<h3>Data Source</h3>
|
||||
<input type="text" id="txt-url" class="py-input" size="70">
|
||||
<button type="submit" id="btn-load" class="py-button" py-click="loadFromURL()">Load CSV</button>
|
||||
</div>
|
||||
<div id="pandas-source">
|
||||
<h3>Data Source</h3>
|
||||
<input type="text" id="txt-url" class="py-input" size="70" />
|
||||
<button
|
||||
type="submit"
|
||||
id="btn-load"
|
||||
class="py-button"
|
||||
py-click="loadFromURL()"
|
||||
>
|
||||
Load CSV
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="pandas-repl" hidden>
|
||||
<h3>Python REPL</h3>
|
||||
<py-repl id ="pandas-repl-inner" output="pandas-output-inner">
|
||||
# Hit SHIFT + ENTER to execute example code
|
||||
<div id="pandas-repl" hidden>
|
||||
<h3>Python REPL</h3>
|
||||
<py-repl id="pandas-repl-inner" output="pandas-output-inner">
|
||||
# Hit SHIFT + ENTER to execute example code # Get all closed airports in
|
||||
Great Britain df2 = df.query("type == 'closed' & iso_country == 'GB'")
|
||||
df2
|
||||
</py-repl>
|
||||
</div>
|
||||
|
||||
# Get all closed airports in Great Britain
|
||||
df2 = df.query("type == 'closed' & iso_country == 'GB'")
|
||||
df2
|
||||
</py-repl>
|
||||
<div id="pandas-output" hidden>
|
||||
<h3>Output</h3>
|
||||
<div id="pandas-output-inner"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div id="pandas-dev-console" hidden>
|
||||
<h3>Dev Console</h3>
|
||||
<py-terminal auto></py-terminal>
|
||||
</div>
|
||||
|
||||
<div id ="pandas-output" hidden>
|
||||
<h3>Output</h3>
|
||||
<div id="pandas-output-inner"></div>
|
||||
</div>
|
||||
<py-tutor>
|
||||
<py-config>
|
||||
plugins = [
|
||||
"../build/plugins/python/py_tutor.py"
|
||||
]
|
||||
packages = ["pandas"]
|
||||
</py-config>
|
||||
|
||||
<div id="pandas-dev-console" hidden>
|
||||
<h3>Dev Console</h3>
|
||||
<py-terminal auto></py-terminal>
|
||||
</div>
|
||||
<section class="pyscript">
|
||||
<py-script>
|
||||
import pandas as pd
|
||||
from pyodide.http import open_url
|
||||
import sys
|
||||
|
||||
<py-tutor>
|
||||
<py-config>
|
||||
plugins = [
|
||||
"../build/plugins/python/py_tutor.py"
|
||||
]
|
||||
packages = ["pandas"]
|
||||
</py-config>
|
||||
title = "Pandas (and basic DOM manipulation)"
|
||||
page_message = "This example loads a remote CSV file into a Pandas dataframe, displays it and lets you manipulate it through a Python REPL"
|
||||
|
||||
<section class="pyscript">
|
||||
<py-script>
|
||||
import pandas as pd
|
||||
from pyodide.http import open_url
|
||||
import sys
|
||||
url = "https://raw.githubusercontent.com/datasets/airport-codes/master/data/airport-codes.csv"
|
||||
|
||||
title = "Pandas (and basic DOM manipulation)"
|
||||
page_message = "This example loads a remote CSV file into a Pandas dataframe, displays it and lets you manipulate it through a Python REPL"
|
||||
Element("header-title").element.innerText = title
|
||||
Element("page-title").element.innerText = title
|
||||
Element("page-message").element.innerText = page_message
|
||||
|
||||
url = "https://raw.githubusercontent.com/datasets/airport-codes/master/data/airport-codes.csv"
|
||||
Element("txt-url").element.value = url
|
||||
|
||||
Element("header-title").element.innerText = title
|
||||
Element("page-title").element.innerText = title
|
||||
Element("page-message").element.innerText = page_message
|
||||
# Depending on the type of DOM element, there are several alternative methods to write to it
|
||||
# Element("id-of-dom-element").write("example")
|
||||
# Element("id-of-dom-element").innerText = "example"
|
||||
# Element("id-of-dom-element").value = "example"
|
||||
# Element("id-of-dom-element").element.innerText = "example"
|
||||
# Element("id-of-dom-element").element.value = "example"
|
||||
# js.document.getElementById("id-of-dom-element").innerText = "example"
|
||||
# js.document.getElementById("id-of-dom-element").value = "example"
|
||||
|
||||
Element("txt-url").element.value = url
|
||||
|
||||
# Depending on the type of DOM element, there are several alternative methods to write to it
|
||||
# Element("id-of-dom-element").write("example")
|
||||
# Element("id-of-dom-element").innerText = "example"
|
||||
# Element("id-of-dom-element").value = "example"
|
||||
# Element("id-of-dom-element").element.innerText = "example"
|
||||
# Element("id-of-dom-element").element.value = "example"
|
||||
# js.document.getElementById("id-of-dom-element").innerText = "example"
|
||||
# js.document.getElementById("id-of-dom-element").value = "example"
|
||||
|
||||
df = pd.DataFrame()
|
||||
df = pd.DataFrame()
|
||||
|
||||
|
||||
def loadFromURL(*ags, **kws):
|
||||
global df
|
||||
def loadFromURL(*ags, **kws):
|
||||
global df
|
||||
|
||||
# clear dataframe & output
|
||||
df = pd.DataFrame()
|
||||
Element("pandas-output-inner").element.innerHTML = ""
|
||||
# clear dataframe & output
|
||||
df = pd.DataFrame()
|
||||
Element("pandas-output-inner").element.innerHTML = ""
|
||||
|
||||
url = Element("txt-url").element.value
|
||||
log ("Trying to fetch CSV from " + url)
|
||||
url = Element("txt-url").element.value
|
||||
log ("Trying to fetch CSV from " + url)
|
||||
|
||||
df = pd.read_csv(open_url(url))
|
||||
df = pd.read_csv(open_url(url))
|
||||
|
||||
Element("pandas-repl").element.style.display = "block"
|
||||
Element("pandas-output").element.style.display = "block"
|
||||
Element("pandas-dev-console").element.style.display = "block"
|
||||
Element("pandas-repl").element.style.display = "block"
|
||||
Element("pandas-output").element.style.display = "block"
|
||||
Element("pandas-dev-console").element.style.display = "block"
|
||||
|
||||
display (df, target="pandas-output-inner", append="False")
|
||||
display (df, target="pandas-output-inner", append="False")
|
||||
|
||||
def log(message):
|
||||
# log to pyscript dev console
|
||||
print (message)
|
||||
def log(message):
|
||||
# log to pyscript dev console
|
||||
print (message)
|
||||
|
||||
# log to JS console
|
||||
js.console.log (message)
|
||||
</py-script>
|
||||
</section>
|
||||
</py-tutor>
|
||||
</body>
|
||||
# log to JS console
|
||||
js.console.log (message)
|
||||
</py-script>
|
||||
</section>
|
||||
</py-tutor>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,23 +1,35 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Panel Example</title>
|
||||
<meta charset="iso-8859-1">
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@holoviz/panel@0.14.1/dist/panel.min.js"></script>
|
||||
<meta charset="iso-8859-1" />
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.jsdelivr.net/npm/@holoviz/panel@0.14.1/dist/panel.min.js"
|
||||
></script>
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Panel Example</a>
|
||||
<a class="title" href="" style="color: #f0ab3c">Panel Example</a>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
|
||||
@@ -1,34 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||
<meta name="theme-color" content="#0072b5">
|
||||
<meta name="name" content="PyScript/Panel DeckGL Demo">
|
||||
<meta charset="utf-8" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||
<meta name="theme-color" content="#0072b5" />
|
||||
<meta name="name" content="PyScript/Panel DeckGL Demo" />
|
||||
|
||||
<title>PyScript/Panel DeckGL Demo</title>
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css" type="text/css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
|
||||
type="text/css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css"
|
||||
type="text/css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css"
|
||||
type="text/css"
|
||||
/>
|
||||
|
||||
<script type="text/javascript" src="https://unpkg.com/h3-js@3.7.2/dist/h3-js.umd.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/deck.gl@8.6.7/dist.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@deck.gl/json@8.6.7/dist.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@loaders.gl/csv@3.1.7/dist/dist.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@loaders.gl/json@3.1.7/dist/dist.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@loaders.gl/3d-tiles@3.1.7/dist/dist.min.js"></script>
|
||||
<script type="text/javascript" src="https://api.mapbox.com/mapbox-gl-js/v2.6.1/mapbox-gl.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.js"></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://unpkg.com/h3-js@3.7.2/dist/h3-js.umd.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.jsdelivr.net/npm/deck.gl@8.6.7/dist.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.jsdelivr.net/npm/@deck.gl/json@8.6.7/dist.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.jsdelivr.net/npm/@loaders.gl/csv@3.1.7/dist/dist.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.jsdelivr.net/npm/@loaders.gl/json@3.1.7/dist/dist.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.jsdelivr.net/npm/@loaders.gl/3d-tiles@3.1.7/dist/dist.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://api.mapbox.com/mapbox-gl-js/v2.6.1/mapbox-gl.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.js"
|
||||
></script>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css">
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css"
|
||||
/>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
|
||||
@@ -44,20 +98,22 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Panel DeckGL NYC Taxi Demo</a>
|
||||
<a class="title" href="" style="color: #f0ab3c"
|
||||
>Panel DeckGL NYC Taxi Demo</a
|
||||
>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
<div class="d-flex flex-nowrap" id="content">
|
||||
<div class="sidenav" id="sidebar">
|
||||
<ul class="nav flex-column" >
|
||||
<div class="bk-root" id="widgets"></div>
|
||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||
<ul class="nav flex-column">
|
||||
<div class="bk-root" id="widgets"></div>
|
||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col mh-100" style="padding: 0">
|
||||
@@ -79,148 +135,147 @@
|
||||
</py-config>
|
||||
|
||||
<py-script>
|
||||
import panel as pn
|
||||
import pandas as pd
|
||||
import param
|
||||
import panel as pn
|
||||
import pandas as pd
|
||||
import param
|
||||
|
||||
from pyodide.http import open_url
|
||||
from pyodide.http import open_url
|
||||
|
||||
MAPBOX_KEY = "pk.eyJ1IjoicGFuZWxvcmciLCJhIjoiY2s1enA3ejhyMWhmZjNobjM1NXhtbWRrMyJ9.B_frQsAVepGIe-HiOJeqvQ"
|
||||
MAPBOX_KEY = "pk.eyJ1IjoicGFuZWxvcmciLCJhIjoiY2s1enA3ejhyMWhmZjNobjM1NXhtbWRrMyJ9.B_frQsAVepGIe-HiOJeqvQ"
|
||||
|
||||
class App(param.Parameterized):
|
||||
class App(param.Parameterized):
|
||||
|
||||
data = param.DataFrame(precedence=-1)
|
||||
data = param.DataFrame(precedence=-1)
|
||||
|
||||
view = param.DataFrame(precedence=-1)
|
||||
view = param.DataFrame(precedence=-1)
|
||||
|
||||
arc_view = param.DataFrame(precedence=-1)
|
||||
arc_view = param.DataFrame(precedence=-1)
|
||||
|
||||
radius = param.Integer(default=50, bounds=(20, 1000))
|
||||
radius = param.Integer(default=50, bounds=(20, 1000))
|
||||
|
||||
elevation = param.Integer(default=10, bounds=(0, 50))
|
||||
elevation = param.Integer(default=10, bounds=(0, 50))
|
||||
|
||||
hour = param.Integer(default=0, bounds=(0, 23))
|
||||
hour = param.Integer(default=0, bounds=(0, 23))
|
||||
|
||||
speed = param.Integer(default=1, bounds=(0, 10), precedence=-1)
|
||||
speed = param.Integer(default=1, bounds=(0, 10), precedence=-1)
|
||||
|
||||
play = param.Event(label='▷')
|
||||
play = param.Event(label='▷')
|
||||
|
||||
def __init__(self, **params):
|
||||
self.deck_gl = None
|
||||
super().__init__(**params)
|
||||
self.deck_gl = pn.pane.DeckGL(
|
||||
dict(self.spec),
|
||||
mapbox_api_key=MAPBOX_KEY,
|
||||
throttle={'click': 10},
|
||||
sizing_mode='stretch_both',
|
||||
margin=0
|
||||
)
|
||||
self.deck_gl.param.watch(self._update_arc_view, 'click_state')
|
||||
self._playing = False
|
||||
self._cb = pn.state.add_periodic_callback(
|
||||
self._update_hour, 1000//self.speed, start=False
|
||||
)
|
||||
def __init__(self, **params):
|
||||
self.deck_gl = None
|
||||
super().__init__(**params)
|
||||
self.deck_gl = pn.pane.DeckGL(
|
||||
dict(self.spec),
|
||||
mapbox_api_key=MAPBOX_KEY,
|
||||
throttle={'click': 10},
|
||||
sizing_mode='stretch_both',
|
||||
margin=0
|
||||
)
|
||||
self.deck_gl.param.watch(self._update_arc_view, 'click_state')
|
||||
self._playing = False
|
||||
self._cb = pn.state.add_periodic_callback(
|
||||
self._update_hour, 1000//self.speed, start=False
|
||||
)
|
||||
|
||||
@property
|
||||
def spec(self):
|
||||
return {
|
||||
"initialViewState": {
|
||||
"bearing": 0,
|
||||
"latitude": 40.7,
|
||||
"longitude": -73.9,
|
||||
"maxZoom": 15,
|
||||
"minZoom": 5,
|
||||
"pitch": 40.5,
|
||||
"zoom": 11
|
||||
},
|
||||
"layers": [self.hex_layer, self.arc_layer],
|
||||
"mapStyle": "mapbox://styles/mapbox/dark-v9",
|
||||
"views": [
|
||||
{"@@type": "MapView", "controller": True}
|
||||
]
|
||||
}
|
||||
@property
|
||||
def spec(self):
|
||||
return {
|
||||
"initialViewState": {
|
||||
"bearing": 0,
|
||||
"latitude": 40.7,
|
||||
"longitude": -73.9,
|
||||
"maxZoom": 15,
|
||||
"minZoom": 5,
|
||||
"pitch": 40.5,
|
||||
"zoom": 11
|
||||
},
|
||||
"layers": [self.hex_layer, self.arc_layer],
|
||||
"mapStyle": "mapbox://styles/mapbox/dark-v9",
|
||||
"views": [
|
||||
{"@@type": "MapView", "controller": True}
|
||||
]
|
||||
}
|
||||
|
||||
@property
|
||||
def hex_layer(self):
|
||||
return {
|
||||
"@@type": "HexagonLayer",
|
||||
"autoHighlight": True,
|
||||
"coverage": 1,
|
||||
"data": self.data if self.view is None else self.view,
|
||||
"elevationRange": [0, 100],
|
||||
"elevationScale": self.elevation,
|
||||
"radius": self.radius,
|
||||
"extruded": True,
|
||||
"getPosition": "@@=[pickup_x, pickup_y]",
|
||||
"id": "8a553b25-ef3a-489c-bbe2-e102d18a3211"
|
||||
}
|
||||
@property
|
||||
def hex_layer(self):
|
||||
return {
|
||||
"@@type": "HexagonLayer",
|
||||
"autoHighlight": True,
|
||||
"coverage": 1,
|
||||
"data": self.data if self.view is None else self.view,
|
||||
"elevationRange": [0, 100],
|
||||
"elevationScale": self.elevation,
|
||||
"radius": self.radius,
|
||||
"extruded": True,
|
||||
"getPosition": "@@=[pickup_x, pickup_y]",
|
||||
"id": "8a553b25-ef3a-489c-bbe2-e102d18a3211"
|
||||
}
|
||||
|
||||
@property
|
||||
def arc_layer(self):
|
||||
return {
|
||||
"@@type": "ArcLayer",
|
||||
"id": 'arc-layer',
|
||||
"data": self.arc_view,
|
||||
"pickable": True,
|
||||
"getWidth": 1,
|
||||
"getSourcePosition": "@@=[pickup_x, pickup_y]",
|
||||
"getTargetPosition": "@@=[dropoff_x, dropoff_y]",
|
||||
"getSourceColor": [0, 255, 0, 180],
|
||||
"getTargetColor": [240, 100, 0, 180]
|
||||
}
|
||||
@property
|
||||
def arc_layer(self):
|
||||
return {
|
||||
"@@type": "ArcLayer",
|
||||
"id": 'arc-layer',
|
||||
"data": self.arc_view,
|
||||
"pickable": True,
|
||||
"getWidth": 1,
|
||||
"getSourcePosition": "@@=[pickup_x, pickup_y]",
|
||||
"getTargetPosition": "@@=[dropoff_x, dropoff_y]",
|
||||
"getSourceColor": [0, 255, 0, 180],
|
||||
"getTargetColor": [240, 100, 0, 180]
|
||||
}
|
||||
|
||||
def _update_hour(self):
|
||||
self.hour = (self.hour+1) % 24
|
||||
def _update_hour(self):
|
||||
self.hour = (self.hour+1) % 24
|
||||
|
||||
@param.depends('view', watch=True)
|
||||
def _update_arc_view(self, event=None):
|
||||
data = self.data if self.view is None else self.view
|
||||
if not self.deck_gl or not self.deck_gl.click_state:
|
||||
self.arc_view = data.iloc[:0]
|
||||
return
|
||||
lon, lat = self.deck_gl.click_state['coordinate']
|
||||
tol = 0.001
|
||||
self.arc_view = data[
|
||||
(df.pickup_x>=float(lon-tol)) &
|
||||
(df.pickup_x<=float(lon+tol)) &
|
||||
(df.pickup_y>=float(lat-tol)) &
|
||||
(df.pickup_y<=float(lat+tol))
|
||||
]
|
||||
@param.depends('view', watch=True)
|
||||
def _update_arc_view(self, event=None):
|
||||
data = self.data if self.view is None else self.view
|
||||
if not self.deck_gl or not self.deck_gl.click_state:
|
||||
self.arc_view = data.iloc[:0]
|
||||
return
|
||||
lon, lat = self.deck_gl.click_state['coordinate']
|
||||
tol = 0.001
|
||||
self.arc_view = data[
|
||||
(df.pickup_x>=float(lon-tol)) &
|
||||
(df.pickup_x<=float(lon+tol)) &
|
||||
(df.pickup_y>=float(lat-tol)) &
|
||||
(df.pickup_y<=float(lat+tol))
|
||||
]
|
||||
|
||||
@param.depends('hour', watch=True, on_init=True)
|
||||
def _update_hourly_view(self):
|
||||
self.view = self.data[self.data.hour==self.hour]
|
||||
@param.depends('hour', watch=True, on_init=True)
|
||||
def _update_hourly_view(self):
|
||||
self.view = self.data[self.data.hour==self.hour]
|
||||
|
||||
@param.depends('speed', watch=True)
|
||||
def _update_speed(self):
|
||||
self._cb.period = 1000//self.speed
|
||||
@param.depends('speed', watch=True)
|
||||
def _update_speed(self):
|
||||
self._cb.period = 1000//self.speed
|
||||
|
||||
@param.depends('play', watch=True)
|
||||
def _play_pause(self):
|
||||
if self._playing:
|
||||
self._cb.stop()
|
||||
self.param.play.label = '▷'
|
||||
self.param.speed.precedence = -1
|
||||
else:
|
||||
self._cb.start()
|
||||
self.param.play.label = '❚❚'
|
||||
self.param.speed.precedence = 1
|
||||
self._playing = not self._playing
|
||||
@param.depends('play', watch=True)
|
||||
def _play_pause(self):
|
||||
if self._playing:
|
||||
self._cb.stop()
|
||||
self.param.play.label = '▷'
|
||||
self.param.speed.precedence = -1
|
||||
else:
|
||||
self._cb.start()
|
||||
self.param.play.label = '❚❚'
|
||||
self.param.speed.precedence = 1
|
||||
self._playing = not self._playing
|
||||
|
||||
@param.depends('view', 'radius', 'elevation', 'arc_view', watch=True)
|
||||
def update_spec(self):
|
||||
self.deck_gl.object = dict(self.spec)
|
||||
@param.depends('view', 'radius', 'elevation', 'arc_view', watch=True)
|
||||
def update_spec(self):
|
||||
self.deck_gl.object = dict(self.spec)
|
||||
|
||||
url = 'https://s3.eu-west-1.amazonaws.com/assets.holoviews.org/data/nyc_taxi_wide.csv'
|
||||
df = pd.read_csv(open_url(url))
|
||||
app = App(data=df)
|
||||
controls = pn.Param(app.param, sizing_mode='stretch_width', show_name=False)
|
||||
url = 'https://s3.eu-west-1.amazonaws.com/assets.holoviews.org/data/nyc_taxi_wide.csv'
|
||||
df = pd.read_csv(open_url(url))
|
||||
app = App(data=df)
|
||||
controls = pn.Param(app.param, sizing_mode='stretch_width', show_name=False)
|
||||
|
||||
app.deck_gl.servable(target='plot')
|
||||
controls.servable(target='widgets');
|
||||
app.deck_gl.servable(target='plot')
|
||||
controls.servable(target='widgets');
|
||||
</py-script>
|
||||
</py-tutor>
|
||||
</section>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,38 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<meta name="name" content="PyScript/Panel KMeans Demo">
|
||||
<meta charset="utf-8" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="name" content="PyScript/Panel KMeans Demo" />
|
||||
|
||||
<title>Pyscript/Panel KMeans Demo</title>
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css" type="text/css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
|
||||
type="text/css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css"
|
||||
type="text/css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css"
|
||||
type="text/css"
|
||||
/>
|
||||
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vega@5"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/tabulator-tables@4.9.3/dist/js/tabulator.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js"></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.jsdelivr.net/npm/vega@5"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.jsdelivr.net/npm/vega-lite@5"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.jsdelivr.net/npm/vega-embed@6"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://unpkg.com/tabulator-tables@4.9.3/dist/js/tabulator.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js"
|
||||
></script>
|
||||
<script type="text/javascript">
|
||||
Bokeh.set_log_level("info");
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css">
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css"
|
||||
/>
|
||||
|
||||
<style>
|
||||
#sidebar {
|
||||
width: 350px;
|
||||
width: 350px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -45,21 +90,23 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Panel KMeans Clustering Demo</a>
|
||||
<a class="title" href="" style="color: #f0ab3c"
|
||||
>Panel KMeans Clustering Demo</a
|
||||
>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
<div class="row overflow-hidden" id="content">
|
||||
<div class="sidenav" id="sidebar">
|
||||
<div class="sidenav" id="sidebar">
|
||||
<ul class="nav flex-column">
|
||||
<div class="bk-root" id="x-widget"></div>
|
||||
<div class="bk-root" id="y-widget"></div>
|
||||
<div class="bk-root" id="n-widget"></div>
|
||||
<div class="bk-root" id="x-widget"></div>
|
||||
<div class="bk-root" id="y-widget"></div>
|
||||
<div class="bk-root" id="n-widget"></div>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col mh-100 float-left" id="main">
|
||||
@@ -159,15 +206,19 @@
|
||||
update_table()
|
||||
update_chart()
|
||||
</py-script>
|
||||
</py-tutor>
|
||||
</py-tutor>
|
||||
</section>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('#sidebarCollapse').on('click', function () {
|
||||
$('#sidebar').toggleClass('active')
|
||||
$(this).toggleClass('active')
|
||||
var interval = setInterval(function () { window.dispatchEvent(new Event('resize')); }, 10);
|
||||
setTimeout(function () { clearInterval(interval) }, 210)
|
||||
$("#sidebarCollapse").on("click", function () {
|
||||
$("#sidebar").toggleClass("active");
|
||||
$(this).toggleClass("active");
|
||||
var interval = setInterval(function () {
|
||||
window.dispatchEvent(new Event("resize"));
|
||||
}, 10);
|
||||
setTimeout(function () {
|
||||
clearInterval(interval);
|
||||
}, 210);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,31 +1,67 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<meta name="name" content="PyScript/Panel Streaming Demo">
|
||||
<meta charset="utf-8" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="name" content="PyScript/Panel Streaming Demo" />
|
||||
|
||||
<title>PyScript/Panel Streaming Demo</title>
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.ico">
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.ico" />
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css" type="text/css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
|
||||
type="text/css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css"
|
||||
type="text/css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css"
|
||||
type="text/css"
|
||||
/>
|
||||
|
||||
<script type="text/javascript" src="https://unpkg.com/tabulator-tables@4.9.3/dist/js/tabulator.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js"></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://unpkg.com/tabulator-tables@4.9.3/dist/js/tabulator.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
||||
></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js"
|
||||
></script>
|
||||
<script type="text/javascript">
|
||||
Bokeh.set_log_level("info");
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css">
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css"
|
||||
/>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
|
||||
@@ -36,12 +72,12 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Panel Streaming Demo</a>
|
||||
<a class="title" href="" style="color: #f0ab3c">Panel Streaming Demo</a>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#output > div {
|
||||
font-family: 'monospace';
|
||||
background-color: #e5e5e5;
|
||||
border: 1px solid lightgray;
|
||||
border-top: 0;
|
||||
font-size: 0.875rem;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
font-family: "monospace";
|
||||
background-color: #e5e5e5;
|
||||
border: 1px solid lightgray;
|
||||
border-top: 0;
|
||||
font-size: 0.875rem;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
#output > div:first-child {
|
||||
border-top: 1px solid lightgray;
|
||||
}
|
||||
#output > div:first-child {
|
||||
border-top: 1px solid lightgray;
|
||||
}
|
||||
|
||||
#output > div:nth-child(even) {
|
||||
border: 0;
|
||||
}
|
||||
#output > div:nth-child(even) {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@@ -13,18 +13,18 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">PyScript REPL</a>
|
||||
<a class="title" href="" style="color: #f0ab3c">PyScript REPL</a>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
<h1><b>PyScript REPL</b></h1>
|
||||
Tip: press Shift-ENTER to evaluate a cell
|
||||
<br>
|
||||
<br />
|
||||
<py-tutor modules="antigravity.py">
|
||||
<py-config>
|
||||
plugins = [
|
||||
@@ -33,10 +33,10 @@
|
||||
[[fetch]]
|
||||
files = ["./antigravity.py"]
|
||||
</py-config>
|
||||
<div style="margin-right: 3rem;">
|
||||
<div style="margin-right: 3rem">
|
||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||
</div>
|
||||
</py-tutor>
|
||||
</section>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@@ -14,12 +14,12 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Custom REPL</a>
|
||||
<a class="title" href="" style="color: #f0ab3c">Custom REPL</a>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
@@ -37,11 +37,11 @@
|
||||
[[fetch]]
|
||||
files = ["./utils.py", "./antigravity.py"]
|
||||
</py-config>
|
||||
<div style="margin-right: 3rem;">
|
||||
<div style="margin-right: 3rem">
|
||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||
<div id="output" class="p-4"></div>
|
||||
</div>
|
||||
</py-tutor>
|
||||
</section>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,129 +1,172 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>PyScript — Simple Bioinformatics Example</title>
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||
<link rel='stylesheet' type='text/css' media='screen' href='https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css'>
|
||||
<link rel="icon" type="image/png" href="https://user-images.githubusercontent.com/49681382/166738771-d0c26557-426c-4688-9641-8db5e6b08348.png" />
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
media="screen"
|
||||
href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="https://user-images.githubusercontent.com/49681382/166738771-d0c26557-426c-4688-9641-8db5e6b08348.png"
|
||||
/>
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Header -->
|
||||
<section class="hero is-primary is-small">
|
||||
<div class="hero-body">
|
||||
<p class="title is-3">PyScript — Simple Bioinformatics Example <span class="tag is-white">v.1</span></p>
|
||||
<p class="subtitle is-6">
|
||||
Demonstrates the simple use of <a href="https://pyscript.net/" target="_blank"><code>PyScript</code></a>
|
||||
in <strong>Bioinformatics/Computational Biology</strong> fields!
|
||||
</head>
|
||||
<body>
|
||||
<!-- Header -->
|
||||
<section class="hero is-primary is-small">
|
||||
<div class="hero-body">
|
||||
<p class="title is-3">
|
||||
PyScript — Simple Bioinformatics Example
|
||||
<span class="tag is-white">v.1</span>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
<p class="subtitle is-6">
|
||||
Demonstrates the simple use of
|
||||
<a href="https://pyscript.net/" target="_blank"
|
||||
><code>PyScript</code></a
|
||||
>
|
||||
in <strong>Bioinformatics/Computational Biology</strong> fields!
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="container is-white is-fluid" style="margin-top: 45px">
|
||||
<p class="title is-3">🧬 DNA Sequence Tool</p>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="container is-white is-fluid" style="margin-top:45px">
|
||||
<p class="title is-3">🧬 DNA Sequence Tool</p>
|
||||
|
||||
<!--- DNA Sequence Input -->
|
||||
<div class="field">
|
||||
<!--- DNA Sequence Input -->
|
||||
<div class="field">
|
||||
<label class="label">Input DNA Sequence</label>
|
||||
<div class="control">
|
||||
<textarea class="textarea" placeholder="GATTACA" id="dna_seq"></textarea>
|
||||
<textarea
|
||||
class="textarea"
|
||||
placeholder="GATTACA"
|
||||
id="dna_seq"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Operation Selection -->
|
||||
<label class="label">Pick the operation to be applied</label>
|
||||
<div class="field has-addons">
|
||||
<!-- Operation Selection -->
|
||||
<label class="label">Pick the operation to be applied</label>
|
||||
<div class="field has-addons">
|
||||
<div class="control is-expanded">
|
||||
<div class="select is-fullwidth">
|
||||
<div class="select is-fullwidth">
|
||||
<select name="operation" id="operation">
|
||||
<option value="Reverse">Compute the reverse counterpart</option>
|
||||
<option value="Complement">Compute the complement counterpart</option>
|
||||
<option value="ReverseComplement">Compute the reverse complement counterpart</option>
|
||||
<option value="Reverse">Compute the reverse counterpart</option>
|
||||
<option value="Complement">
|
||||
Compute the complement counterpart
|
||||
</option>
|
||||
<option value="ReverseComplement">
|
||||
Compute the reverse complement counterpart
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button id="run" type="button" class="button is-primary" py-onClick="run()">Run!</button>
|
||||
<button id="clear" type="button" class="button is-danger" py-onClick="clear()">Clear</button>
|
||||
</div>
|
||||
<button
|
||||
id="run"
|
||||
type="button"
|
||||
class="button is-primary"
|
||||
py-onClick="run()"
|
||||
>
|
||||
Run!
|
||||
</button>
|
||||
<button
|
||||
id="clear"
|
||||
type="button"
|
||||
class="button is-danger"
|
||||
py-onClick="clear()"
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<hr />
|
||||
|
||||
<!--- DNA Sequence Output -->
|
||||
<label class="label">Output for the <code id="operation_name_output">given operation</code></label>
|
||||
<div id="output"></div>
|
||||
</div>
|
||||
|
||||
<br><br>
|
||||
<!-- Footer -->
|
||||
<footer class="footer">
|
||||
<div class="content has-text-centered">
|
||||
<p>
|
||||
Developed by <a href="mailto:furkanmtorun@gmail.com"><strong>Furkan M. Torun (@furkanmtorun)</strong></a>
|
||||
<br>
|
||||
<a href="https://github.com/furkanmtorun">GitHub</a>
|
||||
| <a href="https://scholar.google.com/citations?user=d5ZyOZ4AAAAJ">Google Scholar</a>
|
||||
| <a href="https://twitter.com/furkanmtorun">Twitter</a>
|
||||
| <a href="https://www.linkedin.com/in/furkanmtorun/">LinkedIn</a>
|
||||
</p>
|
||||
<!--- DNA Sequence Output -->
|
||||
<label class="label"
|
||||
>Output for the
|
||||
<code id="operation_name_output">given operation</code></label
|
||||
>
|
||||
<div id="output"></div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<py-script>
|
||||
# Define HTML elements and inputs
|
||||
dna_alphabet = "ATGC"
|
||||
output = Element("output")
|
||||
dna_seq_element = Element("dna_seq")
|
||||
operation_element = Element("operation")
|
||||
operation_name_output_element = Element("operation_name_output")
|
||||
<br /><br />
|
||||
<!-- Footer -->
|
||||
<footer class="footer">
|
||||
<div class="content has-text-centered">
|
||||
<p>
|
||||
Developed by
|
||||
<a href="mailto:furkanmtorun@gmail.com"
|
||||
><strong>Furkan M. Torun (@furkanmtorun)</strong></a
|
||||
>
|
||||
<br />
|
||||
<a href="https://github.com/furkanmtorun">GitHub</a>
|
||||
|
|
||||
<a href="https://scholar.google.com/citations?user=d5ZyOZ4AAAAJ"
|
||||
>Google Scholar</a
|
||||
>
|
||||
| <a href="https://twitter.com/furkanmtorun">Twitter</a> |
|
||||
<a href="https://www.linkedin.com/in/furkanmtorun/">LinkedIn</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
# DNA Sequene Operations
|
||||
def return_reverse(dna_seq):
|
||||
return dna_seq[::-1]
|
||||
def return_complement(dna_seq):
|
||||
return dna_seq.translate(str.maketrans("ATCG", "TAGC"))
|
||||
def return_reverse_complement(dna_seq):
|
||||
return dna_seq.translate(str.maketrans("ATCG", "TAGC"))[::-1]
|
||||
<py-script>
|
||||
# Define HTML elements and inputs
|
||||
dna_alphabet = "ATGC"
|
||||
output = Element("output")
|
||||
dna_seq_element = Element("dna_seq")
|
||||
operation_element = Element("operation")
|
||||
operation_name_output_element = Element("operation_name_output")
|
||||
|
||||
# Check DNA seq is valid
|
||||
def check_dna_seq(dna_seq):
|
||||
return all(letter in dna_alphabet for letter in dna_seq.upper())
|
||||
# DNA Sequene Operations
|
||||
def return_reverse(dna_seq):
|
||||
return dna_seq[::-1]
|
||||
def return_complement(dna_seq):
|
||||
return dna_seq.translate(str.maketrans("ATCG", "TAGC"))
|
||||
def return_reverse_complement(dna_seq):
|
||||
return dna_seq.translate(str.maketrans("ATCG", "TAGC"))[::-1]
|
||||
|
||||
# Clear the form and output
|
||||
def clear(*args, **kwargs):
|
||||
dna_seq_element.clear()
|
||||
output.clear()
|
||||
# Check DNA seq is valid
|
||||
def check_dna_seq(dna_seq):
|
||||
return all(letter in dna_alphabet for letter in dna_seq.upper())
|
||||
|
||||
# Run
|
||||
def run(*args, **kwargs):
|
||||
dna_seq = dna_seq_element.value
|
||||
is_dna_seq_valid = check_dna_seq(dna_seq)
|
||||
if is_dna_seq_valid:
|
||||
operation_name = operation_element.value
|
||||
operation_name_output_element.write(operation_name)
|
||||
# Clear the form and output
|
||||
def clear(*args, **kwargs):
|
||||
dna_seq_element.clear()
|
||||
output.clear()
|
||||
|
||||
# Compute the desired outputs
|
||||
if operation_name == "Reverse":
|
||||
output_dna_seq = return_reverse(dna_seq)
|
||||
elif operation_name == "Complement":
|
||||
output_dna_seq = return_complement(dna_seq)
|
||||
elif operation_name == "ReverseComplement":
|
||||
output_dna_seq = return_reverse_complement(dna_seq)
|
||||
# Run
|
||||
def run(*args, **kwargs):
|
||||
dna_seq = dna_seq_element.value
|
||||
is_dna_seq_valid = check_dna_seq(dna_seq)
|
||||
if is_dna_seq_valid:
|
||||
operation_name = operation_element.value
|
||||
operation_name_output_element.write(operation_name)
|
||||
|
||||
# Output the result
|
||||
output.write(output_dna_seq)
|
||||
elif (dna_seq.strip() == "") or (dna_seq is None):
|
||||
output.write("No DNA sequence provided")
|
||||
else:
|
||||
output.write("Invalid DNA sequence entered")
|
||||
</py-script>
|
||||
# Compute the desired outputs
|
||||
if operation_name == "Reverse":
|
||||
output_dna_seq = return_reverse(dna_seq)
|
||||
elif operation_name == "Complement":
|
||||
output_dna_seq = return_complement(dna_seq)
|
||||
elif operation_name == "ReverseComplement":
|
||||
output_dna_seq = return_reverse_complement(dna_seq)
|
||||
|
||||
</body>
|
||||
# Output the result
|
||||
output.write(output_dna_seq)
|
||||
elif (dna_seq.strip() == "") or (dna_seq is None):
|
||||
output.write("No DNA sequence provided")
|
||||
else:
|
||||
output.write("Invalid DNA sequence entered")
|
||||
</py-script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@@ -14,12 +14,12 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Simple Clock</a>
|
||||
<a class="title" href="" style="color: #f0ab3c">Simple Clock</a>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
@@ -36,29 +36,29 @@
|
||||
files = ["./utils.py"]
|
||||
</py-config>
|
||||
<py-script>
|
||||
import utils
|
||||
display(utils.now())
|
||||
import utils
|
||||
display(utils.now())
|
||||
</py-script>
|
||||
|
||||
<py-script>
|
||||
from utils import now
|
||||
import asyncio
|
||||
from utils import now
|
||||
import asyncio
|
||||
|
||||
async def foo():
|
||||
while True:
|
||||
await asyncio.sleep(1)
|
||||
output = now()
|
||||
Element("outputDiv2").write(output)
|
||||
async def foo():
|
||||
while True:
|
||||
await asyncio.sleep(1)
|
||||
output = now()
|
||||
Element("outputDiv2").write(output)
|
||||
|
||||
out3 = Element("outputDiv3")
|
||||
if output[-1] in ["0", "4", "8"]:
|
||||
out3.write("It's espresso time!")
|
||||
else:
|
||||
out3.clear()
|
||||
out3 = Element("outputDiv3")
|
||||
if output[-1] in ["0", "4", "8"]:
|
||||
out3.write("It's espresso time!")
|
||||
else:
|
||||
out3.clear()
|
||||
|
||||
pyscript.run_until_complete(foo())
|
||||
pyscript.run_until_complete(foo())
|
||||
</py-script>
|
||||
</py-tutor>
|
||||
</section>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@@ -13,18 +13,24 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Pyscript Native TODO App</a>
|
||||
<a class="title" href="" style="color: #f0ab3c"
|
||||
>Pyscript Native TODO App</a
|
||||
>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
<h1>To Do List</h1>
|
||||
<py-tutor modules="utils.py;pylist.py">
|
||||
<py-register-widget src="./pylist.py" name="py-list" klass="PyList"></py-register-widget>
|
||||
<py-register-widget
|
||||
src="./pylist.py"
|
||||
name="py-list"
|
||||
klass="PyList"
|
||||
></py-register-widget>
|
||||
|
||||
<py-config>
|
||||
plugins = [
|
||||
@@ -62,11 +68,12 @@
|
||||
"keypress",
|
||||
handle_keypress
|
||||
)
|
||||
|
||||
</py-script>
|
||||
<div class="py-box">
|
||||
<input id="new-task-content" />
|
||||
<button py-click="add_task()" id="new-task-btn" class="py-button">Add Task!</button>
|
||||
<button py-click="add_task()" id="new-task-btn" class="py-button">
|
||||
Add Task!
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<py-list id="myList"></py-list>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@@ -14,12 +14,12 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar" style="background-color: #000000;">
|
||||
<nav class="navbar" style="background-color: #000000">
|
||||
<div class="app-header">
|
||||
<a href="/">
|
||||
<img src="./logo.png" class="logo">
|
||||
<img src="./logo.png" class="logo" />
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Todo App</a>
|
||||
<a class="title" href="" style="color: #f0ab3c">Todo App</a>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="pyscript">
|
||||
@@ -32,34 +32,45 @@
|
||||
files = ["./utils.py", "./todo.py"]
|
||||
</py-config>
|
||||
|
||||
<py-script src="./todo.py"> </py-script>
|
||||
</py-tutor>
|
||||
<py-script src="./todo.py"></py-script>
|
||||
</py-tutor>
|
||||
<main>
|
||||
<section>
|
||||
|
||||
<div class="text-center w-full mb-8">
|
||||
<h1 class="text-3xl font-bold text-gray-800 uppercase tracking-tight">To Do List</h1>
|
||||
<h1
|
||||
class="text-3xl font-bold text-gray-800 uppercase tracking-tight"
|
||||
>
|
||||
To Do List
|
||||
</h1>
|
||||
</div>
|
||||
<div>
|
||||
<input id="new-task-content" class="py-input" type="text">
|
||||
<button id="new-task-btn" class="py-button" type="submit" py-click="add_task()">
|
||||
<input id="new-task-content" class="py-input" type="text" />
|
||||
<button
|
||||
id="new-task-btn"
|
||||
class="py-button"
|
||||
type="submit"
|
||||
py-click="add_task()"
|
||||
>
|
||||
Add task
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<py-list id="myList"></py-list>
|
||||
<div id="list-tasks-container" class="flex flex-col-reverse mt-4"></div>
|
||||
<div
|
||||
id="list-tasks-container"
|
||||
class="flex flex-col-reverse mt-4"
|
||||
></div>
|
||||
|
||||
<template id="task-template">
|
||||
<section class="task py-li-element">
|
||||
<label for="flex items-center p-2 ">
|
||||
<input class="mr-2" type="checkbox">
|
||||
<p class="m-0 inline"></p>
|
||||
</label>
|
||||
<label for="flex items-center p-2 ">
|
||||
<input class="mr-2" type="checkbox" />
|
||||
<p class="m-0 inline"></p>
|
||||
</label>
|
||||
</section>
|
||||
</template>
|
||||
</section>
|
||||
</main>
|
||||
</section>
|
||||
</body>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -9,13 +9,13 @@ It can be served as a Single Page App from a static web server.
|
||||
1. Create and activate a virtual environment, and move into the `freedom`
|
||||
project directory:
|
||||
|
||||
$ python -m venv venv
|
||||
$ . ./venv/bin/activate
|
||||
$ cd freedom
|
||||
$ python -m venv venv
|
||||
$ . ./venv/bin/activate
|
||||
$ cd freedom
|
||||
|
||||
2. Install Briefcase:
|
||||
|
||||
$ pip install briefcase
|
||||
$ pip install briefcase
|
||||
|
||||
## Web app
|
||||
|
||||
|
||||
@@ -1,51 +1,59 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>Freedom Units</title>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||
/>
|
||||
<title>Freedom Units</title>
|
||||
|
||||
<link rel="icon" type="image/png" href="/static/logo-32.png"/>
|
||||
<link rel="icon" type="image/png" href="/static/logo-32.png" />
|
||||
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
|
||||
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
|
||||
<link rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
|
||||
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N"
|
||||
crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="/static/css/briefcase.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app-placeholder"></div>
|
||||
|
||||
<link rel="stylesheet" href="/static/css/briefcase.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app-placeholder"></div>
|
||||
<script
|
||||
src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"
|
||||
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
<script
|
||||
src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"
|
||||
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct"
|
||||
crossorigin="anonymous"></script>
|
||||
<py-config>
|
||||
name = "Freedom Units"
|
||||
description = "A testing app"
|
||||
version = "0.0.1"
|
||||
terminal = false
|
||||
packages = [
|
||||
"./static/wheels/freedom-0.0.1-py3-none-any.whl",
|
||||
"toga_core==0.3.0",
|
||||
"toga_web==0.3.0",
|
||||
"travertino==0.1.3",
|
||||
]
|
||||
|
||||
<py-config>
|
||||
name = "Freedom Units"
|
||||
description = "A testing app"
|
||||
version = "0.0.1"
|
||||
terminal = false
|
||||
packages = [
|
||||
"./static/wheels/freedom-0.0.1-py3-none-any.whl",
|
||||
"toga_core==0.3.0",
|
||||
"toga_web==0.3.0",
|
||||
"travertino==0.1.3",
|
||||
]
|
||||
|
||||
[splashscreen]
|
||||
autoclose = true
|
||||
</py-config>
|
||||
<py-script>
|
||||
import runpy
|
||||
result = runpy.run_module("freedom", run_name="__main__", alter_sys=True)
|
||||
</py-script>
|
||||
</body>
|
||||
[splashscreen]
|
||||
autoclose = true
|
||||
</py-config>
|
||||
<py-script>
|
||||
import runpy
|
||||
result = runpy.run_module("freedom", run_name="__main__", alter_sys=True)
|
||||
</py-script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
|
||||
/* Unset the overly generic pyscript .label style */
|
||||
#app-placeholder .label {
|
||||
margin-top: inherit;
|
||||
color: inherit;
|
||||
text-align: inherit;
|
||||
width: inherit;
|
||||
display: inherit;
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
margin-top: inherit;
|
||||
|
||||
margin-top: inherit;
|
||||
color: inherit;
|
||||
text-align: inherit;
|
||||
width: inherit;
|
||||
display: inherit;
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
margin-top: inherit;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@@ -23,15 +21,15 @@
|
||||
*******************************************************/
|
||||
|
||||
main.toga.window {
|
||||
margin-top: 5em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 5em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
div.toga.box {
|
||||
display: flex;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
span.toga.label {
|
||||
white-space: nowrap;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -1,194 +1,192 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Raycaster</title>
|
||||
<link rel="icon" type="image/png" href="../favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid fixed-top header disable-selection">
|
||||
<div class="row">
|
||||
<div class="col"></div>
|
||||
<div class="col-md-6">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Raycaster</title>
|
||||
<link rel="icon" type="image/png" href="../favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="./style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid fixed-top header disable-selection">
|
||||
<div class="row">
|
||||
<div class="col"></div>
|
||||
<div class="col-md-6">
|
||||
<div class="row">
|
||||
<div class="col"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col"></div>
|
||||
</div>
|
||||
<div class="col"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/0.147.0/three.min.js'></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.147.0/three.min.js"></script>
|
||||
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<py-script>
|
||||
from pyodide.ffi import create_proxy, to_js
|
||||
from js import window
|
||||
from js import Math
|
||||
from js import THREE
|
||||
from js import performance
|
||||
from js import Object
|
||||
from js import document
|
||||
import asyncio
|
||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||
<py-script>
|
||||
from pyodide.ffi import create_proxy, to_js
|
||||
from js import window
|
||||
from js import Math
|
||||
from js import THREE
|
||||
from js import performance
|
||||
from js import Object
|
||||
from js import document
|
||||
import asyncio
|
||||
|
||||
mouse = THREE.Vector2.new();
|
||||
mouse = THREE.Vector2.new();
|
||||
|
||||
renderer = THREE.WebGLRenderer.new({"antialias":True})
|
||||
renderer.setSize(1000, 1000)
|
||||
renderer.shadowMap.enabled = False
|
||||
renderer.shadowMap.type = THREE.PCFSoftShadowMap
|
||||
renderer.shadowMap.needsUpdate = True
|
||||
renderer = THREE.WebGLRenderer.new({"antialias":True})
|
||||
renderer.setSize(1000, 1000)
|
||||
renderer.shadowMap.enabled = False
|
||||
renderer.shadowMap.type = THREE.PCFSoftShadowMap
|
||||
renderer.shadowMap.needsUpdate = True
|
||||
|
||||
document.body.appendChild( renderer.domElement )
|
||||
document.body.appendChild( renderer.domElement )
|
||||
|
||||
import js, pyodide
|
||||
def onMouseMove(event):
|
||||
event.preventDefault();
|
||||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
|
||||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
||||
js.document.addEventListener('mousemove', pyodide.ffi.create_proxy(onMouseMove))
|
||||
import js, pyodide
|
||||
def onMouseMove(event):
|
||||
event.preventDefault();
|
||||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
|
||||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
||||
js.document.addEventListener('mousemove', pyodide.ffi.create_proxy(onMouseMove))
|
||||
|
||||
camera = THREE.PerspectiveCamera.new( 35, window.innerWidth / window.innerHeight, 1, 500 )
|
||||
scene = THREE.Scene.new()
|
||||
cameraRange = 3
|
||||
camera = THREE.PerspectiveCamera.new( 35, window.innerWidth / window.innerHeight, 1, 500 )
|
||||
scene = THREE.Scene.new()
|
||||
cameraRange = 3
|
||||
|
||||
camera.aspect = window.innerWidth / window.innerHeight
|
||||
camera.updateProjectionMatrix()
|
||||
renderer.setSize( window.innerWidth, window.innerHeight )
|
||||
camera.aspect = window.innerWidth / window.innerHeight
|
||||
camera.updateProjectionMatrix()
|
||||
renderer.setSize( window.innerWidth, window.innerHeight )
|
||||
|
||||
setcolor = "#000000"
|
||||
setcolor = "#000000"
|
||||
|
||||
scene.background = THREE.Color.new(setcolor)
|
||||
scene.fog = THREE.Fog.new(setcolor, 2.5, 3.5);
|
||||
scene.background = THREE.Color.new(setcolor)
|
||||
scene.fog = THREE.Fog.new(setcolor, 2.5, 3.5);
|
||||
|
||||
sceneGroup = THREE.Object3D.new();
|
||||
particularGroup = THREE.Object3D.new();
|
||||
sceneGroup = THREE.Object3D.new();
|
||||
particularGroup = THREE.Object3D.new();
|
||||
|
||||
def mathRandom(num = 1):
|
||||
setNumber = - Math.random() * num + Math.random() * num
|
||||
return setNumber
|
||||
def mathRandom(num = 1):
|
||||
setNumber = - Math.random() * num + Math.random() * num
|
||||
return setNumber
|
||||
|
||||
particularGroup = THREE.Object3D.new();
|
||||
modularGroup = THREE.Object3D.new();
|
||||
particularGroup = THREE.Object3D.new();
|
||||
modularGroup = THREE.Object3D.new();
|
||||
|
||||
perms = {"flatShading":True, "color":"#111111", "transparent":False, "opacity":1, "wireframe":False}
|
||||
perms = Object.fromEntries(to_js(perms))
|
||||
perms = {"flatShading":True, "color":"#111111", "transparent":False, "opacity":1, "wireframe":False}
|
||||
perms = Object.fromEntries(to_js(perms))
|
||||
|
||||
particle_perms = {"color":"#FFFFFF", "side":THREE.DoubleSide}
|
||||
particle_perms = Object.fromEntries(to_js(particle_perms))
|
||||
particle_perms = {"color":"#FFFFFF", "side":THREE.DoubleSide}
|
||||
particle_perms = Object.fromEntries(to_js(particle_perms))
|
||||
|
||||
def create_cubes(mathRandom, modularGroup):
|
||||
i = 0
|
||||
while i < 30:
|
||||
geometry = THREE.IcosahedronGeometry.new();
|
||||
material = THREE.MeshStandardMaterial.new(perms);
|
||||
cube = THREE.Mesh.new(geometry, material);
|
||||
cube.speedRotation = Math.random() * 0.1;
|
||||
cube.positionX = mathRandom();
|
||||
cube.positionY = mathRandom();
|
||||
cube.positionZ = mathRandom();
|
||||
cube.castShadow = True;
|
||||
cube.receiveShadow = True;
|
||||
newScaleValue = mathRandom(0.3);
|
||||
cube.scale.set(newScaleValue,newScaleValue,newScaleValue);
|
||||
cube.rotation.x = mathRandom(180 * Math.PI / 180);
|
||||
cube.rotation.y = mathRandom(180 * Math.PI / 180);
|
||||
cube.rotation.z = mathRandom(180 * Math.PI / 180);
|
||||
cube.position.set(cube.positionX, cube.positionY, cube.positionZ);
|
||||
modularGroup.add(cube);
|
||||
i += 1
|
||||
def create_cubes(mathRandom, modularGroup):
|
||||
i = 0
|
||||
while i < 30:
|
||||
geometry = THREE.IcosahedronGeometry.new();
|
||||
material = THREE.MeshStandardMaterial.new(perms);
|
||||
cube = THREE.Mesh.new(geometry, material);
|
||||
cube.speedRotation = Math.random() * 0.1;
|
||||
cube.positionX = mathRandom();
|
||||
cube.positionY = mathRandom();
|
||||
cube.positionZ = mathRandom();
|
||||
cube.castShadow = True;
|
||||
cube.receiveShadow = True;
|
||||
newScaleValue = mathRandom(0.3);
|
||||
cube.scale.set(newScaleValue,newScaleValue,newScaleValue);
|
||||
cube.rotation.x = mathRandom(180 * Math.PI / 180);
|
||||
cube.rotation.y = mathRandom(180 * Math.PI / 180);
|
||||
cube.rotation.z = mathRandom(180 * Math.PI / 180);
|
||||
cube.position.set(cube.positionX, cube.positionY, cube.positionZ);
|
||||
modularGroup.add(cube);
|
||||
i += 1
|
||||
|
||||
create_cubes(mathRandom, modularGroup)
|
||||
create_cubes(mathRandom, modularGroup)
|
||||
|
||||
|
||||
def generateParticle(mathRandom, particularGroup, num, amp = 2):
|
||||
gmaterial = THREE.MeshPhysicalMaterial.new(particle_perms);
|
||||
gparticular = THREE.CircleGeometry.new(0.2,5);
|
||||
i = 0
|
||||
while i < num:
|
||||
pscale = 0.001+Math.abs(mathRandom(0.03));
|
||||
particular = THREE.Mesh.new(gparticular, gmaterial);
|
||||
particular.position.set(mathRandom(amp),mathRandom(amp),mathRandom(amp));
|
||||
particular.rotation.set(mathRandom(),mathRandom(),mathRandom());
|
||||
particular.scale.set(pscale,pscale,pscale);
|
||||
particular.speedValue = mathRandom(1);
|
||||
particularGroup.add(particular);
|
||||
i += 1
|
||||
def generateParticle(mathRandom, particularGroup, num, amp = 2):
|
||||
gmaterial = THREE.MeshPhysicalMaterial.new(particle_perms);
|
||||
gparticular = THREE.CircleGeometry.new(0.2,5);
|
||||
i = 0
|
||||
while i < num:
|
||||
pscale = 0.001+Math.abs(mathRandom(0.03));
|
||||
particular = THREE.Mesh.new(gparticular, gmaterial);
|
||||
particular.position.set(mathRandom(amp),mathRandom(amp),mathRandom(amp));
|
||||
particular.rotation.set(mathRandom(),mathRandom(),mathRandom());
|
||||
particular.scale.set(pscale,pscale,pscale);
|
||||
particular.speedValue = mathRandom(1);
|
||||
particularGroup.add(particular);
|
||||
i += 1
|
||||
|
||||
generateParticle(mathRandom, particularGroup, 200, 2)
|
||||
generateParticle(mathRandom, particularGroup, 200, 2)
|
||||
|
||||
sceneGroup.add(particularGroup);
|
||||
scene.add(modularGroup);
|
||||
scene.add(sceneGroup);
|
||||
sceneGroup.add(particularGroup);
|
||||
scene.add(modularGroup);
|
||||
scene.add(sceneGroup);
|
||||
|
||||
camera.position.set(0, 0, cameraRange);
|
||||
cameraValue = False;
|
||||
camera.position.set(0, 0, cameraRange);
|
||||
cameraValue = False;
|
||||
|
||||
ambientLight = THREE.AmbientLight.new(0xFFFFFF, 0.1);
|
||||
ambientLight = THREE.AmbientLight.new(0xFFFFFF, 0.1);
|
||||
|
||||
light = THREE.SpotLight.new(0xFFFFFF, 3);
|
||||
light.position.set(5, 5, 2);
|
||||
light.castShadow = True;
|
||||
light.shadow.mapSize.width = 10000;
|
||||
light.shadow.mapSize.height = light.shadow.mapSize.width;
|
||||
light.penumbra = 0.5;
|
||||
light = THREE.SpotLight.new(0xFFFFFF, 3);
|
||||
light.position.set(5, 5, 2);
|
||||
light.castShadow = True;
|
||||
light.shadow.mapSize.width = 10000;
|
||||
light.shadow.mapSize.height = light.shadow.mapSize.width;
|
||||
light.penumbra = 0.5;
|
||||
|
||||
lightBack = THREE.PointLight.new(0x0FFFFF, 1);
|
||||
lightBack.position.set(0, -3, -1);
|
||||
lightBack = THREE.PointLight.new(0x0FFFFF, 1);
|
||||
lightBack.position.set(0, -3, -1);
|
||||
|
||||
scene.add(sceneGroup);
|
||||
scene.add(light);
|
||||
scene.add(lightBack);
|
||||
scene.add(sceneGroup);
|
||||
scene.add(light);
|
||||
scene.add(lightBack);
|
||||
|
||||
rectSize = 2
|
||||
intensity = 14
|
||||
rectLight = THREE.RectAreaLight.new( 0x0FFFFF, intensity, rectSize, rectSize )
|
||||
rectLight.position.set( 0, 0, 1 )
|
||||
rectLight.lookAt( 0, 0, 0 )
|
||||
scene.add( rectLight )
|
||||
rectSize = 2
|
||||
intensity = 14
|
||||
rectLight = THREE.RectAreaLight.new( 0x0FFFFF, intensity, rectSize, rectSize )
|
||||
rectLight.position.set( 0, 0, 1 )
|
||||
rectLight.lookAt( 0, 0, 0 )
|
||||
scene.add( rectLight )
|
||||
|
||||
raycaster = THREE.Raycaster.new();
|
||||
uSpeed = 0.1
|
||||
raycaster = THREE.Raycaster.new();
|
||||
uSpeed = 0.1
|
||||
|
||||
time = 0.0003;
|
||||
camera.lookAt(scene.position)
|
||||
time = 0.0003;
|
||||
camera.lookAt(scene.position)
|
||||
|
||||
async def main():
|
||||
while True:
|
||||
time = performance.now() * 0.0003;
|
||||
i = 0
|
||||
while i < particularGroup.children.length:
|
||||
newObject = particularGroup.children[i];
|
||||
newObject.rotation.x += newObject.speedValue/10;
|
||||
newObject.rotation.y += newObject.speedValue/10;
|
||||
newObject.rotation.z += newObject.speedValue/10;
|
||||
i += 1
|
||||
async def main():
|
||||
while True:
|
||||
time = performance.now() * 0.0003;
|
||||
i = 0
|
||||
while i < particularGroup.children.length:
|
||||
newObject = particularGroup.children[i];
|
||||
newObject.rotation.x += newObject.speedValue/10;
|
||||
newObject.rotation.y += newObject.speedValue/10;
|
||||
newObject.rotation.z += newObject.speedValue/10;
|
||||
i += 1
|
||||
|
||||
i = 0
|
||||
while i < modularGroup.children.length:
|
||||
newCubes = modularGroup.children[i];
|
||||
newCubes.rotation.x += 0.008;
|
||||
newCubes.rotation.y += 0.005;
|
||||
newCubes.rotation.z += 0.003;
|
||||
i = 0
|
||||
while i < modularGroup.children.length:
|
||||
newCubes = modularGroup.children[i];
|
||||
newCubes.rotation.x += 0.008;
|
||||
newCubes.rotation.y += 0.005;
|
||||
newCubes.rotation.z += 0.003;
|
||||
|
||||
newCubes.position.x = Math.sin(time * newCubes.positionZ) * newCubes.positionY;
|
||||
newCubes.position.y = Math.cos(time * newCubes.positionX) * newCubes.positionZ;
|
||||
newCubes.position.z = Math.sin(time * newCubes.positionY) * newCubes.positionX;
|
||||
i += 1
|
||||
newCubes.position.x = Math.sin(time * newCubes.positionZ) * newCubes.positionY;
|
||||
newCubes.position.y = Math.cos(time * newCubes.positionX) * newCubes.positionZ;
|
||||
newCubes.position.z = Math.sin(time * newCubes.positionY) * newCubes.positionX;
|
||||
i += 1
|
||||
|
||||
particularGroup.rotation.y += 0.005;
|
||||
particularGroup.rotation.y += 0.005;
|
||||
|
||||
modularGroup.rotation.y -= ((mouse.x * 4) + modularGroup.rotation.y) * uSpeed;
|
||||
modularGroup.rotation.x -= ((-mouse.y * 4) + modularGroup.rotation.x) * uSpeed;
|
||||
modularGroup.rotation.y -= ((mouse.x * 4) + modularGroup.rotation.y) * uSpeed;
|
||||
modularGroup.rotation.x -= ((-mouse.y * 4) + modularGroup.rotation.x) * uSpeed;
|
||||
|
||||
renderer.render( scene, camera )
|
||||
await asyncio.sleep(0.02)
|
||||
renderer.render( scene, camera )
|
||||
await asyncio.sleep(0.02)
|
||||
|
||||
asyncio.ensure_future(main())
|
||||
|
||||
</py-script>
|
||||
</body>
|
||||
asyncio.ensure_future(main())
|
||||
</py-script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -12,10 +12,10 @@ canvas {
|
||||
.header {
|
||||
/*top:45%;*/
|
||||
top: 45%;
|
||||
color: #DDDDDD;
|
||||
color: #dddddd;
|
||||
}
|
||||
.footer {
|
||||
bottom:3%;
|
||||
bottom: 3%;
|
||||
}
|
||||
.description {
|
||||
color: gray;
|
||||
@@ -25,29 +25,31 @@ canvas {
|
||||
border-radius: 30px;
|
||||
padding: 10px 30px;
|
||||
}
|
||||
a, a:hover, a:visited {
|
||||
a,
|
||||
a:hover,
|
||||
a:visited {
|
||||
color: red;
|
||||
text-decoration: none;
|
||||
}
|
||||
.disable-selection {
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* Internet Explorer */
|
||||
-khtml-user-select: none; /* KHTML browsers (e.g. Konqueror) */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* Internet Explorer */
|
||||
-khtml-user-select: none; /* KHTML browsers (e.g. Konqueror) */
|
||||
-webkit-user-select: none; /* Chrome, Safari, and Opera */
|
||||
-webkit-touch-callout: none; /* Disable Android and iOS callouts*/
|
||||
}
|
||||
h1::after {
|
||||
content: ' V 2.0';
|
||||
content: " V 2.0";
|
||||
font-size: 12px;
|
||||
position:absolute;
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
padding-left: 5px;
|
||||
font-weight: 400;
|
||||
}
|
||||
h2::after {
|
||||
content: '2';
|
||||
content: "2";
|
||||
font-size: 12px;
|
||||
position:absolute;
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user