From 22fd0236355ce01194a4b1cdb4cae9e5119381f7 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 6 Mar 2023 16:06:30 +0100 Subject: [PATCH] More automatically generated formatter changes (#1254) Apparently some of these were accidentally lost when generating #1210... --- .github/workflows/build-unstable.yml | 8 +- .github/workflows/docs-release.yml | 12 +- .github/workflows/docs-review.yml | 16 +- .github/workflows/docs-unstable.yml | 8 +- .github/workflows/prepare-release.yml | 4 +- .github/workflows/publish-release.yml | 4 +- .github/workflows/sync-examples.yml | 6 +- CONTRIBUTING.md | 38 +- README.md | 22 +- TROUBLESHOOTING.md | 2 +- examples/altair.html | 143 ++-- examples/antigravity.html | 71 +- examples/assets/css/examples.css | 106 +-- examples/assets/css/index.css | 70 +- examples/assets/css/main.css | 26 +- examples/assets/css/reset.css | 18 +- examples/assets/css/variables.css | 8 +- examples/await/await0.html | 49 +- examples/await/await1.html | 73 +- examples/await/await2.html | 69 +- examples/await/await3.html | 73 +- examples/await/await4.html | 65 +- examples/await/await5.html | 35 +- examples/bokeh.html | 145 ++-- examples/bokeh_interactive.html | 225 +++--- examples/d3.html | 244 +++--- examples/folium.html | 121 +-- examples/hello_world.html | 73 +- examples/index.html | 550 +++++++------ examples/mario/css/game.css | 30 +- examples/mario/js/bcoin.js | 66 +- examples/mario/js/block.js | 143 ++-- examples/mario/js/coin.js | 101 +-- examples/mario/js/entity.js | 56 +- examples/mario/js/fireball.js | 261 +++--- examples/mario/js/fireflower.js | 149 ++-- examples/mario/js/flag.js | 80 +- examples/mario/js/floor.js | 138 ++-- examples/mario/js/game.js | 330 ++++---- examples/mario/js/goomba.js | 263 +++--- examples/mario/js/input.js | 104 +-- examples/mario/js/koopa.js | 423 +++++----- examples/mario/js/levels/11.js | 621 ++++++++------- examples/mario/js/levels/11tunnel.js | 235 +++--- examples/mario/js/levels/level.js | 603 +++++++------- examples/mario/js/mushroom.js | 233 +++--- examples/mario/js/pipe.js | 428 +++++----- examples/mario/js/player.js | 971 ++++++++++++----------- examples/mario/js/prop.js | 20 +- examples/mario/js/resources.js | 100 +-- examples/mario/js/rubble.js | 108 +-- examples/mario/js/sprite.js | 99 +-- examples/mario/js/star.js | 227 +++--- examples/mario/js/util.js | 18 +- examples/markdown-plugin.html | 44 +- examples/matplotlib.html | 121 +-- examples/message_passing.html | 88 +- examples/micrograd_ai.html | 356 +++++---- examples/numpy_canvas_fractals.html | 666 ++++++++-------- examples/pandas.html | 202 ++--- examples/panel.html | 117 +-- examples/panel_deckgl.html | 497 ++++++------ examples/panel_kmeans.html | 403 +++++----- examples/panel_stream.html | 271 +++---- examples/repl.css | 16 +- examples/repl.html | 77 +- examples/repl2.html | 83 +- examples/simple_bioinformatics_tool.html | 323 ++++---- examples/simple_clock.html | 109 +-- examples/todo-pylist.html | 143 ++-- examples/todo.html | 137 ++-- examples/toga/README.md | 8 +- examples/toga/freedom.html | 101 +-- examples/toga/static/css/briefcase.css | 26 +- examples/webgl/raycaster/index.html | 309 ++++---- examples/webgl/raycaster/style.css | 66 +- 76 files changed, 6311 insertions(+), 5943 deletions(-) diff --git a/.github/workflows/build-unstable.yml b/.github/workflows/build-unstable.yml index 77b548ea..726c4ee3 100644 --- a/.github/workflows/build-unstable.yml +++ b/.github/workflows/build-unstable.yml @@ -7,7 +7,7 @@ on: paths: - pyscriptjs/** - examples/** - - .github/workflows/build-latest.yml # Test that workflow works when changed + - .github/workflows/build-latest.yml # Test that workflow works when changed pull_request: # Run on any PR that modifies files under pyscriptjs/ and examples/ branches: @@ -15,7 +15,7 @@ on: paths: - pyscriptjs/** - examples/** - - .github/workflows/build-unstable.yml # Test that workflow works when changed + - .github/workflows/build-unstable.yml # Test that workflow works when changed workflow_dispatch: jobs: @@ -41,7 +41,7 @@ jobs: env: cache-name: cache-node-modules with: - # npm cache files are stored in `~/.npm` on Linux/macOS + # npm cache files are stored in `~/.npm` on Linux/macOS path: ~/.npm key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} restore-keys: | @@ -96,7 +96,7 @@ jobs: name: pyscript path: ./build/ - # Deploy to S3 + # Deploy to S3 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1.6.1 with: diff --git a/.github/workflows/docs-release.yml b/.github/workflows/docs-release.yml index 3e1b60de..c35f2dd1 100644 --- a/.github/workflows/docs-release.yml +++ b/.github/workflows/docs-release.yml @@ -16,8 +16,8 @@ jobs: - name: Checkout uses: actions/checkout@v3 with: - persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token. - fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. + persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token. + fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. - name: Setup uses: conda-incubator/setup-miniconda@v2 @@ -39,7 +39,7 @@ jobs: name: pyscript-docs-${{ github.ref_name }} path: docs/_build/html/ - # Deploy to S3 + # Deploy to S3 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1.6.1 with: @@ -52,11 +52,11 @@ jobs: - name: Sync to S3 run: aws s3 sync --quiet ./docs/_build/html/ s3://docs.pyscript.net/${{ github.ref_name }}/ - # Make sure to remove the latest folder so we sync the full docs upon release + # Make sure to remove the latest folder so we sync the full docs upon release - name: Delete latest directory run: aws s3 rm --recursive s3://docs.pyscript.net/latest/ - # Note that the files are the same as above, but we want to have folders with - # // AND /latest/ which latest will always point to the latest release + # Note that the files are the same as above, but we want to have folders with + # // AND /latest/ which latest will always point to the latest release - name: Sync to /latest run: aws s3 sync --quiet ./docs/_build/html/ s3://docs.pyscript.net/latest/ diff --git a/.github/workflows/docs-review.yml b/.github/workflows/docs-review.yml index 0635f0c1..8ba138cd 100644 --- a/.github/workflows/docs-review.yml +++ b/.github/workflows/docs-review.yml @@ -8,11 +8,11 @@ on: - docs/** concurrency: - # Concurrency group that uses the workflow name and PR number if available - # or commit SHA as a fallback. If a new build is triggered under that - # concurrency group while a previous build is running it will be canceled. - # Repeated pushes to a PR will cancel all previous builds, while multiple - # merges to main will not cancel. + # Concurrency group that uses the workflow name and PR number if available + # or commit SHA as a fallback. If a new build is triggered under that + # concurrency group while a previous build is running it will be canceled. + # Repeated pushes to a PR will cancel all previous builds, while multiple + # merges to main will not cancel. group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} cancel-in-progress: true @@ -29,8 +29,8 @@ jobs: - name: Checkout uses: actions/checkout@v3 with: - persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token. - fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. + persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token. + fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. - name: Setup uses: conda-incubator/setup-miniconda@v2 @@ -52,7 +52,7 @@ jobs: name: pyscript-docs-review-${{ github.event.number }} path: docs/_build/html/ - # Deploy to S3 + # Deploy to S3 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1.6.1 with: diff --git a/.github/workflows/docs-unstable.yml b/.github/workflows/docs-unstable.yml index c1cd427e..860f24e9 100644 --- a/.github/workflows/docs-unstable.yml +++ b/.github/workflows/docs-unstable.yml @@ -19,8 +19,8 @@ jobs: - name: Checkout uses: actions/checkout@v3 with: - persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token. - fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. + persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token. + fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. - name: Setup uses: conda-incubator/setup-miniconda@v2 @@ -42,13 +42,13 @@ jobs: name: pyscript-docs-latest path: docs/_build/html/ - # Deploy to S3 + # Deploy to S3 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1.6.1 with: aws-region: ${{ secrets.AWS_REGION }} role-to-assume: ${{ secrets.AWS_OIDC_RUNNER_ROLE }} - # Sync will only copy changed files + # Sync will only copy changed files - name: Sync to S3 run: aws s3 sync --quiet ./docs/_build/html/ s3://docs.pyscript.net/unstable/ diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 7ce0853a..cc0adbc2 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -3,7 +3,7 @@ name: '[CI] Prepare Release' on: push: tags: - - '[0-9][0-9][0-9][0-9].[0-9][0-9].[0-9]+' # YYYY.MM.MICRO + - '[0-9][0-9][0-9][0-9].[0-9][0-9].[0-9]+' # YYYY.MM.MICRO env: MINICONDA_PYTHON_VERSION: py38 @@ -30,7 +30,7 @@ jobs: env: cache-name: cache-node-modules with: - # npm cache files are stored in `~/.npm` on Linux/macOS + # npm cache files are stored in `~/.npm` on Linux/macOS path: ~/.npm key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} restore-keys: | diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 30524d62..34d9c2da 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -32,7 +32,7 @@ jobs: env: cache-name: cache-node-modules with: - # npm cache files are stored in `~/.npm` on Linux/macOS + # npm cache files are stored in `~/.npm` on Linux/macOS path: ~/.npm key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} restore-keys: | @@ -49,7 +49,7 @@ jobs: - name: Build and Test run: make test - # Upload to S3 + # Upload to S3 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1.6.1 with: diff --git a/.github/workflows/sync-examples.yml b/.github/workflows/sync-examples.yml index 0e012cd6..ea3de64b 100644 --- a/.github/workflows/sync-examples.yml +++ b/.github/workflows/sync-examples.yml @@ -15,7 +15,7 @@ jobs: working-directory: examples steps: - # Deploy to S3 + # Deploy to S3 - name: Checkout uses: actions/checkout@v3 - name: Configure AWS credentials @@ -24,5 +24,5 @@ jobs: aws-region: ${{ secrets.AWS_REGION }} role-to-assume: ${{ secrets.AWS_OIDC_RUNNER_ROLE }} - name: Sync to S3 - # Sync outdated or new files, delete ones no longer in source - run: aws s3 sync --quiet --delete . s3://pyscript.net/examples/ # Sync directory, delete what is not in source + # Sync outdated or new files, delete ones no longer in source + run: aws s3 sync --quiet --delete . s3://pyscript.net/examples/ # Sync directory, delete what is not in source diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4c59be57..043e5519 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,17 +4,17 @@ Thank you for wanting to contribute to the PyScript project! ## Table of contents -- [Code of Conduct](#code-of-conduct) -- [Contributing](#contributing) - - [Reporting bugs](#reporting-bugs) - - [Reporting security issues](#reporting-security-issues) - - [Asking questions](#asking-questions) - - [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing) - - [Places to start](#places-to-start) - - [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing) -- [License terms for contributions](#license-terms-for-contributions) -- [Becoming a maintainer](#becoming-a-maintainer) -- [Trademarks](#trademarks) +- [Code of Conduct](#code-of-conduct) +- [Contributing](#contributing) + - [Reporting bugs](#reporting-bugs) + - [Reporting security issues](#reporting-security-issues) + - [Asking questions](#asking-questions) + - [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing) + - [Places to start](#places-to-start) + - [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing) +- [License terms for contributions](#license-terms-for-contributions) +- [Becoming a maintainer](#becoming-a-maintainer) +- [Trademarks](#trademarks) # Code of Conduct @@ -28,10 +28,10 @@ Bugs are tracked on the [project issues page](https://github.com/pyscript/pyscri ## Creating useful issues -- Use a clear and descriptive title. -- Describe the specific steps that reproduce the problem with as many details as possible so that someone can verify the issue. -- Describe the behavior you observed, and the behavior you had expected. -- Include screenshots if they help make the issue clear. +- Use a clear and descriptive title. +- Describe the specific steps that reproduce the problem with as many details as possible so that someone can verify the issue. +- Describe the behavior you observed, and the behavior you had expected. +- Include screenshots if they help make the issue clear. ## Reporting security issues @@ -45,10 +45,10 @@ If you have questions about the project, using PyScript, or anything else, pleas If you would like to contribute to PyScript, but you aren't sure where to begin, here are some suggestions. -- **Read over the existing documentation.** Are there things missing, or could they be clearer? Make some changes/additions to those documents. -- **Review the open issues.** Are they clear? Can you reproduce them? You can add comments, clarifications, or additions to those issues. If you think you have an idea of how to address the issue, submit a fix! -- **Look over the open pull requests.** Do you have comments or suggestions for the proposed changes? Add them. -- **Check out the examples.** Is there a use case that would be good to have sample code for? Create an example for it. +- **Read over the existing documentation.** Are there things missing, or could they be clearer? Make some changes/additions to those documents. +- **Review the open issues.** Are they clear? Can you reproduce them? You can add comments, clarifications, or additions to those issues. If you think you have an idea of how to address the issue, submit a fix! +- **Look over the open pull requests.** Do you have comments or suggestions for the proposed changes? Add them. +- **Check out the examples.** Is there a use case that would be good to have sample code for? Create an example for it. ## Setting up your local environment and developing diff --git a/README.md b/README.md index e525a307..15dd62e9 100644 --- a/README.md +++ b/README.md @@ -20,15 +20,15 @@ To try PyScript, import the appropriate pyscript files into the `` tag of ```html - - + + ``` You can then use PyScript components in your html page. PyScript currently implements the following elements: -- ``: can be used to define python code that is executable within the web page. The element itself is not rendered to the page and is only used to add logic -- ``: creates a REPL component that is rendered to the page as a code editor and allows users to write executable code +- ``: can be used to define python code that is executable within the web page. The element itself is not rendered to the page and is only used to add logic +- ``: creates a REPL component that is rendered to the page as a code editor and allows users to write executable code Check out the [the examples directory](examples) folder for more examples on how to use it, all you need to do is open them in Chrome. @@ -40,16 +40,16 @@ Check out the [developing process](https://docs.pyscript.net/latest/development/ ## Resources -- [Official docs](https://docs.pyscript.net) -- [Discussion board](https://community.anaconda.cloud/c/tech-topics/pyscript) -- [Home Page](https://pyscript.net/) -- [Blog Post](https://engineering.anaconda.com/2022/04/welcome-pyscript.html) -- [Discord Channel](https://discord.gg/BYB2kvyFwm) +- [Official docs](https://docs.pyscript.net) +- [Discussion board](https://community.anaconda.cloud/c/tech-topics/pyscript) +- [Home Page](https://pyscript.net/) +- [Blog Post](https://engineering.anaconda.com/2022/04/welcome-pyscript.html) +- [Discord Channel](https://discord.gg/BYB2kvyFwm) ## Notes -- This is an extremely experimental project, so expect things to break! -- PyScript has been only tested on Chrome at the moment. +- This is an extremely experimental project, so expect things to break! +- PyScript has been only tested on Chrome at the moment. ## Governance diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md index dfe35ff4..4f480bb3 100644 --- a/TROUBLESHOOTING.md +++ b/TROUBLESHOOTING.md @@ -4,7 +4,7 @@ This page is meant for troubleshooting common problems with PyScript. ## Table of contents: -- [Make Setup](#make-setup) +- [Make Setup](#make-setup) ## Make setup diff --git a/examples/altair.html b/examples/altair.html index 121f0589..262ee2f3 100644 --- a/examples/altair.html +++ b/examples/altair.html @@ -1,78 +1,81 @@ - - Altair - - - - - - - - -
-
- - - packages = [ - "altair", - "pandas", - "vega_datasets" - ] - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - - - import altair as alt - from vega_datasets import data + + Altair + + + + + + + + +
+
+ + + packages = [ + "altair", + "pandas", + "vega_datasets" + ] + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + + + 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") - - -
- + display(alt.vconcat( + rect + circ, + bar + ).resolve_legend( + color="independent", + size="independent" + ), target="altair") +
+
+
+ diff --git a/examples/antigravity.html b/examples/antigravity.html index 87955189..64e40421 100644 --- a/examples/antigravity.html +++ b/examples/antigravity.html @@ -1,36 +1,39 @@ - - Antigravity - - - - - - - - - -
- - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - [[fetch]] - files = ["./antigravity.py"] - - Based on xkcd: antigravity https://xkcd.com/353/. - - import antigravity - antigravity.fly() - -
-
- + + Antigravity + + + + + + + + + +
+ + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + [[fetch]] + files = ["./antigravity.py"] + + Based on xkcd: antigravity https://xkcd.com/353/. + + import antigravity + antigravity.fly() + +
+
+ diff --git a/examples/assets/css/examples.css b/examples/assets/css/examples.css index de13fad2..8b8bc96e 100644 --- a/examples/assets/css/examples.css +++ b/examples/assets/css/examples.css @@ -1,91 +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; + margin: 0; + font-style: italic; + font-size: small; } .language-html, .language-python { - float: left; + 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; } diff --git a/examples/assets/css/index.css b/examples/assets/css/index.css index 051156ea..a14c1078 100644 --- a/examples/assets/css/index.css +++ b/examples/assets/css/index.css @@ -1,74 +1,74 @@ .example { - margin-bottom: 5rem; + margin-bottom: 5rem; } .example h2 { - /* color: #000000; */ - font-family: "Inconsolata", monospace; - font-size: 2.25rem; - margin-bottom: 1rem; + /* 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; + 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); + 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); + } } diff --git a/examples/assets/css/main.css b/examples/assets/css/main.css index b5541bcc..0a67bb18 100644 --- a/examples/assets/css/main.css +++ b/examples/assets/css/main.css @@ -3,23 +3,23 @@ @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; } diff --git a/examples/assets/css/reset.css b/examples/assets/css/reset.css index 6f98549d..0620972c 100644 --- a/examples/assets/css/reset.css +++ b/examples/assets/css/reset.css @@ -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; } diff --git a/examples/assets/css/variables.css b/examples/assets/css/variables.css index 3ad2a720..88173b4a 100644 --- a/examples/assets/css/variables.css +++ b/examples/assets/css/variables.css @@ -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%); } diff --git a/examples/await/await0.html b/examples/await/await0.html index ba0e5679..085aee77 100644 --- a/examples/await/await0.html +++ b/examples/await/await0.html @@ -1,26 +1,29 @@ - - - - Async Await BLOCKING LOOP Pyscript Twice - - - - - - 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('B', i) - await asyncio.sleep(0.1) - - + + + + Async Await BLOCKING LOOP Pyscript Twice + + + + + + 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('B', i) + await asyncio.sleep(0.1) + + diff --git a/examples/await/await1.html b/examples/await/await1.html index 156b55cc..595f3186 100644 --- a/examples/await/await1.html +++ b/examples/await/await1.html @@ -1,42 +1,45 @@ - - - - Async Await BLOCKING LOOP Pyscript Twice - - - - -
- Pyscript - FIRST ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME LEVEL AS - LOOP Pyscript writing to console.log: - - import js - import asyncio + + + + Async Await BLOCKING LOOP Pyscript Twice + + + + +
+ Pyscript - FIRST ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME + LEVEL AS LOOP Pyscript writing to console.log: + + import js + import asyncio - async def asyncCallLoop1(): - for i in range(3): - js.console.log('A', i) - await asyncio.sleep(2) + async def asyncCallLoop1(): + for i in range(3): + js.console.log('A', i) + await asyncio.sleep(2) - asyncCallLoop1() - -
-
- Pyscript - SECOND ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME LEVEL AS - LOOP Pyscript writing to console.log: - - import js - import asyncio + asyncCallLoop1() + +
+
+ Pyscript - SECOND ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME + LEVEL AS LOOP Pyscript writing to console.log: + + import js + import asyncio - async def asyncCallLoop2(): - for i in range(3): - js.console.log('B', i) - await asyncio.sleep(2) + async def asyncCallLoop2(): + for i in range(3): + js.console.log('B', i) + await asyncio.sleep(2) - asyncCallLoop2() - -
- + asyncCallLoop2() +
+
+ diff --git a/examples/await/await2.html b/examples/await/await2.html index a08111f9..f1d0f98a 100644 --- a/examples/await/await2.html +++ b/examples/await/await2.html @@ -1,39 +1,42 @@ - - - - Async Await BLOCKING LOOP Pyscript Twice - - - - -
- Pyscript - FIRST ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME LEVEL AS - LOOP Pyscript writing to console.log: - - import js - import asyncio + + + + Async Await BLOCKING LOOP Pyscript Twice + + + + +
+ Pyscript - FIRST ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME + LEVEL AS LOOP Pyscript writing to console.log: + + import js + import asyncio - async def asyncCallLoop1(): - for i in range(3): - js.console.log('A', i) - await asyncio.sleep(2) + async def asyncCallLoop1(): + for i in range(3): + js.console.log('A', i) + await asyncio.sleep(2) - asyncCallLoop1() - -
-
- Pyscript - SECOND ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME LEVEL - AS LOOP Pyscript writing to console.log: - - import js - import asyncio + asyncCallLoop1() + +
+
+ Pyscript - SECOND ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME + LEVEL AS LOOP Pyscript writing to console.log: + + import js + import asyncio - for i in range(3): - js.console.log('B', i) - await asyncio.sleep(2) - -
- + for i in range(3): + js.console.log('B', i) + await asyncio.sleep(2) +
+
+ diff --git a/examples/await/await3.html b/examples/await/await3.html index 632af2a2..82c425ed 100644 --- a/examples/await/await3.html +++ b/examples/await/await3.html @@ -1,42 +1,45 @@ - - - - Async Await NON-BLOCKING Pyscript Twice - - - - -
- Pyscript - FIRST ASYNC WITH NON-BLOCKING AWAIT AT ONE LEVEL LOWER THAN - LOOP Pyscript writing to console.log: - - import js - import asyncio + + + + Async Await NON-BLOCKING Pyscript Twice + + + + +
+ Pyscript - FIRST ASYNC WITH NON-BLOCKING AWAIT AT ONE LEVEL LOWER + THAN LOOP Pyscript writing to console.log: + + import js + import asyncio - async def asyncCall1(): - await asyncio.sleep(2) + async def asyncCall1(): + await asyncio.sleep(2) - for i in range(3): - js.console.log('A', i) - asyncCall1() - -
-
- Pyscript - SECOND ASYNC WITH NON-BLOCKING AWAIT AT ONE LEVEL LOWER THAN - LOOP Pyscript writing to console.log: - - import js - import asyncio + for i in range(3): + js.console.log('A', i) + asyncCall1() + +
+
+ Pyscript - SECOND ASYNC WITH NON-BLOCKING AWAIT AT ONE LEVEL LOWER + THAN LOOP Pyscript writing to console.log: + + import js + import asyncio - async def asyncCall2(): - await asyncio.sleep(2) + async def asyncCall2(): + await asyncio.sleep(2) - for i in range(3): - js.console.log('B', i) - asyncCall2() - -
- + for i in range(3): + js.console.log('B', i) + asyncCall2() +
+
+ diff --git a/examples/await/await4.html b/examples/await/await4.html index 2bd9c87f..c78d7c38 100644 --- a/examples/await/await4.html +++ b/examples/await/await4.html @@ -1,36 +1,39 @@ - - - - Async Await BLOCKING LOOP Pyscript Twice - - - - -
- Pyscript - FIRST ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME LEVEL AS - LOOP Pyscript writing to console.log: - - import js - import asyncio + + + + Async Await BLOCKING LOOP Pyscript Twice + + + + +
+ Pyscript - FIRST ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME + LEVEL AS LOOP Pyscript writing to console.log: + + import js + import asyncio - for i in range(3): - js.console.log('A', i) - await asyncio.sleep(2) - -
-
- Pyscript - SECOND ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME LEVEL - AS LOOP Pyscript writing to console.log: - - import js - import asyncio + for i in range(3): + js.console.log('A', i) + await asyncio.sleep(2) + +
+
+ Pyscript - SECOND ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME + LEVEL AS LOOP Pyscript writing to console.log: + + import js + import asyncio - for i in range(3): - js.console.log('B', i) - await asyncio.sleep(2) - -
- + for i in range(3): + js.console.log('B', i) + await asyncio.sleep(2) +
+
+ diff --git a/examples/await/await5.html b/examples/await/await5.html index 69277aa3..3312c765 100644 --- a/examples/await/await5.html +++ b/examples/await/await5.html @@ -1,19 +1,22 @@ - - - - Async Await BLOCKING LOOP Pyscript Twice - - - - - - import asyncio - from itertools import count - for i in count(): - print(f"Count: {i}") - await asyncio.sleep(1) - - + + + + Async Await BLOCKING LOOP Pyscript Twice + + + + + + import asyncio + from itertools import count + for i in count(): + print(f"Count: {i}") + await asyncio.sleep(1) + + diff --git a/examples/bokeh.html b/examples/bokeh.html index 8d087c44..ec19577c 100644 --- a/examples/bokeh.html +++ b/examples/bokeh.html @@ -1,81 +1,86 @@ - - Bokeh Example - - - - - - - + + Bokeh Example + + + + + + + - - + + - - - - - - -
-
+ + + + + + +
+
- - packages = [ - "pandas", - "bokeh", - "xyzservices" - ] - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - + + packages = [ + "pandas", + "bokeh", + "xyzservices" + ] + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + - - 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)) + +
+
+ diff --git a/examples/bokeh_interactive.html b/examples/bokeh_interactive.html index 3b804906..09566a1f 100644 --- a/examples/bokeh_interactive.html +++ b/examples/bokeh_interactive.html @@ -1,131 +1,136 @@ - - Bokeh Example - - - - - - - - + + Bokeh Example + + + + + + + + - - + + - - - - - -
-

Bokeh Example

-
+ + + + + +
+

Bokeh Example

+
- - 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" - ] - + + 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" + ] + - - import asyncio - import json - import pyodide + + 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')) - -
-
- + asyncio.ensure_future(show(row, 'myplot')) + +
+
+ diff --git a/examples/d3.html b/examples/d3.html index b7759bce..bd6f671a 100644 --- a/examples/d3.html +++ b/examples/d3.html @@ -1,134 +1,138 @@ - - d3: JavaScript & PyScript visualizations side-by-side - - + + d3: JavaScript & PyScript visualizations side-by-side + + - - - - - - - - + @keyframes spin { + to { + transform: rotate(360deg); + } + } + + + + -
- - - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - [[fetch]] - files = ["./d3.py"] - - - - Based on - Learn D3: Shapes - tutorial. - -
-
-
JavaScript version
-
-
-
-
-
-
PyScript version
-
-
-
-
-
- -
+
+ + + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + [[fetch]] + files = ["./d3.py"] + + + + Based on + Learn D3: Shapes + tutorial. + +
+
+
JavaScript version
+
+
+
+
+
+
PyScript version
+
+
+
+
+
+ +
- - + text.append("tspan") + .style("font-size", "18") + .attr("x", "0") + .attr("dy", "1.3em") + .text(d.value); + } + + diff --git a/examples/folium.html b/examples/folium.html index 38f25ece..41778524 100644 --- a/examples/folium.html +++ b/examples/folium.html @@ -1,69 +1,72 @@ - - Folium - - - - - - - - -
-
+ + Folium + + + + + + + + +
+
- - - packages = [ - "folium", - "pandas" - ] - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - + + + packages = [ + "folium", + "pandas" + ] + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + - - 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") + + +
+ diff --git a/examples/hello_world.html b/examples/hello_world.html index 5e153222..71cfc323 100644 --- a/examples/hello_world.html +++ b/examples/hello_world.html @@ -1,43 +1,46 @@ - - - + + + - PyScript Hello World + PyScript Hello World - - - - - + + + + + - - + + - - - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - + + + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + -
- Hello world!
- This is the current date and time, as computed by Python: - - from datetime import datetime - now = datetime.now() - display(now.strftime("%m/%d/%Y, %H:%M:%S")) - -
-
- +
+ Hello world!
+ This is the current date and time, as computed by Python: + + from datetime import datetime + now = datetime.now() + display(now.strftime("%m/%d/%Y, %H:%M:%S")) + +
+
+ diff --git a/examples/index.html b/examples/index.html index 95045554..afb6f974 100644 --- a/examples/index.html +++ b/examples/index.html @@ -1,277 +1,315 @@ - - - - PyScript demo - - - - + + + + PyScript demo + + + + - -

PyScript demos

-
-

Basic examples

-
-
-
- -

Hello world

-
-

A static demo of the <py-script> tag

-
-
+ +

PyScript demos

+
+

Basic examples

+
+
+
+ +

Hello world

+
+

+ A static demo of the + <py-script> tag +

+
+
-
-
- -

Simple clock

-
-

A dynamic demo of the <py-script> tag

-
-
+
+
+ +

Simple clock

+
+

+ A dynamic demo of the + <py-script> tag +

+
+
-
-
- -

REPL

-
-

A Python REPL (Read Eval Print Loop)

-
-
+
+
+ +

REPL

+
+

A Python REPL (Read Eval Print Loop)

+
+
-
-
- -

REPL2

-
-

- A Python REPL (Read Eval Print Loop) with slightly better - formatting -

-
-
+
+
+ +

REPL2

+
+

+ A Python REPL (Read Eval Print Loop) with slightly + better formatting +

+
+
-
-
- -

TODO App

-
-

Simple TODO App

-
-
+
+
+ +

TODO App

+
+

Simple TODO App

+
+
-
-
- -

PyScript Native TODO App

-
-

Simple TODO App using <py-list>

-
-
-
-
+
+
+ +

PyScript Native TODO App

+
+

+ Simple TODO App using <py-list> +

+
+
+
+
-
-

MIME Rendering

-
-
-
- -

Matplotlib

-
-

- Demonstrates rendering a - Matplotlib - figure as output of the py-script tag -

-
-
+
+

MIME Rendering

+
+
+
+ +

Matplotlib

+
+

+ Demonstrates rendering a + Matplotlib + figure as output of the py-script tag +

+
+
-
-
- -

Altair

-
-

- Demonstrates rendering a - Altair - plot as output of the py-script tag -

-
-
+
+
+ +

Altair

+
+

+ Demonstrates rendering a + Altair + plot as output of the py-script tag +

+
+
-
-
- -

Folium

-
-

- Demonstrates rendering a - Folium - map as output of the py-script tag -

-
-
-
-
+
+
+ +

Folium

+
+

+ Demonstrates rendering a + Folium + map as output of the py-script tag +

+
+
+
+
-
-

JS Interaction

-
-
-
- -

Simple d3 visualization

-
-

- Minimal D3 - demo demonstrating how to create a visualization -

-
-
+
+

JS Interaction

+
+
+
+ +

Simple d3 visualization

+
+

+ Minimal + D3 + demo demonstrating how to create a visualization +

+
+
-
-
- -

Webgl Icosahedron Example

-
-

- Demo showing how a Simple - WebGL - scene would work in the <py-script> tag -

-
-
-
-
+
+
+ +

Webgl Icosahedron Example

+
+

+ Demo showing how a Simple + WebGL + scene would work in the + <py-script> tag +

+
+
+
+
-
-

Visualizations & Dashboards

-
-
-
- -

Simple Static Bokeh Plot

-
-

- Minimal Bokeh demo demonstrating how to create a simple - Bokeh - plot from code -

-
-
+
+

Visualizations & Dashboards

+
+
+
+ +

Simple Static Bokeh Plot

+
+

+ Minimal Bokeh demo demonstrating how to create a + simple + Bokeh + plot from code +

+
+
-
-
- -

- Bokeh Interactive -

-
-

- Interactive demo using a - Bokeh - slider widget to dynamically change a value in the page WARNING: - This examples takes a little longer to load. So be patient :) -

-
-
+
+
+ +

+ Bokeh Interactive +

+
+

+ Interactive demo using a + Bokeh + slider widget to dynamically change a value in the + page WARNING: This examples takes a little longer to + load. So be patient :) +

+
+
-
-
- -

- KMeans Demo in Panel -

-
-

- Interactive KMeans Chart using - Panel - WARNING: This examples takes a little longer to load. So be - patient :) -

-
-
+
+
+ +

+ KMeans Demo in Panel +

+
+

+ Interactive KMeans Chart using + Panel + WARNING: This examples takes a little longer to + load. So be patient :) +

+
+
-
-
- -

- Streaming Demo in Panel -

-
-

- Interactive Streaming Table and Bokeh plot using - Panel - WARNING: This examples takes a little longer to load. So be - patient :) -

-
-
+
+
+ +

+ Streaming Demo in Panel +

+
+

+ Interactive Streaming Table and Bokeh plot using + Panel + WARNING: This examples takes a little longer to + load. So be patient :) +

+
+
-
-
- -

- Simple Panel Demo -

-
-

- Simple demo showing - Panel - widgets interacting with parts of the page WARNING: This examples - takes a little longer to load. So be patient :) -

-
-
+
+
+ +

+ Simple Panel Demo +

+
+

+ Simple demo showing + Panel + widgets interacting with parts of the page WARNING: + This examples takes a little longer to load. So be + patient :) +

+
+
-
-
- -

- NYC Taxi Data Panel DeckGL Demo -

-
-

- Interactive application exploring the NYC Taxi dataset using - Panel and - DeckGL - WARNING: This examples takes a little longer to load. So be - patient :) -

-
-
+
+
+ +

+ NYC Taxi Data Panel DeckGL Demo +

+
+

+ Interactive application exploring the NYC Taxi + dataset using + Panel + and + DeckGL + WARNING: This examples takes a little longer to + load. So be patient :) +

+
+
-
-
- -

- Fractals with NumPy and canvas -

-
-

- Visualization of Mandelbrot and Julia sets with - Numpy and - - HTML5 canvas - -

-
-
-
-
- +
+
+ +

+ Fractals with NumPy and canvas +

+
+

+ Visualization of Mandelbrot and Julia sets with + Numpy + and + + HTML5 canvas + +

+
+
+
+
+ diff --git a/examples/mario/css/game.css b/examples/mario/css/game.css index b6872532..85a1d155 100644 --- a/examples/mario/css/game.css +++ b/examples/mario/css/game.css @@ -2,34 +2,34 @@ html, body, ul, li { - margin: 0; - border: 0; - padding: 0; + margin: 0; + border: 0; + padding: 0; } canvas { - display: block; - width: 762; - margin: 0 auto; - background-color: blue; + display: block; + width: 762; + margin: 0 auto; + background-color: blue; } p { - text-align: center; + text-align: center; } body { - overflow: hidden; - height: 100%; + overflow: hidden; + height: 100%; } html { - overflow: hidden; - height: 100%; + overflow: hidden; + height: 100%; } .info { - position: absolute; - top: 0; - left: 0; + position: absolute; + top: 0; + left: 0; } diff --git a/examples/mario/js/bcoin.js b/examples/mario/js/bcoin.js index ddfde6f3..d74e320a 100644 --- a/examples/mario/js/bcoin.js +++ b/examples/mario/js/bcoin.js @@ -1,43 +1,43 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + if (typeof Mario === "undefined") window.Mario = {}; - var Bcoin = (Mario.Bcoin = function (pos) { - Mario.Entity.call(this, { - pos: pos, - sprite: level.bcoinSprite(), - hitbox: [0, 0, 16, 16], + var Bcoin = (Mario.Bcoin = function (pos) { + Mario.Entity.call(this, { + pos: pos, + sprite: level.bcoinSprite(), + hitbox: [0, 0, 16, 16], + }); }); - }); - Mario.Util.inherits(Bcoin, Mario.Entity); + 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 () { - sounds.coin.currentTime = 0.05; - sounds.coin.play(); - this.idx = level.items.length; - level.items.push(this); - this.active = true; - this.vel = -12; - this.targetpos = this.pos[1] - 32; - }; + //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 () { + sounds.coin.currentTime = 0.05; + sounds.coin.play(); + this.idx = level.items.length; + level.items.push(this); + this.active = true; + this.vel = -12; + this.targetpos = this.pos[1] - 32; + }; - Bcoin.prototype.update = function (dt) { - if (!this.active) return; + Bcoin.prototype.update = function (dt) { + if (!this.active) return; - if (this.vel > 0 && this.pos[1] >= this.targetpos) { - player.coins += 1; - //spawn a score thingy. - delete level.items[this.idx]; - } + if (this.vel > 0 && this.pos[1] >= this.targetpos) { + player.coins += 1; + //spawn a score thingy. + delete level.items[this.idx]; + } - this.acc = 0.75; - this.vel += this.acc; - this.pos[1] += this.vel; - this.sprite.update(dt); - }; + this.acc = 0.75; + this.vel += this.acc; + this.pos[1] += this.vel; + this.sprite.update(dt); + }; - Bcoin.prototype.checkCollisions = function () {}; + Bcoin.prototype.checkCollisions = function () {}; })(); diff --git a/examples/mario/js/block.js b/examples/mario/js/block.js index b3b14be0..662c89aa 100644 --- a/examples/mario/js/block.js +++ b/examples/mario/js/block.js @@ -1,81 +1,84 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + 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. + //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) { - this.item = options.item; - this.usedSprite = options.usedSprite; - this.bounceSprite = options.bounceSprite; - this.breakable = options.breakable; + var Block = (Mario.Block = function (options) { + this.item = options.item; + this.usedSprite = options.usedSprite; + this.bounceSprite = options.bounceSprite; + this.breakable = options.breakable; - Mario.Entity.call(this, { - pos: options.pos, - sprite: options.sprite, - hitbox: [0, 0, 16, 16], + Mario.Entity.call(this, { + pos: options.pos, + sprite: options.sprite, + hitbox: [0, 0, 16, 16], + }); + + this.standing = true; }); - this.standing = true; - }); + Mario.Util.inherits(Block, Mario.Floor); - Mario.Util.inherits(Block, Mario.Floor); - - Block.prototype.break = function () { - sounds.breakBlock.play(); - 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) { - sounds.bump.play(); - if (power > 0 && this.breakable) { - this.break(); - } else if (this.standing) { - this.standing = false; - if (this.item) { - this.item.spawn(); - this.item = null; - } - this.opos = []; - this.opos[0] = this.pos[0]; - this.opos[1] = this.pos[1]; - if (this.bounceSprite) { - this.osprite = this.sprite; - this.sprite = this.bounceSprite; - } else { - this.sprite = this.usedSprite; - } - - this.vel[1] = -2; - } - }; - - Block.prototype.update = function (dt, gameTime) { - if (!this.standing) { - if (this.pos[1] < this.opos[1] - 8) { - this.vel[1] = 2; - } - if (this.pos[1] > this.opos[1]) { - this.vel[1] = 0; - this.pos = this.opos; - if (this.osprite) { - this.sprite = this.osprite; - } - this.standing = true; - } - } else { - if (this.sprite === this.usedSprite) { + Block.prototype.break = function () { + sounds.breakBlock.play(); + new Mario.Rubble().spawn(this.pos); var x = this.pos[0] / 16, - y = this.pos[1] / 16; - level.statics[y][x] = new Mario.Floor(this.pos, this.usedSprite); + y = this.pos[1] / 16; delete level.blocks[y][x]; - } - } + }; - this.pos[1] += this.vel[1]; - this.sprite.update(dt, gameTime); - }; + Block.prototype.bonk = function (power) { + sounds.bump.play(); + if (power > 0 && this.breakable) { + this.break(); + } else if (this.standing) { + this.standing = false; + if (this.item) { + this.item.spawn(); + this.item = null; + } + this.opos = []; + this.opos[0] = this.pos[0]; + this.opos[1] = this.pos[1]; + if (this.bounceSprite) { + this.osprite = this.sprite; + this.sprite = this.bounceSprite; + } else { + this.sprite = this.usedSprite; + } + + this.vel[1] = -2; + } + }; + + Block.prototype.update = function (dt, gameTime) { + if (!this.standing) { + if (this.pos[1] < this.opos[1] - 8) { + this.vel[1] = 2; + } + if (this.pos[1] > this.opos[1]) { + this.vel[1] = 0; + this.pos = this.opos; + if (this.osprite) { + this.sprite = this.osprite; + } + this.standing = true; + } + } else { + if (this.sprite === this.usedSprite) { + 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]; + } + } + + this.pos[1] += this.vel[1]; + this.sprite.update(dt, gameTime); + }; })(); diff --git a/examples/mario/js/coin.js b/examples/mario/js/coin.js index 6f211e34..d7521d31 100644 --- a/examples/mario/js/coin.js +++ b/examples/mario/js/coin.js @@ -1,59 +1,62 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + if (typeof Mario === "undefined") window.Mario = {}; - var Coin = (Mario.Coin = function (pos, sprite) { - Mario.Entity.call(this, { - pos: pos, - sprite: sprite, - hitbox: [0, 0, 16, 16], + var Coin = (Mario.Coin = function (pos, sprite) { + Mario.Entity.call(this, { + pos: pos, + sprite: sprite, + hitbox: [0, 0, 16, 16], + }); + this.idx = level.items.length; }); - this.idx = level.items.length; - }); - Mario.Util.inherits(Coin, Mario.Entity); + Mario.Util.inherits(Coin, Mario.Entity); - 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], - ]; + 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], + ]; - //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] - ) - ) { - this.collect(); - } - } - }; + //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] + ) + ) { + this.collect(); + } + } + }; - Coin.prototype.render = function (ctx, vX, vY) { - this.sprite.render(ctx, this.pos[0], this.pos[1], 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) { - this.sprite.update(dt); - }; - Coin.prototype.checkCollisions = function () { - this.isPlayerCollided(); - }; + //money is not affected by gravity, you see. + Coin.prototype.update = function (dt) { + this.sprite.update(dt); + }; + Coin.prototype.checkCollisions = function () { + this.isPlayerCollided(); + }; - Coin.prototype.collect = function () { - sounds.coin.currentTime = 0.05; - sounds.coin.play(); - player.coins += 1; - delete level.items[this.idx]; - }; + Coin.prototype.collect = function () { + sounds.coin.currentTime = 0.05; + sounds.coin.play(); + player.coins += 1; + delete level.items[this.idx]; + }; })(); diff --git a/examples/mario/js/entity.js b/examples/mario/js/entity.js index f877501d..b90ae851 100644 --- a/examples/mario/js/entity.js +++ b/examples/mario/js/entity.js @@ -1,34 +1,34 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + 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 () {}; })(); diff --git a/examples/mario/js/fireball.js b/examples/mario/js/fireball.js index 0fcacd63..c80cb888 100644 --- a/examples/mario/js/fireball.js +++ b/examples/mario/js/fireball.js @@ -1,142 +1,145 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + if (typeof Mario === "undefined") window.Mario = {}; - var Fireball = (Mario.Fireball = function (pos) { - this.hit = 0; - this.standing = false; + 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], + 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], + }); }); - }); - Mario.Util.inherits(Fireball, Mario.Entity); + Mario.Util.inherits(Fireball, Mario.Entity); - Fireball.prototype.spawn = function (left) { - sounds.fireball.currentTime = 0; - sounds.fireball.play(); - if (fireballs[0]) { - this.idx = 1; - fireballs[1] = this; - } else { - this.idx = 0; - fireballs[0] = this; - } - this.vel[0] = left ? -5 : 5; - this.standing = false; - this.vel[1] = 0; - }; - - Fireball.prototype.render = function (ctx, vX, vY) { - this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY); - }; - - 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.speed = 8; - this.hit += 1; - return; - } else if (this.hit == 5) { - delete fireballs[this.idx]; - player.fireballs -= 1; - return; - } else if (this.hit) { - this.hit += 1; - return; - } - - //In retrospect, the way collision is being handled is RIDICULOUS - //but I don't have to use some horrible kludge for this. - if (this.standing) { - this.standing = false; - this.vel[1] = -4; - } - - this.acc[1] = 0.5; - - this.vel[1] += this.acc[1]; - this.pos[0] += this.vel[0]; - this.pos[1] += this.vel[1]; - if (this.pos[0] < vX || this.pos[0] > vX + 256) { - this.hit = 1; - } - this.sprite.update(dt); - }; - - Fireball.prototype.collideWall = function () { - if (!this.hit) this.hit = 1; - }; - - 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; - - var baseX = Math.floor(this.pos[0] / 16); - var baseY = Math.floor(this.pos[1] / 16); - - if (baseY + h > 15) { - delete fireballs[this.idx]; - player.fireballs -= 1; - return; - } - - for (var i = 0; i < h; i++) { - for (var j = 0; j < w; j++) { - if (level.statics[baseY + i][baseX + j]) { - level.statics[baseY + i][baseX + j].isCollideWith(this); + Fireball.prototype.spawn = function (left) { + sounds.fireball.currentTime = 0; + sounds.fireball.play(); + if (fireballs[0]) { + this.idx = 1; + fireballs[1] = this; + } else { + this.idx = 0; + fireballs[0] = this; } - if (level.blocks[baseY + i][baseX + j]) { - level.blocks[baseY + i][baseX + j].isCollideWith(this); + this.vel[0] = left ? -5 : 5; + this.standing = false; + this.vel[1] = 0; + }; + + Fireball.prototype.render = function (ctx, vX, vY) { + this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY); + }; + + 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.speed = 8; + this.hit += 1; + return; + } else if (this.hit == 5) { + delete fireballs[this.idx]; + player.fireballs -= 1; + return; + } else if (this.hit) { + this.hit += 1; + return; } - } - } - 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. - return; - } else { - that.isCollideWith(enemy); - } - }); - }; + //In retrospect, the way collision is being handled is RIDICULOUS + //but I don't have to use some horrible kludge for this. + if (this.standing) { + this.standing = false; + this.vel[1] = -4; + } - 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]]; + this.acc[1] = 0.5; - //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] - ) - ) { - this.hit = 1; - ent.bump(); - } - } - }; + this.vel[1] += this.acc[1]; + this.pos[0] += this.vel[0]; + this.pos[1] += this.vel[1]; + if (this.pos[0] < vX || this.pos[0] > vX + 256) { + this.hit = 1; + } + this.sprite.update(dt); + }; - Fireball.prototype.bump = function () {}; + Fireball.prototype.collideWall = function () { + if (!this.hit) this.hit = 1; + }; + + 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; + + var baseX = Math.floor(this.pos[0] / 16); + var baseY = Math.floor(this.pos[1] / 16); + + if (baseY + h > 15) { + delete fireballs[this.idx]; + player.fireballs -= 1; + return; + } + + for (var i = 0; i < h; i++) { + for (var j = 0; j < w; j++) { + 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); + } + } + } + + 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. + return; + } else { + that.isCollideWith(enemy); + } + }); + }; + + 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] + ) + ) { + this.hit = 1; + ent.bump(); + } + } + }; + + Fireball.prototype.bump = function () {}; })(); diff --git a/examples/mario/js/fireflower.js b/examples/mario/js/fireflower.js index e974ef4a..7bac50b3 100644 --- a/examples/mario/js/fireflower.js +++ b/examples/mario/js/fireflower.js @@ -1,87 +1,90 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + if (typeof Mario === "undefined") window.Mario = {}; - var Fireflower = (Mario.Fireflower = function (pos) { - this.spawning = false; - this.waiting = 0; + 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], + Mario.Entity.call(this, { + pos: pos, + sprite: level.fireFlowerSprite, + hitbox: [0, 0, 16, 16], + }); }); - }); - Mario.Util.inherits(Fireflower, Mario.Entity); + Mario.Util.inherits(Fireflower, Mario.Entity); - 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.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 () { - sounds.itemAppear.play(); - 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; - }; + Fireflower.prototype.spawn = function () { + sounds.itemAppear.play(); + 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; + }; - Fireflower.prototype.update = function (dt) { - if (this.spawning > 1) { - this.spawning -= 1; - if (this.spawning == 1) this.vel[1] = -0.5; - return; - } - if (this.spawning) { - if (this.pos[1] <= this.targetpos[1]) { - this.pos[1] = this.targetpos[1]; - this.vel[1] = 0; - this.spawning = 0; - } - } + Fireflower.prototype.update = function (dt) { + if (this.spawning > 1) { + this.spawning -= 1; + if (this.spawning == 1) this.vel[1] = -0.5; + return; + } + if (this.spawning) { + if (this.pos[1] <= this.targetpos[1]) { + this.pos[1] = this.targetpos[1]; + this.vel[1] = 0; + this.spawning = 0; + } + } - 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; - } - this.isPlayerCollided(); - }; + Fireflower.prototype.checkCollisions = function () { + if (this.spawning) { + return; + } + this.isPlayerCollided(); + }; - 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], - ]; + 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], + ]; - //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] - ) - ) { - player.powerUp(this.idx); - } - } - }; + //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] + ) + ) { + player.powerUp(this.idx); + } + } + }; - //This should never be called, but just in case. - Fireflower.prototype.bump = function () {}; + //This should never be called, but just in case. + Fireflower.prototype.bump = function () {}; })(); diff --git a/examples/mario/js/flag.js b/examples/mario/js/flag.js index ab96efae..146e92a4 100644 --- a/examples/mario/js/flag.js +++ b/examples/mario/js/flag.js @@ -1,45 +1,51 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + if (typeof Mario === "undefined") window.Mario = {}; - 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]; - }; + 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]; + }; - Flag.prototype.collideWall = function () {}; + Flag.prototype.collideWall = function () {}; - Flag.prototype.update = function (dt) { - if (!this.done && this.pos[1] >= 170) { - this.vel = [0, 0]; - this.pos[1] = 170; - player.exit(); - this.done = true; - } - this.pos[1] += this.vel[1]; - }; + Flag.prototype.update = function (dt) { + if (!this.done && this.pos[1] >= 170) { + this.vel = [0, 0]; + this.pos[1] = 170; + player.exit(); + this.done = true; + } + this.pos[1] += this.vel[1]; + }; - Flag.prototype.checkCollisions = function () { - this.isPlayerCollided(); - }; + Flag.prototype.checkCollisions = function () { + this.isPlayerCollided(); + }; - Flag.prototype.isPlayerCollided = function () { - if (this.hit) return; - if (player.pos[0] + 8 >= this.pos[0]) { - music.overworld.pause(); - sounds.flagpole.play(); - setTimeout(function () { - music.clear.play(); - }, 2000); - this.hit = true; - player.flag(); - this.vel = [0, 2]; - } - }; + Flag.prototype.isPlayerCollided = function () { + if (this.hit) return; + if (player.pos[0] + 8 >= this.pos[0]) { + music.overworld.pause(); + sounds.flagpole.play(); + 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, + ); + }; })(); diff --git a/examples/mario/js/floor.js b/examples/mario/js/floor.js index fbbccb95..ecf5cf0f 100644 --- a/examples/mario/js/floor.js +++ b/examples/mario/js/floor.js @@ -1,75 +1,83 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + if (typeof Mario === "undefined") window.Mario = {}; - var Floor = (Mario.Floor = function (pos, sprite) { - Mario.Entity.call(this, { - pos: pos, - sprite: sprite, - hitbox: [0, 0, 16, 16], + var Floor = (Mario.Floor = function (pos, sprite) { + 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; + //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); + } + } } - 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 () {}; })(); diff --git a/examples/mario/js/game.js b/examples/mario/js/game.js index 3b326d51..f65451b1 100644 --- a/examples/mario/js/game.js +++ b/examples/mario/js/game.js @@ -1,14 +1,14 @@ var requestAnimFrame = (function () { - return ( - window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - window.msRequestAnimationFrame || - function (callback) { - window.setTimeout(callback, 1000 / 60); - } - ); + return ( + window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function (callback) { + window.setTimeout(callback, 1000 / 60); + } + ); })(); //create the canvas @@ -30,18 +30,18 @@ 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); @@ -52,194 +52,202 @@ var music; //initialize 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"), - }; - 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"), - }; - Mario.oneone(); - lastTime = Date.now(); - main(); + 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"), + }; + 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"), + }; + Mario.oneone(); + lastTime = Date.now(); + main(); } var gameTime = 0; //set up the game loop function main() { - var now = Date.now(); - var dt = (now - lastTime) / 1000.0; + var now = Date.now(); + var dt = (now - lastTime) / 1000.0; - update(dt); - render(); + update(dt); + render(); - lastTime = now; - requestAnimFrame(main); + lastTime = now; + requestAnimFrame(main); } function update(dt) { - gameTime += dt; + gameTime += dt; - handleInput(dt); - updateEntities(dt, gameTime); + handleInput(dt); + updateEntities(dt, gameTime); - checkCollisions(); + checkCollisions(); } function handleInput(dt) { - if (player.piping || player.dying || player.noInput) return; //don't accept input + if (player.piping || player.dying || player.noInput) return; //don't accept input - if (input.isDown("RUN")) { - player.run(); - } else { - player.noRun(); - } - 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("RUN")) { + player.run(); + } else { + player.noRun(); + } + 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")) { - player.crouch(); - } else { - player.noCrouch(); - } + if (input.isDown("DOWN")) { + player.crouch(); + } else { + player.noCrouch(); + } - if (input.isDown("LEFT")) { - // 'd' or left arrow - player.moveLeft(); - } else if (input.isDown("RIGHT")) { - // 'k' or right arrow - player.moveRight(); - } else { - player.noWalk(); - } + if (input.isDown("LEFT")) { + // 'd' or left arrow + player.moveLeft(); + } else if (input.isDown("RIGHT")) { + // 'k' or right arrow + player.moveRight(); + } else { + player.noWalk(); + } } //update all the moving stuff function updateEntities(dt, gameTime) { - player.update(dt, vX); - updateables.forEach(function (ent) { - ent.update(dt, gameTime); - }); + player.update(dt, vX); + 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) { - vX = player.pos[0] - 80; - } + //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) { + vX = player.pos[0] - 80; + } - if (player.powering.length !== 0 || player.dying) { - return; - } - level.items.forEach(function (ent) { - ent.update(dt); - }); + if (player.powering.length !== 0 || player.dying) { + return; + } + level.items.forEach(function (ent) { + ent.update(dt); + }); - level.enemies.forEach(function (ent) { - ent.update(dt, vX); - }); + level.enemies.forEach(function (ent) { + ent.update(dt, vX); + }); - fireballs.forEach(function (fireball) { - fireball.update(dt); - }); - level.pipes.forEach(function (pipe) { - pipe.update(dt); - }); + fireballs.forEach(function (fireball) { + fireball.update(dt); + }); + level.pipes.forEach(function (pipe) { + pipe.update(dt); + }); } //scan for collisions function checkCollisions() { - if (player.powering.length !== 0 || player.dying) { - return; - } - player.checkCollisions(); + 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) { - item.checkCollisions(); - }); - level.enemies.forEach(function (ent) { - ent.checkCollisions(); - }); - fireballs.forEach(function (fireball) { - fireball.checkCollisions(); - }); - level.pipes.forEach(function (pipe) { - pipe.checkCollisions(); - }); + //Apparently for each will just skip indices where things were deleted. + level.items.forEach(function (item) { + item.checkCollisions(); + }); + level.enemies.forEach(function (ent) { + ent.checkCollisions(); + }); + fireballs.forEach(function (fireball) { + fireball.checkCollisions(); + }); + level.pipes.forEach(function (pipe) { + pipe.checkCollisions(); + }); } //draw the game! function render() { - updateables = []; - ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.fillStyle = level.background; - ctx.fillRect(0, 0, canvas.width, canvas.height); + updateables = []; + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.fillStyle = level.background; + 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++) { - if (level.scenery[i][j]) { - renderEntity(level.scenery[i][j]); - } + //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++ + ) { + if (level.scenery[i][j]) { + renderEntity(level.scenery[i][j]); + } + } } - } - //then items - level.items.forEach(function (item) { - renderEntity(item); - }); + //then items + level.items.forEach(function (item) { + renderEntity(item); + }); - level.enemies.forEach(function (enemy) { - renderEntity(enemy); - }); + level.enemies.forEach(function (enemy) { + renderEntity(enemy); + }); - fireballs.forEach(function (fireball) { - renderEntity(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++) { - if (level.statics[i][j]) { - renderEntity(level.statics[i][j]); - } - if (level.blocks[i][j]) { - renderEntity(level.blocks[i][j]); - updateables.push(level.blocks[i][j]); - } + //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++ + ) { + if (level.statics[i][j]) { + renderEntity(level.statics[i][j]); + } + if (level.blocks[i][j]) { + renderEntity(level.blocks[i][j]); + updateables.push(level.blocks[i][j]); + } + } } - } - //then the player - if (player.invincibility % 2 === 0) { - renderEntity(player); - } + //then the player + if (player.invincibility % 2 === 0) { + renderEntity(player); + } - //Mario goes INTO pipes, so naturally they go after. - level.pipes.forEach(function (pipe) { - renderEntity(pipe); - }); + //Mario goes INTO pipes, so naturally they go after. + level.pipes.forEach(function (pipe) { + renderEntity(pipe); + }); } function renderEntity(entity) { - entity.render(ctx, vX, vY); + entity.render(ctx, vX, vY); } diff --git a/examples/mario/js/goomba.js b/examples/mario/js/goomba.js index 6c30d306..0cfcaffc 100644 --- a/examples/mario/js/goomba.js +++ b/examples/mario/js/goomba.js @@ -1,144 +1,147 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + if (typeof Mario === "undefined") window.Mario = {}; - //TODO: On console the hitbox is smaller. Measure it and edit this. + //TODO: On console the hitbox is smaller. Measure it and edit this. - var Goomba = (Mario.Goomba = function (pos, sprite) { - this.dying = false; - Mario.Entity.call(this, { - pos: pos, - sprite: sprite, - hitbox: [0, 0, 16, 16], + var Goomba = (Mario.Goomba = function (pos, sprite) { + this.dying = false; + Mario.Entity.call(this, { + pos: pos, + sprite: sprite, + hitbox: [0, 0, 16, 16], + }); + this.vel[0] = -0.5; + this.idx = level.enemies.length; }); - this.vel[0] = -0.5; - this.idx = level.enemies.length; - }); - Goomba.prototype.render = function (ctx, vX, vY) { - this.sprite.render(ctx, this.pos[0], this.pos[1], 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. - return; - } else if (this.pos[0] - vX < -32) { - delete level.enemies[this.idx]; - } - - if (this.dying) { - this.dying -= 1; - if (!this.dying) { - delete level.enemies[this.idx]; - } - } - this.acc[1] = 0.2; - this.vel[1] += this.acc[1]; - this.pos[0] += this.vel[0]; - this.pos[1] += this.vel[1]; - this.sprite.update(dt); - }; - - Goomba.prototype.collideWall = function () { - this.vel[0] = -this.vel[0]; - }; - - Goomba.prototype.checkCollisions = function () { - if (this.flipping) { - return; - } - - var h = this.pos[1] % 16 === 0 ? 1 : 2; - var w = this.pos[0] % 16 === 0 ? 1 : 2; - - var baseX = Math.floor(this.pos[0] / 16); - var baseY = Math.floor(this.pos[1] / 16); - - if (baseY + h > 15) { - delete level.enemies[this.idx]; - return; - } - - for (var i = 0; i < h; i++) { - for (var j = 0; j < w; j++) { - if (level.statics[baseY + i][baseX + j]) { - level.statics[baseY + i][baseX + j].isCollideWith(this); + 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]; } - if (level.blocks[baseY + i][baseX + j]) { - level.blocks[baseY + i][baseX + j].isCollideWith(this); + + if (this.dying) { + this.dying -= 1; + if (!this.dying) { + delete level.enemies[this.idx]; + } } - } - } - var that = this; - 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. - return; - } else { - that.isCollideWith(enemy); - } - }); - this.isCollideWith(player); - }; + this.acc[1] = 0.2; + this.vel[1] += this.acc[1]; + this.pos[0] += this.vel[0]; + this.pos[1] += this.vel[1]; + this.sprite.update(dt); + }; - Goomba.prototype.isCollideWith = function (ent) { - if (ent instanceof Mario.Player && (this.dying || ent.invincibility)) { - return; - } + Goomba.prototype.collideWall = function () { + this.vel[0] = -this.vel[0]; + }; - //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 (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 - ent.damage(); - } - } else { - this.collideWall(); + Goomba.prototype.checkCollisions = function () { + if (this.flipping) { + return; } - } - } - }; - Goomba.prototype.stomp = function () { - sounds.stomp.play(); - player.bounce = true; - this.sprite.pos[0] = 32; - this.sprite.speed = 0; - this.vel[0] = 0; - this.dying = 10; - }; + var h = this.pos[1] % 16 === 0 ? 1 : 2; + var w = this.pos[0] % 16 === 0 ? 1 : 2; - Goomba.prototype.bump = function () { - sounds.kick.play(); - this.sprite.img = "sprites/enemyr.png"; - this.flipping = true; - this.pos[1] -= 1; - this.vel[0] = 0; - this.vel[1] = -2.5; - }; + var baseX = Math.floor(this.pos[0] / 16); + var baseY = Math.floor(this.pos[1] / 16); + + if (baseY + h > 15) { + delete level.enemies[this.idx]; + return; + } + + for (var i = 0; i < h; i++) { + for (var j = 0; j < w; j++) { + 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); + } + } + } + var that = this; + 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. + return; + } else { + that.isCollideWith(enemy); + } + }); + this.isCollideWith(player); + }; + + Goomba.prototype.isCollideWith = function (ent) { + if (ent instanceof Mario.Player && (this.dying || ent.invincibility)) { + return; + } + + //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 (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 + ent.damage(); + } + } else { + this.collideWall(); + } + } + } + }; + + Goomba.prototype.stomp = function () { + sounds.stomp.play(); + player.bounce = true; + this.sprite.pos[0] = 32; + this.sprite.speed = 0; + this.vel[0] = 0; + this.dying = 10; + }; + + Goomba.prototype.bump = function () { + sounds.kick.play(); + this.sprite.img = "sprites/enemyr.png"; + this.flipping = true; + this.pos[1] -= 1; + this.vel[0] = 0; + this.vel[1] = -2.5; + }; })(); diff --git a/examples/mario/js/input.js b/examples/mario/js/input.js index 8945bc55..6e2edc97 100644 --- a/examples/mario/js/input.js +++ b/examples/mario/js/input.js @@ -1,61 +1,61 @@ (function () { - var pressedKeys = {}; + 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); + 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; } - pressedKeys[key] = status; - } + document.addEventListener("keydown", function (e) { + setKey(e, true); + }); - document.addEventListener("keydown", function (e) { - setKey(e, true); - }); + document.addEventListener("keyup", function (e) { + setKey(e, false); + }); - document.addEventListener("keyup", function (e) { - setKey(e, false); - }); + window.addEventListener("blur", function () { + pressedKeys = {}; + }); - 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; - }, - }; + 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; + }, + }; })(); diff --git a/examples/mario/js/koopa.js b/examples/mario/js/koopa.js index 7a0f7029..51d143c1 100644 --- a/examples/mario/js/koopa.js +++ b/examples/mario/js/koopa.js @@ -1,225 +1,228 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + if (typeof Mario === "undefined") window.Mario = {}; - var Koopa = (Mario.Koopa = function (pos, sprite, para) { - this.dying = false; - this.shell = false; + var Koopa = (Mario.Koopa = function (pos, sprite, para) { + this.dying = false; + this.shell = false; - this.para = para; //para. As in, is it a paratroopa? + this.para = para; //para. As in, is it a paratroopa? - //So, funny story. The actual hitboxes don't reach all the way to the ground. - //What that means is, as long as I use them to keep things on the floor - //making the hitboxes accurate will make enemies sink into the ground. - Mario.Entity.call(this, { - pos: pos, - sprite: sprite, - hitbox: [2, 8, 12, 24], + //So, funny story. The actual hitboxes don't reach all the way to the ground. + //What that means is, as long as I use them to keep things on the floor + //making the hitboxes accurate will make enemies sink into the ground. + Mario.Entity.call(this, { + pos: pos, + sprite: sprite, + hitbox: [2, 8, 12, 24], + }); + this.vel[0] = -0.5; + this.idx = level.enemies.length; }); - this.vel[0] = -0.5; - this.idx = level.enemies.length; - }); - Koopa.prototype.render = function (ctx, vX, vY) { - this.sprite.render(ctx, this.pos[0], this.pos[1], 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) { - 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; - } - - if (this.left) { - this.sprite.img = "sprites/enemy.png"; - } else { - this.sprite.img = "sprites/enemyr.png"; - } - - 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]; - } - - if (this.dying) { - this.dying -= 1; - if (!this.dying) { - delete level.enemies[this.idx]; - } - } - - if (this.shell) { - if (this.vel[0] == 0) { - this.shell -= 1; - if (this.shell < 120) { - this.sprite.speed = 5; + 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.shell == 0) { - this.sprite = level.koopaSprite(); - this.hitbox = [2, 8, 12, 24]; - if (this.left) { - this.sprite.img = "sprites/enemyr.png"; - this.vel[0] = 0.5; - this.left = false; - } else { - this.vel[0] = -0.5; - this.left = true; - } - this.pos[1] -= 16; + if (this.vel[0] != 0) { + this.left = this.vel[0] < 0; } - } else { - this.shell = 360; - this.sprite.speed = 0; - this.sprite.setFrame(0); - } - } - this.acc[1] = 0.2; - this.vel[1] += this.acc[1]; - this.pos[0] += this.vel[0]; - this.pos[1] += this.vel[1]; - this.sprite.update(dt); - }; - 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 () { - var h = this.shell ? 1 : 2; - if (this.pos[1] % 16 !== 0) { - h += 1; - } - var w = this.pos[0] % 16 === 0 ? 1 : 2; - - var baseX = Math.floor(this.pos[0] / 16); - var baseY = Math.floor(this.pos[1] / 16); - - if (baseY + h > 15) { - delete level.enemies[this.idx]; - return; - } - - if (this.flipping) { - return; - } - - for (var i = 0; i < h; i++) { - for (var j = 0; j < w; j++) { - 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); - } - } - } - var that = this; - 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. - return; - } else { - that.isCollideWith(enemy); - } - }); - this.isCollideWith(player); - }; - - Koopa.prototype.isCollideWith = function (ent) { - if (ent instanceof Mario.Player && (this.dying || ent.invincibility)) { - return; - } - - //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 (ent instanceof Mario.Player) { - if (ent.vel[1] > 0) { - player.bounce = true; - } - if (this.shell) { - sounds.kick.play(); - if (this.vel[0] === 0) { - if (ent.left) { - //I'm pretty sure this isn't the real logic. - this.vel[0] = -4; - } else { - this.vel[0] = 4; - } - } else { - if (ent.bounce) { - this.vel[0] = 0; - } else ent.damage(); - } - } else if (ent.vel[1] > 0) { - //then we get BOPPED. - this.stomp(); - } else { - //or the player gets hit - ent.damage(); - } + if (this.left) { + this.sprite.img = "sprites/enemy.png"; } else { - if (this.shell && ent instanceof Mario.Goomba) { - ent.bump(); - } else this.collideWall(); + this.sprite.img = "sprites/enemyr.png"; } - } - } - }; - 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) { - this.para = false; - this.sprite.pos[0] -= 32; - } else { - sounds.stomp.play(); - 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.speed = 0; - this.frames = [0, 1]; - this.vel = [0, 0]; - this.pos[1] += 16; - } - }; + 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]; + } - 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.hitbox = [2, 0, 12, 16]; - this.sprite.speed = 0; - this.vel[0] = 0; - this.vel[1] = -2.5; - }; + if (this.dying) { + this.dying -= 1; + if (!this.dying) { + delete level.enemies[this.idx]; + } + } + + if (this.shell) { + if (this.vel[0] == 0) { + this.shell -= 1; + if (this.shell < 120) { + this.sprite.speed = 5; + } + if (this.shell == 0) { + this.sprite = level.koopaSprite(); + this.hitbox = [2, 8, 12, 24]; + if (this.left) { + this.sprite.img = "sprites/enemyr.png"; + this.vel[0] = 0.5; + this.left = false; + } else { + this.vel[0] = -0.5; + this.left = true; + } + this.pos[1] -= 16; + } + } else { + this.shell = 360; + this.sprite.speed = 0; + this.sprite.setFrame(0); + } + } + this.acc[1] = 0.2; + this.vel[1] += this.acc[1]; + this.pos[0] += this.vel[0]; + this.pos[1] += this.vel[1]; + this.sprite.update(dt); + }; + + 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 () { + var h = this.shell ? 1 : 2; + if (this.pos[1] % 16 !== 0) { + h += 1; + } + var w = this.pos[0] % 16 === 0 ? 1 : 2; + + var baseX = Math.floor(this.pos[0] / 16); + var baseY = Math.floor(this.pos[1] / 16); + + if (baseY + h > 15) { + delete level.enemies[this.idx]; + return; + } + + if (this.flipping) { + return; + } + + for (var i = 0; i < h; i++) { + for (var j = 0; j < w; j++) { + 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); + } + } + } + var that = this; + 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. + return; + } else { + that.isCollideWith(enemy); + } + }); + this.isCollideWith(player); + }; + + Koopa.prototype.isCollideWith = function (ent) { + if (ent instanceof Mario.Player && (this.dying || ent.invincibility)) { + return; + } + + //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 (ent instanceof Mario.Player) { + if (ent.vel[1] > 0) { + player.bounce = true; + } + if (this.shell) { + sounds.kick.play(); + if (this.vel[0] === 0) { + if (ent.left) { + //I'm pretty sure this isn't the real logic. + this.vel[0] = -4; + } else { + this.vel[0] = 4; + } + } else { + if (ent.bounce) { + this.vel[0] = 0; + } else ent.damage(); + } + } else if (ent.vel[1] > 0) { + //then we get BOPPED. + this.stomp(); + } else { + //or the player gets hit + ent.damage(); + } + } else { + if (this.shell && ent instanceof Mario.Goomba) { + ent.bump(); + } else this.collideWall(); + } + } + } + }; + + 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) { + this.para = false; + this.sprite.pos[0] -= 32; + } else { + sounds.stomp.play(); + 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.speed = 0; + this.frames = [0, 1]; + this.vel = [0, 0]; + this.pos[1] += 16; + } + }; + + 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.hitbox = [2, 0, 12, 16]; + this.sprite.speed = 0; + this.vel[0] = 0; + this.vel[1] = -2.5; + }; })(); diff --git a/examples/mario/js/levels/11.js b/examples/mario/js/levels/11.js index a454d08c..ce2c8b63 100644 --- a/examples/mario/js/levels/11.js +++ b/examples/mario/js/levels/11.js @@ -1,310 +1,341 @@ 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], - 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, - ), - rubbleSprite: function () { - 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, - ), + //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], + 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, + ), + rubbleSprite: function () { + 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, + ), - 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), - ], - 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), - ], - 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], - ]; - player.pos[0] = level.playerPos[0]; - player.pos[1] = level.playerPos[1]; - vX = 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], + ); + }, + 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), + ], + 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], + ]; + 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]); - }); + //build THE GROUND + 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]); - }); + //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]); + }); - 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) { - level.putBigHill(hill, 12); - }); + bHills = [0, 48, 96, 144, 192]; + bHills.forEach(function (hill) { + level.putBigHill(hill, 12); + }); - sHills = [16, 64, 111, 160]; - sHills.forEach(function (hill) { - level.putSmallHill(hill, 12); - }); + sHills = [16, 64, 111, 160]; + sHills.forEach(function (hill) { + level.putSmallHill(hill, 12); + }); - bushes = [23, 71, 118, 167]; - bushes.forEach(function (bush) { - level.putBush(bush, 12); - }); + bushes = [23, 71, 118, 167]; + bushes.forEach(function (bush) { + level.putBush(bush, 12); + }); - twoBushes = [41, 89, 137]; - twoBushes.forEach(function (bush) { - level.putTwoBush(bush, 12); - }); + twoBushes = [41, 89, 137]; + twoBushes.forEach(function (bush) { + level.putTwoBush(bush, 12); + }); - threeBushes = [11, 59, 106]; - threeBushes.forEach(function (bush) { - level.putThreeBush(bush, 12); - }); + threeBushes = [11, 59, 106]; + threeBushes.forEach(function (bush) { + level.putThreeBush(bush, 12); + }); - //interactable terrain - level.putQBlock(16, 9, new Mario.Bcoin([256, 144])); - level.putBrick(20, 9, null); - level.putQBlock(21, 9, new Mario.Mushroom([336, 144])); - level.putBrick(22, 9, null); - level.putQBlock(22, 5, new Mario.Bcoin([352, 80])); - level.putQBlock(23, 9, new Mario.Bcoin([368, 144])); - level.putBrick(24, 9, null); - level.putPipe(28, 13, 2); - level.putPipe(38, 13, 3); - level.putPipe(46, 13, 4); - level.putRealPipe(57, 9, 4, "DOWN", Mario.oneonetunnel); - level.putBrick(77, 9, null); - level.putQBlock(78, 9, new Mario.Mushroom([1248, 144])); - level.putBrick(79, 9, null); - level.putBrick(80, 5, null); - level.putBrick(81, 5, null); - level.putBrick(82, 5, null); - level.putBrick(83, 5, null); - level.putBrick(84, 5, null); - level.putBrick(85, 5, null); - level.putBrick(86, 5, null); - level.putBrick(87, 5, null); - level.putBrick(91, 5, null); - level.putBrick(92, 5, null); - level.putBrick(93, 5, null); - level.putQBlock(94, 5, new Mario.Bcoin([1504, 80])); - level.putBrick(94, 9, null); - level.putBrick(100, 9, new Mario.Star([1600, 144])); - level.putBrick(101, 9, null); - level.putQBlock(105, 9, new Mario.Bcoin([1680, 144])); - level.putQBlock(108, 9, new Mario.Bcoin([1728, 144])); - level.putQBlock(108, 5, new Mario.Mushroom([1728, 80])); - level.putQBlock(111, 9, new Mario.Bcoin([1776, 144])); - level.putBrick(117, 9, null); - level.putBrick(120, 5, null); - level.putBrick(121, 5, null); - level.putBrick(122, 5, null); - level.putBrick(123, 5, null); - level.putBrick(128, 5, null); - level.putQBlock(129, 5, new Mario.Bcoin([2074, 80])); - level.putBrick(129, 9, null); - level.putQBlock(130, 5, new Mario.Bcoin([2080, 80])); - level.putBrick(130, 9, null); - level.putBrick(131, 5, null); - level.putWall(134, 13, 1); - level.putWall(135, 13, 2); - level.putWall(136, 13, 3); - level.putWall(137, 13, 4); - level.putWall(140, 13, 4); - level.putWall(141, 13, 3); - level.putWall(142, 13, 2); - level.putWall(143, 13, 1); - level.putWall(148, 13, 1); - level.putWall(149, 13, 2); - level.putWall(150, 13, 3); - level.putWall(151, 13, 4); - level.putWall(152, 13, 4); - level.putWall(155, 13, 4); - level.putWall(156, 13, 3); - level.putWall(157, 13, 2); - level.putWall(158, 13, 1); - level.putPipe(163, 13, 2); - level.putBrick(168, 9, null); - level.putBrick(169, 9, null); - level.putQBlock(170, 9, new Mario.Bcoin([2720, 144])); - level.putBrick(171, 9, null); - level.putPipe(179, 13, 2); - level.putWall(181, 13, 1); - level.putWall(182, 13, 2); - level.putWall(183, 13, 3); - level.putWall(184, 13, 4); - level.putWall(185, 13, 5); - level.putWall(186, 13, 6); - level.putWall(187, 13, 7); - level.putWall(188, 13, 8); - level.putWall(189, 13, 8); - level.putFlagpole(198); + //interactable terrain + level.putQBlock(16, 9, new Mario.Bcoin([256, 144])); + level.putBrick(20, 9, null); + level.putQBlock(21, 9, new Mario.Mushroom([336, 144])); + level.putBrick(22, 9, null); + level.putQBlock(22, 5, new Mario.Bcoin([352, 80])); + level.putQBlock(23, 9, new Mario.Bcoin([368, 144])); + level.putBrick(24, 9, null); + level.putPipe(28, 13, 2); + level.putPipe(38, 13, 3); + level.putPipe(46, 13, 4); + level.putRealPipe(57, 9, 4, "DOWN", Mario.oneonetunnel); + level.putBrick(77, 9, null); + level.putQBlock(78, 9, new Mario.Mushroom([1248, 144])); + level.putBrick(79, 9, null); + level.putBrick(80, 5, null); + level.putBrick(81, 5, null); + level.putBrick(82, 5, null); + level.putBrick(83, 5, null); + level.putBrick(84, 5, null); + level.putBrick(85, 5, null); + level.putBrick(86, 5, null); + level.putBrick(87, 5, null); + level.putBrick(91, 5, null); + level.putBrick(92, 5, null); + level.putBrick(93, 5, null); + level.putQBlock(94, 5, new Mario.Bcoin([1504, 80])); + level.putBrick(94, 9, null); + level.putBrick(100, 9, new Mario.Star([1600, 144])); + level.putBrick(101, 9, null); + level.putQBlock(105, 9, new Mario.Bcoin([1680, 144])); + level.putQBlock(108, 9, new Mario.Bcoin([1728, 144])); + level.putQBlock(108, 5, new Mario.Mushroom([1728, 80])); + level.putQBlock(111, 9, new Mario.Bcoin([1776, 144])); + level.putBrick(117, 9, null); + level.putBrick(120, 5, null); + level.putBrick(121, 5, null); + level.putBrick(122, 5, null); + level.putBrick(123, 5, null); + level.putBrick(128, 5, null); + level.putQBlock(129, 5, new Mario.Bcoin([2074, 80])); + level.putBrick(129, 9, null); + level.putQBlock(130, 5, new Mario.Bcoin([2080, 80])); + level.putBrick(130, 9, null); + level.putBrick(131, 5, null); + level.putWall(134, 13, 1); + level.putWall(135, 13, 2); + level.putWall(136, 13, 3); + level.putWall(137, 13, 4); + level.putWall(140, 13, 4); + level.putWall(141, 13, 3); + level.putWall(142, 13, 2); + level.putWall(143, 13, 1); + level.putWall(148, 13, 1); + level.putWall(149, 13, 2); + level.putWall(150, 13, 3); + level.putWall(151, 13, 4); + level.putWall(152, 13, 4); + level.putWall(155, 13, 4); + level.putWall(156, 13, 3); + level.putWall(157, 13, 2); + level.putWall(158, 13, 1); + level.putPipe(163, 13, 2); + level.putBrick(168, 9, null); + level.putBrick(169, 9, null); + level.putQBlock(170, 9, new Mario.Bcoin([2720, 144])); + level.putBrick(171, 9, null); + level.putPipe(179, 13, 2); + level.putWall(181, 13, 1); + level.putWall(182, 13, 2); + level.putWall(183, 13, 3); + level.putWall(184, 13, 4); + level.putWall(185, 13, 5); + level.putWall(186, 13, 6); + level.putWall(187, 13, 7); + level.putWall(188, 13, 8); + level.putWall(189, 13, 8); + level.putFlagpole(198); - //and enemies - level.putGoomba(22, 12); - level.putGoomba(40, 12); - level.putGoomba(50, 12); - level.putGoomba(51, 12); - level.putGoomba(82, 4); - level.putGoomba(84, 4); - level.putGoomba(100, 12); - level.putGoomba(102, 12); - level.putGoomba(114, 12); - level.putGoomba(115, 12); - level.putGoomba(122, 12); - level.putGoomba(123, 12); - level.putGoomba(125, 12); - level.putGoomba(126, 12); - level.putGoomba(170, 12); - level.putGoomba(172, 12); - level.putKoopa(35, 11); + //and enemies + level.putGoomba(22, 12); + level.putGoomba(40, 12); + level.putGoomba(50, 12); + level.putGoomba(51, 12); + level.putGoomba(82, 4); + level.putGoomba(84, 4); + level.putGoomba(100, 12); + level.putGoomba(102, 12); + level.putGoomba(114, 12); + level.putGoomba(115, 12); + level.putGoomba(122, 12); + level.putGoomba(123, 12); + level.putGoomba(125, 12); + level.putGoomba(126, 12); + level.putGoomba(170, 12); + level.putGoomba(172, 12); + level.putKoopa(35, 11); - music.underground.pause(); - // music.overworld.currentTime = 0; - music.overworld.play(); + music.underground.pause(); + // music.overworld.currentTime = 0; + music.overworld.play(); }); diff --git a/examples/mario/js/levels/11tunnel.js b/examples/mario/js/levels/11tunnel.js index 0160db16..4cadc280 100644 --- a/examples/mario/js/levels/11tunnel.js +++ b/examples/mario/js/levels/11tunnel.js @@ -1,113 +1,138 @@ var oneonetunnel = (Mario.oneonetunnel = function () { - level = new Mario.Level({ - 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], - ); - }, - 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), + level = new Mario.Level({ + 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], + ); + }, + 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), - ], - }); + 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); - }); + 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); + }); - 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 () { - Mario.oneone.call(); - player.pos = [2616, 177]; - player.pipe("UP", function () {}); - }); + //level.putLeftPipe(13,11); + level.putRealPipe(13, 11, 3, "RIGHT", function () { + Mario.oneone.call(); + 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(); + music.overworld.pause(); + music.underground.currentTime = 0; + music.underground.play(); }); diff --git a/examples/mario/js/levels/level.js b/examples/mario/js/levels/level.js index 08719b17..12c5d1a9 100644 --- a/examples/mario/js/levels/level.js +++ b/examples/mario/js/levels/level.js @@ -1,295 +1,348 @@ (function () { - var Level = (Mario.Level = function (options) { - this.playerPos = options.playerPos; - this.scrolling = options.scrolling; - this.loader = options.loader; - this.background = options.background; - this.exit = options.exit; + var Level = (Mario.Level = function (options) { + this.playerPos = options.playerPos; + this.scrolling = options.scrolling; + this.loader = options.loader; + this.background = options.background; + this.exit = options.exit; - this.floorSprite = options.floorSprite; - this.cloudSprite = options.cloudSprite; - this.wallSprite = options.wallSprite; - this.brickSprite = options.brickSprite; - this.rubbleSprite = options.rubbleSprite; - this.brickBounceSprite = options.brickBounceSprite; - this.ublockSprite = options.ublockSprite; - this.superShroomSprite = options.superShroomSprite; - this.fireFlowerSprite = options.fireFlowerSprite; - this.starSprite = options.starSprite; - this.coinSprite = options.coinSprite; - this.bcoinSprite = options.bcoinSprite; - this.goombaSprite = options.goombaSprite; - this.koopaSprite = options.koopaSprite; + this.floorSprite = options.floorSprite; + this.cloudSprite = options.cloudSprite; + this.wallSprite = options.wallSprite; + this.brickSprite = options.brickSprite; + this.rubbleSprite = options.rubbleSprite; + this.brickBounceSprite = options.brickBounceSprite; + this.ublockSprite = options.ublockSprite; + this.superShroomSprite = options.superShroomSprite; + this.fireFlowerSprite = options.fireFlowerSprite; + this.starSprite = options.starSprite; + this.coinSprite = options.coinSprite; + this.bcoinSprite = options.bcoinSprite; + this.goombaSprite = options.goombaSprite; + this.koopaSprite = options.koopaSprite; - //prop pipe sprites, to be phased out - this.pipeLEndSprite = options.pipeLEndSprite; - this.pipeREndSprite = options.pipeREndSprite; - this.pipeLMidSprite = options.pipeLMidSprite; - this.pipeRMidSprite = options.pipeRMidSprite; + //prop pipe sprites, to be phased out + this.pipeLEndSprite = options.pipeLEndSprite; + this.pipeREndSprite = options.pipeREndSprite; + this.pipeLMidSprite = options.pipeLMidSprite; + this.pipeRMidSprite = options.pipeRMidSprite; - //real pipe sprites, use these. - this.pipeUpMid = options.pipeUpMid; - this.pipeSideMid = options.pipeSideMid; - this.pipeLeft = options.pipeLeft; - this.pipeTop = options.pipeTop; + //real pipe sprites, use these. + this.pipeUpMid = options.pipeUpMid; + this.pipeSideMid = options.pipeSideMid; + this.pipeLeft = options.pipeLeft; + this.pipeTop = options.pipeTop; - this.flagpoleSprites = options.flagPoleSprites; + this.flagpoleSprites = options.flagPoleSprites; - this.LPipeSprites = options.LPipeSprites; - this.cloudSprites = options.cloudSprites; - this.hillSprites = options.hillSprites; - this.bushSprite = options.bushSprite; - this.bushSprites = options.bushSprites; - this.qblockSprite = options.qblockSprite; + this.LPipeSprites = options.LPipeSprites; + this.cloudSprites = options.cloudSprites; + this.hillSprites = options.hillSprites; + this.bushSprite = options.bushSprite; + this.bushSprites = options.bushSprites; + this.qblockSprite = options.qblockSprite; - this.invincibility = options.invincibility; - this.statics = []; - this.scenery = []; - this.blocks = []; - this.enemies = []; - this.items = []; - this.pipes = []; + this.invincibility = options.invincibility; + this.statics = []; + this.scenery = []; + this.blocks = []; + this.enemies = []; + this.items = []; + this.pipes = []; - for (var i = 0; i < 15; i++) { - this.statics[i] = []; - this.scenery[i] = []; - this.blocks[i] = []; - } - }); - - 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); - } - }; - - 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.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); - } - }; - - 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, - ); - } 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, - ); - } - } - }; - - //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.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.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, + for (var i = 0; i < 15; i++) { + this.statics[i] = []; + this.scenery[i] = []; + this.blocks[i] = []; + } }); - }; - Level.prototype.putBrick = function (x, y, item) { - this.blocks[y][x] = new Mario.Block({ - pos: [x * 16, y * 16], - item: item, - sprite: this.brickSprite, - bounceSprite: this.brickBounceSprite, - usedSprite: this.ublockSprite, - breakable: !item, - }); - }; + 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, + ); + } + }; - 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]); - }; + Level.prototype.putGoomba = function (x, y) { + this.enemies.push( + new Mario.Goomba([16 * x, 16 * y], this.goombaSprite()), + ); + }; - Level.prototype.putBush = function (x, y) { - this.scenery[y][x] = new Mario.Prop([x * 16, y * 16], this.bushSprite); - }; + Level.prototype.putKoopa = function (x, y) { + this.enemies.push( + new Mario.Koopa([16 * x, 16 * y], this.koopaSprite(), false), + ); + }; - 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]); - }; + 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, + ); + } + }; - 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]); - }; + 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, + ); + } 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, + ); + } + } + }; - 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]); - }; + //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.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], - ); - }; + Level.prototype.putCoin = function (x, y) { + this.items.push(new Mario.Coin([x * 16, y * 16], this.coinSprite())); + }; - 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], - ); - }; + Level.prototype.putCloud = function (x, y) { + this.scenery[y][x] = new Mario.Prop([x * 16, y * 16], this.cloudSprite); + }; - 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.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, + }); + }; - 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)); - }; + Level.prototype.putBrick = function (x, y, item) { + this.blocks[y][x] = new Mario.Block({ + pos: [x * 16, y * 16], + item: item, + sprite: this.brickSprite, + bounceSprite: this.brickBounceSprite, + usedSprite: this.ublockSprite, + breakable: !item, + }); + }; + + 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], + ); + }; + + 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; + 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], + ); + }; + + 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], + ); + }; + + 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], + ); + }; + + 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], + ); + }; + + 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], + ); + }; + + 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], + ); + } + this.scenery[2][x] = new Mario.Prop( + [16 * x, 32], + this.flagpoleSprites[0], + ); + this.items.push(new Mario.Flag(16 * x)); + }; })(); diff --git a/examples/mario/js/mushroom.js b/examples/mario/js/mushroom.js index 7b212081..9ef20004 100644 --- a/examples/mario/js/mushroom.js +++ b/examples/mario/js/mushroom.js @@ -1,129 +1,132 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + if (typeof Mario === "undefined") window.Mario = {}; - var Mushroom = (Mario.Mushroom = function (pos) { - this.spawning = false; - this.waiting = 0; + 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], + Mario.Entity.call(this, { + pos: pos, + sprite: level.superShroomSprite, + hitbox: [0, 0, 16, 16], + }); }); - }); - Mario.Util.inherits(Mushroom, Mario.Entity); + Mario.Util.inherits(Mushroom, Mario.Entity); - 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.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 () { - if (player.power > 0) { - //replace this with a fire flower - var ff = new Mario.Fireflower(this.pos); - ff.spawn(); - return; - } - sounds.itemAppear.play(); - 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; - }; - - Mushroom.prototype.update = function (dt) { - if (this.spawning > 1) { - this.spawning -= 1; - if (this.spawning == 1) this.vel[1] = -0.5; - return; - } - if (this.spawning) { - if (this.pos[1] <= this.targetpos[1]) { - this.pos[1] = this.targetpos[1]; - this.vel[1] = 0; - this.waiting = 5; - this.spawning = 0; - this.vel[0] = 1; - } - } else { - this.acc[1] = 0.2; - } - - if (this.waiting) { - this.waiting -= 1; - } else { - this.vel[1] += this.acc[1]; - this.pos[0] += this.vel[0]; - this.pos[1] += this.vel[1]; - this.sprite.update(dt); - } - }; - - Mushroom.prototype.collideWall = function () { - this.vel[0] = -this.vel[0]; - }; - - Mushroom.prototype.checkCollisions = function () { - if (this.spawning) { - return; - } - var h = this.pos[1] % 16 == 0 ? 1 : 2; - var w = this.pos[0] % 16 == 0 ? 1 : 2; - - var baseX = Math.floor(this.pos[0] / 16); - var baseY = Math.floor(this.pos[1] / 16); - - if (baseY + h > 15) { - delete level.items[this.idx]; - return; - } - - for (var i = 0; i < h; i++) { - for (var j = 0; j < w; j++) { - if (level.statics[baseY + i][baseX + j]) { - level.statics[baseY + i][baseX + j].isCollideWith(this); + Mushroom.prototype.spawn = function () { + if (player.power > 0) { + //replace this with a fire flower + var ff = new Mario.Fireflower(this.pos); + ff.spawn(); + return; } - if (level.blocks[baseY + i][baseX + j]) { - level.blocks[baseY + i][baseX + j].isCollideWith(this); + sounds.itemAppear.play(); + 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; + }; + + Mushroom.prototype.update = function (dt) { + if (this.spawning > 1) { + this.spawning -= 1; + if (this.spawning == 1) this.vel[1] = -0.5; + return; + } + if (this.spawning) { + if (this.pos[1] <= this.targetpos[1]) { + this.pos[1] = this.targetpos[1]; + this.vel[1] = 0; + this.waiting = 5; + this.spawning = 0; + this.vel[0] = 1; + } + } else { + this.acc[1] = 0.2; } - } - } - this.isPlayerCollided(); - }; + if (this.waiting) { + this.waiting -= 1; + } else { + this.vel[1] += this.acc[1]; + this.pos[0] += this.vel[0]; + this.pos[1] += this.vel[1]; + this.sprite.update(dt); + } + }; - //we have access to player everywhere, so let's just do this. - 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], - ]; + Mushroom.prototype.collideWall = function () { + this.vel[0] = -this.vel[0]; + }; - //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] - ) - ) { - player.powerUp(this.idx); - } - } - }; + Mushroom.prototype.checkCollisions = function () { + if (this.spawning) { + return; + } + var h = this.pos[1] % 16 == 0 ? 1 : 2; + var w = this.pos[0] % 16 == 0 ? 1 : 2; - Mushroom.prototype.bump = function () { - this.vel[1] = -2; - }; + var baseX = Math.floor(this.pos[0] / 16); + var baseY = Math.floor(this.pos[1] / 16); + + if (baseY + h > 15) { + delete level.items[this.idx]; + return; + } + + for (var i = 0; i < h; i++) { + for (var j = 0; j < w; j++) { + 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); + } + } + } + + this.isPlayerCollided(); + }; + + //we have access to player everywhere, so let's just do this. + 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], + ]; + + //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] + ) + ) { + player.powerUp(this.idx); + } + } + }; + + Mushroom.prototype.bump = function () { + this.vel[1] = -2; + }; })(); diff --git a/examples/mario/js/pipe.js b/examples/mario/js/pipe.js index c46a1992..eedb4aad 100644 --- a/examples/mario/js/pipe.js +++ b/examples/mario/js/pipe.js @@ -1,224 +1,228 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + 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; + //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; - //NOTE: direction is the direction you move INTO the pipe. - this.direction = options.direction; - this.destination = options.destination; - this.length = options.length; + //NOTE: direction is the direction you move INTO the pipe. + 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.midsection = level.pipeUpMid; - this.endsection = level.pipeTop; - } else { - this.hitbox = [0, 0, 16 * this.length, 32]; - this.midsection = level.pipeSideMid; - this.endsection = level.pipeLeft; - } - }; - - Pipe.prototype.checkPipe = function () { - if (this.destination === undefined || !input.isDown(this.direction)) return; - - 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); - } - 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); - } - 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); - } - 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); - } - 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 () { - var that = this; - level.enemies.forEach(function (ent) { - that.isCollideWith(ent); - }); - - level.items.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]), - ]; - - //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 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]) { - 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) { - ent.jumping = 0; - } + if (this.direction === "UP" || this.direction === "DOWN") { + this.hitbox = [0, 0, 32, this.length * 16]; + this.midsection = level.pipeUpMid; + this.endsection = level.pipeTop; } else { - //entity is hitting it from the side, we're a wall - ent.collideWall(this); + this.hitbox = [0, 0, 16 * this.length, 32]; + this.midsection = level.pipeSideMid; + this.endsection = level.pipeLeft; } - } - } - }; + }; - //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) { - if (this.destination) this.checkPipe(); - }; + Pipe.prototype.checkPipe = function () { + if (this.destination === undefined || !input.isDown(this.direction)) + return; - //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 + 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); + } + 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); + } + 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); + } + 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); + } + break; + } + }; - //TODO: edit the spritesheet so UP and LEFT pipes aren't backwards. - 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, - ); + //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 () { + var that = this; + level.enemies.forEach(function (ent) { + that.isCollideWith(ent); + }); + + level.items.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]), + ]; + + //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 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] + ) { + 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) { + ent.jumping = 0; + } + } else { + //entity is hitting it from the side, we're a wall + ent.collideWall(this); + } + } } - 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, - ); + }; + + //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) { + 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) { + 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, + ); + } + 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, + ); + } + break; + case "RIGHT": + 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, + ); + } + 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, + ); + } + break; } - break; - case "RIGHT": - 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, - ); - } - 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, - ); - } - break; - } - }; + }; })(); diff --git a/examples/mario/js/player.js b/examples/mario/js/player.js index e1969cb3..c8f66761 100644 --- a/examples/mario/js/player.js +++ b/examples/mario/js/player.js @@ -1,498 +1,505 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + 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 = []; - - 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); - - 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; + 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; - } else this.jumping -= 1; - } - }; + this.canJump = true; + this.invincibility = 0; + this.crouching = false; + this.fireballs = 0; + this.runheld = false; + this.noInput = false; + this.targetPos = []; - Player.prototype.setAnimation = function () { - if (this.dying) return; + Mario.Entity.call(this, { + pos: pos, + sprite: new Mario.Sprite( + "sprites/player.png", + [80, 32], + [16, 16], + 0, + ), + hitbox: [0, 0, 16, 16], + }); + }); - if (this.starTime) { - var index; - if (this.starTime > 60) index = Math.floor(this.starTime / 2) % 3; - else index = Math.floor(this.starTime / 8) % 3; + Mario.Util.inherits(Player, Mario.Entity); - 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; + Player.prototype.run = function () { + this.maxSpeed = 2.5; + if (this.power == 2 && !this.runheld) { + this.shoot(); } - } - } - //okay cool, now set the sprite - if (this.crouching) { - this.sprite.pos[0] = 176; - this.sprite.speed = 0; - return; - } + this.runheld = true; + }; - 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; + 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; } - } else { - this.sprite.pos[0] = 80; + }; + + 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.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); + }; + + 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); + } + } + } + }; + + 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. + } + }; + + 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(); + + this.acc[0] = 0; + this.sprite.pos = [176, 32]; this.sprite.speed = 0; - } - if (this.shooting) { - this.sprite.pos[0] += 160; - this.shooting -= 1; - } - } + this.power = 0; + this.waiting = 0.5; + this.dying = 2; - 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); - }; - - 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 (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 (level.statics[baseY + i][baseX + j]) { - level.statics[baseY + i][baseX + j].isCollideWith(this); + }; + + 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; } - 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.flag = function () { + this.noInput = true; + this.flagging = true; + this.vel = [0, 2]; + this.acc = [0, 0]; + }; - 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.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; - - 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.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.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; + }; })(); diff --git a/examples/mario/js/prop.js b/examples/mario/js/prop.js index f251ed42..ca3510e2 100644 --- a/examples/mario/js/prop.js +++ b/examples/mario/js/prop.js @@ -1,14 +1,14 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + 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) { - this.pos = pos; - this.sprite = sprite; - }); + //props do even less than entities, so they don't need to inherit really + 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) { - this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY); - }; + //but we will be using the same Render, more or less. + Prop.prototype.render = function (ctx, vX, vY) { + this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY); + }; })(); diff --git a/examples/mario/js/resources.js b/examples/mario/js/resources.js index 525ba2d0..43f76c52 100644 --- a/examples/mario/js/resources.js +++ b/examples/mario/js/resources.js @@ -1,61 +1,61 @@ //simple resource loader (function () { - var resourceCache = {}; - var loading = []; - var readyCallbacks = []; + 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); - } - } - - 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(); - }); + // 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); } - }; - resourceCache[url] = false; - img.src = url; } - } - function get(url) { - return resourceCache[url]; - } + function _load(url) { + if (resourceCache[url]) { + return resourceCache[url]; + } else { + var img = new Image(); + img.onload = function () { + resourceCache[url] = img; - function isReady() { - var ready = true; - for (var k in resourceCache) { - if (resourceCache.hasOwnProperty(k) && !resourceCache[k]) { - ready = false; - } + if (isReady()) { + readyCallbacks.forEach(function (func) { + func(); + }); + } + }; + resourceCache[url] = false; + img.src = url; + } } - return ready; - } - function onReady(func) { - readyCallbacks.push(func); - } + function get(url) { + return resourceCache[url]; + } - window.resources = { - load: load, - get: get, - onReady: onReady, - isReady: isReady, - }; + 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); + } + + window.resources = { + load: load, + get: get, + onReady: onReady, + isReady: isReady, + }; })(); diff --git a/examples/mario/js/rubble.js b/examples/mario/js/rubble.js index 873ab07a..41da9964 100644 --- a/examples/mario/js/rubble.js +++ b/examples/mario/js/rubble.js @@ -1,58 +1,64 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + 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 () { - this.sprites = []; - this.poss = []; - this.vels = []; - }); + //TODO: make each rubble an entity, use that render and write in Entity.update + var Rubble = (Mario.Rubble = function () { + this.sprites = []; + this.poss = []; + this.vels = []; + }); - Rubble.prototype.spawn = function (pos) { - this.idx = level.items.length; - level.items.push(this); - this.sprites[0] = level.rubbleSprite(); - this.sprites[1] = level.rubbleSprite(); - 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.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.spawn = function (pos) { + this.idx = level.items.length; + level.items.push(this); + this.sprites[0] = level.rubbleSprite(); + this.sprites[1] = level.rubbleSprite(); + 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.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] += 0.3; - this.poss[i][0] += this.vels[i][0]; - this.poss[i][1] += this.vels[i][1]; - this.sprites[i].update(dt); - if (this.poss[i][1] > 256) { - delete this.sprites[i]; - } - } - if ( - this.sprites.every(function (el) { - return !el; - }) - ) { - delete level.items[this.idx]; - } - }; + 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); + if (this.poss[i][1] > 256) { + delete this.sprites[i]; + } + } + 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 () {}; + //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.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); - } - }; + 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, + ); + } + }; })(); diff --git a/examples/mario/js/sprite.js b/examples/mario/js/sprite.js index 8b5cbdea..5d768b95 100644 --- a/examples/mario/js/sprite.js +++ b/examples/mario/js/sprite.js @@ -1,56 +1,63 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + if (typeof Mario === "undefined") window.Mario = {}; - var Sprite = (Mario.Sprite = function (img, pos, size, speed, frames, once) { - this.pos = pos; - this.size = size; - this.speed = speed; - this._index = 0; - this.img = img; - this.once = once; - this.frames = frames; - }); + var Sprite = (Mario.Sprite = function ( + img, + pos, + size, + speed, + frames, + once, + ) { + this.pos = pos; + this.size = size; + this.speed = speed; + this._index = 0; + this.img = img; + this.once = once; + this.frames = frames; + }); - Sprite.prototype.update = function (dt, gameTime) { - if (gameTime && gameTime == this.lastUpdated) return; - this._index += this.speed * dt; - if (gameTime) this.lastUpdated = gameTime; - }; + Sprite.prototype.update = function (dt, gameTime) { + if (gameTime && gameTime == this.lastUpdated) return; + this._index += this.speed * dt; + if (gameTime) this.lastUpdated = gameTime; + }; - Sprite.prototype.setFrame = function (frame) { - this._index = frame; - }; + Sprite.prototype.setFrame = function (frame) { + this._index = frame; + }; - Sprite.prototype.render = function (ctx, posx, posy, vX, vY) { - var frame; + Sprite.prototype.render = function (ctx, posx, posy, vX, vY) { + var frame; - if (this.speed > 0) { - var max = this.frames.length; - var idx = Math.floor(this._index); - frame = this.frames[idx % max]; + if (this.speed > 0) { + var max = this.frames.length; + var idx = Math.floor(this._index); + frame = this.frames[idx % max]; - if (this.once && idx >= max) { - this.done = true; - return; - } - } else { - frame = 0; - } + if (this.once && idx >= max) { + this.done = true; + return; + } + } else { + frame = 0; + } - var x = this.pos[0]; - var y = this.pos[1]; + 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], + ); + }; })(); diff --git a/examples/mario/js/star.js b/examples/mario/js/star.js index 6359d4af..2a678e8a 100644 --- a/examples/mario/js/star.js +++ b/examples/mario/js/star.js @@ -1,127 +1,130 @@ (function () { - if (typeof Mario === "undefined") window.Mario = {}; + if (typeof Mario === "undefined") window.Mario = {}; - var Star = (Mario.Star = function (pos) { - this.spawning = false; - this.waiting = 0; + 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], + Mario.Entity.call(this, { + pos: pos, + sprite: level.starSprite, + hitbox: [0, 0, 16, 16], + }); }); - }); - Mario.Util.inherits(Star, Mario.Entity); + Mario.Util.inherits(Star, Mario.Entity); - 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.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 () { - 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.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) { - if (this.spawning > 1) { - this.spawning -= 1; - if (this.spawning == 1) this.vel[1] = -0.5; - return; - } - if (this.spawning) { - if (this.pos[1] <= this.targetpos[1]) { - this.pos[1] = this.targetpos[1]; - this.vel[1] = 0; - this.waiting = 5; - this.spawning = 0; - this.vel[0] = 1; - } - } else { - this.acc[1] = 0.2; - } - - if (this.standing) { - this.standing = false; - this.vel[1] = -3; - } - - if (this.waiting) { - this.waiting -= 1; - } else { - this.vel[1] += this.acc[1]; - this.pos[0] += this.vel[0]; - this.pos[1] += this.vel[1]; - this.sprite.update(dt); - } - }; - - Star.prototype.collideWall = function () { - this.vel[0] = -this.vel[0]; - }; - - Star.prototype.checkCollisions = function () { - if (this.spawning) { - return; - } - var h = this.pos[1] % 16 == 0 ? 1 : 2; - var w = this.pos[0] % 16 == 0 ? 1 : 2; - - var baseX = Math.floor(this.pos[0] / 16); - var baseY = Math.floor(this.pos[1] / 16); - - if (baseY + h > 15) { - delete level.items[this.idx]; - return; - } - - for (var i = 0; i < h; i++) { - for (var j = 0; j < w; j++) { - if (level.statics[baseY + i][baseX + j]) { - level.statics[baseY + i][baseX + j].isCollideWith(this); + Star.prototype.update = function (dt) { + if (this.spawning > 1) { + this.spawning -= 1; + if (this.spawning == 1) this.vel[1] = -0.5; + return; } - if (level.blocks[baseY + i][baseX + j]) { - level.blocks[baseY + i][baseX + j].isCollideWith(this); + if (this.spawning) { + if (this.pos[1] <= this.targetpos[1]) { + this.pos[1] = this.targetpos[1]; + this.vel[1] = 0; + this.waiting = 5; + this.spawning = 0; + this.vel[0] = 1; + } + } else { + this.acc[1] = 0.2; } - } - } - this.isPlayerCollided(); - }; + if (this.standing) { + this.standing = false; + this.vel[1] = -3; + } - //we have access to player everywhere, so let's just do this. - 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], - ]; + if (this.waiting) { + this.waiting -= 1; + } else { + this.vel[1] += this.acc[1]; + this.pos[0] += this.vel[0]; + this.pos[1] += this.vel[1]; + this.sprite.update(dt); + } + }; - //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] - ) - ) { - player.star(this.idx); - } - } - }; + Star.prototype.collideWall = function () { + this.vel[0] = -this.vel[0]; + }; - Star.prototype.bump = function () { - this.vel[1] = -2; - }; + Star.prototype.checkCollisions = function () { + if (this.spawning) { + return; + } + var h = this.pos[1] % 16 == 0 ? 1 : 2; + var w = this.pos[0] % 16 == 0 ? 1 : 2; + + var baseX = Math.floor(this.pos[0] / 16); + var baseY = Math.floor(this.pos[1] / 16); + + if (baseY + h > 15) { + delete level.items[this.idx]; + return; + } + + for (var i = 0; i < h; i++) { + for (var j = 0; j < w; j++) { + 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); + } + } + } + + this.isPlayerCollided(); + }; + + //we have access to player everywhere, so let's just do this. + 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], + ]; + + //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] + ) + ) { + player.star(this.idx); + } + } + }; + + Star.prototype.bump = function () { + this.vel[1] = -2; + }; })(); diff --git a/examples/mario/js/util.js b/examples/mario/js/util.js index 95a11f7f..efcc03f5 100644 --- a/examples/mario/js/util.js +++ b/examples/mario/js/util.js @@ -1,14 +1,14 @@ (function () { - if (typeof Mario === "undefined") { - window.Mario = {}; - } + 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(); + }; })(); diff --git a/examples/markdown-plugin.html b/examples/markdown-plugin.html index 97e96199..e3a0a278 100644 --- a/examples/markdown-plugin.html +++ b/examples/markdown-plugin.html @@ -1,30 +1,30 @@ - - + + - PyMarkdown + PyMarkdown - - + + - - - + + + - - - - packages = [ - "markdown" - ] - plugins = [ - "../build/plugins/python/py_markdown.py", - "../build/plugins/python/py_tutor.py" - ] - + + + + packages = [ + "markdown" + ] + plugins = [ + "../build/plugins/python/py_markdown.py", + "../build/plugins/python/py_tutor.py" + ] + - #Hello world! - - + #Hello world! + + diff --git a/examples/matplotlib.html b/examples/matplotlib.html index 849cc829..ed87e154 100644 --- a/examples/matplotlib.html +++ b/examples/matplotlib.html @@ -1,70 +1,73 @@ - - Matplotlib - - - - - - - - -
-
+ + Matplotlib + + + + + + + + +
+
- - - packages = [ - "matplotlib" - ] - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - + + + packages = [ + "matplotlib" + ] + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + - - 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") + + +
+ diff --git a/examples/message_passing.html b/examples/message_passing.html index 2000d232..f5dda57e 100644 --- a/examples/message_passing.html +++ b/examples/message_passing.html @@ -1,35 +1,38 @@ - - - - + + + + - - + + - - - - packages = [ - "numpy", - "networkx", - "matplotlib" - ] - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - + + + + packages = [ + "numpy", + "networkx", + "matplotlib" + ] + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + - - import numpy as np - import networkx as nx - + + import numpy as np + import networkx as nx + -

Message passing with linear algebra: a demo.

-

Imagine we have a chain graph that looks like this:

-
O --> 1 --> 2 --> 3
-

In NetworkX this graph would look like the following:

-
+            

Message passing with linear algebra: a demo.

+

Imagine we have a chain graph that looks like this:

+
O --> 1 --> 2 --> 3
+

In NetworkX this graph would look like the following:

+
         
 G = nx.Graph()
 nodes = list(range(4))
@@ -37,29 +40,30 @@ G.add_edges_from(zip(nodes[0:-1], nodes[1:]))
 print(G.edges())
         
     
-

This chain graph has the following adjacency matrix:

-
+            

This chain graph has the following adjacency matrix:

+
         
 adj_mat = np.eye(4, k=1)
 print(f"A: {adj_mat}")
         
     
-

And imagine that we have a message that lives on the graph:

-
+            

And imagine that we have a message that lives on the graph:

+
         
 message = np.array([1.0, 0.0, 0.0, 0.0])
 print(f"message: {message}")
         
     
-

- Try out message passing below by doing any one of the following steps: -

-
message @ adj_mat
-
message @ adj_mat @ adj_mat
-
message @ adj_mat @ adj_mat @ adj_mat
-
- -
- - +

+ Try out message passing below by doing any one of the following + steps: +

+
message @ adj_mat
+
message @ adj_mat @ adj_mat
+
message @ adj_mat @ adj_mat @ adj_mat
+
+ +
+ + diff --git a/examples/micrograd_ai.html b/examples/micrograd_ai.html index 9f003dfb..8a09170c 100644 --- a/examples/micrograd_ai.html +++ b/examples/micrograd_ai.html @@ -1,186 +1,196 @@ - - - + + + - micrograd + micrograd - - + + - - + + - -

Micrograd - A tiny Autograd engine (with a bite! :))

-
+ +

Micrograd - A tiny Autograd engine (with a bite! :))

+
- - packages = [ - "micrograd", - "numpy", - "matplotlib" - ] - + + packages = [ + "micrograd", + "numpy", + "matplotlib" + ] + -
-

- Micrograd is a tiny - Autograd engine created by - Andrej Karpathy. This app - recreates the - demo - he prepared for this package using pyscript to train a basic model, - written in Python, natively in the browser.
-

-
-
-

- 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.
-

-

- Currently the > symbol is being imported incorrectly as - &gt; into the REPL's. In this app the - > symbol has been replaced with - ().__gt__() so you can run the code without issue. Ex: - instead of a > b, you will see - (a).__gt__(b) instead.
-

- - import js; js.document.getElementById('python-status').innerHTML = 'Python is now ready. You may proceed.' - -
Python is currently starting. Please wait...
-
- -
-
-
-
-
-
- - import random import numpy as np import matplotlib.pyplot as plt
- - from micrograd.engine import Value from micrograd.nn import Neuron, Layer, - MLP
- - np.random.seed(1337) random.seed(1337)
- - #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)
- - 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
- - model = MLP(2, [16, 16, 1]) # 2-layer neural network print(model) - print("number of parameters", len(model.parameters()))
+
+

+ Micrograd is + a tiny Autograd engine created by + Andrej Karpathy. This + app recreates the + demo + he prepared for this package using pyscript to train a basic + model, written in Python, natively in the browser.
+

+
+
+

+ 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. +
+

+

+ Currently the > symbol is being imported + incorrectly as &gt; into the REPL's. In this + app the > symbol has been replaced with + ().__gt__() so you can run the code without issue. + Ex: instead of a > b, you will see + (a).__gt__(b) instead.
+

+ + import js; js.document.getElementById('python-status').innerHTML = 'Python is now ready. You may proceed.' + +
+ Python is currently starting. Please wait... +
+
+ +
+
+
+
+
+
+ + import random import numpy as np import matplotlib.pyplot as plt
+ + from micrograd.engine import Value from micrograd.nn import Neuron, + Layer, MLP
+ + np.random.seed(1337) random.seed(1337)
+ + #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)
+ + 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
+ + model = MLP(2, [16, 16, 1]) # 2-layer neural network print(model) + print("number of parameters", len(model.parameters()))
-
- Line 24 has been changed from:
- accuracy = [(yi > 0) == (scorei.data > 0) for yi, scorei in - zip(yb, scores)]
- to:
- accuracy = [((yi).__gt__(0)) == ((scorei.data).__gt__(0)) for yi, - scorei in zip(yb, scores)]
-
+
+ Line 24 has been changed from:
+ accuracy = [(yi > 0) == (scorei.data > 0) for yi, scorei + in zip(yb, scores)]
+ to:
+ accuracy = [((yi).__gt__(0)) == ((scorei.data).__gt__(0)) for + yi, scorei in zip(yb, scores)]
+
- - # 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)
- - # 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}%")
-
-

- 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.

+ + # 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)
+ + # 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}%")
+

+

+ 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.

- Line 9 has been changed from:
- Z = np.array([s.data > 0 for s in scores])
- to:
- Z = np.array([(s.data).__gt__(0) for s in scores])
-

-
- - 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
- 1+1
- + Line 9 has been changed from:
+ Z = np.array([s.data > 0 for s in scores])
+ to:
+ Z = np.array([(s.data).__gt__(0) for s in scores])
+

+
+ + 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
+ 1+1
+ diff --git a/examples/numpy_canvas_fractals.html b/examples/numpy_canvas_fractals.html index 3d395ad0..b6ccc115 100644 --- a/examples/numpy_canvas_fractals.html +++ b/examples/numpy_canvas_fractals.html @@ -1,385 +1,411 @@ - - - Visualization of Mandelbrot, Julia and Newton sets with NumPy and HTML5 - canvas - - - - - - - - - - -
-
-
-
Mandelbrot set
-
-
- -
-
-
-
Julia set
-
-
- -
-
-
-
Newton set
-
-
- p(z) = + @keyframes spin { + to { + transform: rotate(360deg); + } + } + + + + +
+
+
+
Mandelbrot set
+
+
+ +
+
+
+
Julia set
+
+
+ +
+
+
+
Newton set
+
+
+ p(z) = +
+
+ a = +
+
+ x = [ + + , + + ] +
+
+ y = [ + + , + + ] +
+
+
+ + convergence +
+
+ + iterations +
+
+
+
+
+ +
+
-
- x = [ - - , - - ] -
-
- y = [ - - , - - ] -
-
-
- - convergence -
-
- - iterations -
-
-
-
-
- -
-
-
- - - { - "packages": [ - "numpy", - "sympy" - ], - "fetch": [ - { - "files": [ - "./palettes.py", - "./fractals.py" - ] - } - ], - "plugins": [ - "../build/plugins/python/py_tutor.py" - ] - } - + + + { + "packages": [ + "numpy", + "sympy" + ], + "fetch": [ + { + "files": [ + "./palettes.py", + "./fractals.py" + ] + } + ], + "plugins": [ + "../build/plugins/python/py_tutor.py" + ] + } + - - 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()) + + + + diff --git a/examples/pandas.html b/examples/pandas.html index 3a40462d..8e640ba9 100644 --- a/examples/pandas.html +++ b/examples/pandas.html @@ -1,124 +1,132 @@ - - - - - - - + + + + + + + - - + + - - + + -
-
+
+
-
-

Data Source

- - -
+
+

Data Source

+ + +
- + - + - + - - - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - packages = ["pandas"] - + + + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + packages = ["pandas"] + -
- - import pandas as pd - from pyodide.http import open_url - import sys +
+ + import pandas as pd + from pyodide.http import open_url + import sys - 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" + 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" - url = "https://raw.githubusercontent.com/datasets/airport-codes/master/data/airport-codes.csv" + url = "https://raw.githubusercontent.com/datasets/airport-codes/master/data/airport-codes.csv" - Element("header-title").element.innerText = title - Element("page-title").element.innerText = title - Element("page-message").element.innerText = page_message + Element("header-title").element.innerText = title + Element("page-title").element.innerText = title + Element("page-message").element.innerText = page_message - Element("txt-url").element.value = url + 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" + # 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) - -
- - + # log to JS console + js.console.log (message) +
+
+
+ diff --git a/examples/panel.html b/examples/panel.html index 5b45973e..4e2b2e6a 100644 --- a/examples/panel.html +++ b/examples/panel.html @@ -1,63 +1,68 @@ - - Panel Example - - - - - - - - - - - - -
-
+ + Panel Example + + + + + + + + + + + + +
+
- - - packages = [ - "https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl", - "numpy", - "panel==0.14.1" - ] - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - + + + packages = [ + "https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl", + "numpy", + "panel==0.14.1" + ] + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + - - import panel as pn + + import panel as pn - slider = pn.widgets.FloatSlider(start=0, end=10, name='Amplitude') + slider = pn.widgets.FloatSlider(start=0, end=10, name='Amplitude') - def callback(new): - return f'Amplitude is: {new}' + def callback(new): + return f'Amplitude is: {new}' - pn.Row(slider, pn.bind(callback, slider)).servable(target='simple_app'); - - -
- + pn.Row(slider, pn.bind(callback, slider)).servable(target='simple_app'); + + +
+ diff --git a/examples/panel_deckgl.html b/examples/panel_deckgl.html index 26a3d8d0..d3008ce8 100644 --- a/examples/panel_deckgl.html +++ b/examples/panel_deckgl.html @@ -1,281 +1,284 @@ - - - - - - + + + + + + - PyScript/Panel DeckGL Demo - + PyScript/Panel DeckGL Demo + - - - + + + - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - - - - - - + + + + + + + - - -
-
- -
-
-
-
+ + +
+
+ +
+
+
+
- - - packages = [ - "https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl", - "numpy", - "pandas", - "panel==0.13.1" - ] - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - + + + packages = [ + "https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl", + "numpy", + "pandas", + "panel==0.13.1" + ] + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + - - 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'); + + +
+ diff --git a/examples/panel_kmeans.html b/examples/panel_kmeans.html index ec287beb..f853fb04 100644 --- a/examples/panel_kmeans.html +++ b/examples/panel_kmeans.html @@ -1,226 +1,229 @@ - - - - - - + + + + + + - Pyscript/Panel KMeans Demo - + Pyscript/Panel KMeans Demo + - - - + + + - - - - - - - - - + + + + + + + + + - - - + + + - + - - + + - - - - + + + + - - -
-
- -
-
-
-
-
-
- - - packages = [ - "https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl", - "altair", - "numpy", - "pandas", - "scikit-learn", - "panel==0.13.1" - ] - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - + + +
+
+ +
+
+
+
+
+
+ + + packages = [ + "https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl", + "altair", + "numpy", + "pandas", + "scikit-learn", + "panel==0.13.1" + ] + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + - - import altair as alt - import panel as pn - import pandas as pd + + import altair as alt + import panel as pn + import pandas as pd - from sklearn.cluster import KMeans - from pyodide.http import open_url + from sklearn.cluster import KMeans + from pyodide.http import open_url - pn.config.sizing_mode = 'stretch_width' + pn.config.sizing_mode = 'stretch_width' - url = 'https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-07-28/penguins.csv' - penguins = pd.read_csv(open_url(url)).dropna() - cols = list(penguins.columns)[2:6] + url = 'https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-07-28/penguins.csv' + penguins = pd.read_csv(open_url(url)).dropna() + cols = list(penguins.columns)[2:6] - x = pn.widgets.Select(name='x', options=cols, value='bill_depth_mm').servable(target='x-widget') - y = pn.widgets.Select(name='y', options=cols, value='bill_length_mm').servable(target='y-widget') - n_clusters = pn.widgets.IntSlider(name='n_clusters', start=1, end=5, value=3).servable(target='n-widget') + x = pn.widgets.Select(name='x', options=cols, value='bill_depth_mm').servable(target='x-widget') + y = pn.widgets.Select(name='y', options=cols, value='bill_length_mm').servable(target='y-widget') + n_clusters = pn.widgets.IntSlider(name='n_clusters', start=1, end=5, value=3).servable(target='n-widget') - brush = alt.selection_interval(name='brush') # selection of type "interval" + brush = alt.selection_interval(name='brush') # selection of type "interval" - def get_clusters(n_clusters): - kmeans = KMeans(n_clusters=n_clusters) - est = kmeans.fit(penguins[cols].values) - df = penguins.copy() - df['labels'] = est.labels_.astype('str') - return df + def get_clusters(n_clusters): + kmeans = KMeans(n_clusters=n_clusters) + est = kmeans.fit(penguins[cols].values) + df = penguins.copy() + df['labels'] = est.labels_.astype('str') + return df - def get_chart(x, y, df): - centers = df.groupby('labels').mean() - return ( - alt.Chart(df) - .mark_point(size=100) - .encode( - x=alt.X(x, scale=alt.Scale(zero=False)), - y=alt.Y(y, scale=alt.Scale(zero=False)), - shape='labels', - color='species' - ).add_selection(brush).properties(width=800) + - alt.Chart(centers) - .mark_point(size=250, shape='cross', color='black') - .encode(x=x+':Q', y=y+':Q') - ) + def get_chart(x, y, df): + centers = df.groupby('labels').mean() + return ( + alt.Chart(df) + .mark_point(size=100) + .encode( + x=alt.X(x, scale=alt.Scale(zero=False)), + y=alt.Y(y, scale=alt.Scale(zero=False)), + shape='labels', + color='species' + ).add_selection(brush).properties(width=800) + + alt.Chart(centers) + .mark_point(size=250, shape='cross', color='black') + .encode(x=x+':Q', y=y+':Q') + ) - intro = pn.pane.Markdown(""" - This app provides an example of **building a simple dashboard using - Panel**.\n\nIt demonstrates how to take the output of **k-means - clustering on the Penguins dataset** using scikit-learn, - parameterizing the number of clusters and the variables to - plot.\n\nThe plot and the table are linked, i.e. selecting on the plot - will filter the data in the table.\n\n The **`x` marks the center** of - the cluster. - """).servable(target='intro') + intro = pn.pane.Markdown(""" + This app provides an example of **building a simple dashboard using + Panel**.\n\nIt demonstrates how to take the output of **k-means + clustering on the Penguins dataset** using scikit-learn, + parameterizing the number of clusters and the variables to + plot.\n\nThe plot and the table are linked, i.e. selecting on the plot + will filter the data in the table.\n\n The **`x` marks the center** of + the cluster. + """).servable(target='intro') - chart = pn.pane.Vega().servable(target='cluster-plot') - table = pn.widgets.Tabulator(pagination='remote', page_size=10).servable(target='table') + chart = pn.pane.Vega().servable(target='cluster-plot') + table = pn.widgets.Tabulator(pagination='remote', page_size=10).servable(target='table') - def update_table(event=None): - table.value = get_clusters(n_clusters.value) + def update_table(event=None): + table.value = get_clusters(n_clusters.value) - n_clusters.param.watch(update_table, 'value') + n_clusters.param.watch(update_table, 'value') - @pn.depends(x, y, n_clusters, watch=True) - def update_chart(*events): - chart.object = get_chart(x.value, y.value, table.value) - chart.selection.param.watch(update_filters, 'brush') + @pn.depends(x, y, n_clusters, watch=True) + def update_chart(*events): + chart.object = get_chart(x.value, y.value, table.value) + chart.selection.param.watch(update_filters, 'brush') - def update_filters(event=None): - filters = [] - for k, v in (getattr(event, 'new') or {}).items(): - filters.append(dict(field=k, type='>=', value=v[0])) - filters.append(dict(field=k, type='<=', value=v[1])) - table.filters = filters + def update_filters(event=None): + filters = [] + for k, v in (getattr(event, 'new') or {}).items(): + filters.append(dict(field=k, type='>=', value=v[0])) + filters.append(dict(field=k, type='<=', value=v[1])) + table.filters = filters - update_table() - update_chart() - - -
- - + update_table() + update_chart() + +
+
+ + diff --git a/examples/panel_stream.html b/examples/panel_stream.html index 3b0a24f6..7e4475b4 100644 --- a/examples/panel_stream.html +++ b/examples/panel_stream.html @@ -1,157 +1,162 @@ - - - - - - + + + + + + - PyScript/Panel Streaming Demo - + PyScript/Panel Streaming Demo + - - - + + + - - - - - - + + + + + + - - - + + + - - + + - - - - + + + + - - -
-
-
-
-
-
-
-
-
-
+ + +
+
+
+
+
+
+
+
+
+
- - - packages = [ - "https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl", - "numpy", - "pandas", - "panel==0.13.1" - ] - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - + + + packages = [ + "https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl", + "numpy", + "pandas", + "panel==0.13.1" + ] + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + - - import panel as pn - import numpy as np - import pandas as pd + + import panel as pn + import numpy as np + import pandas as pd - from bokeh.models import ColumnDataSource - from bokeh.plotting import figure + from bokeh.models import ColumnDataSource + from bokeh.plotting import figure - df = pd.DataFrame(np.random.randn(10, 4), columns=list('ABCD')).cumsum() + df = pd.DataFrame(np.random.randn(10, 4), columns=list('ABCD')).cumsum() - rollover = pn.widgets.IntInput(name='Rollover', value=15) - follow = pn.widgets.Checkbox(name='Follow', value=True, align='end') + rollover = pn.widgets.IntInput(name='Rollover', value=15) + follow = pn.widgets.Checkbox(name='Follow', value=True, align='end') - tabulator = pn.widgets.Tabulator(df, height=450, width=400).servable(target='table') + tabulator = pn.widgets.Tabulator(df, height=450, width=400).servable(target='table') - def color_negative_red(val): - """ - Takes a scalar and returns a string with - the css property `'color: red'` for negative - strings, black otherwise. - """ - color = 'red' if val < 0 else 'green' - return 'color: %s' % color + def color_negative_red(val): + """ + Takes a scalar and returns a string with + the css property `'color: red'` for negative + strings, black otherwise. + """ + color = 'red' if val < 0 else 'green' + return 'color: %s' % color - tabulator.style.applymap(color_negative_red) + tabulator.style.applymap(color_negative_red) - p = figure(height=450, width=600) + p = figure(height=450, width=600) - cds = ColumnDataSource(data=ColumnDataSource.from_df(df)) + cds = ColumnDataSource(data=ColumnDataSource.from_df(df)) - p.line('index', 'A', source=cds, line_color='red') - p.line('index', 'B', source=cds, line_color='green') - p.line('index', 'C', source=cds, line_color='blue') - p.line('index', 'D', source=cds, line_color='purple') + p.line('index', 'A', source=cds, line_color='red') + p.line('index', 'B', source=cds, line_color='green') + p.line('index', 'C', source=cds, line_color='blue') + p.line('index', 'D', source=cds, line_color='purple') - def stream(): - data = df.iloc[-1] + np.random.randn(4) - tabulator.stream(data, rollover=rollover.value, follow=follow.value) - value = {k: [v] for k, v in tabulator.value.iloc[-1].to_dict().items()} - value['index'] = [tabulator.value.index[-1]] - cds.stream(value) + def stream(): + data = df.iloc[-1] + np.random.randn(4) + tabulator.stream(data, rollover=rollover.value, follow=follow.value) + value = {k: [v] for k, v in tabulator.value.iloc[-1].to_dict().items()} + value['index'] = [tabulator.value.index[-1]] + cds.stream(value) - cb = pn.state.add_periodic_callback(stream, 200) + cb = pn.state.add_periodic_callback(stream, 200) - pn.pane.Bokeh(p).servable(target='plot') - pn.Row(cb.param.period, rollover, follow, width=400).servable(target='controls') - - -
- + pn.pane.Bokeh(p).servable(target='plot') + pn.Row(cb.param.period, rollover, follow, width=400).servable(target='controls') + + +
+ diff --git a/examples/repl.css b/examples/repl.css index 52555218..18c6c7d3 100644 --- a/examples/repl.css +++ b/examples/repl.css @@ -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; + border-top: 1px solid lightgray; } #output > div:nth-child(even) { - border: 0; + border: 0; } diff --git a/examples/repl.html b/examples/repl.html index 6e39fbaa..2163c2e0 100644 --- a/examples/repl.html +++ b/examples/repl.html @@ -1,42 +1,47 @@ - - - + + + - REPL + REPL - - - - - + + + + + - - -
-

PyScript REPL

- Tip: press Shift-ENTER to evaluate a cell -
- - - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - [[fetch]] - files = ["./antigravity.py"] - -
- -
-
-
- + + +
+

PyScript REPL

+ Tip: press Shift-ENTER to evaluate a cell +
+ + + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + [[fetch]] + files = ["./antigravity.py"] + +
+ +
+
+
+ diff --git a/examples/repl2.html b/examples/repl2.html index 7d591b02..ce5289b7 100644 --- a/examples/repl2.html +++ b/examples/repl2.html @@ -1,47 +1,50 @@ - - - + + + - Custom REPL Example + Custom REPL Example - - - - - - + + + + + + - - -
-

Custom REPL

- - - packages = [ - "bokeh", - "numpy" - ] - plugins = [ - "../build/plugins/python/py_tutor.py" - ] + + +
+

Custom REPL

+ + + packages = [ + "bokeh", + "numpy" + ] + plugins = [ + "../build/plugins/python/py_tutor.py" + ] - [[fetch]] - files = ["./utils.py", "./antigravity.py"] - -
- -
-
-
-
- + [[fetch]] + files = ["./utils.py", "./antigravity.py"] +
+
+ +
+
+
+
+ diff --git a/examples/simple_bioinformatics_tool.html b/examples/simple_bioinformatics_tool.html index 93417f0c..eb6b5e9c 100644 --- a/examples/simple_bioinformatics_tool.html +++ b/examples/simple_bioinformatics_tool.html @@ -1,172 +1,179 @@ - - - - PyScript — Simple Bioinformatics Example - - - - - - - - -
-
-

- PyScript — Simple Bioinformatics Example - v.1 -

-

- Demonstrates the simple use of - PyScript - in Bioinformatics/Computational Biology fields! -

-
-
+ + + + PyScript — Simple Bioinformatics Example + + + + + + + + +
+
+

+ PyScript — Simple Bioinformatics Example + v.1 +

+

+ Demonstrates the simple use of + PyScript + in + Bioinformatics/Computational Biology + fields! +

+
+
- -
-

🧬 DNA Sequence Tool

+ +
+

🧬 DNA Sequence Tool

- -
- -
- + +
+ +
+ +
+
+ + + +
+
+
+ +
+
+
+ + +
+
+ +
+ + + +
-
- - -
-
-
- -
-
-
- - -
-
+

+ + -
+ + # 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") - - -
-
+ # 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] -

- - + # Check DNA seq is valid + def check_dna_seq(dna_seq): + return all(letter in dna_alphabet for letter in dna_seq.upper()) - - # 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") + # Clear the form and output + def clear(*args, **kwargs): + dna_seq_element.clear() + output.clear() - # 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] + # 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) - # Check DNA seq is valid - def check_dna_seq(dna_seq): - return all(letter in dna_alphabet for letter in dna_seq.upper()) + # 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) - # Clear the form and output - def clear(*args, **kwargs): - dna_seq_element.clear() - output.clear() - - # 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) - - # 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) - - # 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") - - + # 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") + + diff --git a/examples/simple_clock.html b/examples/simple_clock.html index 7bd01e92..bb56ac7b 100644 --- a/examples/simple_clock.html +++ b/examples/simple_clock.html @@ -1,64 +1,69 @@ - - - + + + - Simple Clock Demo + Simple Clock Demo - - + + - - - + + + - - -
-
start time:
-
-
+ + +
+
+ start time: +
+
+
- - - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - [[fetch]] - files = ["./utils.py"] - - - import utils - display(utils.now()) - + + + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + [[fetch]] + files = ["./utils.py"] + + + import utils + display(utils.now()) + - - 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()) + + +
+ diff --git a/examples/todo-pylist.html b/examples/todo-pylist.html index 23d12583..b8a2744e 100644 --- a/examples/todo-pylist.html +++ b/examples/todo-pylist.html @@ -1,84 +1,91 @@ - - + + - Todo App + Todo App - - + + - - - + + + - - -
-

To Do List

- - + + +
+

To Do List

+ + - - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - [[fetch]] - files = ["./utils.py", "./pylist.py"] - + + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + [[fetch]] + files = ["./utils.py", "./pylist.py"] + - - from js import document - from pyodide.ffi.wrappers import add_event_listener + + from js import document + from pyodide.ffi.wrappers import add_event_listener - def add_task(*ags, **kws): - # create a new dictionary representing the new task - new_task_content = Element("new-task-content") - task = { "content": new_task_content.value, "done": False, "created_at": dt.now() } + def add_task(*ags, **kws): + # create a new dictionary representing the new task + new_task_content = Element("new-task-content") + task = { "content": new_task_content.value, "done": False, "created_at": dt.now() } - # add a new task to the list and tell it to use the `content` key to show in the UI - # and to use the key `done` to sync the task status with a checkbox element in the UI - myList.add(task) + # add a new task to the list and tell it to use the `content` key to show in the UI + # and to use the key `done` to sync the task status with a checkbox element in the UI + myList.add(task) - # clear the inputbox element used to create the new task - new_task_content.clear() + # clear the inputbox element used to create the new task + new_task_content.clear() - def on_click(evt): - add_task() + def on_click(evt): + add_task() - def handle_keypress(evt): - if evt.key == "Enter": - add_task() + def handle_keypress(evt): + if evt.key == "Enter": + add_task() - add_event_listener( - document.getElementById("new-task-content"), - "keypress", - handle_keypress - ) - -
- - -
+ add_event_listener( + document.getElementById("new-task-content"), + "keypress", + handle_keypress + ) +
+
+ + +
- - -
-
- + + +
+
+ diff --git a/examples/todo.html b/examples/todo.html index d2569c3a..765d6744 100644 --- a/examples/todo.html +++ b/examples/todo.html @@ -1,76 +1,83 @@ - - - + + + - Todo App + Todo App - - + + - - - + + + - - -
- - - plugins = [ - "../build/plugins/python/py_tutor.py" - ] - [[fetch]] - files = ["./utils.py", "./todo.py"] - + + +
+ + + plugins = [ + "../build/plugins/python/py_tutor.py" + ] + [[fetch]] + files = ["./utils.py", "./todo.py"] + - - -
-
-
-

- To Do List -

-
-
- - -
+ + +
+
+
+

+ To Do List +

+
+
+ + +
- -
+ +
- + +
+
-
-
- + diff --git a/examples/toga/README.md b/examples/toga/README.md index 038c8647..23c1145b 100644 --- a/examples/toga/README.md +++ b/examples/toga/README.md @@ -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 diff --git a/examples/toga/freedom.html b/examples/toga/freedom.html index 9eaaab49..6d61a1c4 100644 --- a/examples/toga/freedom.html +++ b/examples/toga/freedom.html @@ -1,59 +1,62 @@ - - - - Freedom Units + + + + Freedom Units - + - - + + - + - - - -
+ + + +
- - + + - - 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", - ] + + 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 - - - import runpy - result = runpy.run_module("freedom", run_name="__main__", alter_sys=True) - - + [splashscreen] + autoclose = true + + + import runpy + result = runpy.run_module("freedom", run_name="__main__", alter_sys=True) + + diff --git a/examples/toga/static/css/briefcase.css b/examples/toga/static/css/briefcase.css index 5c6652ff..b6f87c85 100644 --- a/examples/toga/static/css/briefcase.css +++ b/examples/toga/static/css/briefcase.css @@ -1,13 +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; } /******************************************************************* @@ -21,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; } diff --git a/examples/webgl/raycaster/index.html b/examples/webgl/raycaster/index.html index 8e6b4e30..a98f8a3f 100644 --- a/examples/webgl/raycaster/index.html +++ b/examples/webgl/raycaster/index.html @@ -1,192 +1,195 @@ - - - Raycaster - - - - - -
-
-
-
-
-
-
+ + + Raycaster + + + + + +
+
+
+
+
+
+
+
+
+
-
-
-
- + - - - - 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 + + + + 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()) - - + asyncio.ensure_future(main()) + + diff --git a/examples/webgl/raycaster/style.css b/examples/webgl/raycaster/style.css index afcd608b..d70645cf 100644 --- a/examples/webgl/raycaster/style.css +++ b/examples/webgl/raycaster/style.css @@ -1,55 +1,55 @@ body { - margin: 0; - text-align: center; - background-color: black; - cursor: crosshair; + margin: 0; + text-align: center; + background-color: black; + cursor: crosshair; } canvas { - display: block; - width: 100%; - height: 100%; + display: block; + width: 100%; + height: 100%; } .header { - /*top:45%;*/ - top: 45%; - color: #dddddd; + /*top:45%;*/ + top: 45%; + color: #dddddd; } .footer { - bottom: 3%; + bottom: 3%; } .description { - color: gray; - padding-top: 50px; + color: gray; + padding-top: 50px; } .btn { - border-radius: 30px; - padding: 10px 30px; + border-radius: 30px; + padding: 10px 30px; } a, a:hover, a:visited { - color: red; - text-decoration: none; + 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) */ - -webkit-user-select: none; /* Chrome, Safari, and Opera */ - -webkit-touch-callout: none; /* Disable Android and iOS callouts*/ + -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"; - font-size: 12px; - position: absolute; - top: 3px; - padding-left: 5px; - font-weight: 400; + content: " V 2.0"; + font-size: 12px; + position: absolute; + top: 3px; + padding-left: 5px; + font-weight: 400; } h2::after { - content: "2"; - font-size: 12px; - position: absolute; - top: 14px; - padding-left: 5px; + content: "2"; + font-size: 12px; + position: absolute; + top: 14px; + padding-left: 5px; }