mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
More automatically generated formatter changes (#1254)
Apparently some of these were accidentally lost when generating #1210...
This commit is contained in:
8
.github/workflows/build-unstable.yml
vendored
8
.github/workflows/build-unstable.yml
vendored
@@ -7,7 +7,7 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- pyscriptjs/**
|
- pyscriptjs/**
|
||||||
- examples/**
|
- 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/
|
pull_request: # Run on any PR that modifies files under pyscriptjs/ and examples/
|
||||||
branches:
|
branches:
|
||||||
@@ -15,7 +15,7 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- pyscriptjs/**
|
- pyscriptjs/**
|
||||||
- examples/**
|
- 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:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
cache-name: cache-node-modules
|
cache-name: cache-node-modules
|
||||||
with:
|
with:
|
||||||
# npm cache files are stored in `~/.npm` on Linux/macOS
|
# npm cache files are stored in `~/.npm` on Linux/macOS
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
@@ -96,7 +96,7 @@ jobs:
|
|||||||
name: pyscript
|
name: pyscript
|
||||||
path: ./build/
|
path: ./build/
|
||||||
|
|
||||||
# Deploy to S3
|
# Deploy to S3
|
||||||
- name: Configure AWS credentials
|
- name: Configure AWS credentials
|
||||||
uses: aws-actions/configure-aws-credentials@v1.6.1
|
uses: aws-actions/configure-aws-credentials@v1.6.1
|
||||||
with:
|
with:
|
||||||
|
|||||||
12
.github/workflows/docs-release.yml
vendored
12
.github/workflows/docs-release.yml
vendored
@@ -16,8 +16,8 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token.
|
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.
|
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
|
||||||
|
|
||||||
- name: Setup
|
- name: Setup
|
||||||
uses: conda-incubator/setup-miniconda@v2
|
uses: conda-incubator/setup-miniconda@v2
|
||||||
@@ -39,7 +39,7 @@ jobs:
|
|||||||
name: pyscript-docs-${{ github.ref_name }}
|
name: pyscript-docs-${{ github.ref_name }}
|
||||||
path: docs/_build/html/
|
path: docs/_build/html/
|
||||||
|
|
||||||
# Deploy to S3
|
# Deploy to S3
|
||||||
- name: Configure AWS credentials
|
- name: Configure AWS credentials
|
||||||
uses: aws-actions/configure-aws-credentials@v1.6.1
|
uses: aws-actions/configure-aws-credentials@v1.6.1
|
||||||
with:
|
with:
|
||||||
@@ -52,11 +52,11 @@ jobs:
|
|||||||
- name: Sync to S3
|
- name: Sync to S3
|
||||||
run: aws s3 sync --quiet ./docs/_build/html/ s3://docs.pyscript.net/${{ github.ref_name }}/
|
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
|
- name: Delete latest directory
|
||||||
run: aws s3 rm --recursive s3://docs.pyscript.net/latest/
|
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
|
# Note that the files are the same as above, but we want to have folders with
|
||||||
# /<tag name>/ AND /latest/ which latest will always point to the latest release
|
# /<tag name>/ AND /latest/ which latest will always point to the latest release
|
||||||
- name: Sync to /latest
|
- name: Sync to /latest
|
||||||
run: aws s3 sync --quiet ./docs/_build/html/ s3://docs.pyscript.net/latest/
|
run: aws s3 sync --quiet ./docs/_build/html/ s3://docs.pyscript.net/latest/
|
||||||
|
|||||||
16
.github/workflows/docs-review.yml
vendored
16
.github/workflows/docs-review.yml
vendored
@@ -8,11 +8,11 @@ on:
|
|||||||
- docs/**
|
- docs/**
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
# Concurrency group that uses the workflow name and PR number if available
|
# 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
|
# 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.
|
# concurrency group while a previous build is running it will be canceled.
|
||||||
# Repeated pushes to a PR will cancel all previous builds, while multiple
|
# Repeated pushes to a PR will cancel all previous builds, while multiple
|
||||||
# merges to main will not cancel.
|
# merges to main will not cancel.
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
@@ -29,8 +29,8 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token.
|
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.
|
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
|
||||||
|
|
||||||
- name: Setup
|
- name: Setup
|
||||||
uses: conda-incubator/setup-miniconda@v2
|
uses: conda-incubator/setup-miniconda@v2
|
||||||
@@ -52,7 +52,7 @@ jobs:
|
|||||||
name: pyscript-docs-review-${{ github.event.number }}
|
name: pyscript-docs-review-${{ github.event.number }}
|
||||||
path: docs/_build/html/
|
path: docs/_build/html/
|
||||||
|
|
||||||
# Deploy to S3
|
# Deploy to S3
|
||||||
- name: Configure AWS credentials
|
- name: Configure AWS credentials
|
||||||
uses: aws-actions/configure-aws-credentials@v1.6.1
|
uses: aws-actions/configure-aws-credentials@v1.6.1
|
||||||
with:
|
with:
|
||||||
|
|||||||
8
.github/workflows/docs-unstable.yml
vendored
8
.github/workflows/docs-unstable.yml
vendored
@@ -19,8 +19,8 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token.
|
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.
|
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
|
||||||
|
|
||||||
- name: Setup
|
- name: Setup
|
||||||
uses: conda-incubator/setup-miniconda@v2
|
uses: conda-incubator/setup-miniconda@v2
|
||||||
@@ -42,13 +42,13 @@ jobs:
|
|||||||
name: pyscript-docs-latest
|
name: pyscript-docs-latest
|
||||||
path: docs/_build/html/
|
path: docs/_build/html/
|
||||||
|
|
||||||
# Deploy to S3
|
# Deploy to S3
|
||||||
- name: Configure AWS credentials
|
- name: Configure AWS credentials
|
||||||
uses: aws-actions/configure-aws-credentials@v1.6.1
|
uses: aws-actions/configure-aws-credentials@v1.6.1
|
||||||
with:
|
with:
|
||||||
aws-region: ${{ secrets.AWS_REGION }}
|
aws-region: ${{ secrets.AWS_REGION }}
|
||||||
role-to-assume: ${{ secrets.AWS_OIDC_RUNNER_ROLE }}
|
role-to-assume: ${{ secrets.AWS_OIDC_RUNNER_ROLE }}
|
||||||
|
|
||||||
# Sync will only copy changed files
|
# Sync will only copy changed files
|
||||||
- name: Sync to S3
|
- name: Sync to S3
|
||||||
run: aws s3 sync --quiet ./docs/_build/html/ s3://docs.pyscript.net/unstable/
|
run: aws s3 sync --quiet ./docs/_build/html/ s3://docs.pyscript.net/unstable/
|
||||||
|
|||||||
4
.github/workflows/prepare-release.yml
vendored
4
.github/workflows/prepare-release.yml
vendored
@@ -3,7 +3,7 @@ name: '[CI] Prepare Release'
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
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:
|
env:
|
||||||
MINICONDA_PYTHON_VERSION: py38
|
MINICONDA_PYTHON_VERSION: py38
|
||||||
@@ -30,7 +30,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
cache-name: cache-node-modules
|
cache-name: cache-node-modules
|
||||||
with:
|
with:
|
||||||
# npm cache files are stored in `~/.npm` on Linux/macOS
|
# npm cache files are stored in `~/.npm` on Linux/macOS
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
|
|||||||
4
.github/workflows/publish-release.yml
vendored
4
.github/workflows/publish-release.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
cache-name: cache-node-modules
|
cache-name: cache-node-modules
|
||||||
with:
|
with:
|
||||||
# npm cache files are stored in `~/.npm` on Linux/macOS
|
# npm cache files are stored in `~/.npm` on Linux/macOS
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
@@ -49,7 +49,7 @@ jobs:
|
|||||||
- name: Build and Test
|
- name: Build and Test
|
||||||
run: make test
|
run: make test
|
||||||
|
|
||||||
# Upload to S3
|
# Upload to S3
|
||||||
- name: Configure AWS credentials
|
- name: Configure AWS credentials
|
||||||
uses: aws-actions/configure-aws-credentials@v1.6.1
|
uses: aws-actions/configure-aws-credentials@v1.6.1
|
||||||
with:
|
with:
|
||||||
|
|||||||
6
.github/workflows/sync-examples.yml
vendored
6
.github/workflows/sync-examples.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
working-directory: examples
|
working-directory: examples
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
# Deploy to S3
|
# Deploy to S3
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Configure AWS credentials
|
- name: Configure AWS credentials
|
||||||
@@ -24,5 +24,5 @@ jobs:
|
|||||||
aws-region: ${{ secrets.AWS_REGION }}
|
aws-region: ${{ secrets.AWS_REGION }}
|
||||||
role-to-assume: ${{ secrets.AWS_OIDC_RUNNER_ROLE }}
|
role-to-assume: ${{ secrets.AWS_OIDC_RUNNER_ROLE }}
|
||||||
- name: Sync to S3
|
- name: Sync to S3
|
||||||
# Sync outdated or new files, delete ones no longer 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
|
run: aws s3 sync --quiet --delete . s3://pyscript.net/examples/ # Sync directory, delete what is not in source
|
||||||
|
|||||||
@@ -4,17 +4,17 @@ Thank you for wanting to contribute to the PyScript project!
|
|||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
- [Code of Conduct](#code-of-conduct)
|
- [Code of Conduct](#code-of-conduct)
|
||||||
- [Contributing](#contributing)
|
- [Contributing](#contributing)
|
||||||
- [Reporting bugs](#reporting-bugs)
|
- [Reporting bugs](#reporting-bugs)
|
||||||
- [Reporting security issues](#reporting-security-issues)
|
- [Reporting security issues](#reporting-security-issues)
|
||||||
- [Asking questions](#asking-questions)
|
- [Asking questions](#asking-questions)
|
||||||
- [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing)
|
- [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing)
|
||||||
- [Places to start](#places-to-start)
|
- [Places to start](#places-to-start)
|
||||||
- [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing)
|
- [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing)
|
||||||
- [License terms for contributions](#license-terms-for-contributions)
|
- [License terms for contributions](#license-terms-for-contributions)
|
||||||
- [Becoming a maintainer](#becoming-a-maintainer)
|
- [Becoming a maintainer](#becoming-a-maintainer)
|
||||||
- [Trademarks](#trademarks)
|
- [Trademarks](#trademarks)
|
||||||
|
|
||||||
# Code of Conduct
|
# Code of Conduct
|
||||||
|
|
||||||
@@ -28,10 +28,10 @@ Bugs are tracked on the [project issues page](https://github.com/pyscript/pyscri
|
|||||||
|
|
||||||
## Creating useful issues
|
## Creating useful issues
|
||||||
|
|
||||||
- Use a clear and descriptive title.
|
- 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 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.
|
- Describe the behavior you observed, and the behavior you had expected.
|
||||||
- Include screenshots if they help make the issue clear.
|
- Include screenshots if they help make the issue clear.
|
||||||
|
|
||||||
## Reporting security issues
|
## 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.
|
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.
|
- **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!
|
- **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.
|
- **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.
|
- **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
|
## Setting up your local environment and developing
|
||||||
|
|
||||||
|
|||||||
22
README.md
22
README.md
@@ -20,15 +20,15 @@ To try PyScript, import the appropriate pyscript files into the `<head>` tag of
|
|||||||
|
|
||||||
```html
|
```html
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
</head>
|
</head>
|
||||||
```
|
```
|
||||||
|
|
||||||
You can then use PyScript components in your html page. PyScript currently implements the following elements:
|
You can then use PyScript components in your html page. PyScript currently implements the following elements:
|
||||||
|
|
||||||
- `<py-script>`: 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
|
- `<py-script>`: 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
|
||||||
- `<py-repl>`: creates a REPL component that is rendered to the page as a code editor and allows users to write executable code
|
- `<py-repl>`: 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.
|
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
|
## Resources
|
||||||
|
|
||||||
- [Official docs](https://docs.pyscript.net)
|
- [Official docs](https://docs.pyscript.net)
|
||||||
- [Discussion board](https://community.anaconda.cloud/c/tech-topics/pyscript)
|
- [Discussion board](https://community.anaconda.cloud/c/tech-topics/pyscript)
|
||||||
- [Home Page](https://pyscript.net/)
|
- [Home Page](https://pyscript.net/)
|
||||||
- [Blog Post](https://engineering.anaconda.com/2022/04/welcome-pyscript.html)
|
- [Blog Post](https://engineering.anaconda.com/2022/04/welcome-pyscript.html)
|
||||||
- [Discord Channel](https://discord.gg/BYB2kvyFwm)
|
- [Discord Channel](https://discord.gg/BYB2kvyFwm)
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- This is an extremely experimental project, so expect things to break!
|
- This is an extremely experimental project, so expect things to break!
|
||||||
- PyScript has been only tested on Chrome at the moment.
|
- PyScript has been only tested on Chrome at the moment.
|
||||||
|
|
||||||
## Governance
|
## Governance
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ This page is meant for troubleshooting common problems with PyScript.
|
|||||||
|
|
||||||
## Table of contents:
|
## Table of contents:
|
||||||
|
|
||||||
- [Make Setup](#make-setup)
|
- [Make Setup](#make-setup)
|
||||||
|
|
||||||
## Make setup
|
## Make setup
|
||||||
|
|
||||||
|
|||||||
@@ -1,78 +1,81 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Altair</title>
|
<title>Altair</title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
rel="stylesheet"
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
</head>
|
/>
|
||||||
<body>
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
<div class="app-header">
|
</head>
|
||||||
<a href="/">
|
<body>
|
||||||
<img src="./logo.png" class="logo" />
|
<nav class="navbar" style="background-color: #000000">
|
||||||
</a>
|
<div class="app-header">
|
||||||
<a class="title" href="" style="color: #f0ab3c">Altair</a>
|
<a href="/">
|
||||||
</div>
|
<img src="./logo.png" class="logo" />
|
||||||
</nav>
|
</a>
|
||||||
<section class="pyscript">
|
<a class="title" href="" style="color: #f0ab3c">Altair</a>
|
||||||
<div id="altair"></div>
|
</div>
|
||||||
<py-tutor>
|
</nav>
|
||||||
<py-config>
|
<section class="pyscript">
|
||||||
packages = [
|
<div id="altair"></div>
|
||||||
"altair",
|
<py-tutor>
|
||||||
"pandas",
|
<py-config>
|
||||||
"vega_datasets"
|
packages = [
|
||||||
]
|
"altair",
|
||||||
plugins = [
|
"pandas",
|
||||||
"../build/plugins/python/py_tutor.py"
|
"vega_datasets"
|
||||||
]
|
]
|
||||||
</py-config>
|
plugins = [
|
||||||
<py-script>
|
"../build/plugins/python/py_tutor.py"
|
||||||
import altair as alt
|
]
|
||||||
from vega_datasets import data
|
</py-config>
|
||||||
|
<py-script>
|
||||||
|
import altair as alt
|
||||||
|
from vega_datasets import data
|
||||||
|
|
||||||
source = data.movies.url
|
source = data.movies.url
|
||||||
|
|
||||||
pts = alt.selection(type="single", encodings=['x'])
|
pts = alt.selection(type="single", encodings=['x'])
|
||||||
|
|
||||||
rect = alt.Chart(data.movies.url).mark_rect().encode(
|
rect = alt.Chart(data.movies.url).mark_rect().encode(
|
||||||
alt.X('IMDB_Rating:Q', bin=True),
|
alt.X('IMDB_Rating:Q', bin=True),
|
||||||
alt.Y('Rotten_Tomatoes_Rating:Q', bin=True),
|
alt.Y('Rotten_Tomatoes_Rating:Q', bin=True),
|
||||||
alt.Color('count()',
|
alt.Color('count()',
|
||||||
scale=alt.Scale(scheme='greenblue'),
|
scale=alt.Scale(scheme='greenblue'),
|
||||||
legend=alt.Legend(title='Total Records')
|
legend=alt.Legend(title='Total Records')
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
circ = rect.mark_point().encode(
|
circ = rect.mark_point().encode(
|
||||||
alt.ColorValue('grey'),
|
alt.ColorValue('grey'),
|
||||||
alt.Size('count()',
|
alt.Size('count()',
|
||||||
legend=alt.Legend(title='Records in Selection')
|
legend=alt.Legend(title='Records in Selection')
|
||||||
)
|
)
|
||||||
).transform_filter(
|
).transform_filter(
|
||||||
pts
|
pts
|
||||||
)
|
)
|
||||||
|
|
||||||
bar = alt.Chart(source).mark_bar().encode(
|
bar = alt.Chart(source).mark_bar().encode(
|
||||||
x='Major_Genre:N',
|
x='Major_Genre:N',
|
||||||
y='count()',
|
y='count()',
|
||||||
color=alt.condition(pts, alt.ColorValue("steelblue"), alt.ColorValue("grey"))
|
color=alt.condition(pts, alt.ColorValue("steelblue"), alt.ColorValue("grey"))
|
||||||
).properties(
|
).properties(
|
||||||
width=550,
|
width=550,
|
||||||
height=200
|
height=200
|
||||||
).add_selection(pts)
|
).add_selection(pts)
|
||||||
|
|
||||||
display(alt.vconcat(
|
display(alt.vconcat(
|
||||||
rect + circ,
|
rect + circ,
|
||||||
bar
|
bar
|
||||||
).resolve_legend(
|
).resolve_legend(
|
||||||
color="independent",
|
color="independent",
|
||||||
size="independent"
|
size="independent"
|
||||||
), target="altair")
|
), target="altair")
|
||||||
</py-script>
|
</py-script>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</section>
|
</section>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,36 +1,39 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Antigravity</title>
|
<title>Antigravity</title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
rel="stylesheet"
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
</head>
|
/>
|
||||||
<body>
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
<div class="app-header">
|
</head>
|
||||||
<a href="/">
|
<body>
|
||||||
<img src="./logo.png" class="logo" />
|
<nav class="navbar" style="background-color: #000000">
|
||||||
</a>
|
<div class="app-header">
|
||||||
<a class="title" href="" style="color: #f0ab3c">Antigravity</a>
|
<a href="/">
|
||||||
</div>
|
<img src="./logo.png" class="logo" />
|
||||||
</nav>
|
</a>
|
||||||
<py-tutor modules="antigravity.py">
|
<a class="title" href="" style="color: #f0ab3c">Antigravity</a>
|
||||||
<section class="pyscript">
|
</div>
|
||||||
<py-config>
|
</nav>
|
||||||
plugins = [
|
<py-tutor modules="antigravity.py">
|
||||||
"../build/plugins/python/py_tutor.py"
|
<section class="pyscript">
|
||||||
]
|
<py-config>
|
||||||
[[fetch]]
|
plugins = [
|
||||||
files = ["./antigravity.py"]
|
"../build/plugins/python/py_tutor.py"
|
||||||
</py-config>
|
]
|
||||||
<b>Based on xkcd: antigravity https://xkcd.com/353/.</b>
|
[[fetch]]
|
||||||
<py-script>
|
files = ["./antigravity.py"]
|
||||||
import antigravity
|
</py-config>
|
||||||
antigravity.fly()
|
<b>Based on xkcd: antigravity https://xkcd.com/353/.</b>
|
||||||
</py-script>
|
<py-script>
|
||||||
</section>
|
import antigravity
|
||||||
</py-tutor>
|
antigravity.fly()
|
||||||
</body>
|
</py-script>
|
||||||
|
</section>
|
||||||
|
</py-tutor>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,91 +1,91 @@
|
|||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pyscript {
|
.pyscript {
|
||||||
margin: 0.5rem;
|
margin: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.code {
|
.code {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0px;
|
right: 0px;
|
||||||
z-index: 9998;
|
z-index: 9998;
|
||||||
top: 7rem;
|
top: 7rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1300px) {
|
@media (max-width: 1300px) {
|
||||||
.code:has(> .code-section-visible) {
|
.code:has(> .code-section-visible) {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
/* Absolute position is messing up the layout on small screens */
|
/* Absolute position is messing up the layout on small screens */
|
||||||
right: 70px;
|
right: 70px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-section-hidden {
|
.code-section-hidden {
|
||||||
width: 0px;
|
width: 0px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-section-visible {
|
.code-section-visible {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: rgb(45 46 53 / 90%);
|
background-color: rgb(45 46 53 / 90%);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 10px 0px 0px 10px;
|
border-radius: 10px 0px 0px 10px;
|
||||||
color: #c6c6c8;
|
color: #c6c6c8;
|
||||||
}
|
}
|
||||||
.code-section-visible p {
|
.code-section-visible p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-size: small;
|
font-size: small;
|
||||||
}
|
}
|
||||||
|
|
||||||
.language-html,
|
.language-html,
|
||||||
.language-python {
|
.language-python {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
#view-code-button {
|
#view-code-button {
|
||||||
writing-mode: tb-rl;
|
writing-mode: tb-rl;
|
||||||
text-orientation: sideways-right;
|
text-orientation: sideways-right;
|
||||||
background-color: #1d1d22;
|
background-color: #1d1d22;
|
||||||
color: white;
|
color: white;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 81px;
|
height: 81px;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav {
|
nav {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
max-width: inherit;
|
max-width: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
text-decoration-line: none;
|
text-decoration-line: none;
|
||||||
text-decoration-style: initial;
|
text-decoration-style: initial;
|
||||||
text-decoration-color: initial;
|
text-decoration-color: initial;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
line-height: 2em;
|
line-height: 2em;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-header {
|
.app-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,74 +1,74 @@
|
|||||||
.example {
|
.example {
|
||||||
margin-bottom: 5rem;
|
margin-bottom: 5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.example h2 {
|
.example h2 {
|
||||||
/* color: #000000; */
|
/* color: #000000; */
|
||||||
font-family: "Inconsolata", monospace;
|
font-family: "Inconsolata", monospace;
|
||||||
font-size: 2.25rem;
|
font-size: 2.25rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
height: 15rem;
|
height: 15rem;
|
||||||
background-color: var(--color-secondary);
|
background-color: var(--color-secondary);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card:hover,
|
.card:hover,
|
||||||
.card:hover a,
|
.card:hover a,
|
||||||
.card:hover a:visited,
|
.card:hover a:visited,
|
||||||
.card:hover h2 {
|
.card:hover h2 {
|
||||||
background-color: var(--color-primary);
|
background-color: var(--color-primary);
|
||||||
color: #1d1d22;
|
color: #1d1d22;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card a h2 {
|
.card a h2 {
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: "Inconsolata", monospace;
|
font-family: "Inconsolata", monospace;
|
||||||
font-size: 2.25rem;
|
font-size: 2.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card a p {
|
.card a p {
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
a .card {
|
a .card {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-content {
|
.card-content {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-content a,
|
.card-content a,
|
||||||
.card-content a:visited {
|
.card-content a:visited {
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.container-card {
|
.container-card {
|
||||||
max-width: 1500px;
|
max-width: 1500px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 600px) {
|
@media (min-width: 600px) {
|
||||||
.container-card {
|
.container-card {
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 900px) {
|
@media (min-width: 900px) {
|
||||||
.container-card {
|
.container-card {
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,23 +3,23 @@
|
|||||||
@import "./reset.css";
|
@import "./reset.css";
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: #2d2e35
|
background: #2d2e35
|
||||||
url("https://assets.anaconda.com/production/Content/1650828148240.png?w=3240&auto=compress%2Cformat&fit=crop&dm=1650828161&s=c558dc55e0ed1f8419a892e842a5728f")
|
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;
|
repeat-x center bottom / 250px;
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
max-width: 1510px;
|
max-width: 1510px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
padding: 0 2rem;
|
padding: 0 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-main {
|
.title-main {
|
||||||
font-size: 4.25rem;
|
font-size: 4.25rem;
|
||||||
font-family: "Inconsolata", monospace;
|
font-family: "Inconsolata", monospace;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
*,
|
*,
|
||||||
*:after,
|
*:after,
|
||||||
*:before {
|
*:before {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-size: 100%;
|
font-size: 100%;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-family: "Inconsolata", monospace;
|
font-family: "Inconsolata", monospace;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
:root {
|
:root {
|
||||||
--color-primary: #fda703;
|
--color-primary: #fda703;
|
||||||
--color-secondary: #1d1d22;
|
--color-secondary: #1d1d22;
|
||||||
--text-color: white;
|
--text-color: white;
|
||||||
--card-shadow: 0px 5px 11px 0px rgb(0 0 0 / 15%);
|
--card-shadow: 0px 5px 11px 0px rgb(0 0 0 / 15%);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,29 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<title>Async Await BLOCKING LOOP Pyscript Twice</title>
|
<title>Async Await BLOCKING LOOP Pyscript Twice</title>
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
</head>
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
<body>
|
/>
|
||||||
<py-script>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
import js
|
</head>
|
||||||
import asyncio
|
<body>
|
||||||
for i in range(3):
|
<py-script>
|
||||||
js.console.log('A', i)
|
import js
|
||||||
await asyncio.sleep(0.1)
|
import asyncio
|
||||||
</py-script>
|
for i in range(3):
|
||||||
<py-script>
|
js.console.log('A', i)
|
||||||
import js
|
await asyncio.sleep(0.1)
|
||||||
import asyncio
|
</py-script>
|
||||||
for i in range(3):
|
<py-script>
|
||||||
js.console.log('B', i)
|
import js
|
||||||
await asyncio.sleep(0.1)
|
import asyncio
|
||||||
</py-script>
|
for i in range(3):
|
||||||
</body>
|
js.console.log('B', i)
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
</py-script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,42 +1,45 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<title>Async Await BLOCKING LOOP Pyscript Twice</title>
|
<title>Async Await BLOCKING LOOP Pyscript Twice</title>
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
</head>
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
<body>
|
/>
|
||||||
<div>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
Pyscript - FIRST ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME LEVEL AS
|
</head>
|
||||||
LOOP Pyscript writing to console.log:
|
<body>
|
||||||
<py-script>
|
<div>
|
||||||
import js
|
Pyscript - FIRST ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME
|
||||||
import asyncio
|
LEVEL AS LOOP Pyscript writing to console.log:
|
||||||
|
<py-script>
|
||||||
|
import js
|
||||||
|
import asyncio
|
||||||
|
|
||||||
async def asyncCallLoop1():
|
async def asyncCallLoop1():
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
js.console.log('A', i)
|
js.console.log('A', i)
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(2)
|
||||||
|
|
||||||
asyncCallLoop1()
|
asyncCallLoop1()
|
||||||
</py-script>
|
</py-script>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Pyscript - SECOND ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME LEVEL AS
|
Pyscript - SECOND ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME
|
||||||
LOOP Pyscript writing to console.log:
|
LEVEL AS LOOP Pyscript writing to console.log:
|
||||||
<py-script>
|
<py-script>
|
||||||
import js
|
import js
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
async def asyncCallLoop2():
|
async def asyncCallLoop2():
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
js.console.log('B', i)
|
js.console.log('B', i)
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(2)
|
||||||
|
|
||||||
asyncCallLoop2()
|
asyncCallLoop2()
|
||||||
</py-script>
|
</py-script>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,39 +1,42 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<title>Async Await BLOCKING LOOP Pyscript Twice</title>
|
<title>Async Await BLOCKING LOOP Pyscript Twice</title>
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
</head>
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
<body>
|
/>
|
||||||
<div>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
Pyscript - FIRST ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME LEVEL AS
|
</head>
|
||||||
LOOP Pyscript writing to console.log:
|
<body>
|
||||||
<py-script>
|
<div>
|
||||||
import js
|
Pyscript - FIRST ASYNC WITH INVOKED LOOP BLOCKING AWAIT AT SAME
|
||||||
import asyncio
|
LEVEL AS LOOP Pyscript writing to console.log:
|
||||||
|
<py-script>
|
||||||
|
import js
|
||||||
|
import asyncio
|
||||||
|
|
||||||
async def asyncCallLoop1():
|
async def asyncCallLoop1():
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
js.console.log('A', i)
|
js.console.log('A', i)
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(2)
|
||||||
|
|
||||||
asyncCallLoop1()
|
asyncCallLoop1()
|
||||||
</py-script>
|
</py-script>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Pyscript - SECOND ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME LEVEL
|
Pyscript - SECOND ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME
|
||||||
AS LOOP Pyscript writing to console.log:
|
LEVEL AS LOOP Pyscript writing to console.log:
|
||||||
<py-script>
|
<py-script>
|
||||||
import js
|
import js
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
js.console.log('B', i)
|
js.console.log('B', i)
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(2)
|
||||||
</py-script>
|
</py-script>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,42 +1,45 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<title>Async Await NON-BLOCKING Pyscript Twice</title>
|
<title>Async Await NON-BLOCKING Pyscript Twice</title>
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
</head>
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
<body>
|
/>
|
||||||
<div>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
Pyscript - FIRST ASYNC WITH NON-BLOCKING AWAIT AT ONE LEVEL LOWER THAN
|
</head>
|
||||||
LOOP Pyscript writing to console.log:
|
<body>
|
||||||
<py-script>
|
<div>
|
||||||
import js
|
Pyscript - FIRST ASYNC WITH NON-BLOCKING AWAIT AT ONE LEVEL LOWER
|
||||||
import asyncio
|
THAN LOOP Pyscript writing to console.log:
|
||||||
|
<py-script>
|
||||||
|
import js
|
||||||
|
import asyncio
|
||||||
|
|
||||||
async def asyncCall1():
|
async def asyncCall1():
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(2)
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
js.console.log('A', i)
|
js.console.log('A', i)
|
||||||
asyncCall1()
|
asyncCall1()
|
||||||
</py-script>
|
</py-script>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Pyscript - SECOND ASYNC WITH NON-BLOCKING AWAIT AT ONE LEVEL LOWER THAN
|
Pyscript - SECOND ASYNC WITH NON-BLOCKING AWAIT AT ONE LEVEL LOWER
|
||||||
LOOP Pyscript writing to console.log:
|
THAN LOOP Pyscript writing to console.log:
|
||||||
<py-script>
|
<py-script>
|
||||||
import js
|
import js
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
async def asyncCall2():
|
async def asyncCall2():
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(2)
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
js.console.log('B', i)
|
js.console.log('B', i)
|
||||||
asyncCall2()
|
asyncCall2()
|
||||||
</py-script>
|
</py-script>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,36 +1,39 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<title>Async Await BLOCKING LOOP Pyscript Twice</title>
|
<title>Async Await BLOCKING LOOP Pyscript Twice</title>
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
</head>
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
<body>
|
/>
|
||||||
<div>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
Pyscript - FIRST ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME LEVEL AS
|
</head>
|
||||||
LOOP Pyscript writing to console.log:
|
<body>
|
||||||
<py-script>
|
<div>
|
||||||
import js
|
Pyscript - FIRST ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME
|
||||||
import asyncio
|
LEVEL AS LOOP Pyscript writing to console.log:
|
||||||
|
<py-script>
|
||||||
|
import js
|
||||||
|
import asyncio
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
js.console.log('A', i)
|
js.console.log('A', i)
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(2)
|
||||||
</py-script>
|
</py-script>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Pyscript - SECOND ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME LEVEL
|
Pyscript - SECOND ASYNC WITH TOP-LEVEL LOOP BLOCKING AWAIT AT SAME
|
||||||
AS LOOP Pyscript writing to console.log:
|
LEVEL AS LOOP Pyscript writing to console.log:
|
||||||
<py-script>
|
<py-script>
|
||||||
import js
|
import js
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
js.console.log('B', i)
|
js.console.log('B', i)
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(2)
|
||||||
</py-script>
|
</py-script>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<title>Async Await BLOCKING LOOP Pyscript Twice</title>
|
<title>Async Await BLOCKING LOOP Pyscript Twice</title>
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
</head>
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
<body>
|
/>
|
||||||
<py-script>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
import asyncio
|
</head>
|
||||||
from itertools import count
|
<body>
|
||||||
for i in count():
|
<py-script>
|
||||||
print(f"Count: {i}")
|
import asyncio
|
||||||
await asyncio.sleep(1)
|
from itertools import count
|
||||||
</py-script>
|
for i in count():
|
||||||
</body>
|
print(f"Count: {i}")
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
</py-script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,81 +1,86 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Bokeh Example</title>
|
<title>Bokeh Example</title>
|
||||||
<meta charset="iso-8859-1" />
|
<meta charset="iso-8859-1" />
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-3.0.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-3.0.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.0.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.0.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.0.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.0.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.0.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.0.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.0.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.0.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
|
/>
|
||||||
|
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" href="" style="color: #f0ab3c">Bokeh Example</a>
|
<a class="title" href="" style="color: #f0ab3c"
|
||||||
</div>
|
>Bokeh Example</a
|
||||||
</nav>
|
>
|
||||||
<py-tutor>
|
</div>
|
||||||
<section class="pyscript">
|
</nav>
|
||||||
<div id="myplot"></div>
|
<py-tutor>
|
||||||
|
<section class="pyscript">
|
||||||
|
<div id="myplot"></div>
|
||||||
|
|
||||||
<py-config>
|
<py-config>
|
||||||
packages = [
|
packages = [
|
||||||
"pandas",
|
"pandas",
|
||||||
"bokeh",
|
"bokeh",
|
||||||
"xyzservices"
|
"xyzservices"
|
||||||
]
|
]
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<py-script id="main">
|
<py-script id="main">
|
||||||
import json
|
import json
|
||||||
import pyodide
|
import pyodide
|
||||||
|
|
||||||
from js import Bokeh, console, JSON
|
from js import Bokeh, console, JSON
|
||||||
|
|
||||||
from bokeh.embed import json_item
|
from bokeh.embed import json_item
|
||||||
from bokeh.plotting import figure
|
from bokeh.plotting import figure
|
||||||
from bokeh.resources import CDN
|
from bokeh.resources import CDN
|
||||||
|
|
||||||
# create a new plot with default tools, using figure
|
# create a new plot with default tools, using figure
|
||||||
p = figure(width=400, height=400)
|
p = figure(width=400, height=400)
|
||||||
|
|
||||||
# add a circle renderer with x and y coordinates, size, color, and alpha
|
# 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.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"))
|
p_json = json.dumps(json_item(p, "myplot"))
|
||||||
|
|
||||||
Bokeh.embed.embed_item(JSON.parse(p_json))
|
Bokeh.embed.embed_item(JSON.parse(p_json))
|
||||||
</py-script>
|
</py-script>
|
||||||
</section>
|
</section>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,131 +1,136 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Bokeh Example</title>
|
<title>Bokeh Example</title>
|
||||||
<meta charset="iso-8859-1" />
|
<meta charset="iso-8859-1" />
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
|
/>
|
||||||
|
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" href="" style="color: #f0ab3c">Bokeh Example</a>
|
<a class="title" href="" style="color: #f0ab3c"
|
||||||
</div>
|
>Bokeh Example</a
|
||||||
</nav>
|
>
|
||||||
<py-tutor>
|
</div>
|
||||||
<section class="pyscript">
|
</nav>
|
||||||
<h1>Bokeh Example</h1>
|
<py-tutor>
|
||||||
<div id="myplot"></div>
|
<section class="pyscript">
|
||||||
|
<h1>Bokeh Example</h1>
|
||||||
|
<div id="myplot"></div>
|
||||||
|
|
||||||
<py-config>
|
<py-config>
|
||||||
packages = [
|
packages = [
|
||||||
"https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
|
"https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
|
||||||
"numpy",
|
"numpy",
|
||||||
]
|
]
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<py-script id="main">
|
<py-script id="main">
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
import pyodide
|
import pyodide
|
||||||
|
|
||||||
from js import Bokeh, console, JSON
|
from js import Bokeh, console, JSON
|
||||||
|
|
||||||
from bokeh import __version__
|
from bokeh import __version__
|
||||||
from bokeh.document import Document
|
from bokeh.document import Document
|
||||||
from bokeh.embed.util import OutputDocumentFor, standalone_docs_json_and_render_items
|
from bokeh.embed.util import OutputDocumentFor, standalone_docs_json_and_render_items
|
||||||
from bokeh.models import Slider, Div
|
from bokeh.models import Slider, Div
|
||||||
from bokeh.layouts import Row
|
from bokeh.layouts import Row
|
||||||
from bokeh.protocol.messages.patch_doc import process_document_events
|
from bokeh.protocol.messages.patch_doc import process_document_events
|
||||||
|
|
||||||
# create a new plot with default tools, using figure
|
# create a new plot with default tools, using figure
|
||||||
p = Slider(start=0.1, end=10, value=1, step=.1, title="Amplitude")
|
p = Slider(start=0.1, end=10, value=1, step=.1, title="Amplitude")
|
||||||
div = Div(text=f'Amplitude is: {p.value}')
|
div = Div(text=f'Amplitude is: {p.value}')
|
||||||
|
|
||||||
def callback(attr, old, new):
|
def callback(attr, old, new):
|
||||||
div.text = f'Amplitude is: {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):
|
def doc_json(model, target):
|
||||||
with OutputDocumentFor([model]) as doc:
|
with OutputDocumentFor([model]) as doc:
|
||||||
doc.title = ""
|
doc.title = ""
|
||||||
docs_json, _ = standalone_docs_json_and_render_items(
|
docs_json, _ = standalone_docs_json_and_render_items(
|
||||||
[model], suppress_callback_warning=True
|
[model], suppress_callback_warning=True
|
||||||
)
|
)
|
||||||
|
|
||||||
doc_json = list(docs_json.values())[0]
|
doc_json = list(docs_json.values())[0]
|
||||||
root_id = doc_json['roots']['root_ids'][0]
|
root_id = doc_json['roots']['root_ids'][0]
|
||||||
|
|
||||||
return doc, json.dumps(dict(
|
return doc, json.dumps(dict(
|
||||||
target_id = target,
|
target_id = target,
|
||||||
root_id = root_id,
|
root_id = root_id,
|
||||||
doc = doc_json,
|
doc = doc_json,
|
||||||
version = __version__,
|
version = __version__,
|
||||||
))
|
))
|
||||||
|
|
||||||
def _link_docs(pydoc, jsdoc):
|
def _link_docs(pydoc, jsdoc):
|
||||||
def jssync(event):
|
def jssync(event):
|
||||||
if getattr(event, 'setter_id', None) is not None:
|
if getattr(event, 'setter_id', None) is not None:
|
||||||
return
|
return
|
||||||
events = [event]
|
events = [event]
|
||||||
json_patch = jsdoc.create_json_patch_string(pyodide.ffi.to_js(events))
|
json_patch = jsdoc.create_json_patch_string(pyodide.ffi.to_js(events))
|
||||||
pydoc.apply_json_patch(json.loads(json_patch))
|
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):
|
def pysync(event):
|
||||||
json_patch, buffers = process_document_events([event], use_buffers=True)
|
json_patch, buffers = process_document_events([event], use_buffers=True)
|
||||||
buffer_map = {}
|
buffer_map = {}
|
||||||
for (ref, buffer) in buffers:
|
for (ref, buffer) in buffers:
|
||||||
buffer_map[ref['id']] = buffer
|
buffer_map[ref['id']] = buffer
|
||||||
jsdoc.apply_json_patch(JSON.parse(json_patch), pyodide.ffi.to_js(buffer_map), setter_id='js')
|
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):
|
async def show(plot, target):
|
||||||
pydoc, model_json = doc_json(plot, target)
|
pydoc, model_json = doc_json(plot, target)
|
||||||
views = await Bokeh.embed.embed_item(JSON.parse(model_json))
|
views = await Bokeh.embed.embed_item(JSON.parse(model_json))
|
||||||
jsdoc = views[0].model.document
|
jsdoc = views[0].model.document
|
||||||
_link_docs(pydoc, jsdoc)
|
_link_docs(pydoc, jsdoc)
|
||||||
|
|
||||||
asyncio.ensure_future(show(row, 'myplot'))
|
asyncio.ensure_future(show(row, 'myplot'))
|
||||||
</py-script>
|
</py-script>
|
||||||
</section>
|
</section>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
244
examples/d3.html
244
examples/d3.html
@@ -1,134 +1,138 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>d3: JavaScript & PyScript visualizations side-by-side</title>
|
<title>d3: JavaScript & PyScript visualizations side-by-side</title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
<script src="https://d3js.org/d3.v7.min.js"></script>
|
/>
|
||||||
<style>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
.loading {
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
display: inline-block;
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||||
width: 50px;
|
<style>
|
||||||
height: 50px;
|
.loading {
|
||||||
border: 3px solid rgba(255, 255, 255, 0.3);
|
display: inline-block;
|
||||||
border-radius: 50%;
|
width: 50px;
|
||||||
border-top-color: black;
|
height: 50px;
|
||||||
animation: spin 1s ease-in-out infinite;
|
border: 3px solid rgba(255, 255, 255, 0.3);
|
||||||
}
|
border-radius: 50%;
|
||||||
|
border-top-color: black;
|
||||||
|
animation: spin 1s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
to {
|
to {
|
||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" href="" style="color: #f0ab3c"
|
<a class="title" href="" style="color: #f0ab3c"
|
||||||
>Simple d3 visualization</a
|
>Simple d3 visualization</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<section class="pyscript">
|
<section class="pyscript">
|
||||||
<py-tutor modules="d3.py">
|
<py-tutor modules="d3.py">
|
||||||
<py-config>
|
<py-config>
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
[[fetch]]
|
[[fetch]]
|
||||||
files = ["./d3.py"]
|
files = ["./d3.py"]
|
||||||
</py-config>
|
</py-config>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
<b>
|
<b>
|
||||||
Based on
|
Based on
|
||||||
<i
|
<i
|
||||||
><a
|
><a
|
||||||
href="https://observablehq.com/@d3/learn-d3-shapes?collection=@d3/learn-d3>"
|
href="https://observablehq.com/@d3/learn-d3-shapes?collection=@d3/learn-d3>"
|
||||||
>Learn D3: Shapes</a
|
>Learn D3: Shapes</a
|
||||||
></i
|
></i
|
||||||
>
|
>
|
||||||
tutorial.
|
tutorial.
|
||||||
</b>
|
</b>
|
||||||
<div style="display: flex; flex-direction: row">
|
<div style="display: flex; flex-direction: row">
|
||||||
<div>
|
<div>
|
||||||
<div style="text-align: center">JavaScript version</div>
|
<div style="text-align: center">JavaScript version</div>
|
||||||
<div id="js" style="width: 400px; height: 400px">
|
<div id="js" style="width: 400px; height: 400px">
|
||||||
<div class="loading"></div>
|
<div class="loading"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div style="text-align: center">PyScript version</div>
|
<div style="text-align: center">PyScript version</div>
|
||||||
<div id="py" style="width: 400px; height: 400px">
|
<div id="py" style="width: 400px; height: 400px">
|
||||||
<div class="loading"></div>
|
<div class="loading"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<py-script src="d3.py"></py-script>
|
<py-script src="d3.py"></py-script>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
const fruits = [
|
const fruits = [
|
||||||
{ name: "🍊", count: 21 },
|
{ name: "🍊", count: 21 },
|
||||||
{ name: "🍇", count: 13 },
|
{ name: "🍇", count: 13 },
|
||||||
{ name: "🍏", count: 8 },
|
{ name: "🍏", count: 8 },
|
||||||
{ name: "🍌", count: 5 },
|
{ name: "🍌", count: 5 },
|
||||||
{ name: "🍐", count: 3 },
|
{ name: "🍐", count: 3 },
|
||||||
{ name: "🍋", count: 2 },
|
{ name: "🍋", count: 2 },
|
||||||
{ name: "🍎", count: 1 },
|
{ name: "🍎", count: 1 },
|
||||||
{ name: "🍉", count: 1 },
|
{ name: "🍉", count: 1 },
|
||||||
];
|
];
|
||||||
|
|
||||||
const fn = (d) => d.count;
|
const fn = (d) => d.count;
|
||||||
const data = d3.pie().value(fn)(fruits);
|
const data = d3.pie().value(fn)(fruits);
|
||||||
|
|
||||||
const arc = d3
|
const arc = d3
|
||||||
.arc()
|
.arc()
|
||||||
.innerRadius(210)
|
.innerRadius(210)
|
||||||
.outerRadius(310)
|
.outerRadius(310)
|
||||||
.padRadius(300)
|
.padRadius(300)
|
||||||
.padAngle(2 / 300)
|
.padAngle(2 / 300)
|
||||||
.cornerRadius(8);
|
.cornerRadius(8);
|
||||||
|
|
||||||
const js = d3.select("#js");
|
const js = d3.select("#js");
|
||||||
js.select(".loading").remove();
|
js.select(".loading").remove();
|
||||||
|
|
||||||
const svg = js
|
const svg = js
|
||||||
.append("svg")
|
.append("svg")
|
||||||
.attr("viewBox", "-320 -320 640 640")
|
.attr("viewBox", "-320 -320 640 640")
|
||||||
.attr("width", "400")
|
.attr("width", "400")
|
||||||
.attr("height", "400");
|
.attr("height", "400");
|
||||||
|
|
||||||
for (const d of data) {
|
for (const d of data) {
|
||||||
svg.append("path").style("fill", "steelblue").attr("d", arc(d));
|
svg.append("path").style("fill", "steelblue").attr("d", arc(d));
|
||||||
|
|
||||||
const text = svg
|
const text = svg
|
||||||
.append("text")
|
.append("text")
|
||||||
.style("fill", "white")
|
.style("fill", "white")
|
||||||
.attr("transform", `translate(${arc.centroid(d).join(",")})`)
|
.attr(
|
||||||
.attr("text-anchor", "middle");
|
"transform",
|
||||||
|
`translate(${arc.centroid(d).join(",")})`,
|
||||||
|
)
|
||||||
|
.attr("text-anchor", "middle");
|
||||||
|
|
||||||
text
|
text.append("tspan")
|
||||||
.append("tspan")
|
.style("font-size", "24")
|
||||||
.style("font-size", "24")
|
.attr("x", "0")
|
||||||
.attr("x", "0")
|
.text(d.data.name);
|
||||||
.text(d.data.name);
|
|
||||||
|
|
||||||
text
|
text.append("tspan")
|
||||||
.append("tspan")
|
.style("font-size", "18")
|
||||||
.style("font-size", "18")
|
.attr("x", "0")
|
||||||
.attr("x", "0")
|
.attr("dy", "1.3em")
|
||||||
.attr("dy", "1.3em")
|
.text(d.value);
|
||||||
.text(d.value);
|
}
|
||||||
}
|
</script>
|
||||||
</script>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,69 +1,72 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Folium</title>
|
<title>Folium</title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
</head>
|
/>
|
||||||
<body>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
<div class="app-header">
|
</head>
|
||||||
<a href="/">
|
<body>
|
||||||
<img src="./logo.png" class="logo" />
|
<nav class="navbar" style="background-color: #000000">
|
||||||
</a>
|
<div class="app-header">
|
||||||
<a class="title" href="" style="color: #f0ab3c">Folium</a>
|
<a href="/">
|
||||||
</div>
|
<img src="./logo.png" class="logo" />
|
||||||
</nav>
|
</a>
|
||||||
<section class="pyscript">
|
<a class="title" href="" style="color: #f0ab3c">Folium</a>
|
||||||
<div id="folium"></div>
|
</div>
|
||||||
|
</nav>
|
||||||
|
<section class="pyscript">
|
||||||
|
<div id="folium"></div>
|
||||||
|
|
||||||
<py-tutor>
|
<py-tutor>
|
||||||
<py-config>
|
<py-config>
|
||||||
packages = [
|
packages = [
|
||||||
"folium",
|
"folium",
|
||||||
"pandas"
|
"pandas"
|
||||||
]
|
]
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<py-script>
|
<py-script>
|
||||||
import folium
|
import folium
|
||||||
import json
|
import json
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from pyodide.http import open_url
|
from pyodide.http import open_url
|
||||||
|
|
||||||
url = (
|
url = (
|
||||||
"https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
|
"https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
|
||||||
)
|
)
|
||||||
state_geo = f"{url}/us-states.json"
|
state_geo = f"{url}/us-states.json"
|
||||||
state_unemployment = f"{url}/US_Unemployment_Oct2012.csv"
|
state_unemployment = f"{url}/US_Unemployment_Oct2012.csv"
|
||||||
state_data = pd.read_csv(open_url(state_unemployment))
|
state_data = pd.read_csv(open_url(state_unemployment))
|
||||||
geo_json = json.loads(open_url(state_geo).read())
|
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(
|
folium.Choropleth(
|
||||||
geo_data=geo_json,
|
geo_data=geo_json,
|
||||||
name="choropleth",
|
name="choropleth",
|
||||||
data=state_data,
|
data=state_data,
|
||||||
columns=["State", "Unemployment"],
|
columns=["State", "Unemployment"],
|
||||||
key_on="feature.id",
|
key_on="feature.id",
|
||||||
fill_color="YlGn",
|
fill_color="YlGn",
|
||||||
fill_opacity=0.7,
|
fill_opacity=0.7,
|
||||||
line_opacity=0.2,
|
line_opacity=0.2,
|
||||||
legend_name="Unemployment Rate (%)",
|
legend_name="Unemployment Rate (%)",
|
||||||
).add_to(m)
|
).add_to(m)
|
||||||
|
|
||||||
folium.LayerControl().add_to(m)
|
folium.LayerControl().add_to(m)
|
||||||
|
|
||||||
display(m, target="folium")
|
display(m, target="folium")
|
||||||
</py-script>
|
</py-script>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</section>
|
</section>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,43 +1,46 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
|
|
||||||
<title>PyScript Hello World</title>
|
<title>PyScript Hello World</title>
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png" />
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
rel="stylesheet"
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
</head>
|
/>
|
||||||
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" href="" style="color: #f0ab3c">Hello World</a>
|
<a class="title" href="" style="color: #f0ab3c">Hello World</a>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<py-tutor>
|
<py-tutor>
|
||||||
<py-config>
|
<py-config>
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<section class="pyscript">
|
<section class="pyscript">
|
||||||
Hello world! <br />
|
Hello world! <br />
|
||||||
This is the current date and time, as computed by Python:
|
This is the current date and time, as computed by Python:
|
||||||
<py-script>
|
<py-script>
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
display(now.strftime("%m/%d/%Y, %H:%M:%S"))
|
display(now.strftime("%m/%d/%Y, %H:%M:%S"))
|
||||||
</py-script>
|
</py-script>
|
||||||
</section>
|
</section>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,277 +1,315 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<title>PyScript demo</title>
|
<title>PyScript demo</title>
|
||||||
<link rel="icon" type="image/png" href="favicon.png" />
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
<link rel="stylesheet" href="./assets/css/main.css" />
|
<link rel="stylesheet" href="./assets/css/main.css" />
|
||||||
<link rel="stylesheet" href="./assets/css/index.css" />
|
<link rel="stylesheet" href="./assets/css/index.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="container">
|
<body class="container">
|
||||||
<h1 class="title-main">PyScript demos</h1>
|
<h1 class="title-main">PyScript demos</h1>
|
||||||
<section class="example">
|
<section class="example">
|
||||||
<h2>Basic examples</h2>
|
<h2>Basic examples</h2>
|
||||||
<div class="container-card">
|
<div class="container-card">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./hello_world.html" target="_blank">
|
<a href="./hello_world.html" target="_blank">
|
||||||
<h2>Hello world</h2>
|
<h2>Hello world</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>A static demo of the <code><py-script></code> tag</p>
|
<p>
|
||||||
</div>
|
A static demo of the
|
||||||
</div>
|
<code><py-script></code> tag
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./simple_clock.html" target="_blank">
|
<a href="./simple_clock.html" target="_blank">
|
||||||
<h2>Simple clock</h2>
|
<h2>Simple clock</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>A dynamic demo of the <code><py-script></code> tag</p>
|
<p>
|
||||||
</div>
|
A dynamic demo of the
|
||||||
</div>
|
<code><py-script></code> tag
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./repl.html" target="_blank">
|
<a href="./repl.html" target="_blank">
|
||||||
<h2>REPL</h2>
|
<h2>REPL</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>A Python REPL (Read Eval Print Loop)</p>
|
<p>A Python REPL (Read Eval Print Loop)</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./repl2.html" target="_blank">
|
<a href="./repl2.html" target="_blank">
|
||||||
<h2>REPL2</h2>
|
<h2>REPL2</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
A Python REPL (Read Eval Print Loop) with slightly better
|
A Python REPL (Read Eval Print Loop) with slightly
|
||||||
formatting
|
better formatting
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./todo.html" target="_blank">
|
<a href="./todo.html" target="_blank">
|
||||||
<h2>TODO App</h2>
|
<h2>TODO App</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>Simple TODO App</p>
|
<p>Simple TODO App</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./todo-pylist.html" target="_blank">
|
<a href="./todo-pylist.html" target="_blank">
|
||||||
<h2>PyScript Native TODO App</h2>
|
<h2>PyScript Native TODO App</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>Simple TODO App using <code><py-list></code></p>
|
<p>
|
||||||
</div>
|
Simple TODO App using <code><py-list></code>
|
||||||
</div>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="example">
|
<section class="example">
|
||||||
<h2>MIME Rendering</h2>
|
<h2>MIME Rendering</h2>
|
||||||
<div class="container-card">
|
<div class="container-card">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./matplotlib.html" target="_blank">
|
<a href="./matplotlib.html" target="_blank">
|
||||||
<h2>Matplotlib</h2>
|
<h2>Matplotlib</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
Demonstrates rendering a
|
Demonstrates rendering a
|
||||||
<a href="https://matplotlib.org/" target="_blank">Matplotlib</a>
|
<a href="https://matplotlib.org/" target="_blank"
|
||||||
figure as output of the py-script tag
|
>Matplotlib</a
|
||||||
</p>
|
>
|
||||||
</div>
|
figure as output of the py-script tag
|
||||||
</div>
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./altair.html" target="_blank">
|
<a href="./altair.html" target="_blank">
|
||||||
<h2>Altair</h2>
|
<h2>Altair</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
Demonstrates rendering a
|
Demonstrates rendering a
|
||||||
<a href="https://altair-viz.github.io/" target="_blank">Altair</a>
|
<a
|
||||||
plot as output of the py-script tag
|
href="https://altair-viz.github.io/"
|
||||||
</p>
|
target="_blank"
|
||||||
</div>
|
>Altair</a
|
||||||
</div>
|
>
|
||||||
|
plot as output of the py-script tag
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./folium.html" target="_blank">
|
<a href="./folium.html" target="_blank">
|
||||||
<h2>Folium</h2>
|
<h2>Folium</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
Demonstrates rendering a
|
Demonstrates rendering a
|
||||||
<a
|
<a
|
||||||
href="https://python-visualization.github.io/folium/"
|
href="https://python-visualization.github.io/folium/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>Folium</a
|
>Folium</a
|
||||||
>
|
>
|
||||||
map as output of the py-script tag
|
map as output of the py-script tag
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="example">
|
<section class="example">
|
||||||
<h2>JS Interaction</h2>
|
<h2>JS Interaction</h2>
|
||||||
<div class="container-card">
|
<div class="container-card">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./d3.html" target="_blank">
|
<a href="./d3.html" target="_blank">
|
||||||
<h2>Simple d3 visualization</h2>
|
<h2>Simple d3 visualization</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
Minimal <a href="https://d3js.org/" target="_blank">D3</a>
|
Minimal
|
||||||
demo demonstrating how to create a visualization
|
<a href="https://d3js.org/" target="_blank">D3</a>
|
||||||
</p>
|
demo demonstrating how to create a visualization
|
||||||
</div>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./webgl/raycaster/index.html" target="_blank">
|
<a href="./webgl/raycaster/index.html" target="_blank">
|
||||||
<h2>Webgl Icosahedron Example</h2>
|
<h2>Webgl Icosahedron Example</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
Demo showing how a Simple
|
Demo showing how a Simple
|
||||||
<a
|
<a
|
||||||
href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API"
|
href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>WebGL</a
|
>WebGL</a
|
||||||
>
|
>
|
||||||
scene would work in the <code><py-script></code> tag
|
scene would work in the
|
||||||
</p>
|
<code><py-script></code> tag
|
||||||
</div>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="example">
|
<section class="example">
|
||||||
<h2>Visualizations & Dashboards</h2>
|
<h2>Visualizations & Dashboards</h2>
|
||||||
<div class="container-card">
|
<div class="container-card">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./bokeh.html" target="_blank">
|
<a href="./bokeh.html" target="_blank">
|
||||||
<h2>Simple Static Bokeh Plot</h2>
|
<h2>Simple Static Bokeh Plot</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
Minimal Bokeh demo demonstrating how to create a simple
|
Minimal Bokeh demo demonstrating how to create a
|
||||||
<a href="https://bokeh.org/" target="_blank">Bokeh</a>
|
simple
|
||||||
plot from code
|
<a href="https://bokeh.org/" target="_blank"
|
||||||
</p>
|
>Bokeh</a
|
||||||
</div>
|
>
|
||||||
</div>
|
plot from code
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./bokeh_interactive.html" target="_blank">
|
<a href="./bokeh_interactive.html" target="_blank">
|
||||||
<h2 class="text-2xl font-bold text-blue-600">
|
<h2 class="text-2xl font-bold text-blue-600">
|
||||||
Bokeh Interactive
|
Bokeh Interactive
|
||||||
</h2>
|
</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
Interactive demo using a
|
Interactive demo using a
|
||||||
<a href="https://bokeh.org/" target="_blank">Bokeh</a>
|
<a href="https://bokeh.org/" target="_blank"
|
||||||
slider widget to dynamically change a value in the page WARNING:
|
>Bokeh</a
|
||||||
This examples takes a little longer to load. So be patient :)
|
>
|
||||||
</p>
|
slider widget to dynamically change a value in the
|
||||||
</div>
|
page WARNING: This examples takes a little longer to
|
||||||
</div>
|
load. So be patient :)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./panel_kmeans.html" target="_blank">
|
<a href="./panel_kmeans.html" target="_blank">
|
||||||
<h2 class="text-2xl font-bold text-blue-600">
|
<h2 class="text-2xl font-bold text-blue-600">
|
||||||
KMeans Demo in Panel
|
KMeans Demo in Panel
|
||||||
</h2>
|
</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
Interactive KMeans Chart using
|
Interactive KMeans Chart using
|
||||||
<a href="https://panel.holoviz.org/" target="_blank">Panel</a>
|
<a href="https://panel.holoviz.org/" target="_blank"
|
||||||
WARNING: This examples takes a little longer to load. So be
|
>Panel</a
|
||||||
patient :)
|
>
|
||||||
</p>
|
WARNING: This examples takes a little longer to
|
||||||
</div>
|
load. So be patient :)
|
||||||
</div>
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./panel_stream.html" target="_blank">
|
<a href="./panel_stream.html" target="_blank">
|
||||||
<h2 class="text-2xl font-bold text-blue-600">
|
<h2 class="text-2xl font-bold text-blue-600">
|
||||||
Streaming Demo in Panel
|
Streaming Demo in Panel
|
||||||
</h2>
|
</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
Interactive Streaming Table and Bokeh plot using
|
Interactive Streaming Table and Bokeh plot using
|
||||||
<a href="https://panel.holoviz.org/" target="_blank">Panel</a>
|
<a href="https://panel.holoviz.org/" target="_blank"
|
||||||
WARNING: This examples takes a little longer to load. So be
|
>Panel</a
|
||||||
patient :)
|
>
|
||||||
</p>
|
WARNING: This examples takes a little longer to
|
||||||
</div>
|
load. So be patient :)
|
||||||
</div>
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./panel.html" target="_blank">
|
<a href="./panel.html" target="_blank">
|
||||||
<h2 class="text-3xl font-bold text-blue-600">
|
<h2 class="text-3xl font-bold text-blue-600">
|
||||||
Simple Panel Demo
|
Simple Panel Demo
|
||||||
</h2>
|
</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
Simple demo showing
|
Simple demo showing
|
||||||
<a href="https://panel.holoviz.org/" target="_blank">Panel</a>
|
<a href="https://panel.holoviz.org/" target="_blank"
|
||||||
widgets interacting with parts of the page WARNING: This examples
|
>Panel</a
|
||||||
takes a little longer to load. So be patient :)
|
>
|
||||||
</p>
|
widgets interacting with parts of the page WARNING:
|
||||||
</div>
|
This examples takes a little longer to load. So be
|
||||||
</div>
|
patient :)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./panel_deckgl.html" target="_blank">
|
<a href="./panel_deckgl.html" target="_blank">
|
||||||
<h2 class="text-2xl font-bold text-blue-600">
|
<h2 class="text-2xl font-bold text-blue-600">
|
||||||
NYC Taxi Data Panel DeckGL Demo
|
NYC Taxi Data Panel DeckGL Demo
|
||||||
</h2>
|
</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
Interactive application exploring the NYC Taxi dataset using
|
Interactive application exploring the NYC Taxi
|
||||||
<a href="https://panel.holoviz.org/" target="_blank">Panel</a> and
|
dataset using
|
||||||
<a href="https://deck.gl/" target="_blank">DeckGL</a>
|
<a href="https://panel.holoviz.org/" target="_blank"
|
||||||
WARNING: This examples takes a little longer to load. So be
|
>Panel</a
|
||||||
patient :)
|
>
|
||||||
</p>
|
and
|
||||||
</div>
|
<a href="https://deck.gl/" target="_blank"
|
||||||
</div>
|
>DeckGL</a
|
||||||
|
>
|
||||||
|
WARNING: This examples takes a little longer to
|
||||||
|
load. So be patient :)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a href="./numpy_canvas_fractals.html" target="_blank">
|
<a href="./numpy_canvas_fractals.html" target="_blank">
|
||||||
<h2 class="text-2xl font-bold text-blue-600">
|
<h2 class="text-2xl font-bold text-blue-600">
|
||||||
Fractals with NumPy and canvas
|
Fractals with NumPy and canvas
|
||||||
</h2>
|
</h2>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
Visualization of Mandelbrot and Julia sets with
|
Visualization of Mandelbrot and Julia sets with
|
||||||
<a href="https://numpy.org/" target="_blank">Numpy</a> and
|
<a href="https://numpy.org/" target="_blank"
|
||||||
<a
|
>Numpy</a
|
||||||
href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API"
|
>
|
||||||
target="_blank"
|
and
|
||||||
>
|
<a
|
||||||
HTML5 canvas
|
href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API"
|
||||||
</a>
|
target="_blank"
|
||||||
</p>
|
>
|
||||||
</div>
|
HTML5 canvas
|
||||||
</div>
|
</a>
|
||||||
</div>
|
</p>
|
||||||
</section>
|
</div>
|
||||||
</body>
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -2,34 +2,34 @@ html,
|
|||||||
body,
|
body,
|
||||||
ul,
|
ul,
|
||||||
li {
|
li {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas {
|
canvas {
|
||||||
display: block;
|
display: block;
|
||||||
width: 762;
|
width: 762;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
background-color: blue;
|
background-color: blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,43 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") window.Mario = {};
|
if (typeof Mario === "undefined") window.Mario = {};
|
||||||
|
|
||||||
var Bcoin = (Mario.Bcoin = function (pos) {
|
var Bcoin = (Mario.Bcoin = function (pos) {
|
||||||
Mario.Entity.call(this, {
|
Mario.Entity.call(this, {
|
||||||
pos: pos,
|
pos: pos,
|
||||||
sprite: level.bcoinSprite(),
|
sprite: level.bcoinSprite(),
|
||||||
hitbox: [0, 0, 16, 16],
|
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
|
//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
|
//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.
|
//it's literally impossible for these to move left or right.
|
||||||
Bcoin.prototype.spawn = function () {
|
Bcoin.prototype.spawn = function () {
|
||||||
sounds.coin.currentTime = 0.05;
|
sounds.coin.currentTime = 0.05;
|
||||||
sounds.coin.play();
|
sounds.coin.play();
|
||||||
this.idx = level.items.length;
|
this.idx = level.items.length;
|
||||||
level.items.push(this);
|
level.items.push(this);
|
||||||
this.active = true;
|
this.active = true;
|
||||||
this.vel = -12;
|
this.vel = -12;
|
||||||
this.targetpos = this.pos[1] - 32;
|
this.targetpos = this.pos[1] - 32;
|
||||||
};
|
};
|
||||||
|
|
||||||
Bcoin.prototype.update = function (dt) {
|
Bcoin.prototype.update = function (dt) {
|
||||||
if (!this.active) return;
|
if (!this.active) return;
|
||||||
|
|
||||||
if (this.vel > 0 && this.pos[1] >= this.targetpos) {
|
if (this.vel > 0 && this.pos[1] >= this.targetpos) {
|
||||||
player.coins += 1;
|
player.coins += 1;
|
||||||
//spawn a score thingy.
|
//spawn a score thingy.
|
||||||
delete level.items[this.idx];
|
delete level.items[this.idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.acc = 0.75;
|
this.acc = 0.75;
|
||||||
this.vel += this.acc;
|
this.vel += this.acc;
|
||||||
this.pos[1] += this.vel;
|
this.pos[1] += this.vel;
|
||||||
this.sprite.update(dt);
|
this.sprite.update(dt);
|
||||||
};
|
};
|
||||||
|
|
||||||
Bcoin.prototype.checkCollisions = function () {};
|
Bcoin.prototype.checkCollisions = function () {};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,81 +1,84 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") window.Mario = {};
|
if (typeof Mario === "undefined") window.Mario = {};
|
||||||
|
|
||||||
//TODO: clean up the logic for sprite switching.
|
//TODO: clean up the logic for sprite switching.
|
||||||
//TODO: There's a weird bug with the collision logic. Look into it.
|
//TODO: There's a weird bug with the collision logic. Look into it.
|
||||||
|
|
||||||
var Block = (Mario.Block = function (options) {
|
var Block = (Mario.Block = function (options) {
|
||||||
this.item = options.item;
|
this.item = options.item;
|
||||||
this.usedSprite = options.usedSprite;
|
this.usedSprite = options.usedSprite;
|
||||||
this.bounceSprite = options.bounceSprite;
|
this.bounceSprite = options.bounceSprite;
|
||||||
this.breakable = options.breakable;
|
this.breakable = options.breakable;
|
||||||
|
|
||||||
Mario.Entity.call(this, {
|
Mario.Entity.call(this, {
|
||||||
pos: options.pos,
|
pos: options.pos,
|
||||||
sprite: options.sprite,
|
sprite: options.sprite,
|
||||||
hitbox: [0, 0, 16, 16],
|
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();
|
||||||
Block.prototype.break = function () {
|
new Mario.Rubble().spawn(this.pos);
|
||||||
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) {
|
|
||||||
var x = this.pos[0] / 16,
|
var x = this.pos[0] / 16,
|
||||||
y = this.pos[1] / 16;
|
y = this.pos[1] / 16;
|
||||||
level.statics[y][x] = new Mario.Floor(this.pos, this.usedSprite);
|
|
||||||
delete level.blocks[y][x];
|
delete level.blocks[y][x];
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
this.pos[1] += this.vel[1];
|
Block.prototype.bonk = function (power) {
|
||||||
this.sprite.update(dt, gameTime);
|
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);
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,59 +1,62 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") window.Mario = {};
|
if (typeof Mario === "undefined") window.Mario = {};
|
||||||
|
|
||||||
var Coin = (Mario.Coin = function (pos, sprite) {
|
var Coin = (Mario.Coin = function (pos, sprite) {
|
||||||
Mario.Entity.call(this, {
|
Mario.Entity.call(this, {
|
||||||
pos: pos,
|
pos: pos,
|
||||||
sprite: sprite,
|
sprite: sprite,
|
||||||
hitbox: [0, 0, 16, 16],
|
hitbox: [0, 0, 16, 16],
|
||||||
|
});
|
||||||
|
this.idx = level.items.length;
|
||||||
});
|
});
|
||||||
this.idx = level.items.length;
|
|
||||||
});
|
|
||||||
|
|
||||||
Mario.Util.inherits(Coin, Mario.Entity);
|
Mario.Util.inherits(Coin, Mario.Entity);
|
||||||
|
|
||||||
Coin.prototype.isPlayerCollided = function () {
|
Coin.prototype.isPlayerCollided = function () {
|
||||||
//the first two elements of the hitbox array are an offset, so let's do this now.
|
//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 hpos1 = [
|
||||||
var hpos2 = [
|
this.pos[0] + this.hitbox[0],
|
||||||
player.pos[0] + player.hitbox[0],
|
this.pos[1] + this.hitbox[1],
|
||||||
player.pos[1] + player.hitbox[1],
|
];
|
||||||
];
|
var hpos2 = [
|
||||||
|
player.pos[0] + player.hitbox[0],
|
||||||
|
player.pos[1] + player.hitbox[1],
|
||||||
|
];
|
||||||
|
|
||||||
//if the hitboxes actually overlap
|
//if the hitboxes actually overlap
|
||||||
if (
|
if (
|
||||||
!(
|
!(
|
||||||
hpos1[0] > hpos2[0] + player.hitbox[2] ||
|
hpos1[0] > hpos2[0] + player.hitbox[2] ||
|
||||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
hpos1[0] + this.hitbox[2] < hpos2[0]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
!(
|
!(
|
||||||
hpos1[1] > hpos2[1] + player.hitbox[3] ||
|
hpos1[1] > hpos2[1] + player.hitbox[3] ||
|
||||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
hpos1[1] + this.hitbox[3] < hpos2[1]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
this.collect();
|
this.collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Coin.prototype.render = function (ctx, vX, vY) {
|
Coin.prototype.render = function (ctx, vX, vY) {
|
||||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||||
};
|
};
|
||||||
|
|
||||||
//money is not affected by gravity, you see.
|
//money is not affected by gravity, you see.
|
||||||
Coin.prototype.update = function (dt) {
|
Coin.prototype.update = function (dt) {
|
||||||
this.sprite.update(dt);
|
this.sprite.update(dt);
|
||||||
};
|
};
|
||||||
Coin.prototype.checkCollisions = function () {
|
Coin.prototype.checkCollisions = function () {
|
||||||
this.isPlayerCollided();
|
this.isPlayerCollided();
|
||||||
};
|
};
|
||||||
|
|
||||||
Coin.prototype.collect = function () {
|
Coin.prototype.collect = function () {
|
||||||
sounds.coin.currentTime = 0.05;
|
sounds.coin.currentTime = 0.05;
|
||||||
sounds.coin.play();
|
sounds.coin.play();
|
||||||
player.coins += 1;
|
player.coins += 1;
|
||||||
delete level.items[this.idx];
|
delete level.items[this.idx];
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") window.Mario = {};
|
if (typeof Mario === "undefined") window.Mario = {};
|
||||||
|
|
||||||
var Entity = (Mario.Entity = function (options) {
|
var Entity = (Mario.Entity = function (options) {
|
||||||
this.vel = [0, 0];
|
this.vel = [0, 0];
|
||||||
this.acc = [0, 0];
|
this.acc = [0, 0];
|
||||||
this.standing = true;
|
this.standing = true;
|
||||||
this.pos = options.pos;
|
this.pos = options.pos;
|
||||||
this.sprite = options.sprite;
|
this.sprite = options.sprite;
|
||||||
this.hitbox = options.hitbox;
|
this.hitbox = options.hitbox;
|
||||||
this.left = false;
|
this.left = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
Entity.prototype.render = function (ctx, vX, vY) {
|
Entity.prototype.render = function (ctx, vX, vY) {
|
||||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||||
};
|
};
|
||||||
|
|
||||||
Entity.prototype.collideWall = function (wall) {
|
Entity.prototype.collideWall = function (wall) {
|
||||||
//the wall will always be a 16x16 block with hitbox = [0,0,16,16].
|
//the wall will always be a 16x16 block with hitbox = [0,0,16,16].
|
||||||
if (this.pos[0] > wall.pos[0]) {
|
if (this.pos[0] > wall.pos[0]) {
|
||||||
//from the right
|
//from the right
|
||||||
this.pos[0] = wall.pos[0] + wall.hitbox[2] - this.hitbox[0];
|
this.pos[0] = wall.pos[0] + wall.hitbox[2] - this.hitbox[0];
|
||||||
this.vel[0] = Math.max(0, this.vel[0]);
|
this.vel[0] = Math.max(0, this.vel[0]);
|
||||||
this.acc[0] = Math.max(0, this.acc[0]);
|
this.acc[0] = Math.max(0, this.acc[0]);
|
||||||
} else {
|
} else {
|
||||||
this.pos[0] =
|
this.pos[0] =
|
||||||
wall.pos[0] + wall.hitbox[0] - this.hitbox[2] - this.hitbox[0];
|
wall.pos[0] + wall.hitbox[0] - this.hitbox[2] - this.hitbox[0];
|
||||||
this.vel[0] = Math.min(0, this.vel[0]);
|
this.vel[0] = Math.min(0, this.vel[0]);
|
||||||
this.acc[0] = Math.min(0, this.acc[0]);
|
this.acc[0] = Math.min(0, this.acc[0]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Entity.prototype.bump = function () {};
|
Entity.prototype.bump = function () {};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,142 +1,145 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") window.Mario = {};
|
if (typeof Mario === "undefined") window.Mario = {};
|
||||||
|
|
||||||
var Fireball = (Mario.Fireball = function (pos) {
|
var Fireball = (Mario.Fireball = function (pos) {
|
||||||
this.hit = 0;
|
this.hit = 0;
|
||||||
this.standing = false;
|
this.standing = false;
|
||||||
|
|
||||||
Mario.Entity.call(this, {
|
Mario.Entity.call(this, {
|
||||||
pos: pos,
|
pos: pos,
|
||||||
sprite: new Mario.Sprite(
|
sprite: new Mario.Sprite(
|
||||||
"sprites/items.png",
|
"sprites/items.png",
|
||||||
[96, 144],
|
[96, 144],
|
||||||
[8, 8],
|
[8, 8],
|
||||||
5,
|
5,
|
||||||
[0, 1, 2, 3],
|
[0, 1, 2, 3],
|
||||||
),
|
),
|
||||||
hitbox: [0, 0, 8, 8],
|
hitbox: [0, 0, 8, 8],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
Mario.Util.inherits(Fireball, Mario.Entity);
|
Mario.Util.inherits(Fireball, Mario.Entity);
|
||||||
|
|
||||||
Fireball.prototype.spawn = function (left) {
|
Fireball.prototype.spawn = function (left) {
|
||||||
sounds.fireball.currentTime = 0;
|
sounds.fireball.currentTime = 0;
|
||||||
sounds.fireball.play();
|
sounds.fireball.play();
|
||||||
if (fireballs[0]) {
|
if (fireballs[0]) {
|
||||||
this.idx = 1;
|
this.idx = 1;
|
||||||
fireballs[1] = this;
|
fireballs[1] = this;
|
||||||
} else {
|
} else {
|
||||||
this.idx = 0;
|
this.idx = 0;
|
||||||
fireballs[0] = this;
|
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);
|
|
||||||
}
|
}
|
||||||
if (level.blocks[baseY + i][baseX + j]) {
|
this.vel[0] = left ? -5 : 5;
|
||||||
level.blocks[baseY + i][baseX + j].isCollideWith(this);
|
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;
|
//In retrospect, the way collision is being handled is RIDICULOUS
|
||||||
level.enemies.forEach(function (enemy) {
|
//but I don't have to use some horrible kludge for this.
|
||||||
if (enemy.flipping || enemy.pos[0] - vX > 336) {
|
if (this.standing) {
|
||||||
//stop checking once we get to far away dudes.
|
this.standing = false;
|
||||||
return;
|
this.vel[1] = -4;
|
||||||
} else {
|
}
|
||||||
that.isCollideWith(enemy);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Fireball.prototype.isCollideWith = function (ent) {
|
this.acc[1] = 0.5;
|
||||||
//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
|
this.vel[1] += this.acc[1];
|
||||||
if (
|
this.pos[0] += this.vel[0];
|
||||||
!(
|
this.pos[1] += this.vel[1];
|
||||||
hpos1[0] > hpos2[0] + ent.hitbox[2] ||
|
if (this.pos[0] < vX || this.pos[0] > vX + 256) {
|
||||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
this.hit = 1;
|
||||||
)
|
}
|
||||||
) {
|
this.sprite.update(dt);
|
||||||
if (
|
};
|
||||||
!(
|
|
||||||
hpos1[1] > hpos2[1] + ent.hitbox[3] ||
|
|
||||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
this.hit = 1;
|
|
||||||
ent.bump();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Fireball.prototype.bump = function () {};
|
Fireball.prototype.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 () {};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,87 +1,90 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") window.Mario = {};
|
if (typeof Mario === "undefined") window.Mario = {};
|
||||||
|
|
||||||
var Fireflower = (Mario.Fireflower = function (pos) {
|
var Fireflower = (Mario.Fireflower = function (pos) {
|
||||||
this.spawning = false;
|
this.spawning = false;
|
||||||
this.waiting = 0;
|
this.waiting = 0;
|
||||||
|
|
||||||
Mario.Entity.call(this, {
|
Mario.Entity.call(this, {
|
||||||
pos: pos,
|
pos: pos,
|
||||||
sprite: level.fireFlowerSprite,
|
sprite: level.fireFlowerSprite,
|
||||||
hitbox: [0, 0, 16, 16],
|
hitbox: [0, 0, 16, 16],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
Mario.Util.inherits(Fireflower, Mario.Entity);
|
Mario.Util.inherits(Fireflower, Mario.Entity);
|
||||||
|
|
||||||
Fireflower.prototype.render = function (ctx, vX, vY) {
|
Fireflower.prototype.render = function (ctx, vX, vY) {
|
||||||
if (this.spawning > 1) return;
|
if (this.spawning > 1) return;
|
||||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||||
};
|
};
|
||||||
|
|
||||||
Fireflower.prototype.spawn = function () {
|
Fireflower.prototype.spawn = function () {
|
||||||
sounds.itemAppear.play();
|
sounds.itemAppear.play();
|
||||||
this.idx = level.items.length;
|
this.idx = level.items.length;
|
||||||
level.items.push(this);
|
level.items.push(this);
|
||||||
this.spawning = 12;
|
this.spawning = 12;
|
||||||
this.targetpos = [];
|
this.targetpos = [];
|
||||||
this.targetpos[0] = this.pos[0];
|
this.targetpos[0] = this.pos[0];
|
||||||
this.targetpos[1] = this.pos[1] - 16;
|
this.targetpos[1] = this.pos[1] - 16;
|
||||||
};
|
};
|
||||||
|
|
||||||
Fireflower.prototype.update = function (dt) {
|
Fireflower.prototype.update = function (dt) {
|
||||||
if (this.spawning > 1) {
|
if (this.spawning > 1) {
|
||||||
this.spawning -= 1;
|
this.spawning -= 1;
|
||||||
if (this.spawning == 1) this.vel[1] = -0.5;
|
if (this.spawning == 1) this.vel[1] = -0.5;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.spawning) {
|
if (this.spawning) {
|
||||||
if (this.pos[1] <= this.targetpos[1]) {
|
if (this.pos[1] <= this.targetpos[1]) {
|
||||||
this.pos[1] = this.targetpos[1];
|
this.pos[1] = this.targetpos[1];
|
||||||
this.vel[1] = 0;
|
this.vel[1] = 0;
|
||||||
this.spawning = 0;
|
this.spawning = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.vel[1] += this.acc[1];
|
this.vel[1] += this.acc[1];
|
||||||
this.pos[0] += this.vel[0];
|
this.pos[0] += this.vel[0];
|
||||||
this.pos[1] += this.vel[1];
|
this.pos[1] += this.vel[1];
|
||||||
this.sprite.update(dt);
|
this.sprite.update(dt);
|
||||||
};
|
};
|
||||||
|
|
||||||
Fireflower.prototype.checkCollisions = function () {
|
Fireflower.prototype.checkCollisions = function () {
|
||||||
if (this.spawning) {
|
if (this.spawning) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.isPlayerCollided();
|
this.isPlayerCollided();
|
||||||
};
|
};
|
||||||
|
|
||||||
Fireflower.prototype.isPlayerCollided = function () {
|
Fireflower.prototype.isPlayerCollided = function () {
|
||||||
//the first two elements of the hitbox array are an offset, so let's do this now.
|
//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 hpos1 = [
|
||||||
var hpos2 = [
|
this.pos[0] + this.hitbox[0],
|
||||||
player.pos[0] + player.hitbox[0],
|
this.pos[1] + this.hitbox[1],
|
||||||
player.pos[1] + player.hitbox[1],
|
];
|
||||||
];
|
var hpos2 = [
|
||||||
|
player.pos[0] + player.hitbox[0],
|
||||||
|
player.pos[1] + player.hitbox[1],
|
||||||
|
];
|
||||||
|
|
||||||
//if the hitboxes actually overlap
|
//if the hitboxes actually overlap
|
||||||
if (
|
if (
|
||||||
!(
|
!(
|
||||||
hpos1[0] > hpos2[0] + player.hitbox[2] ||
|
hpos1[0] > hpos2[0] + player.hitbox[2] ||
|
||||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
hpos1[0] + this.hitbox[2] < hpos2[0]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
!(
|
!(
|
||||||
hpos1[1] > hpos2[1] + player.hitbox[3] ||
|
hpos1[1] > hpos2[1] + player.hitbox[3] ||
|
||||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
hpos1[1] + this.hitbox[3] < hpos2[1]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
player.powerUp(this.idx);
|
player.powerUp(this.idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//This should never be called, but just in case.
|
//This should never be called, but just in case.
|
||||||
Fireflower.prototype.bump = function () {};
|
Fireflower.prototype.bump = function () {};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,45 +1,51 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") window.Mario = {};
|
if (typeof Mario === "undefined") window.Mario = {};
|
||||||
|
|
||||||
Flag = Mario.Flag = function (pos) {
|
Flag = Mario.Flag = function (pos) {
|
||||||
//afaik flags always have the same height and Y-position
|
//afaik flags always have the same height and Y-position
|
||||||
this.pos = [pos, 49];
|
this.pos = [pos, 49];
|
||||||
this.hitbox = [0, 0, 0, 0];
|
this.hitbox = [0, 0, 0, 0];
|
||||||
this.vel = [0, 0];
|
this.vel = [0, 0];
|
||||||
this.acc = [0, 0];
|
this.acc = [0, 0];
|
||||||
};
|
};
|
||||||
|
|
||||||
Flag.prototype.collideWall = function () {};
|
Flag.prototype.collideWall = function () {};
|
||||||
|
|
||||||
Flag.prototype.update = function (dt) {
|
Flag.prototype.update = function (dt) {
|
||||||
if (!this.done && this.pos[1] >= 170) {
|
if (!this.done && this.pos[1] >= 170) {
|
||||||
this.vel = [0, 0];
|
this.vel = [0, 0];
|
||||||
this.pos[1] = 170;
|
this.pos[1] = 170;
|
||||||
player.exit();
|
player.exit();
|
||||||
this.done = true;
|
this.done = true;
|
||||||
}
|
}
|
||||||
this.pos[1] += this.vel[1];
|
this.pos[1] += this.vel[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
Flag.prototype.checkCollisions = function () {
|
Flag.prototype.checkCollisions = function () {
|
||||||
this.isPlayerCollided();
|
this.isPlayerCollided();
|
||||||
};
|
};
|
||||||
|
|
||||||
Flag.prototype.isPlayerCollided = function () {
|
Flag.prototype.isPlayerCollided = function () {
|
||||||
if (this.hit) return;
|
if (this.hit) return;
|
||||||
if (player.pos[0] + 8 >= this.pos[0]) {
|
if (player.pos[0] + 8 >= this.pos[0]) {
|
||||||
music.overworld.pause();
|
music.overworld.pause();
|
||||||
sounds.flagpole.play();
|
sounds.flagpole.play();
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
music.clear.play();
|
music.clear.play();
|
||||||
}, 2000);
|
}, 2000);
|
||||||
this.hit = true;
|
this.hit = true;
|
||||||
player.flag();
|
player.flag();
|
||||||
this.vel = [0, 2];
|
this.vel = [0, 2];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Flag.prototype.render = function () {
|
Flag.prototype.render = function () {
|
||||||
level.flagpoleSprites[2].render(ctx, this.pos[0] - 8, this.pos[1], vX, vY);
|
level.flagpoleSprites[2].render(
|
||||||
};
|
ctx,
|
||||||
|
this.pos[0] - 8,
|
||||||
|
this.pos[1],
|
||||||
|
vX,
|
||||||
|
vY,
|
||||||
|
);
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,75 +1,83 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") window.Mario = {};
|
if (typeof Mario === "undefined") window.Mario = {};
|
||||||
|
|
||||||
var Floor = (Mario.Floor = function (pos, sprite) {
|
var Floor = (Mario.Floor = function (pos, sprite) {
|
||||||
Mario.Entity.call(this, {
|
Mario.Entity.call(this, {
|
||||||
pos: pos,
|
pos: pos,
|
||||||
sprite: sprite,
|
sprite: sprite,
|
||||||
hitbox: [0, 0, 16, 16],
|
hitbox: [0, 0, 16, 16],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
Mario.Util.inherits(Floor, Mario.Entity);
|
Mario.Util.inherits(Floor, Mario.Entity);
|
||||||
|
|
||||||
Floor.prototype.isCollideWith = function (ent) {
|
Floor.prototype.isCollideWith = function (ent) {
|
||||||
//the first two elements of the hitbox array are an offset, so let's do this now.
|
//the first two elements of the hitbox array are an offset, so let's do this now.
|
||||||
var hpos1 = [
|
var hpos1 = [
|
||||||
Math.floor(this.pos[0] + this.hitbox[0]),
|
Math.floor(this.pos[0] + this.hitbox[0]),
|
||||||
Math.floor(this.pos[1] + this.hitbox[1]),
|
Math.floor(this.pos[1] + this.hitbox[1]),
|
||||||
];
|
];
|
||||||
var hpos2 = [
|
var hpos2 = [
|
||||||
Math.floor(ent.pos[0] + ent.hitbox[0]),
|
Math.floor(ent.pos[0] + ent.hitbox[0]),
|
||||||
Math.floor(ent.pos[1] + ent.hitbox[1]),
|
Math.floor(ent.pos[1] + ent.hitbox[1]),
|
||||||
];
|
];
|
||||||
|
|
||||||
//if the hitboxes actually overlap
|
//if the hitboxes actually overlap
|
||||||
if (
|
if (
|
||||||
!(
|
!(
|
||||||
hpos1[0] > hpos2[0] + ent.hitbox[2] ||
|
hpos1[0] > hpos2[0] + ent.hitbox[2] ||
|
||||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
hpos1[0] + this.hitbox[2] < hpos2[0]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
!(
|
!(
|
||||||
hpos1[1] > hpos2[1] + ent.hitbox[3] ||
|
hpos1[1] > hpos2[1] + ent.hitbox[3] ||
|
||||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
hpos1[1] + this.hitbox[3] < hpos2[1]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
if (!this.standing) {
|
if (!this.standing) {
|
||||||
ent.bump();
|
ent.bump();
|
||||||
} else {
|
} else {
|
||||||
//if the entity is over the block, it's basically floor
|
//if the entity is over the block, it's basically floor
|
||||||
var center = hpos2[0] + ent.hitbox[2] / 2;
|
var center = hpos2[0] + ent.hitbox[2] / 2;
|
||||||
if (Math.abs(hpos2[1] + ent.hitbox[3] - hpos1[1]) <= ent.vel[1]) {
|
if (
|
||||||
if (level.statics[this.pos[1] / 16 - 1][this.pos[0] / 16]) {
|
Math.abs(hpos2[1] + ent.hitbox[3] - hpos1[1]) <=
|
||||||
return;
|
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 () {};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
var requestAnimFrame = (function () {
|
var requestAnimFrame = (function () {
|
||||||
return (
|
return (
|
||||||
window.requestAnimationFrame ||
|
window.requestAnimationFrame ||
|
||||||
window.webkitRequestAnimationFrame ||
|
window.webkitRequestAnimationFrame ||
|
||||||
window.mozRequestAnimationFrame ||
|
window.mozRequestAnimationFrame ||
|
||||||
window.oRequestAnimationFrame ||
|
window.oRequestAnimationFrame ||
|
||||||
window.msRequestAnimationFrame ||
|
window.msRequestAnimationFrame ||
|
||||||
function (callback) {
|
function (callback) {
|
||||||
window.setTimeout(callback, 1000 / 60);
|
window.setTimeout(callback, 1000 / 60);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
//create the canvas
|
//create the canvas
|
||||||
@@ -30,18 +30,18 @@ document.body.appendChild(canvas);
|
|||||||
|
|
||||||
//viewport
|
//viewport
|
||||||
var vX = 0,
|
var vX = 0,
|
||||||
vY = 0,
|
vY = 0,
|
||||||
vWidth = 256,
|
vWidth = 256,
|
||||||
vHeight = 240;
|
vHeight = 240;
|
||||||
|
|
||||||
//load our images
|
//load our images
|
||||||
resources.load([
|
resources.load([
|
||||||
"sprites/player.png",
|
"sprites/player.png",
|
||||||
"sprites/enemy.png",
|
"sprites/enemy.png",
|
||||||
"sprites/tiles.png",
|
"sprites/tiles.png",
|
||||||
"sprites/playerl.png",
|
"sprites/playerl.png",
|
||||||
"sprites/items.png",
|
"sprites/items.png",
|
||||||
"sprites/enemyr.png",
|
"sprites/enemyr.png",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
resources.onReady(init);
|
resources.onReady(init);
|
||||||
@@ -52,194 +52,202 @@ var music;
|
|||||||
//initialize
|
//initialize
|
||||||
var lastTime;
|
var lastTime;
|
||||||
function init() {
|
function init() {
|
||||||
music = {
|
music = {
|
||||||
overworld: new Audio("sounds/aboveground_bgm.ogg"),
|
overworld: new Audio("sounds/aboveground_bgm.ogg"),
|
||||||
underground: new Audio("sounds/underground_bgm.ogg"),
|
underground: new Audio("sounds/underground_bgm.ogg"),
|
||||||
clear: new Audio("sounds/stage_clear.wav"),
|
clear: new Audio("sounds/stage_clear.wav"),
|
||||||
death: new Audio("sounds/mariodie.wav"),
|
death: new Audio("sounds/mariodie.wav"),
|
||||||
};
|
};
|
||||||
sounds = {
|
sounds = {
|
||||||
smallJump: new Audio("sounds/jump-small.wav"),
|
smallJump: new Audio("sounds/jump-small.wav"),
|
||||||
bigJump: new Audio("sounds/jump-super.wav"),
|
bigJump: new Audio("sounds/jump-super.wav"),
|
||||||
breakBlock: new Audio("sounds/breakblock.wav"),
|
breakBlock: new Audio("sounds/breakblock.wav"),
|
||||||
bump: new Audio("sounds/bump.wav"),
|
bump: new Audio("sounds/bump.wav"),
|
||||||
coin: new Audio("sounds/coin.wav"),
|
coin: new Audio("sounds/coin.wav"),
|
||||||
fireball: new Audio("sounds/fireball.wav"),
|
fireball: new Audio("sounds/fireball.wav"),
|
||||||
flagpole: new Audio("sounds/flagpole.wav"),
|
flagpole: new Audio("sounds/flagpole.wav"),
|
||||||
kick: new Audio("sounds/kick.wav"),
|
kick: new Audio("sounds/kick.wav"),
|
||||||
pipe: new Audio("sounds/pipe.wav"),
|
pipe: new Audio("sounds/pipe.wav"),
|
||||||
itemAppear: new Audio("sounds/itemAppear.wav"),
|
itemAppear: new Audio("sounds/itemAppear.wav"),
|
||||||
powerup: new Audio("sounds/powerup.wav"),
|
powerup: new Audio("sounds/powerup.wav"),
|
||||||
stomp: new Audio("sounds/stomp.wav"),
|
stomp: new Audio("sounds/stomp.wav"),
|
||||||
};
|
};
|
||||||
Mario.oneone();
|
Mario.oneone();
|
||||||
lastTime = Date.now();
|
lastTime = Date.now();
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
var gameTime = 0;
|
var gameTime = 0;
|
||||||
|
|
||||||
//set up the game loop
|
//set up the game loop
|
||||||
function main() {
|
function main() {
|
||||||
var now = Date.now();
|
var now = Date.now();
|
||||||
var dt = (now - lastTime) / 1000.0;
|
var dt = (now - lastTime) / 1000.0;
|
||||||
|
|
||||||
update(dt);
|
update(dt);
|
||||||
render();
|
render();
|
||||||
|
|
||||||
lastTime = now;
|
lastTime = now;
|
||||||
requestAnimFrame(main);
|
requestAnimFrame(main);
|
||||||
}
|
}
|
||||||
|
|
||||||
function update(dt) {
|
function update(dt) {
|
||||||
gameTime += dt;
|
gameTime += dt;
|
||||||
|
|
||||||
handleInput(dt);
|
handleInput(dt);
|
||||||
updateEntities(dt, gameTime);
|
updateEntities(dt, gameTime);
|
||||||
|
|
||||||
checkCollisions();
|
checkCollisions();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleInput(dt) {
|
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")) {
|
if (input.isDown("RUN")) {
|
||||||
player.run();
|
player.run();
|
||||||
} else {
|
} else {
|
||||||
player.noRun();
|
player.noRun();
|
||||||
}
|
}
|
||||||
if (input.isDown("JUMP")) {
|
if (input.isDown("JUMP")) {
|
||||||
player.jump();
|
player.jump();
|
||||||
} else {
|
} else {
|
||||||
//we need this to handle the timing for how long you hold it
|
//we need this to handle the timing for how long you hold it
|
||||||
player.noJump();
|
player.noJump();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.isDown("DOWN")) {
|
if (input.isDown("DOWN")) {
|
||||||
player.crouch();
|
player.crouch();
|
||||||
} else {
|
} else {
|
||||||
player.noCrouch();
|
player.noCrouch();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.isDown("LEFT")) {
|
if (input.isDown("LEFT")) {
|
||||||
// 'd' or left arrow
|
// 'd' or left arrow
|
||||||
player.moveLeft();
|
player.moveLeft();
|
||||||
} else if (input.isDown("RIGHT")) {
|
} else if (input.isDown("RIGHT")) {
|
||||||
// 'k' or right arrow
|
// 'k' or right arrow
|
||||||
player.moveRight();
|
player.moveRight();
|
||||||
} else {
|
} else {
|
||||||
player.noWalk();
|
player.noWalk();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//update all the moving stuff
|
//update all the moving stuff
|
||||||
function updateEntities(dt, gameTime) {
|
function updateEntities(dt, gameTime) {
|
||||||
player.update(dt, vX);
|
player.update(dt, vX);
|
||||||
updateables.forEach(function (ent) {
|
updateables.forEach(function (ent) {
|
||||||
ent.update(dt, gameTime);
|
ent.update(dt, gameTime);
|
||||||
});
|
});
|
||||||
|
|
||||||
//This should stop the jump when he switches sides on the flag.
|
//This should stop the jump when he switches sides on the flag.
|
||||||
if (player.exiting) {
|
if (player.exiting) {
|
||||||
if (player.pos[0] > vX + 96) vX = player.pos[0] - 96;
|
if (player.pos[0] > vX + 96) vX = player.pos[0] - 96;
|
||||||
} else if (level.scrolling && player.pos[0] > vX + 80) {
|
} else if (level.scrolling && player.pos[0] > vX + 80) {
|
||||||
vX = player.pos[0] - 80;
|
vX = player.pos[0] - 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.powering.length !== 0 || player.dying) {
|
if (player.powering.length !== 0 || player.dying) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
level.items.forEach(function (ent) {
|
level.items.forEach(function (ent) {
|
||||||
ent.update(dt);
|
ent.update(dt);
|
||||||
});
|
});
|
||||||
|
|
||||||
level.enemies.forEach(function (ent) {
|
level.enemies.forEach(function (ent) {
|
||||||
ent.update(dt, vX);
|
ent.update(dt, vX);
|
||||||
});
|
});
|
||||||
|
|
||||||
fireballs.forEach(function (fireball) {
|
fireballs.forEach(function (fireball) {
|
||||||
fireball.update(dt);
|
fireball.update(dt);
|
||||||
});
|
});
|
||||||
level.pipes.forEach(function (pipe) {
|
level.pipes.forEach(function (pipe) {
|
||||||
pipe.update(dt);
|
pipe.update(dt);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//scan for collisions
|
//scan for collisions
|
||||||
function checkCollisions() {
|
function checkCollisions() {
|
||||||
if (player.powering.length !== 0 || player.dying) {
|
if (player.powering.length !== 0 || player.dying) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
player.checkCollisions();
|
player.checkCollisions();
|
||||||
|
|
||||||
//Apparently for each will just skip indices where things were deleted.
|
//Apparently for each will just skip indices where things were deleted.
|
||||||
level.items.forEach(function (item) {
|
level.items.forEach(function (item) {
|
||||||
item.checkCollisions();
|
item.checkCollisions();
|
||||||
});
|
});
|
||||||
level.enemies.forEach(function (ent) {
|
level.enemies.forEach(function (ent) {
|
||||||
ent.checkCollisions();
|
ent.checkCollisions();
|
||||||
});
|
});
|
||||||
fireballs.forEach(function (fireball) {
|
fireballs.forEach(function (fireball) {
|
||||||
fireball.checkCollisions();
|
fireball.checkCollisions();
|
||||||
});
|
});
|
||||||
level.pipes.forEach(function (pipe) {
|
level.pipes.forEach(function (pipe) {
|
||||||
pipe.checkCollisions();
|
pipe.checkCollisions();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//draw the game!
|
//draw the game!
|
||||||
function render() {
|
function render() {
|
||||||
updateables = [];
|
updateables = [];
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
ctx.fillStyle = level.background;
|
ctx.fillStyle = level.background;
|
||||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
//scenery gets drawn first to get layering right.
|
//scenery gets drawn first to get layering right.
|
||||||
for (var i = 0; i < 15; i++) {
|
for (var i = 0; i < 15; i++) {
|
||||||
for (var j = Math.floor(vX / 16) - 1; j < Math.floor(vX / 16) + 20; j++) {
|
for (
|
||||||
if (level.scenery[i][j]) {
|
var j = Math.floor(vX / 16) - 1;
|
||||||
renderEntity(level.scenery[i][j]);
|
j < Math.floor(vX / 16) + 20;
|
||||||
}
|
j++
|
||||||
|
) {
|
||||||
|
if (level.scenery[i][j]) {
|
||||||
|
renderEntity(level.scenery[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//then items
|
//then items
|
||||||
level.items.forEach(function (item) {
|
level.items.forEach(function (item) {
|
||||||
renderEntity(item);
|
renderEntity(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
level.enemies.forEach(function (enemy) {
|
level.enemies.forEach(function (enemy) {
|
||||||
renderEntity(enemy);
|
renderEntity(enemy);
|
||||||
});
|
});
|
||||||
|
|
||||||
fireballs.forEach(function (fireball) {
|
fireballs.forEach(function (fireball) {
|
||||||
renderEntity(fireball);
|
renderEntity(fireball);
|
||||||
});
|
});
|
||||||
|
|
||||||
//then we draw every static object.
|
//then we draw every static object.
|
||||||
for (var i = 0; i < 15; i++) {
|
for (var i = 0; i < 15; i++) {
|
||||||
for (var j = Math.floor(vX / 16) - 1; j < Math.floor(vX / 16) + 20; j++) {
|
for (
|
||||||
if (level.statics[i][j]) {
|
var j = Math.floor(vX / 16) - 1;
|
||||||
renderEntity(level.statics[i][j]);
|
j < Math.floor(vX / 16) + 20;
|
||||||
}
|
j++
|
||||||
if (level.blocks[i][j]) {
|
) {
|
||||||
renderEntity(level.blocks[i][j]);
|
if (level.statics[i][j]) {
|
||||||
updateables.push(level.blocks[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
|
//then the player
|
||||||
if (player.invincibility % 2 === 0) {
|
if (player.invincibility % 2 === 0) {
|
||||||
renderEntity(player);
|
renderEntity(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Mario goes INTO pipes, so naturally they go after.
|
//Mario goes INTO pipes, so naturally they go after.
|
||||||
level.pipes.forEach(function (pipe) {
|
level.pipes.forEach(function (pipe) {
|
||||||
renderEntity(pipe);
|
renderEntity(pipe);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderEntity(entity) {
|
function renderEntity(entity) {
|
||||||
entity.render(ctx, vX, vY);
|
entity.render(ctx, vX, vY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,144 +1,147 @@
|
|||||||
(function () {
|
(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) {
|
var Goomba = (Mario.Goomba = function (pos, sprite) {
|
||||||
this.dying = false;
|
this.dying = false;
|
||||||
Mario.Entity.call(this, {
|
Mario.Entity.call(this, {
|
||||||
pos: pos,
|
pos: pos,
|
||||||
sprite: sprite,
|
sprite: sprite,
|
||||||
hitbox: [0, 0, 16, 16],
|
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) {
|
Goomba.prototype.render = function (ctx, vX, vY) {
|
||||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||||
};
|
};
|
||||||
|
|
||||||
Goomba.prototype.update = function (dt, vX) {
|
Goomba.prototype.update = function (dt, vX) {
|
||||||
if (this.pos[0] - vX > 336) {
|
if (this.pos[0] - vX > 336) {
|
||||||
//if we're too far away, do nothing.
|
//if we're too far away, do nothing.
|
||||||
return;
|
return;
|
||||||
} else if (this.pos[0] - vX < -32) {
|
} else if (this.pos[0] - vX < -32) {
|
||||||
delete level.enemies[this.idx];
|
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);
|
|
||||||
}
|
}
|
||||||
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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
this.acc[1] = 0.2;
|
||||||
}
|
this.vel[1] += this.acc[1];
|
||||||
var that = this;
|
this.pos[0] += this.vel[0];
|
||||||
level.enemies.forEach(function (enemy) {
|
this.pos[1] += this.vel[1];
|
||||||
if (enemy === that) {
|
this.sprite.update(dt);
|
||||||
//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) {
|
Goomba.prototype.collideWall = function () {
|
||||||
if (ent instanceof Mario.Player && (this.dying || ent.invincibility)) {
|
this.vel[0] = -this.vel[0];
|
||||||
return;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
//the first two elements of the hitbox array are an offset, so let's do this now.
|
Goomba.prototype.checkCollisions = function () {
|
||||||
var hpos1 = [this.pos[0] + this.hitbox[0], this.pos[1] + this.hitbox[1]];
|
if (this.flipping) {
|
||||||
var hpos2 = [ent.pos[0] + ent.hitbox[0], ent.pos[1] + ent.hitbox[1]];
|
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 (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 () {
|
var h = this.pos[1] % 16 === 0 ? 1 : 2;
|
||||||
sounds.stomp.play();
|
var w = this.pos[0] % 16 === 0 ? 1 : 2;
|
||||||
player.bounce = true;
|
|
||||||
this.sprite.pos[0] = 32;
|
|
||||||
this.sprite.speed = 0;
|
|
||||||
this.vel[0] = 0;
|
|
||||||
this.dying = 10;
|
|
||||||
};
|
|
||||||
|
|
||||||
Goomba.prototype.bump = function () {
|
var baseX = Math.floor(this.pos[0] / 16);
|
||||||
sounds.kick.play();
|
var baseY = Math.floor(this.pos[1] / 16);
|
||||||
this.sprite.img = "sprites/enemyr.png";
|
|
||||||
this.flipping = true;
|
if (baseY + h > 15) {
|
||||||
this.pos[1] -= 1;
|
delete level.enemies[this.idx];
|
||||||
this.vel[0] = 0;
|
return;
|
||||||
this.vel[1] = -2.5;
|
}
|
||||||
};
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,61 +1,61 @@
|
|||||||
(function () {
|
(function () {
|
||||||
var pressedKeys = {};
|
var pressedKeys = {};
|
||||||
|
|
||||||
function setKey(event, status) {
|
function setKey(event, status) {
|
||||||
var code = event.keyCode;
|
var code = event.keyCode;
|
||||||
var key;
|
var key;
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 32:
|
case 32:
|
||||||
key = "SPACE";
|
key = "SPACE";
|
||||||
break;
|
break;
|
||||||
case 37:
|
case 37:
|
||||||
key = "LEFT";
|
key = "LEFT";
|
||||||
break;
|
break;
|
||||||
case 38:
|
case 38:
|
||||||
key = "UP";
|
key = "UP";
|
||||||
break;
|
break;
|
||||||
case 39:
|
case 39:
|
||||||
key = "RIGHT";
|
key = "RIGHT";
|
||||||
break;
|
break;
|
||||||
case 40:
|
case 40:
|
||||||
key = "DOWN";
|
key = "DOWN";
|
||||||
break;
|
break;
|
||||||
case 88:
|
case 88:
|
||||||
key = "JUMP";
|
key = "JUMP";
|
||||||
break;
|
break;
|
||||||
case 90:
|
case 90:
|
||||||
key = "RUN";
|
key = "RUN";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
key = String.fromCharCode(code);
|
key = String.fromCharCode(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
pressedKeys[key] = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
pressedKeys[key] = status;
|
document.addEventListener("keydown", function (e) {
|
||||||
}
|
setKey(e, true);
|
||||||
|
});
|
||||||
|
|
||||||
document.addEventListener("keydown", function (e) {
|
document.addEventListener("keyup", function (e) {
|
||||||
setKey(e, true);
|
setKey(e, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("keyup", function (e) {
|
window.addEventListener("blur", function () {
|
||||||
setKey(e, false);
|
pressedKeys = {};
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener("blur", function () {
|
window.input = {
|
||||||
pressedKeys = {};
|
isDown: function (key) {
|
||||||
});
|
return pressedKeys[key.toUpperCase()];
|
||||||
|
},
|
||||||
window.input = {
|
reset: function () {
|
||||||
isDown: function (key) {
|
pressedKeys["RUN"] = false;
|
||||||
return pressedKeys[key.toUpperCase()];
|
pressedKeys["LEFT"] = false;
|
||||||
},
|
pressedKeys["RIGHT"] = false;
|
||||||
reset: function () {
|
pressedKeys["DOWN"] = false;
|
||||||
pressedKeys["RUN"] = false;
|
pressedKeys["JUMP"] = false;
|
||||||
pressedKeys["LEFT"] = false;
|
},
|
||||||
pressedKeys["RIGHT"] = false;
|
};
|
||||||
pressedKeys["DOWN"] = false;
|
|
||||||
pressedKeys["JUMP"] = false;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,225 +1,228 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") window.Mario = {};
|
if (typeof Mario === "undefined") window.Mario = {};
|
||||||
|
|
||||||
var Koopa = (Mario.Koopa = function (pos, sprite, para) {
|
var Koopa = (Mario.Koopa = function (pos, sprite, para) {
|
||||||
this.dying = false;
|
this.dying = false;
|
||||||
this.shell = 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.
|
//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
|
//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.
|
//making the hitboxes accurate will make enemies sink into the ground.
|
||||||
Mario.Entity.call(this, {
|
Mario.Entity.call(this, {
|
||||||
pos: pos,
|
pos: pos,
|
||||||
sprite: sprite,
|
sprite: sprite,
|
||||||
hitbox: [2, 8, 12, 24],
|
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) {
|
Koopa.prototype.render = function (ctx, vX, vY) {
|
||||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||||
};
|
};
|
||||||
|
|
||||||
Koopa.prototype.update = function (dt, vX) {
|
Koopa.prototype.update = function (dt, vX) {
|
||||||
if (this.turn) {
|
if (this.turn) {
|
||||||
this.vel[0] = -this.vel[0];
|
this.vel[0] = -this.vel[0];
|
||||||
if (this.shell) sounds.bump.play();
|
if (this.shell) sounds.bump.play();
|
||||||
this.turn = false;
|
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;
|
|
||||||
}
|
}
|
||||||
if (this.shell == 0) {
|
if (this.vel[0] != 0) {
|
||||||
this.sprite = level.koopaSprite();
|
this.left = this.vel[0] < 0;
|
||||||
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 () {
|
if (this.left) {
|
||||||
//This stops us from flipping twice on the same frame if we collide
|
this.sprite.img = "sprites/enemy.png";
|
||||||
//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 {
|
} else {
|
||||||
if (this.shell && ent instanceof Mario.Goomba) {
|
this.sprite.img = "sprites/enemyr.png";
|
||||||
ent.bump();
|
|
||||||
} else this.collideWall();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Koopa.prototype.stomp = function () {
|
if (this.pos[0] - vX > 336) {
|
||||||
//Turn this thing into a shell if it isn't already. Kick it if it is.
|
//if we're too far away, do nothing.
|
||||||
player.bounce = true;
|
return;
|
||||||
if (this.para) {
|
} else if (this.pos[0] - vX < -32) {
|
||||||
this.para = false;
|
delete level.enemies[this.idx];
|
||||||
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 () {
|
if (this.dying) {
|
||||||
sounds.kick.play();
|
this.dying -= 1;
|
||||||
if (this.flipping) return;
|
if (!this.dying) {
|
||||||
this.flipping = true;
|
delete level.enemies[this.idx];
|
||||||
this.sprite.pos = [160, 0];
|
}
|
||||||
this.sprite.size = [16, 16];
|
}
|
||||||
this.hitbox = [2, 0, 12, 16];
|
|
||||||
this.sprite.speed = 0;
|
if (this.shell) {
|
||||||
this.vel[0] = 0;
|
if (this.vel[0] == 0) {
|
||||||
this.vel[1] = -2.5;
|
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;
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,310 +1,341 @@
|
|||||||
var oneone = (Mario.oneone = function () {
|
var oneone = (Mario.oneone = function () {
|
||||||
//The things that need to be passed in are basically just dependent on what
|
//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
|
//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.
|
//TODO: put as much of this in the Level object definition as possible.
|
||||||
level = new Mario.Level({
|
level = new Mario.Level({
|
||||||
playerPos: [56, 192],
|
playerPos: [56, 192],
|
||||||
loader: Mario.oneone,
|
loader: Mario.oneone,
|
||||||
background: "#7974FF",
|
background: "#7974FF",
|
||||||
scrolling: true,
|
scrolling: true,
|
||||||
invincibility: [144, 192, 240],
|
invincibility: [144, 192, 240],
|
||||||
exit: 204,
|
exit: 204,
|
||||||
floorSprite: new Mario.Sprite("sprites/tiles.png", [0, 0], [16, 16], 0),
|
floorSprite: new Mario.Sprite("sprites/tiles.png", [0, 0], [16, 16], 0),
|
||||||
cloudSprite: new Mario.Sprite("sprites/tiles.png", [0, 320], [48, 32], 0),
|
cloudSprite: new Mario.Sprite(
|
||||||
wallSprite: new Mario.Sprite("sprites/tiles.png", [0, 16], [16, 16], 0),
|
"sprites/tiles.png",
|
||||||
brickSprite: new Mario.Sprite("sprites/tiles.png", [16, 0], [16, 16], 0),
|
[0, 320],
|
||||||
brickBounceSprite: new Mario.Sprite(
|
[48, 32],
|
||||||
"sprites/tiles.png",
|
0,
|
||||||
[32, 0],
|
),
|
||||||
[16, 16],
|
wallSprite: new Mario.Sprite("sprites/tiles.png", [0, 16], [16, 16], 0),
|
||||||
0,
|
brickSprite: new Mario.Sprite(
|
||||||
),
|
"sprites/tiles.png",
|
||||||
rubbleSprite: function () {
|
[16, 0],
|
||||||
return new Mario.Sprite("sprites/items.png", [64, 0], [8, 8], 3, [0, 1]);
|
[16, 16],
|
||||||
},
|
0,
|
||||||
ublockSprite: new Mario.Sprite("sprites/tiles.png", [48, 0], [16, 16], 0),
|
),
|
||||||
superShroomSprite: new Mario.Sprite(
|
brickBounceSprite: new Mario.Sprite(
|
||||||
"sprites/items.png",
|
"sprites/tiles.png",
|
||||||
[0, 0],
|
[32, 0],
|
||||||
[16, 16],
|
[16, 16],
|
||||||
0,
|
0,
|
||||||
),
|
),
|
||||||
fireFlowerSprite: new Mario.Sprite(
|
rubbleSprite: function () {
|
||||||
"sprites/items.png",
|
return new Mario.Sprite(
|
||||||
[0, 32],
|
"sprites/items.png",
|
||||||
[16, 16],
|
[64, 0],
|
||||||
20,
|
[8, 8],
|
||||||
[0, 1, 2, 3],
|
3,
|
||||||
),
|
[0, 1],
|
||||||
starSprite: new Mario.Sprite(
|
);
|
||||||
"sprites/items.png",
|
},
|
||||||
[0, 48],
|
ublockSprite: new Mario.Sprite(
|
||||||
[16, 16],
|
"sprites/tiles.png",
|
||||||
20,
|
[48, 0],
|
||||||
[0, 1, 2, 3],
|
[16, 16],
|
||||||
),
|
0,
|
||||||
pipeLEndSprite: new Mario.Sprite(
|
),
|
||||||
"sprites/tiles.png",
|
superShroomSprite: new Mario.Sprite(
|
||||||
[0, 128],
|
"sprites/items.png",
|
||||||
[16, 16],
|
[0, 0],
|
||||||
0,
|
[16, 16],
|
||||||
),
|
0,
|
||||||
pipeREndSprite: new Mario.Sprite(
|
),
|
||||||
"sprites/tiles.png",
|
fireFlowerSprite: new Mario.Sprite(
|
||||||
[16, 128],
|
"sprites/items.png",
|
||||||
[16, 16],
|
[0, 32],
|
||||||
0,
|
[16, 16],
|
||||||
),
|
20,
|
||||||
pipeLMidSprite: new Mario.Sprite(
|
[0, 1, 2, 3],
|
||||||
"sprites/tiles.png",
|
),
|
||||||
[0, 144],
|
starSprite: new Mario.Sprite(
|
||||||
[16, 16],
|
"sprites/items.png",
|
||||||
0,
|
[0, 48],
|
||||||
),
|
[16, 16],
|
||||||
pipeRMidSprite: new Mario.Sprite(
|
20,
|
||||||
"sprites/tiles.png",
|
[0, 1, 2, 3],
|
||||||
[16, 144],
|
),
|
||||||
[16, 16],
|
pipeLEndSprite: new Mario.Sprite(
|
||||||
0,
|
"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),
|
pipeUpMid: new Mario.Sprite("sprites/tiles.png", [0, 144], [32, 16], 0),
|
||||||
pipeSideMid: new Mario.Sprite("sprites/tiles.png", [48, 128], [16, 32], 0),
|
pipeSideMid: new Mario.Sprite(
|
||||||
pipeLeft: new Mario.Sprite("sprites/tiles.png", [32, 128], [16, 32], 0),
|
"sprites/tiles.png",
|
||||||
pipeTop: new Mario.Sprite("sprites/tiles.png", [0, 128], [32, 16], 0),
|
[48, 128],
|
||||||
qblockSprite: new Mario.Sprite(
|
[16, 32],
|
||||||
"sprites/tiles.png",
|
0,
|
||||||
[384, 0],
|
),
|
||||||
[16, 16],
|
pipeLeft: new Mario.Sprite("sprites/tiles.png", [32, 128], [16, 32], 0),
|
||||||
8,
|
pipeTop: new Mario.Sprite("sprites/tiles.png", [0, 128], [32, 16], 0),
|
||||||
[0, 0, 0, 0, 1, 2, 1],
|
qblockSprite: new Mario.Sprite(
|
||||||
),
|
"sprites/tiles.png",
|
||||||
bcoinSprite: function () {
|
[384, 0],
|
||||||
return new Mario.Sprite(
|
[16, 16],
|
||||||
"sprites/items.png",
|
8,
|
||||||
[0, 112],
|
[0, 0, 0, 0, 1, 2, 1],
|
||||||
[16, 16],
|
),
|
||||||
20,
|
bcoinSprite: function () {
|
||||||
[0, 1, 2, 3],
|
return new Mario.Sprite(
|
||||||
);
|
"sprites/items.png",
|
||||||
},
|
[0, 112],
|
||||||
cloudSprites: [
|
[16, 16],
|
||||||
new Mario.Sprite("sprites/tiles.png", [0, 320], [16, 32], 0),
|
20,
|
||||||
new Mario.Sprite("sprites/tiles.png", [16, 320], [16, 32], 0),
|
[0, 1, 2, 3],
|
||||||
new Mario.Sprite("sprites/tiles.png", [32, 320], [16, 32], 0),
|
);
|
||||||
],
|
},
|
||||||
hillSprites: [
|
cloudSprites: [
|
||||||
new Mario.Sprite("sprites/tiles.png", [128, 128], [16, 16], 0),
|
new Mario.Sprite("sprites/tiles.png", [0, 320], [16, 32], 0),
|
||||||
new Mario.Sprite("sprites/tiles.png", [144, 128], [16, 16], 0),
|
new Mario.Sprite("sprites/tiles.png", [16, 320], [16, 32], 0),
|
||||||
new Mario.Sprite("sprites/tiles.png", [160, 128], [16, 16], 0),
|
new Mario.Sprite("sprites/tiles.png", [32, 320], [16, 32], 0),
|
||||||
new Mario.Sprite("sprites/tiles.png", [128, 144], [16, 16], 0),
|
],
|
||||||
new Mario.Sprite("sprites/tiles.png", [144, 144], [16, 16], 0),
|
hillSprites: [
|
||||||
new Mario.Sprite("sprites/tiles.png", [160, 144], [16, 16], 0),
|
new Mario.Sprite("sprites/tiles.png", [128, 128], [16, 16], 0),
|
||||||
],
|
new Mario.Sprite("sprites/tiles.png", [144, 128], [16, 16], 0),
|
||||||
bushSprite: new Mario.Sprite("sprites/tiles.png", [176, 144], [48, 16], 0),
|
new Mario.Sprite("sprites/tiles.png", [160, 128], [16, 16], 0),
|
||||||
bushSprites: [
|
new Mario.Sprite("sprites/tiles.png", [128, 144], [16, 16], 0),
|
||||||
new Mario.Sprite("sprites/tiles.png", [176, 144], [16, 16], 0),
|
new Mario.Sprite("sprites/tiles.png", [144, 144], [16, 16], 0),
|
||||||
new Mario.Sprite("sprites/tiles.png", [192, 144], [16, 16], 0),
|
new Mario.Sprite("sprites/tiles.png", [160, 144], [16, 16], 0),
|
||||||
new Mario.Sprite("sprites/tiles.png", [208, 144], [16, 16], 0),
|
],
|
||||||
],
|
bushSprite: new Mario.Sprite(
|
||||||
goombaSprite: function () {
|
"sprites/tiles.png",
|
||||||
return new Mario.Sprite(
|
[176, 144],
|
||||||
"sprites/enemy.png",
|
[48, 16],
|
||||||
[0, 16],
|
0,
|
||||||
[16, 16],
|
),
|
||||||
3,
|
bushSprites: [
|
||||||
[0, 1],
|
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),
|
||||||
koopaSprite: function () {
|
],
|
||||||
return new Mario.Sprite(
|
goombaSprite: function () {
|
||||||
"sprites/enemy.png",
|
return new Mario.Sprite(
|
||||||
[96, 0],
|
"sprites/enemy.png",
|
||||||
[16, 32],
|
[0, 16],
|
||||||
2,
|
[16, 16],
|
||||||
[0, 1],
|
3,
|
||||||
);
|
[0, 1],
|
||||||
},
|
);
|
||||||
flagPoleSprites: [
|
},
|
||||||
new Mario.Sprite("sprites/tiles.png", [256, 128], [16, 16], 0),
|
koopaSprite: function () {
|
||||||
new Mario.Sprite("sprites/tiles.png", [256, 144], [16, 16], 0),
|
return new Mario.Sprite(
|
||||||
new Mario.Sprite("sprites/items.png", [128, 32], [16, 16], 0),
|
"sprites/enemy.png",
|
||||||
],
|
[96, 0],
|
||||||
});
|
[16, 32],
|
||||||
ground = [
|
2,
|
||||||
[0, 69],
|
[0, 1],
|
||||||
[71, 86],
|
);
|
||||||
[89, 153],
|
},
|
||||||
[155, 212],
|
flagPoleSprites: [
|
||||||
];
|
new Mario.Sprite("sprites/tiles.png", [256, 128], [16, 16], 0),
|
||||||
player.pos[0] = level.playerPos[0];
|
new Mario.Sprite("sprites/tiles.png", [256, 144], [16, 16], 0),
|
||||||
player.pos[1] = level.playerPos[1];
|
new Mario.Sprite("sprites/items.png", [128, 32], [16, 16], 0),
|
||||||
vX = 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
|
//build THE GROUND
|
||||||
ground.forEach(function (loc) {
|
ground.forEach(function (loc) {
|
||||||
level.putFloor(loc[0], loc[1]);
|
level.putFloor(loc[0], loc[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
//build scenery
|
//build scenery
|
||||||
clouds = [
|
clouds = [
|
||||||
[7, 3],
|
[7, 3],
|
||||||
[19, 2],
|
[19, 2],
|
||||||
[56, 3],
|
[56, 3],
|
||||||
[67, 2],
|
[67, 2],
|
||||||
[87, 2],
|
[87, 2],
|
||||||
[103, 2],
|
[103, 2],
|
||||||
[152, 3],
|
[152, 3],
|
||||||
[163, 2],
|
[163, 2],
|
||||||
[200, 3],
|
[200, 3],
|
||||||
];
|
];
|
||||||
clouds.forEach(function (cloud) {
|
clouds.forEach(function (cloud) {
|
||||||
level.putCloud(cloud[0], cloud[1]);
|
level.putCloud(cloud[0], cloud[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
twoClouds = [
|
twoClouds = [
|
||||||
[36, 2],
|
[36, 2],
|
||||||
[132, 2],
|
[132, 2],
|
||||||
[180, 2],
|
[180, 2],
|
||||||
];
|
];
|
||||||
twoClouds.forEach(function (cloud) {
|
twoClouds.forEach(function (cloud) {
|
||||||
level.putTwoCloud(cloud[0], cloud[1]);
|
level.putTwoCloud(cloud[0], cloud[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
threeClouds = [
|
threeClouds = [
|
||||||
[27, 3],
|
[27, 3],
|
||||||
[75, 3],
|
[75, 3],
|
||||||
[123, 3],
|
[123, 3],
|
||||||
[171, 3],
|
[171, 3],
|
||||||
];
|
];
|
||||||
threeClouds.forEach(function (cloud) {
|
threeClouds.forEach(function (cloud) {
|
||||||
level.putThreeCloud(cloud[0], cloud[1]);
|
level.putThreeCloud(cloud[0], cloud[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
bHills = [0, 48, 96, 144, 192];
|
bHills = [0, 48, 96, 144, 192];
|
||||||
bHills.forEach(function (hill) {
|
bHills.forEach(function (hill) {
|
||||||
level.putBigHill(hill, 12);
|
level.putBigHill(hill, 12);
|
||||||
});
|
});
|
||||||
|
|
||||||
sHills = [16, 64, 111, 160];
|
sHills = [16, 64, 111, 160];
|
||||||
sHills.forEach(function (hill) {
|
sHills.forEach(function (hill) {
|
||||||
level.putSmallHill(hill, 12);
|
level.putSmallHill(hill, 12);
|
||||||
});
|
});
|
||||||
|
|
||||||
bushes = [23, 71, 118, 167];
|
bushes = [23, 71, 118, 167];
|
||||||
bushes.forEach(function (bush) {
|
bushes.forEach(function (bush) {
|
||||||
level.putBush(bush, 12);
|
level.putBush(bush, 12);
|
||||||
});
|
});
|
||||||
|
|
||||||
twoBushes = [41, 89, 137];
|
twoBushes = [41, 89, 137];
|
||||||
twoBushes.forEach(function (bush) {
|
twoBushes.forEach(function (bush) {
|
||||||
level.putTwoBush(bush, 12);
|
level.putTwoBush(bush, 12);
|
||||||
});
|
});
|
||||||
|
|
||||||
threeBushes = [11, 59, 106];
|
threeBushes = [11, 59, 106];
|
||||||
threeBushes.forEach(function (bush) {
|
threeBushes.forEach(function (bush) {
|
||||||
level.putThreeBush(bush, 12);
|
level.putThreeBush(bush, 12);
|
||||||
});
|
});
|
||||||
|
|
||||||
//interactable terrain
|
//interactable terrain
|
||||||
level.putQBlock(16, 9, new Mario.Bcoin([256, 144]));
|
level.putQBlock(16, 9, new Mario.Bcoin([256, 144]));
|
||||||
level.putBrick(20, 9, null);
|
level.putBrick(20, 9, null);
|
||||||
level.putQBlock(21, 9, new Mario.Mushroom([336, 144]));
|
level.putQBlock(21, 9, new Mario.Mushroom([336, 144]));
|
||||||
level.putBrick(22, 9, null);
|
level.putBrick(22, 9, null);
|
||||||
level.putQBlock(22, 5, new Mario.Bcoin([352, 80]));
|
level.putQBlock(22, 5, new Mario.Bcoin([352, 80]));
|
||||||
level.putQBlock(23, 9, new Mario.Bcoin([368, 144]));
|
level.putQBlock(23, 9, new Mario.Bcoin([368, 144]));
|
||||||
level.putBrick(24, 9, null);
|
level.putBrick(24, 9, null);
|
||||||
level.putPipe(28, 13, 2);
|
level.putPipe(28, 13, 2);
|
||||||
level.putPipe(38, 13, 3);
|
level.putPipe(38, 13, 3);
|
||||||
level.putPipe(46, 13, 4);
|
level.putPipe(46, 13, 4);
|
||||||
level.putRealPipe(57, 9, 4, "DOWN", Mario.oneonetunnel);
|
level.putRealPipe(57, 9, 4, "DOWN", Mario.oneonetunnel);
|
||||||
level.putBrick(77, 9, null);
|
level.putBrick(77, 9, null);
|
||||||
level.putQBlock(78, 9, new Mario.Mushroom([1248, 144]));
|
level.putQBlock(78, 9, new Mario.Mushroom([1248, 144]));
|
||||||
level.putBrick(79, 9, null);
|
level.putBrick(79, 9, null);
|
||||||
level.putBrick(80, 5, null);
|
level.putBrick(80, 5, null);
|
||||||
level.putBrick(81, 5, null);
|
level.putBrick(81, 5, null);
|
||||||
level.putBrick(82, 5, null);
|
level.putBrick(82, 5, null);
|
||||||
level.putBrick(83, 5, null);
|
level.putBrick(83, 5, null);
|
||||||
level.putBrick(84, 5, null);
|
level.putBrick(84, 5, null);
|
||||||
level.putBrick(85, 5, null);
|
level.putBrick(85, 5, null);
|
||||||
level.putBrick(86, 5, null);
|
level.putBrick(86, 5, null);
|
||||||
level.putBrick(87, 5, null);
|
level.putBrick(87, 5, null);
|
||||||
level.putBrick(91, 5, null);
|
level.putBrick(91, 5, null);
|
||||||
level.putBrick(92, 5, null);
|
level.putBrick(92, 5, null);
|
||||||
level.putBrick(93, 5, null);
|
level.putBrick(93, 5, null);
|
||||||
level.putQBlock(94, 5, new Mario.Bcoin([1504, 80]));
|
level.putQBlock(94, 5, new Mario.Bcoin([1504, 80]));
|
||||||
level.putBrick(94, 9, null);
|
level.putBrick(94, 9, null);
|
||||||
level.putBrick(100, 9, new Mario.Star([1600, 144]));
|
level.putBrick(100, 9, new Mario.Star([1600, 144]));
|
||||||
level.putBrick(101, 9, null);
|
level.putBrick(101, 9, null);
|
||||||
level.putQBlock(105, 9, new Mario.Bcoin([1680, 144]));
|
level.putQBlock(105, 9, new Mario.Bcoin([1680, 144]));
|
||||||
level.putQBlock(108, 9, new Mario.Bcoin([1728, 144]));
|
level.putQBlock(108, 9, new Mario.Bcoin([1728, 144]));
|
||||||
level.putQBlock(108, 5, new Mario.Mushroom([1728, 80]));
|
level.putQBlock(108, 5, new Mario.Mushroom([1728, 80]));
|
||||||
level.putQBlock(111, 9, new Mario.Bcoin([1776, 144]));
|
level.putQBlock(111, 9, new Mario.Bcoin([1776, 144]));
|
||||||
level.putBrick(117, 9, null);
|
level.putBrick(117, 9, null);
|
||||||
level.putBrick(120, 5, null);
|
level.putBrick(120, 5, null);
|
||||||
level.putBrick(121, 5, null);
|
level.putBrick(121, 5, null);
|
||||||
level.putBrick(122, 5, null);
|
level.putBrick(122, 5, null);
|
||||||
level.putBrick(123, 5, null);
|
level.putBrick(123, 5, null);
|
||||||
level.putBrick(128, 5, null);
|
level.putBrick(128, 5, null);
|
||||||
level.putQBlock(129, 5, new Mario.Bcoin([2074, 80]));
|
level.putQBlock(129, 5, new Mario.Bcoin([2074, 80]));
|
||||||
level.putBrick(129, 9, null);
|
level.putBrick(129, 9, null);
|
||||||
level.putQBlock(130, 5, new Mario.Bcoin([2080, 80]));
|
level.putQBlock(130, 5, new Mario.Bcoin([2080, 80]));
|
||||||
level.putBrick(130, 9, null);
|
level.putBrick(130, 9, null);
|
||||||
level.putBrick(131, 5, null);
|
level.putBrick(131, 5, null);
|
||||||
level.putWall(134, 13, 1);
|
level.putWall(134, 13, 1);
|
||||||
level.putWall(135, 13, 2);
|
level.putWall(135, 13, 2);
|
||||||
level.putWall(136, 13, 3);
|
level.putWall(136, 13, 3);
|
||||||
level.putWall(137, 13, 4);
|
level.putWall(137, 13, 4);
|
||||||
level.putWall(140, 13, 4);
|
level.putWall(140, 13, 4);
|
||||||
level.putWall(141, 13, 3);
|
level.putWall(141, 13, 3);
|
||||||
level.putWall(142, 13, 2);
|
level.putWall(142, 13, 2);
|
||||||
level.putWall(143, 13, 1);
|
level.putWall(143, 13, 1);
|
||||||
level.putWall(148, 13, 1);
|
level.putWall(148, 13, 1);
|
||||||
level.putWall(149, 13, 2);
|
level.putWall(149, 13, 2);
|
||||||
level.putWall(150, 13, 3);
|
level.putWall(150, 13, 3);
|
||||||
level.putWall(151, 13, 4);
|
level.putWall(151, 13, 4);
|
||||||
level.putWall(152, 13, 4);
|
level.putWall(152, 13, 4);
|
||||||
level.putWall(155, 13, 4);
|
level.putWall(155, 13, 4);
|
||||||
level.putWall(156, 13, 3);
|
level.putWall(156, 13, 3);
|
||||||
level.putWall(157, 13, 2);
|
level.putWall(157, 13, 2);
|
||||||
level.putWall(158, 13, 1);
|
level.putWall(158, 13, 1);
|
||||||
level.putPipe(163, 13, 2);
|
level.putPipe(163, 13, 2);
|
||||||
level.putBrick(168, 9, null);
|
level.putBrick(168, 9, null);
|
||||||
level.putBrick(169, 9, null);
|
level.putBrick(169, 9, null);
|
||||||
level.putQBlock(170, 9, new Mario.Bcoin([2720, 144]));
|
level.putQBlock(170, 9, new Mario.Bcoin([2720, 144]));
|
||||||
level.putBrick(171, 9, null);
|
level.putBrick(171, 9, null);
|
||||||
level.putPipe(179, 13, 2);
|
level.putPipe(179, 13, 2);
|
||||||
level.putWall(181, 13, 1);
|
level.putWall(181, 13, 1);
|
||||||
level.putWall(182, 13, 2);
|
level.putWall(182, 13, 2);
|
||||||
level.putWall(183, 13, 3);
|
level.putWall(183, 13, 3);
|
||||||
level.putWall(184, 13, 4);
|
level.putWall(184, 13, 4);
|
||||||
level.putWall(185, 13, 5);
|
level.putWall(185, 13, 5);
|
||||||
level.putWall(186, 13, 6);
|
level.putWall(186, 13, 6);
|
||||||
level.putWall(187, 13, 7);
|
level.putWall(187, 13, 7);
|
||||||
level.putWall(188, 13, 8);
|
level.putWall(188, 13, 8);
|
||||||
level.putWall(189, 13, 8);
|
level.putWall(189, 13, 8);
|
||||||
level.putFlagpole(198);
|
level.putFlagpole(198);
|
||||||
|
|
||||||
//and enemies
|
//and enemies
|
||||||
level.putGoomba(22, 12);
|
level.putGoomba(22, 12);
|
||||||
level.putGoomba(40, 12);
|
level.putGoomba(40, 12);
|
||||||
level.putGoomba(50, 12);
|
level.putGoomba(50, 12);
|
||||||
level.putGoomba(51, 12);
|
level.putGoomba(51, 12);
|
||||||
level.putGoomba(82, 4);
|
level.putGoomba(82, 4);
|
||||||
level.putGoomba(84, 4);
|
level.putGoomba(84, 4);
|
||||||
level.putGoomba(100, 12);
|
level.putGoomba(100, 12);
|
||||||
level.putGoomba(102, 12);
|
level.putGoomba(102, 12);
|
||||||
level.putGoomba(114, 12);
|
level.putGoomba(114, 12);
|
||||||
level.putGoomba(115, 12);
|
level.putGoomba(115, 12);
|
||||||
level.putGoomba(122, 12);
|
level.putGoomba(122, 12);
|
||||||
level.putGoomba(123, 12);
|
level.putGoomba(123, 12);
|
||||||
level.putGoomba(125, 12);
|
level.putGoomba(125, 12);
|
||||||
level.putGoomba(126, 12);
|
level.putGoomba(126, 12);
|
||||||
level.putGoomba(170, 12);
|
level.putGoomba(170, 12);
|
||||||
level.putGoomba(172, 12);
|
level.putGoomba(172, 12);
|
||||||
level.putKoopa(35, 11);
|
level.putKoopa(35, 11);
|
||||||
|
|
||||||
music.underground.pause();
|
music.underground.pause();
|
||||||
// music.overworld.currentTime = 0;
|
// music.overworld.currentTime = 0;
|
||||||
music.overworld.play();
|
music.overworld.play();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,113 +1,138 @@
|
|||||||
var oneonetunnel = (Mario.oneonetunnel = function () {
|
var oneonetunnel = (Mario.oneonetunnel = function () {
|
||||||
level = new Mario.Level({
|
level = new Mario.Level({
|
||||||
playerPos: [40, 16],
|
playerPos: [40, 16],
|
||||||
loader: Mario.oneonetunnel,
|
loader: Mario.oneonetunnel,
|
||||||
background: "#000000",
|
background: "#000000",
|
||||||
scrolling: false,
|
scrolling: false,
|
||||||
coinSprite: function () {
|
coinSprite: function () {
|
||||||
return new Mario.Sprite(
|
return new Mario.Sprite(
|
||||||
"sprites/items.png",
|
"sprites/items.png",
|
||||||
[0, 96],
|
[0, 96],
|
||||||
[16, 16],
|
[16, 16],
|
||||||
6,
|
6,
|
||||||
[0, 0, 0, 0, 1, 2, 1],
|
[0, 0, 0, 0, 1, 2, 1],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
floorSprite: new Mario.Sprite("sprites/tiles.png", [0, 32], [16, 16], 0),
|
floorSprite: new Mario.Sprite(
|
||||||
wallSprite: new Mario.Sprite("sprites/tiles.png", [32, 32], [16, 16], 0),
|
"sprites/tiles.png",
|
||||||
brickSprite: new Mario.Sprite("sprites/tiles.png", [16, 0], [16, 16], 0),
|
[0, 32],
|
||||||
brickBounceSprite: new Mario.Sprite(
|
[16, 16],
|
||||||
"sprites/tiles.png",
|
0,
|
||||||
[32, 0],
|
),
|
||||||
[16, 16],
|
wallSprite: new Mario.Sprite(
|
||||||
0,
|
"sprites/tiles.png",
|
||||||
),
|
[32, 32],
|
||||||
ublockSprite: new Mario.Sprite("sprites/tiles.png", [48, 0], [16, 16], 0),
|
[16, 16],
|
||||||
pipeLMidSprite: new Mario.Sprite(
|
0,
|
||||||
"sprites/tiles.png",
|
),
|
||||||
[0, 144],
|
brickSprite: new Mario.Sprite(
|
||||||
[16, 16],
|
"sprites/tiles.png",
|
||||||
0,
|
[16, 0],
|
||||||
),
|
[16, 16],
|
||||||
pipeRMidSprite: new Mario.Sprite(
|
0,
|
||||||
"sprites/tiles.png",
|
),
|
||||||
[16, 144],
|
brickBounceSprite: new Mario.Sprite(
|
||||||
[16, 16],
|
"sprites/tiles.png",
|
||||||
0,
|
[32, 0],
|
||||||
),
|
[16, 16],
|
||||||
pipeLEndSprite: new Mario.Sprite(
|
0,
|
||||||
"sprites/tiles.png",
|
),
|
||||||
[0, 128],
|
ublockSprite: new Mario.Sprite(
|
||||||
[16, 16],
|
"sprites/tiles.png",
|
||||||
0,
|
[48, 0],
|
||||||
),
|
[16, 16],
|
||||||
pipeREndSprite: new Mario.Sprite(
|
0,
|
||||||
"sprites/tiles.png",
|
),
|
||||||
[16, 128],
|
pipeLMidSprite: new Mario.Sprite(
|
||||||
[16, 16],
|
"sprites/tiles.png",
|
||||||
0,
|
[0, 144],
|
||||||
),
|
[16, 16],
|
||||||
pipeUpMid: new Mario.Sprite("sprites/tiles.png", [0, 144], [32, 16], 0),
|
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),
|
pipeRMidSprite: new Mario.Sprite(
|
||||||
pipeTop: new Mario.Sprite("sprites/tiles.png", [0, 128], [32, 16], 0),
|
"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: [
|
LPipeSprites: [
|
||||||
new Mario.Sprite("sprites/tiles.png", [32, 128], [16, 16], 0),
|
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", [32, 144], [16, 16], 0),
|
||||||
new Mario.Sprite("sprites/tiles.png", [48, 128], [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", [48, 144], [16, 16], 0),
|
||||||
new Mario.Sprite("sprites/tiles.png", [64, 128], [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),
|
new Mario.Sprite("sprites/tiles.png", [64, 144], [16, 16], 0),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
player.pos[0] = level.playerPos[0];
|
player.pos[0] = level.playerPos[0];
|
||||||
player.pos[1] = level.playerPos[1];
|
player.pos[1] = level.playerPos[1];
|
||||||
vX = 0;
|
vX = 0;
|
||||||
level.putFloor(0, 16);
|
level.putFloor(0, 16);
|
||||||
level.putWall(0, 13, 11);
|
level.putWall(0, 13, 11);
|
||||||
walls = [4, 5, 6, 7, 8, 9, 10];
|
walls = [4, 5, 6, 7, 8, 9, 10];
|
||||||
walls.forEach(function (loc) {
|
walls.forEach(function (loc) {
|
||||||
level.putWall(loc, 13, 3);
|
level.putWall(loc, 13, 3);
|
||||||
level.putWall(loc, 3, 1);
|
level.putWall(loc, 3, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
coins = [
|
coins = [
|
||||||
[5, 5],
|
[5, 5],
|
||||||
[6, 5],
|
[6, 5],
|
||||||
[7, 5],
|
[7, 5],
|
||||||
[8, 5],
|
[8, 5],
|
||||||
[9, 5],
|
[9, 5],
|
||||||
[4, 7],
|
[4, 7],
|
||||||
[5, 7],
|
[5, 7],
|
||||||
[6, 7],
|
[6, 7],
|
||||||
[7, 7],
|
[7, 7],
|
||||||
[8, 7],
|
[8, 7],
|
||||||
[9, 7],
|
[9, 7],
|
||||||
[10, 7],
|
[10, 7],
|
||||||
[4, 9],
|
[4, 9],
|
||||||
[5, 9],
|
[5, 9],
|
||||||
[6, 9],
|
[6, 9],
|
||||||
[7, 9],
|
[7, 9],
|
||||||
[8, 9],
|
[8, 9],
|
||||||
[9, 9],
|
[9, 9],
|
||||||
[10, 9],
|
[10, 9],
|
||||||
];
|
];
|
||||||
coins.forEach(function (pos) {
|
coins.forEach(function (pos) {
|
||||||
level.putCoin(pos[0], pos[1]);
|
level.putCoin(pos[0], pos[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
//level.putLeftPipe(13,11);
|
//level.putLeftPipe(13,11);
|
||||||
level.putRealPipe(13, 11, 3, "RIGHT", function () {
|
level.putRealPipe(13, 11, 3, "RIGHT", function () {
|
||||||
Mario.oneone.call();
|
Mario.oneone.call();
|
||||||
player.pos = [2616, 177];
|
player.pos = [2616, 177];
|
||||||
player.pipe("UP", function () {});
|
player.pipe("UP", function () {});
|
||||||
});
|
});
|
||||||
|
|
||||||
level.putPipe(15, 13, 13);
|
level.putPipe(15, 13, 13);
|
||||||
|
|
||||||
music.overworld.pause();
|
music.overworld.pause();
|
||||||
music.underground.currentTime = 0;
|
music.underground.currentTime = 0;
|
||||||
music.underground.play();
|
music.underground.play();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,295 +1,348 @@
|
|||||||
(function () {
|
(function () {
|
||||||
var Level = (Mario.Level = function (options) {
|
var Level = (Mario.Level = function (options) {
|
||||||
this.playerPos = options.playerPos;
|
this.playerPos = options.playerPos;
|
||||||
this.scrolling = options.scrolling;
|
this.scrolling = options.scrolling;
|
||||||
this.loader = options.loader;
|
this.loader = options.loader;
|
||||||
this.background = options.background;
|
this.background = options.background;
|
||||||
this.exit = options.exit;
|
this.exit = options.exit;
|
||||||
|
|
||||||
this.floorSprite = options.floorSprite;
|
this.floorSprite = options.floorSprite;
|
||||||
this.cloudSprite = options.cloudSprite;
|
this.cloudSprite = options.cloudSprite;
|
||||||
this.wallSprite = options.wallSprite;
|
this.wallSprite = options.wallSprite;
|
||||||
this.brickSprite = options.brickSprite;
|
this.brickSprite = options.brickSprite;
|
||||||
this.rubbleSprite = options.rubbleSprite;
|
this.rubbleSprite = options.rubbleSprite;
|
||||||
this.brickBounceSprite = options.brickBounceSprite;
|
this.brickBounceSprite = options.brickBounceSprite;
|
||||||
this.ublockSprite = options.ublockSprite;
|
this.ublockSprite = options.ublockSprite;
|
||||||
this.superShroomSprite = options.superShroomSprite;
|
this.superShroomSprite = options.superShroomSprite;
|
||||||
this.fireFlowerSprite = options.fireFlowerSprite;
|
this.fireFlowerSprite = options.fireFlowerSprite;
|
||||||
this.starSprite = options.starSprite;
|
this.starSprite = options.starSprite;
|
||||||
this.coinSprite = options.coinSprite;
|
this.coinSprite = options.coinSprite;
|
||||||
this.bcoinSprite = options.bcoinSprite;
|
this.bcoinSprite = options.bcoinSprite;
|
||||||
this.goombaSprite = options.goombaSprite;
|
this.goombaSprite = options.goombaSprite;
|
||||||
this.koopaSprite = options.koopaSprite;
|
this.koopaSprite = options.koopaSprite;
|
||||||
|
|
||||||
//prop pipe sprites, to be phased out
|
//prop pipe sprites, to be phased out
|
||||||
this.pipeLEndSprite = options.pipeLEndSprite;
|
this.pipeLEndSprite = options.pipeLEndSprite;
|
||||||
this.pipeREndSprite = options.pipeREndSprite;
|
this.pipeREndSprite = options.pipeREndSprite;
|
||||||
this.pipeLMidSprite = options.pipeLMidSprite;
|
this.pipeLMidSprite = options.pipeLMidSprite;
|
||||||
this.pipeRMidSprite = options.pipeRMidSprite;
|
this.pipeRMidSprite = options.pipeRMidSprite;
|
||||||
|
|
||||||
//real pipe sprites, use these.
|
//real pipe sprites, use these.
|
||||||
this.pipeUpMid = options.pipeUpMid;
|
this.pipeUpMid = options.pipeUpMid;
|
||||||
this.pipeSideMid = options.pipeSideMid;
|
this.pipeSideMid = options.pipeSideMid;
|
||||||
this.pipeLeft = options.pipeLeft;
|
this.pipeLeft = options.pipeLeft;
|
||||||
this.pipeTop = options.pipeTop;
|
this.pipeTop = options.pipeTop;
|
||||||
|
|
||||||
this.flagpoleSprites = options.flagPoleSprites;
|
this.flagpoleSprites = options.flagPoleSprites;
|
||||||
|
|
||||||
this.LPipeSprites = options.LPipeSprites;
|
this.LPipeSprites = options.LPipeSprites;
|
||||||
this.cloudSprites = options.cloudSprites;
|
this.cloudSprites = options.cloudSprites;
|
||||||
this.hillSprites = options.hillSprites;
|
this.hillSprites = options.hillSprites;
|
||||||
this.bushSprite = options.bushSprite;
|
this.bushSprite = options.bushSprite;
|
||||||
this.bushSprites = options.bushSprites;
|
this.bushSprites = options.bushSprites;
|
||||||
this.qblockSprite = options.qblockSprite;
|
this.qblockSprite = options.qblockSprite;
|
||||||
|
|
||||||
this.invincibility = options.invincibility;
|
this.invincibility = options.invincibility;
|
||||||
this.statics = [];
|
this.statics = [];
|
||||||
this.scenery = [];
|
this.scenery = [];
|
||||||
this.blocks = [];
|
this.blocks = [];
|
||||||
this.enemies = [];
|
this.enemies = [];
|
||||||
this.items = [];
|
this.items = [];
|
||||||
this.pipes = [];
|
this.pipes = [];
|
||||||
|
|
||||||
for (var i = 0; i < 15; i++) {
|
for (var i = 0; i < 15; i++) {
|
||||||
this.statics[i] = [];
|
this.statics[i] = [];
|
||||||
this.scenery[i] = [];
|
this.scenery[i] = [];
|
||||||
this.blocks[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,
|
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
Level.prototype.putBrick = function (x, y, item) {
|
Level.prototype.putFloor = function (start, end) {
|
||||||
this.blocks[y][x] = new Mario.Block({
|
for (var i = start; i < end; i++) {
|
||||||
pos: [x * 16, y * 16],
|
this.statics[13][i] = new Mario.Floor(
|
||||||
item: item,
|
[16 * i, 208],
|
||||||
sprite: this.brickSprite,
|
this.floorSprite,
|
||||||
bounceSprite: this.brickBounceSprite,
|
);
|
||||||
usedSprite: this.ublockSprite,
|
this.statics[14][i] = new Mario.Floor(
|
||||||
breakable: !item,
|
[16 * i, 224],
|
||||||
});
|
this.floorSprite,
|
||||||
};
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Level.prototype.putBigHill = function (x, y) {
|
Level.prototype.putGoomba = function (x, y) {
|
||||||
var px = x * 16,
|
this.enemies.push(
|
||||||
py = y * 16;
|
new Mario.Goomba([16 * x, 16 * y], this.goombaSprite()),
|
||||||
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) {
|
Level.prototype.putKoopa = function (x, y) {
|
||||||
this.scenery[y][x] = new Mario.Prop([x * 16, y * 16], this.bushSprite);
|
this.enemies.push(
|
||||||
};
|
new Mario.Koopa([16 * x, 16 * y], this.koopaSprite(), false),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
Level.prototype.putThreeBush = function (x, y) {
|
Level.prototype.putWall = function (x, y, height) {
|
||||||
px = x * 16;
|
//y is the bottom of the wall in this case.
|
||||||
py = y * 16;
|
for (var i = y - height; i < y; i++) {
|
||||||
this.scenery[y][x] = new Mario.Prop([px, py], this.bushSprites[0]);
|
this.statics[i][x] = new Mario.Floor(
|
||||||
this.scenery[y][x + 1] = new Mario.Prop([px + 16, py], this.bushSprites[1]);
|
[16 * x, 16 * i],
|
||||||
this.scenery[y][x + 2] = new Mario.Prop([px + 32, py], this.bushSprites[1]);
|
this.wallSprite,
|
||||||
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) {
|
Level.prototype.putPipe = function (x, y, height) {
|
||||||
px = x * 16;
|
for (var i = y - height; i < y; i++) {
|
||||||
py = y * 16;
|
if (i === y - height) {
|
||||||
this.scenery[y][x] = new Mario.Prop([px, py], this.bushSprites[0]);
|
this.statics[i][x] = new Mario.Floor(
|
||||||
this.scenery[y][x + 1] = new Mario.Prop([px + 16, py], this.bushSprites[1]);
|
[16 * x, 16 * i],
|
||||||
this.scenery[y][x + 2] = new Mario.Prop([px + 32, py], this.bushSprites[1]);
|
this.pipeLEndSprite,
|
||||||
this.scenery[y][x + 3] = new Mario.Prop([px + 48, py], this.bushSprites[2]);
|
);
|
||||||
};
|
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) {
|
//sometimes, pipes don't go straight up and down.
|
||||||
var px = x * 16,
|
Level.prototype.putLeftPipe = function (x, y) {
|
||||||
py = y * 16;
|
this.statics[y][x] = new Mario.Floor(
|
||||||
this.scenery[y][x] = new Mario.Prop([px, py], this.hillSprites[0]);
|
[16 * x, 16 * y],
|
||||||
this.scenery[y][x + 1] = new Mario.Prop([px + 16, py], this.hillSprites[3]);
|
this.LPipeSprites[0],
|
||||||
this.scenery[y - 1][x + 1] = new Mario.Prop(
|
);
|
||||||
[px + 16, py - 16],
|
this.statics[y + 1][x] = new Mario.Floor(
|
||||||
this.hillSprites[1],
|
[16 * x, 16 * (y + 1)],
|
||||||
);
|
this.LPipeSprites[1],
|
||||||
this.scenery[y][x + 2] = new Mario.Prop([px + 32, py], this.hillSprites[2]);
|
);
|
||||||
};
|
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) {
|
Level.prototype.putCoin = function (x, y) {
|
||||||
px = x * 16;
|
this.items.push(new Mario.Coin([x * 16, y * 16], this.coinSprite()));
|
||||||
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) {
|
Level.prototype.putCloud = function (x, y) {
|
||||||
px = x * 16;
|
this.scenery[y][x] = new Mario.Prop([x * 16, y * 16], this.cloudSprite);
|
||||||
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 (
|
Level.prototype.putQBlock = function (x, y, item) {
|
||||||
x,
|
this.blocks[y][x] = new Mario.Block({
|
||||||
y,
|
pos: [x * 16, y * 16],
|
||||||
length,
|
item: item,
|
||||||
direction,
|
sprite: this.qblockSprite,
|
||||||
destination,
|
usedSprite: this.ublockSprite,
|
||||||
) {
|
});
|
||||||
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) {
|
Level.prototype.putBrick = function (x, y, item) {
|
||||||
this.statics[12][x] = new Mario.Floor([16 * x, 192], this.wallSprite);
|
this.blocks[y][x] = new Mario.Block({
|
||||||
for (i = 3; i < 12; i++) {
|
pos: [x * 16, y * 16],
|
||||||
this.scenery[i][x] = new Mario.Prop(
|
item: item,
|
||||||
[16 * x, 16 * i],
|
sprite: this.brickSprite,
|
||||||
this.flagpoleSprites[1],
|
bounceSprite: this.brickBounceSprite,
|
||||||
);
|
usedSprite: this.ublockSprite,
|
||||||
}
|
breakable: !item,
|
||||||
this.scenery[2][x] = new Mario.Prop([16 * x, 32], this.flagpoleSprites[0]);
|
});
|
||||||
this.items.push(new Mario.Flag(16 * x));
|
};
|
||||||
};
|
|
||||||
|
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));
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,129 +1,132 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") window.Mario = {};
|
if (typeof Mario === "undefined") window.Mario = {};
|
||||||
|
|
||||||
var Mushroom = (Mario.Mushroom = function (pos) {
|
var Mushroom = (Mario.Mushroom = function (pos) {
|
||||||
this.spawning = false;
|
this.spawning = false;
|
||||||
this.waiting = 0;
|
this.waiting = 0;
|
||||||
|
|
||||||
Mario.Entity.call(this, {
|
Mario.Entity.call(this, {
|
||||||
pos: pos,
|
pos: pos,
|
||||||
sprite: level.superShroomSprite,
|
sprite: level.superShroomSprite,
|
||||||
hitbox: [0, 0, 16, 16],
|
hitbox: [0, 0, 16, 16],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
Mario.Util.inherits(Mushroom, Mario.Entity);
|
Mario.Util.inherits(Mushroom, Mario.Entity);
|
||||||
|
|
||||||
Mushroom.prototype.render = function (ctx, vX, vY) {
|
Mushroom.prototype.render = function (ctx, vX, vY) {
|
||||||
if (this.spawning > 1) return;
|
if (this.spawning > 1) return;
|
||||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||||
};
|
};
|
||||||
|
|
||||||
Mushroom.prototype.spawn = function () {
|
Mushroom.prototype.spawn = function () {
|
||||||
if (player.power > 0) {
|
if (player.power > 0) {
|
||||||
//replace this with a fire flower
|
//replace this with a fire flower
|
||||||
var ff = new Mario.Fireflower(this.pos);
|
var ff = new Mario.Fireflower(this.pos);
|
||||||
ff.spawn();
|
ff.spawn();
|
||||||
return;
|
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);
|
|
||||||
}
|
}
|
||||||
if (level.blocks[baseY + i][baseX + j]) {
|
sounds.itemAppear.play();
|
||||||
level.blocks[baseY + i][baseX + j].isCollideWith(this);
|
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.collideWall = function () {
|
||||||
Mushroom.prototype.isPlayerCollided = 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 = [
|
|
||||||
player.pos[0] + player.hitbox[0],
|
|
||||||
player.pos[1] + player.hitbox[1],
|
|
||||||
];
|
|
||||||
|
|
||||||
//if the hitboxes actually overlap
|
Mushroom.prototype.checkCollisions = function () {
|
||||||
if (
|
if (this.spawning) {
|
||||||
!(
|
return;
|
||||||
hpos1[0] > hpos2[0] + player.hitbox[2] ||
|
}
|
||||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
var h = this.pos[1] % 16 == 0 ? 1 : 2;
|
||||||
)
|
var w = this.pos[0] % 16 == 0 ? 1 : 2;
|
||||||
) {
|
|
||||||
if (
|
|
||||||
!(
|
|
||||||
hpos1[1] > hpos2[1] + player.hitbox[3] ||
|
|
||||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
player.powerUp(this.idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Mushroom.prototype.bump = function () {
|
var baseX = Math.floor(this.pos[0] / 16);
|
||||||
this.vel[1] = -2;
|
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;
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,224 +1,228 @@
|
|||||||
(function () {
|
(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
|
//there are too many possible configurations of pipe to capture in a reasonable
|
||||||
//set of simple variables. Joints, etc. are just too much.
|
//set of simple variables. Joints, etc. are just too much.
|
||||||
//To that end, the pipe class handles simple pipes, and we'll put together
|
//To that end, the pipe class handles simple pipes, and we'll put together
|
||||||
//anything more complex with individual props. OK? OK.
|
//anything more complex with individual props. OK? OK.
|
||||||
Pipe = Mario.Pipe = function (options) {
|
Pipe = Mario.Pipe = function (options) {
|
||||||
this.pos = options.pos;
|
this.pos = options.pos;
|
||||||
|
|
||||||
//NOTE: direction is the direction you move INTO the pipe.
|
//NOTE: direction is the direction you move INTO the pipe.
|
||||||
this.direction = options.direction;
|
this.direction = options.direction;
|
||||||
this.destination = options.destination;
|
this.destination = options.destination;
|
||||||
this.length = options.length;
|
this.length = options.length;
|
||||||
|
|
||||||
if (this.direction === "UP" || this.direction === "DOWN") {
|
if (this.direction === "UP" || this.direction === "DOWN") {
|
||||||
this.hitbox = [0, 0, 32, this.length * 16];
|
this.hitbox = [0, 0, 32, this.length * 16];
|
||||||
this.midsection = level.pipeUpMid;
|
this.midsection = level.pipeUpMid;
|
||||||
this.endsection = level.pipeTop;
|
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;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
//entity is hitting it from the side, we're a wall
|
this.hitbox = [0, 0, 16 * this.length, 32];
|
||||||
ent.collideWall(this);
|
this.midsection = level.pipeSideMid;
|
||||||
|
this.endsection = level.pipeLeft;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//we COULD try to write some shenanigans so that the check gets put into the
|
Pipe.prototype.checkPipe = function () {
|
||||||
//collision code, but there won't ever be more than a handful of pipes in a level
|
if (this.destination === undefined || !input.isDown(this.direction))
|
||||||
//so the performance hit of scanning all of them is miniscule.
|
return;
|
||||||
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
|
var h = player.power === 0 ? 16 : 32;
|
||||||
//I honestly have no idea if javascript does this, but I feel like it makes sense
|
var x = Math.floor(player.pos[0]);
|
||||||
//stylistically to prefer branching outside of loops when possible as convention
|
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.
|
//Note to self: next time, decide on a convention for which thing checks for collisions
|
||||||
Pipe.prototype.render = function (ctx, vX, vY) {
|
//and stick to it. This is a pain.
|
||||||
switch (this.direction) {
|
Pipe.prototype.checkCollisions = function () {
|
||||||
case "DOWN":
|
var that = this;
|
||||||
this.endsection.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
level.enemies.forEach(function (ent) {
|
||||||
for (var i = 1; i < this.length; i++) {
|
that.isCollideWith(ent);
|
||||||
this.midsection.render(
|
});
|
||||||
ctx,
|
|
||||||
this.pos[0],
|
level.items.forEach(function (ent) {
|
||||||
this.pos[1] + i * 16,
|
that.isCollideWith(ent);
|
||||||
vX,
|
});
|
||||||
vY,
|
|
||||||
);
|
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(
|
//we COULD try to write some shenanigans so that the check gets put into the
|
||||||
ctx,
|
//collision code, but there won't ever be more than a handful of pipes in a level
|
||||||
this.pos[0],
|
//so the performance hit of scanning all of them is miniscule.
|
||||||
this.pos[1] + 16 * (this.length - 1),
|
Pipe.prototype.update = function (dt) {
|
||||||
vX,
|
if (this.destination) this.checkPipe();
|
||||||
vY,
|
};
|
||||||
);
|
|
||||||
for (var i = 0; i < this.length - 1; i++) {
|
//http://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-an-unsorted-array
|
||||||
this.midsection.render(
|
//I honestly have no idea if javascript does this, but I feel like it makes sense
|
||||||
ctx,
|
//stylistically to prefer branching outside of loops when possible as convention
|
||||||
this.pos[0],
|
|
||||||
this.pos[1] + i * 16,
|
//TODO: edit the spritesheet so UP and LEFT pipes aren't backwards.
|
||||||
vX,
|
Pipe.prototype.render = function (ctx, vX, vY) {
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,498 +1,505 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") window.Mario = {};
|
if (typeof Mario === "undefined") window.Mario = {};
|
||||||
|
|
||||||
var Player = (Mario.Player = function (pos) {
|
var Player = (Mario.Player = function (pos) {
|
||||||
//I know, I know, there are a lot of variables tracking Mario's state.
|
//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.
|
//Maybe these can be consolidated some way? We'll see once they're all in.
|
||||||
this.power = 0;
|
this.power = 0;
|
||||||
this.coins = 0;
|
this.coins = 0;
|
||||||
this.powering = [];
|
this.powering = [];
|
||||||
this.bounce = false;
|
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;
|
|
||||||
this.jumping = 0;
|
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 () {
|
Mario.Entity.call(this, {
|
||||||
if (this.dying) return;
|
pos: pos,
|
||||||
|
sprite: new Mario.Sprite(
|
||||||
|
"sprites/player.png",
|
||||||
|
[80, 32],
|
||||||
|
[16, 16],
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
hitbox: [0, 0, 16, 16],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
if (this.starTime) {
|
Mario.Util.inherits(Player, Mario.Entity);
|
||||||
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];
|
Player.prototype.run = function () {
|
||||||
if (this.power == 0) {
|
this.maxSpeed = 2.5;
|
||||||
this.sprite.pos[1] += 32;
|
if (this.power == 2 && !this.runheld) {
|
||||||
}
|
this.shoot();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
this.runheld = true;
|
||||||
}
|
};
|
||||||
//okay cool, now set the sprite
|
|
||||||
if (this.crouching) {
|
|
||||||
this.sprite.pos[0] = 176;
|
|
||||||
this.sprite.speed = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.jumping) {
|
Player.prototype.shoot = function () {
|
||||||
this.sprite.pos[0] = 160;
|
if (this.fireballs >= 2) return; //Projectile limit!
|
||||||
this.sprite.speed = 0;
|
this.fireballs += 1;
|
||||||
} else if (this.standing) {
|
var fb = new Mario.Fireball([this.pos[0] + 8, this.pos[1]]); //I hate you, Javascript.
|
||||||
if (Math.abs(this.vel[0]) > 0) {
|
fb.spawn(this.left);
|
||||||
if (this.vel[0] * this.acc[0] >= 0) {
|
this.shooting = 2;
|
||||||
this.sprite.pos[0] = 96;
|
};
|
||||||
this.sprite.frames = [0, 1, 2];
|
|
||||||
if (this.vel[0] < 0.2) {
|
Player.prototype.noRun = function () {
|
||||||
this.sprite.speed = 5;
|
this.maxSpeed = 1.5;
|
||||||
} else {
|
this.moveAcc = 0.07;
|
||||||
this.sprite.speed = Math.abs(this.vel[0]) * 8;
|
this.runheld = false;
|
||||||
}
|
};
|
||||||
} else if (
|
|
||||||
(this.vel[0] > 0 && this.left) ||
|
Player.prototype.moveRight = function () {
|
||||||
(this.vel[0] < 0 && !this.left)
|
//we're on the ground
|
||||||
) {
|
if (this.vel[1] === 0 && this.standing) {
|
||||||
this.sprite.pos[0] = 144;
|
if (this.crouching) {
|
||||||
this.sprite.speed = 0;
|
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;
|
this.sprite.speed = 0;
|
||||||
}
|
this.power = 0;
|
||||||
if (this.shooting) {
|
this.waiting = 0.5;
|
||||||
this.sprite.pos[0] += 160;
|
this.dying = 2;
|
||||||
this.shooting -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.flagging) {
|
if (this.pos[1] < 240) {
|
||||||
this.sprite.pos[0] = 192;
|
//falling into a pit doesn't do the animation.
|
||||||
this.sprite.frames = [0, 1];
|
this.targetPos = [this.pos[0], this.pos[1] - 128];
|
||||||
this.sprite.speed = 10;
|
this.vel = [0, -5];
|
||||||
if (this.vel[1] === 0) this.sprite.frames = [0];
|
} else {
|
||||||
}
|
this.vel = [0, 0];
|
||||||
|
this.targetPos = [this.pos[0], this.pos[1] - 16];
|
||||||
//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);
|
|
||||||
|
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) {
|
Player.prototype.flag = function () {
|
||||||
sounds.powerup.play();
|
this.noInput = true;
|
||||||
this.powering = [
|
this.flagging = true;
|
||||||
0, 5, 2, 5, 1, 5, 2, 5, 1, 5, 2, 5, 3, 5, 1, 5, 2, 5, 3, 5, 1, 5, 4,
|
this.vel = [0, 2];
|
||||||
];
|
this.acc = [0, 0];
|
||||||
this.touchedItem = idx;
|
};
|
||||||
|
|
||||||
if (this.power === 0) {
|
Player.prototype.exit = function () {
|
||||||
this.sprite.pos[0] = 80;
|
this.pos[0] += 16;
|
||||||
var newy = this.sprite.pos[1] - 32;
|
this.targetPos[0] = level.exit * 16;
|
||||||
this.powerSprites = [
|
this.left = true;
|
||||||
[80, newy + 32],
|
this.setAnimation();
|
||||||
[80, newy + 32],
|
this.waiting = 1;
|
||||||
[320, newy],
|
this.exiting = true;
|
||||||
[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;
|
|
||||||
};
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
(function () {
|
(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
|
//props do even less than entities, so they don't need to inherit really
|
||||||
var Prop = (Mario.Prop = function (pos, sprite) {
|
var Prop = (Mario.Prop = function (pos, sprite) {
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
this.sprite = sprite;
|
this.sprite = sprite;
|
||||||
});
|
});
|
||||||
|
|
||||||
//but we will be using the same Render, more or less.
|
//but we will be using the same Render, more or less.
|
||||||
Prop.prototype.render = function (ctx, vX, vY) {
|
Prop.prototype.render = function (ctx, vX, vY) {
|
||||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,61 +1,61 @@
|
|||||||
//simple resource loader
|
//simple resource loader
|
||||||
(function () {
|
(function () {
|
||||||
var resourceCache = {};
|
var resourceCache = {};
|
||||||
var loading = [];
|
var loading = [];
|
||||||
var readyCallbacks = [];
|
var readyCallbacks = [];
|
||||||
|
|
||||||
// Load an image url or an array of image urls
|
// Load an image url or an array of image urls
|
||||||
function load(urlOrArr) {
|
function load(urlOrArr) {
|
||||||
if (urlOrArr instanceof Array) {
|
if (urlOrArr instanceof Array) {
|
||||||
urlOrArr.forEach(function (url) {
|
urlOrArr.forEach(function (url) {
|
||||||
_load(url);
|
_load(url);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
_load(urlOrArr);
|
_load(urlOrArr);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _load(url) {
|
|
||||||
if (resourceCache[url]) {
|
|
||||||
return resourceCache[url];
|
|
||||||
} else {
|
|
||||||
var img = new Image();
|
|
||||||
img.onload = function () {
|
|
||||||
resourceCache[url] = img;
|
|
||||||
|
|
||||||
if (isReady()) {
|
|
||||||
readyCallbacks.forEach(function (func) {
|
|
||||||
func();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
resourceCache[url] = false;
|
|
||||||
img.src = url;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function get(url) {
|
function _load(url) {
|
||||||
return resourceCache[url];
|
if (resourceCache[url]) {
|
||||||
}
|
return resourceCache[url];
|
||||||
|
} else {
|
||||||
|
var img = new Image();
|
||||||
|
img.onload = function () {
|
||||||
|
resourceCache[url] = img;
|
||||||
|
|
||||||
function isReady() {
|
if (isReady()) {
|
||||||
var ready = true;
|
readyCallbacks.forEach(function (func) {
|
||||||
for (var k in resourceCache) {
|
func();
|
||||||
if (resourceCache.hasOwnProperty(k) && !resourceCache[k]) {
|
});
|
||||||
ready = false;
|
}
|
||||||
}
|
};
|
||||||
|
resourceCache[url] = false;
|
||||||
|
img.src = url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ready;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onReady(func) {
|
function get(url) {
|
||||||
readyCallbacks.push(func);
|
return resourceCache[url];
|
||||||
}
|
}
|
||||||
|
|
||||||
window.resources = {
|
function isReady() {
|
||||||
load: load,
|
var ready = true;
|
||||||
get: get,
|
for (var k in resourceCache) {
|
||||||
onReady: onReady,
|
if (resourceCache.hasOwnProperty(k) && !resourceCache[k]) {
|
||||||
isReady: isReady,
|
ready = false;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
return ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onReady(func) {
|
||||||
|
readyCallbacks.push(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.resources = {
|
||||||
|
load: load,
|
||||||
|
get: get,
|
||||||
|
onReady: onReady,
|
||||||
|
isReady: isReady,
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,58 +1,64 @@
|
|||||||
(function () {
|
(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
|
//TODO: make each rubble an entity, use that render and write in Entity.update
|
||||||
var Rubble = (Mario.Rubble = function () {
|
var Rubble = (Mario.Rubble = function () {
|
||||||
this.sprites = [];
|
this.sprites = [];
|
||||||
this.poss = [];
|
this.poss = [];
|
||||||
this.vels = [];
|
this.vels = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
Rubble.prototype.spawn = function (pos) {
|
Rubble.prototype.spawn = function (pos) {
|
||||||
this.idx = level.items.length;
|
this.idx = level.items.length;
|
||||||
level.items.push(this);
|
level.items.push(this);
|
||||||
this.sprites[0] = level.rubbleSprite();
|
this.sprites[0] = level.rubbleSprite();
|
||||||
this.sprites[1] = level.rubbleSprite();
|
this.sprites[1] = level.rubbleSprite();
|
||||||
this.sprites[2] = level.rubbleSprite();
|
this.sprites[2] = level.rubbleSprite();
|
||||||
this.sprites[3] = level.rubbleSprite();
|
this.sprites[3] = level.rubbleSprite();
|
||||||
this.poss[0] = pos;
|
this.poss[0] = pos;
|
||||||
this.poss[1] = [pos[0] + 8, pos[1]];
|
this.poss[1] = [pos[0] + 8, pos[1]];
|
||||||
this.poss[2] = [pos[0], pos[1] + 8];
|
this.poss[2] = [pos[0], pos[1] + 8];
|
||||||
this.poss[3] = [pos[0] + 8, pos[1] + 8];
|
this.poss[3] = [pos[0] + 8, pos[1] + 8];
|
||||||
this.vels[0] = [-1.25, -5];
|
this.vels[0] = [-1.25, -5];
|
||||||
this.vels[1] = [1.25, -5];
|
this.vels[1] = [1.25, -5];
|
||||||
this.vels[2] = [-1.25, -3];
|
this.vels[2] = [-1.25, -3];
|
||||||
this.vels[3] = [1.25, -3];
|
this.vels[3] = [1.25, -3];
|
||||||
};
|
};
|
||||||
|
|
||||||
Rubble.prototype.update = function (dt) {
|
Rubble.prototype.update = function (dt) {
|
||||||
for (var i = 0; i < 4; i++) {
|
for (var i = 0; i < 4; i++) {
|
||||||
if (this.sprites[i] === undefined) continue;
|
if (this.sprites[i] === undefined) continue;
|
||||||
this.vels[i][1] += 0.3;
|
this.vels[i][1] += 0.3;
|
||||||
this.poss[i][0] += this.vels[i][0];
|
this.poss[i][0] += this.vels[i][0];
|
||||||
this.poss[i][1] += this.vels[i][1];
|
this.poss[i][1] += this.vels[i][1];
|
||||||
this.sprites[i].update(dt);
|
this.sprites[i].update(dt);
|
||||||
if (this.poss[i][1] > 256) {
|
if (this.poss[i][1] > 256) {
|
||||||
delete this.sprites[i];
|
delete this.sprites[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
this.sprites.every(function (el) {
|
this.sprites.every(function (el) {
|
||||||
return !el;
|
return !el;
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
delete level.items[this.idx];
|
delete level.items[this.idx];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//You might argue that things that can't collide are more like scenery
|
//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.
|
//but these move and need to be deleted, and i'd rather deal with the 1d array.
|
||||||
Rubble.prototype.checkCollisions = function () {};
|
Rubble.prototype.checkCollisions = function () {};
|
||||||
|
|
||||||
Rubble.prototype.render = function () {
|
Rubble.prototype.render = function () {
|
||||||
for (var i = 0; i < 4; i++) {
|
for (var i = 0; i < 4; i++) {
|
||||||
if (this.sprites[i] === undefined) continue;
|
if (this.sprites[i] === undefined) continue;
|
||||||
this.sprites[i].render(ctx, this.poss[i][0], this.poss[i][1], vX, vY);
|
this.sprites[i].render(
|
||||||
}
|
ctx,
|
||||||
};
|
this.poss[i][0],
|
||||||
|
this.poss[i][1],
|
||||||
|
vX,
|
||||||
|
vY,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,56 +1,63 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") window.Mario = {};
|
if (typeof Mario === "undefined") window.Mario = {};
|
||||||
|
|
||||||
var Sprite = (Mario.Sprite = function (img, pos, size, speed, frames, once) {
|
var Sprite = (Mario.Sprite = function (
|
||||||
this.pos = pos;
|
img,
|
||||||
this.size = size;
|
pos,
|
||||||
this.speed = speed;
|
size,
|
||||||
this._index = 0;
|
speed,
|
||||||
this.img = img;
|
frames,
|
||||||
this.once = once;
|
once,
|
||||||
this.frames = frames;
|
) {
|
||||||
});
|
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) {
|
Sprite.prototype.update = function (dt, gameTime) {
|
||||||
if (gameTime && gameTime == this.lastUpdated) return;
|
if (gameTime && gameTime == this.lastUpdated) return;
|
||||||
this._index += this.speed * dt;
|
this._index += this.speed * dt;
|
||||||
if (gameTime) this.lastUpdated = gameTime;
|
if (gameTime) this.lastUpdated = gameTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
Sprite.prototype.setFrame = function (frame) {
|
Sprite.prototype.setFrame = function (frame) {
|
||||||
this._index = frame;
|
this._index = frame;
|
||||||
};
|
};
|
||||||
|
|
||||||
Sprite.prototype.render = function (ctx, posx, posy, vX, vY) {
|
Sprite.prototype.render = function (ctx, posx, posy, vX, vY) {
|
||||||
var frame;
|
var frame;
|
||||||
|
|
||||||
if (this.speed > 0) {
|
if (this.speed > 0) {
|
||||||
var max = this.frames.length;
|
var max = this.frames.length;
|
||||||
var idx = Math.floor(this._index);
|
var idx = Math.floor(this._index);
|
||||||
frame = this.frames[idx % max];
|
frame = this.frames[idx % max];
|
||||||
|
|
||||||
if (this.once && idx >= max) {
|
if (this.once && idx >= max) {
|
||||||
this.done = true;
|
this.done = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
frame = 0;
|
frame = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var x = this.pos[0];
|
var x = this.pos[0];
|
||||||
var y = this.pos[1];
|
var y = this.pos[1];
|
||||||
|
|
||||||
x += frame * this.size[0];
|
x += frame * this.size[0];
|
||||||
ctx.drawImage(
|
ctx.drawImage(
|
||||||
resources.get(this.img),
|
resources.get(this.img),
|
||||||
x + 1 / 3,
|
x + 1 / 3,
|
||||||
y + 1 / 3,
|
y + 1 / 3,
|
||||||
this.size[0] - 2 / 3,
|
this.size[0] - 2 / 3,
|
||||||
this.size[1] - 2 / 3,
|
this.size[1] - 2 / 3,
|
||||||
Math.round(posx - vX),
|
Math.round(posx - vX),
|
||||||
Math.round(posy - vY),
|
Math.round(posy - vY),
|
||||||
this.size[0],
|
this.size[0],
|
||||||
this.size[1],
|
this.size[1],
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,127 +1,130 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") window.Mario = {};
|
if (typeof Mario === "undefined") window.Mario = {};
|
||||||
|
|
||||||
var Star = (Mario.Star = function (pos) {
|
var Star = (Mario.Star = function (pos) {
|
||||||
this.spawning = false;
|
this.spawning = false;
|
||||||
this.waiting = 0;
|
this.waiting = 0;
|
||||||
|
|
||||||
Mario.Entity.call(this, {
|
Mario.Entity.call(this, {
|
||||||
pos: pos,
|
pos: pos,
|
||||||
sprite: level.starSprite,
|
sprite: level.starSprite,
|
||||||
hitbox: [0, 0, 16, 16],
|
hitbox: [0, 0, 16, 16],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
Mario.Util.inherits(Star, Mario.Entity);
|
Mario.Util.inherits(Star, Mario.Entity);
|
||||||
|
|
||||||
Star.prototype.render = function (ctx, vX, vY) {
|
Star.prototype.render = function (ctx, vX, vY) {
|
||||||
if (this.spawning > 1) return;
|
if (this.spawning > 1) return;
|
||||||
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
||||||
};
|
};
|
||||||
|
|
||||||
Star.prototype.spawn = function () {
|
Star.prototype.spawn = function () {
|
||||||
this.idx = level.items.length;
|
this.idx = level.items.length;
|
||||||
level.items.push(this);
|
level.items.push(this);
|
||||||
this.spawning = 12;
|
this.spawning = 12;
|
||||||
this.targetpos = [];
|
this.targetpos = [];
|
||||||
this.targetpos[0] = this.pos[0];
|
this.targetpos[0] = this.pos[0];
|
||||||
this.targetpos[1] = this.pos[1] - 16;
|
this.targetpos[1] = this.pos[1] - 16;
|
||||||
};
|
};
|
||||||
|
|
||||||
Star.prototype.update = function (dt) {
|
Star.prototype.update = function (dt) {
|
||||||
if (this.spawning > 1) {
|
if (this.spawning > 1) {
|
||||||
this.spawning -= 1;
|
this.spawning -= 1;
|
||||||
if (this.spawning == 1) this.vel[1] = -0.5;
|
if (this.spawning == 1) this.vel[1] = -0.5;
|
||||||
return;
|
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);
|
|
||||||
}
|
}
|
||||||
if (level.blocks[baseY + i][baseX + j]) {
|
if (this.spawning) {
|
||||||
level.blocks[baseY + i][baseX + j].isCollideWith(this);
|
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.
|
if (this.waiting) {
|
||||||
Star.prototype.isPlayerCollided = function () {
|
this.waiting -= 1;
|
||||||
//the first two elements of the hitbox array are an offset, so let's do this now.
|
} else {
|
||||||
var hpos1 = [this.pos[0] + this.hitbox[0], this.pos[1] + this.hitbox[1]];
|
this.vel[1] += this.acc[1];
|
||||||
var hpos2 = [
|
this.pos[0] += this.vel[0];
|
||||||
player.pos[0] + player.hitbox[0],
|
this.pos[1] += this.vel[1];
|
||||||
player.pos[1] + player.hitbox[1],
|
this.sprite.update(dt);
|
||||||
];
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//if the hitboxes actually overlap
|
Star.prototype.collideWall = function () {
|
||||||
if (
|
this.vel[0] = -this.vel[0];
|
||||||
!(
|
};
|
||||||
hpos1[0] > hpos2[0] + player.hitbox[2] ||
|
|
||||||
hpos1[0] + this.hitbox[2] < hpos2[0]
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
if (
|
|
||||||
!(
|
|
||||||
hpos1[1] > hpos2[1] + player.hitbox[3] ||
|
|
||||||
hpos1[1] + this.hitbox[3] < hpos2[1]
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
player.star(this.idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Star.prototype.bump = function () {
|
Star.prototype.checkCollisions = function () {
|
||||||
this.vel[1] = -2;
|
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;
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (typeof Mario === "undefined") {
|
if (typeof Mario === "undefined") {
|
||||||
window.Mario = {};
|
window.Mario = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
var Util = (Mario.Util = {});
|
var Util = (Mario.Util = {});
|
||||||
|
|
||||||
Util.inherits = function (subclass, superclass) {
|
Util.inherits = function (subclass, superclass) {
|
||||||
function Surrogate() {}
|
function Surrogate() {}
|
||||||
|
|
||||||
Surrogate.prototype = superclass.prototype;
|
Surrogate.prototype = superclass.prototype;
|
||||||
subclass.prototype = new Surrogate();
|
subclass.prototype = new Surrogate();
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|
||||||
<title>PyMarkdown</title>
|
<title>PyMarkdown</title>
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png" />
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
<link rel="stylesheet" href="../build/pyscript.css" />
|
<link rel="stylesheet" href="../build/pyscript.css" />
|
||||||
|
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
<script defer src="../build/pyscript.js"></script>
|
<script defer src="../build/pyscript.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<py-tutor>
|
<py-tutor>
|
||||||
<py-config>
|
<py-config>
|
||||||
packages = [
|
packages = [
|
||||||
"markdown"
|
"markdown"
|
||||||
]
|
]
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_markdown.py",
|
"../build/plugins/python/py_markdown.py",
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<py-md>#Hello world!</py-md>
|
<py-md>#Hello world!</py-md>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,70 +1,73 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Matplotlib</title>
|
<title>Matplotlib</title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
</head>
|
/>
|
||||||
<body>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
<div class="app-header">
|
</head>
|
||||||
<a href="/">
|
<body>
|
||||||
<img src="./logo.png" class="logo" />
|
<nav class="navbar" style="background-color: #000000">
|
||||||
</a>
|
<div class="app-header">
|
||||||
<a class="title" href="" style="color: #f0ab3c">Matplotlib</a>
|
<a href="/">
|
||||||
</div>
|
<img src="./logo.png" class="logo" />
|
||||||
</nav>
|
</a>
|
||||||
<section class="pyscript">
|
<a class="title" href="" style="color: #f0ab3c">Matplotlib</a>
|
||||||
<div id="mpl"></div>
|
</div>
|
||||||
|
</nav>
|
||||||
|
<section class="pyscript">
|
||||||
|
<div id="mpl"></div>
|
||||||
|
|
||||||
<py-tutor>
|
<py-tutor>
|
||||||
<py-config>
|
<py-config>
|
||||||
packages = [
|
packages = [
|
||||||
"matplotlib"
|
"matplotlib"
|
||||||
]
|
]
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<py-script>
|
<py-script>
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import matplotlib.tri as tri
|
import matplotlib.tri as tri
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
# First create the x and y coordinates of the points.
|
# First create the x and y coordinates of the points.
|
||||||
n_angles = 36
|
n_angles = 36
|
||||||
n_radii = 8
|
n_radii = 8
|
||||||
min_radius = 0.25
|
min_radius = 0.25
|
||||||
radii = np.linspace(min_radius, 0.95, n_radii)
|
radii = np.linspace(min_radius, 0.95, n_radii)
|
||||||
|
|
||||||
angles = np.linspace(0, 2 * np.pi, n_angles, endpoint=False)
|
angles = np.linspace(0, 2 * np.pi, n_angles, endpoint=False)
|
||||||
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)
|
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)
|
||||||
angles[:, 1::2] += np.pi / n_angles
|
angles[:, 1::2] += np.pi / n_angles
|
||||||
|
|
||||||
x = (radii * np.cos(angles)).flatten()
|
x = (radii * np.cos(angles)).flatten()
|
||||||
y = (radii * np.sin(angles)).flatten()
|
y = (radii * np.sin(angles)).flatten()
|
||||||
z = (np.cos(radii) * np.cos(3 * angles)).flatten()
|
z = (np.cos(radii) * np.cos(3 * angles)).flatten()
|
||||||
|
|
||||||
# Create the Triangulation; no triangles so Delaunay triangulation created.
|
# Create the Triangulation; no triangles so Delaunay triangulation created.
|
||||||
triang = tri.Triangulation(x, y)
|
triang = tri.Triangulation(x, y)
|
||||||
|
|
||||||
# Mask off unwanted triangles.
|
# Mask off unwanted triangles.
|
||||||
triang.set_mask(np.hypot(x[triang.triangles].mean(axis=1),
|
triang.set_mask(np.hypot(x[triang.triangles].mean(axis=1),
|
||||||
y[triang.triangles].mean(axis=1))
|
y[triang.triangles].mean(axis=1))
|
||||||
< min_radius)
|
< min_radius)
|
||||||
|
|
||||||
fig1, ax1 = plt.subplots()
|
fig1, ax1 = plt.subplots()
|
||||||
ax1.set_aspect('equal')
|
ax1.set_aspect('equal')
|
||||||
tpc = ax1.tripcolor(triang, z, shading='flat')
|
tpc = ax1.tripcolor(triang, z, shading='flat')
|
||||||
fig1.colorbar(tpc)
|
fig1.colorbar(tpc)
|
||||||
ax1.set_title('tripcolor of Delaunay triangulation, flat shading')
|
ax1.set_title('tripcolor of Delaunay triangulation, flat shading')
|
||||||
|
|
||||||
display(fig1, target="mpl")
|
display(fig1, target="mpl")
|
||||||
</py-script>
|
</py-script>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</section>
|
</section>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,35 +1,38 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
|
/>
|
||||||
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<py-tutor>
|
<py-tutor>
|
||||||
<py-config>
|
<py-config>
|
||||||
packages = [
|
packages = [
|
||||||
"numpy",
|
"numpy",
|
||||||
"networkx",
|
"networkx",
|
||||||
"matplotlib"
|
"matplotlib"
|
||||||
]
|
]
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<py-script>
|
<py-script>
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
</py-script>
|
</py-script>
|
||||||
|
|
||||||
<p>Message passing with linear algebra: a demo.</p>
|
<p>Message passing with linear algebra: a demo.</p>
|
||||||
<p>Imagine we have a chain graph that looks like this:</p>
|
<p>Imagine we have a chain graph that looks like this:</p>
|
||||||
<pre><code>O --> 1 --> 2 --> 3</code></pre>
|
<pre><code>O --> 1 --> 2 --> 3</code></pre>
|
||||||
<p>In NetworkX this graph would look like the following:</p>
|
<p>In NetworkX this graph would look like the following:</p>
|
||||||
<pre>
|
<pre>
|
||||||
<py-script>
|
<py-script>
|
||||||
G = nx.Graph()
|
G = nx.Graph()
|
||||||
nodes = list(range(4))
|
nodes = list(range(4))
|
||||||
@@ -37,29 +40,30 @@ G.add_edges_from(zip(nodes[0:-1], nodes[1:]))
|
|||||||
print(G.edges())
|
print(G.edges())
|
||||||
</py-script>
|
</py-script>
|
||||||
</pre>
|
</pre>
|
||||||
<p>This chain graph has the following adjacency matrix:</p>
|
<p>This chain graph has the following adjacency matrix:</p>
|
||||||
<pre>
|
<pre>
|
||||||
<py-script>
|
<py-script>
|
||||||
adj_mat = np.eye(4, k=1)
|
adj_mat = np.eye(4, k=1)
|
||||||
print(f"A: {adj_mat}")
|
print(f"A: {adj_mat}")
|
||||||
</py-script>
|
</py-script>
|
||||||
</pre>
|
</pre>
|
||||||
<p>And imagine that we have a message that lives on the graph:</p>
|
<p>And imagine that we have a message that lives on the graph:</p>
|
||||||
<pre>
|
<pre>
|
||||||
<py-script>
|
<py-script>
|
||||||
message = np.array([1.0, 0.0, 0.0, 0.0])
|
message = np.array([1.0, 0.0, 0.0, 0.0])
|
||||||
print(f"message: {message}")
|
print(f"message: {message}")
|
||||||
</py-script>
|
</py-script>
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
Try out message passing below by doing any one of the following steps:
|
Try out message passing below by doing any one of the following
|
||||||
</p>
|
steps:
|
||||||
<pre><code>message @ adj_mat</code></pre>
|
</p>
|
||||||
<pre><code>message @ adj_mat @ adj_mat</code></pre>
|
<pre><code>message @ adj_mat</code></pre>
|
||||||
<pre><code>message @ adj_mat @ adj_mat @ adj_mat</code></pre>
|
<pre><code>message @ adj_mat @ adj_mat</code></pre>
|
||||||
<div>
|
<pre><code>message @ adj_mat @ adj_mat @ adj_mat</code></pre>
|
||||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
<div>
|
||||||
</div>
|
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||||
</py-tutor>
|
</div>
|
||||||
</body>
|
</py-tutor>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,186 +1,196 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
|
|
||||||
<title>micrograd</title>
|
<title>micrograd</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
|
/>
|
||||||
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
|
|
||||||
<link
|
<link
|
||||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
|
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
crossorigin="anonymous"
|
crossorigin="anonymous"
|
||||||
/>
|
/>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body
|
<body
|
||||||
style="
|
style="
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<h1>Micrograd - A tiny Autograd engine (with a bite! :))</h1>
|
<h1>Micrograd - A tiny Autograd engine (with a bite! :))</h1>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<py-config>
|
<py-config>
|
||||||
packages = [
|
packages = [
|
||||||
"micrograd",
|
"micrograd",
|
||||||
"numpy",
|
"numpy",
|
||||||
"matplotlib"
|
"matplotlib"
|
||||||
]
|
]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<a href="https://github.com/karpathy/micrograd">Micrograd</a> is a tiny
|
<a href="https://github.com/karpathy/micrograd">Micrograd</a> is
|
||||||
Autograd engine created by
|
a tiny Autograd engine created by
|
||||||
<a href="https://twitter.com/karpathy">Andrej Karpathy</a>. This app
|
<a href="https://twitter.com/karpathy">Andrej Karpathy</a>. This
|
||||||
recreates the
|
app recreates the
|
||||||
<a href="https://github.com/karpathy/micrograd/blob/master/demo.ipynb"
|
<a
|
||||||
>demo</a
|
href="https://github.com/karpathy/micrograd/blob/master/demo.ipynb"
|
||||||
>
|
>demo</a
|
||||||
he prepared for this package using pyscript to train a basic model,
|
>
|
||||||
written in Python, natively in the browser. <br />
|
he prepared for this package using pyscript to train a basic
|
||||||
</p>
|
model, written in Python, natively in the browser. <br />
|
||||||
</div>
|
</p>
|
||||||
<div>
|
</div>
|
||||||
<p>
|
<div>
|
||||||
You may run each Python REPL cell interactively by pressing (Shift +
|
<p>
|
||||||
Enter) or (Ctrl + Enter). You can also modify the code directly as you
|
You may run each Python REPL cell interactively by pressing
|
||||||
wish. If you want to run all the code at once, not each cell
|
(Shift + Enter) or (Ctrl + Enter). You can also modify the code
|
||||||
individually, you may instead click the 'Run All' button. Training the
|
directly as you wish. If you want to run all the code at once,
|
||||||
model takes between 1-2 min if you decide to 'Run All' at once. 'Run
|
not each cell individually, you may instead click the 'Run All'
|
||||||
All' is your only option if you are running this on a mobile device
|
button. Training the model takes between 1-2 min if you decide
|
||||||
where you cannot press (Shift + Enter). After the model is trained, a
|
to 'Run All' at once. 'Run All' is your only option if you are
|
||||||
plot image should be displayed depicting the model's ability to classify
|
running this on a mobile device where you cannot press (Shift +
|
||||||
the data. <br />
|
Enter). After the model is trained, a plot image should be
|
||||||
</p>
|
displayed depicting the model's ability to classify the data.
|
||||||
<p>
|
<br />
|
||||||
Currently the <code>></code> symbol is being imported incorrectly as
|
</p>
|
||||||
<code>&gt;</code> into the REPL's. In this app the
|
<p>
|
||||||
<code>></code> symbol has been replaced with
|
Currently the <code>></code> symbol is being imported
|
||||||
<code>().__gt__()</code> so you can run the code without issue. Ex:
|
incorrectly as <code>&gt;</code> into the REPL's. In this
|
||||||
instead of <code>a > b</code>, you will see
|
app the <code>></code> symbol has been replaced with
|
||||||
<code>(a).__gt__(b)</code> instead. <br />
|
<code>().__gt__()</code> so you can run the code without issue.
|
||||||
</p>
|
Ex: instead of <code>a > b</code>, you will see
|
||||||
<py-script>
|
<code>(a).__gt__(b)</code> instead. <br />
|
||||||
import js; js.document.getElementById('python-status').innerHTML = 'Python is now ready. You may proceed.'
|
</p>
|
||||||
</py-script>
|
<py-script>
|
||||||
<div id="python-status">Python is currently starting. Please wait...</div>
|
import js; js.document.getElementById('python-status').innerHTML = 'Python is now ready. You may proceed.'
|
||||||
<button
|
</py-script>
|
||||||
id="run-all-button"
|
<div id="python-status">
|
||||||
class="btn btn-primary"
|
Python is currently starting. Please wait...
|
||||||
type="submit"
|
</div>
|
||||||
py-onClick="run_all_micrograd_demo()"
|
<button
|
||||||
>
|
id="run-all-button"
|
||||||
Run All</button
|
class="btn btn-primary"
|
||||||
><br />
|
type="submit"
|
||||||
<py-script src="/micrograd_ai.py"></py-script>
|
py-onClick="run_all_micrograd_demo()"
|
||||||
<div id="micrograd-run-all-print-div"></div>
|
>
|
||||||
<br />
|
Run All</button
|
||||||
<div id="micrograd-run-all-fig1-div"></div>
|
><br />
|
||||||
<div id="micrograd-run-all-fig2-div"></div>
|
<py-script src="/micrograd_ai.py"></py-script>
|
||||||
<br />
|
<div id="micrograd-run-all-print-div"></div>
|
||||||
</div>
|
<br />
|
||||||
<py-repl auto-generate="false">
|
<div id="micrograd-run-all-fig1-div"></div>
|
||||||
import random import numpy as np import matplotlib.pyplot as plt </py-repl
|
<div id="micrograd-run-all-fig2-div"></div>
|
||||||
><br />
|
<br />
|
||||||
<py-repl auto-generate="false">
|
</div>
|
||||||
from micrograd.engine import Value from micrograd.nn import Neuron, Layer,
|
<py-repl auto-generate="false">
|
||||||
MLP </py-repl
|
import random import numpy as np import matplotlib.pyplot as plt </py-repl
|
||||||
><br />
|
><br />
|
||||||
<py-repl auto-generate="true">
|
<py-repl auto-generate="false">
|
||||||
np.random.seed(1337) random.seed(1337) </py-repl
|
from micrograd.engine import Value from micrograd.nn import Neuron,
|
||||||
><br />
|
Layer, MLP </py-repl
|
||||||
<py-repl auto-generate="true">
|
><br />
|
||||||
#An adaptation of sklearn's make_moons function
|
<py-repl auto-generate="true">
|
||||||
https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_moons.html
|
np.random.seed(1337) random.seed(1337) </py-repl
|
||||||
def make_moons(n_samples=100, noise=None): n_samples_out, n_samples_in =
|
><br />
|
||||||
n_samples, n_samples outer_circ_x = np.cos(np.linspace(0, np.pi,
|
<py-repl auto-generate="true">
|
||||||
n_samples_out)) outer_circ_y = np.sin(np.linspace(0, np.pi,
|
#An adaptation of sklearn's make_moons function
|
||||||
n_samples_out)) inner_circ_x = 1 - np.cos(np.linspace(0, np.pi,
|
https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_moons.html
|
||||||
n_samples_in)) inner_circ_y = 1 - np.sin(np.linspace(0, np.pi,
|
def make_moons(n_samples=100, noise=None): n_samples_out,
|
||||||
n_samples_in)) - 0.5 X = np.vstack([np.append(outer_circ_x, inner_circ_x),
|
n_samples_in = n_samples, n_samples outer_circ_x =
|
||||||
np.append(outer_circ_y, inner_circ_y)]).T y =
|
np.cos(np.linspace(0, np.pi, n_samples_out)) outer_circ_y =
|
||||||
np.hstack([np.zeros(n_samples_out, dtype=np.intp), np.ones(n_samples_in,
|
np.sin(np.linspace(0, np.pi, n_samples_out)) inner_circ_x = 1 -
|
||||||
dtype=np.intp)]) if noise is not None: X += np.random.normal(loc=0.0,
|
np.cos(np.linspace(0, np.pi, n_samples_in)) inner_circ_y = 1 -
|
||||||
scale=noise, size=X.shape) return X, y X, y = make_moons(n_samples=100,
|
np.sin(np.linspace(0, np.pi, n_samples_in)) - 0.5 X =
|
||||||
noise=0.1) </py-repl
|
np.vstack([np.append(outer_circ_x, inner_circ_x),
|
||||||
><br />
|
np.append(outer_circ_y, inner_circ_y)]).T y =
|
||||||
<py-repl auto-generate="true">
|
np.hstack([np.zeros(n_samples_out, dtype=np.intp),
|
||||||
y = y*2 - 1 # make y be -1 or 1 # visualize in 2D
|
np.ones(n_samples_in, dtype=np.intp)]) if noise is not None: X +=
|
||||||
plt.figure(figsize=(5,5)) plt.scatter(X[:,0], X[:,1], c=y, s=20,
|
np.random.normal(loc=0.0, scale=noise, size=X.shape) return X, y X,
|
||||||
cmap='jet') plt </py-repl
|
y = make_moons(n_samples=100, noise=0.1) </py-repl
|
||||||
><br />
|
><br />
|
||||||
<py-repl auto-generate="true">
|
<py-repl auto-generate="true">
|
||||||
model = MLP(2, [16, 16, 1]) # 2-layer neural network print(model)
|
y = y*2 - 1 # make y be -1 or 1 # visualize in 2D
|
||||||
print("number of parameters", len(model.parameters())) </py-repl
|
plt.figure(figsize=(5,5)) plt.scatter(X[:,0], X[:,1], c=y, s=20,
|
||||||
><br />
|
cmap='jet') plt </py-repl
|
||||||
|
><br />
|
||||||
|
<py-repl auto-generate="true">
|
||||||
|
model = MLP(2, [16, 16, 1]) # 2-layer neural network print(model)
|
||||||
|
print("number of parameters", len(model.parameters())) </py-repl
|
||||||
|
><br />
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
Line 24 has been changed from: <br />
|
Line 24 has been changed from: <br />
|
||||||
<code
|
<code
|
||||||
>accuracy = [(yi > 0) == (scorei.data > 0) for yi, scorei in
|
>accuracy = [(yi > 0) == (scorei.data > 0) for yi, scorei
|
||||||
zip(yb, scores)]</code
|
in zip(yb, scores)]</code
|
||||||
><br />
|
><br />
|
||||||
to: <br />
|
to: <br />
|
||||||
<code
|
<code
|
||||||
>accuracy = [((yi).__gt__(0)) == ((scorei.data).__gt__(0)) for yi,
|
>accuracy = [((yi).__gt__(0)) == ((scorei.data).__gt__(0)) for
|
||||||
scorei in zip(yb, scores)]</code
|
yi, scorei in zip(yb, scores)]</code
|
||||||
><br />
|
><br />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<py-repl auto-generate="true">
|
<py-repl auto-generate="true">
|
||||||
# loss function def loss(batch_size=None): # inline DataLoader :) if
|
# loss function def loss(batch_size=None): # inline DataLoader :) if
|
||||||
batch_size is None: Xb, yb = X, y else: ri =
|
batch_size is None: Xb, yb = X, y else: ri =
|
||||||
np.random.permutation(X.shape[0])[:batch_size] Xb, yb = X[ri], y[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
|
inputs = [list(map(Value, xrow)) for xrow in Xb] # forward the model
|
||||||
get scores scores = list(map(model, inputs)) # svm "max-margin" loss
|
to get scores scores = list(map(model, inputs)) # svm "max-margin"
|
||||||
losses = [(1 + -yi*scorei).relu() for yi, scorei in zip(yb, scores)]
|
loss losses = [(1 + -yi*scorei).relu() for yi, scorei in zip(yb,
|
||||||
data_loss = sum(losses) * (1.0 / len(losses)) # L2 regularization alpha =
|
scores)] data_loss = sum(losses) * (1.0 / len(losses)) # L2
|
||||||
1e-4 reg_loss = alpha * sum((p*p for p in model.parameters())) total_loss
|
regularization alpha = 1e-4 reg_loss = alpha * sum((p*p for p in
|
||||||
= data_loss + reg_loss # also get accuracy accuracy = [((yi).__gt__(0)) ==
|
model.parameters())) total_loss = data_loss + reg_loss # also get
|
||||||
((scorei.data).__gt__(0)) for yi, scorei in zip(yb, scores)] return
|
accuracy accuracy = [((yi).__gt__(0)) == ((scorei.data).__gt__(0))
|
||||||
total_loss, sum(accuracy) / len(accuracy) total_loss, acc = loss()
|
for yi, scorei in zip(yb, scores)] return total_loss, sum(accuracy)
|
||||||
print(total_loss, acc) </py-repl
|
/ len(accuracy) total_loss, acc = loss() print(total_loss, acc) </py-repl
|
||||||
><br />
|
><br />
|
||||||
<py-repl auto-generate="true">
|
<py-repl auto-generate="true">
|
||||||
# optimization for k in range(20): #was 100. Accuracy can be further
|
# optimization for k in range(20): #was 100. Accuracy can be further
|
||||||
improved w/ more epochs (to 100%). # forward total_loss, acc = loss() #
|
improved w/ more epochs (to 100%). # forward total_loss, acc =
|
||||||
backward model.zero_grad() total_loss.backward() # update (sgd)
|
loss() # backward model.zero_grad() total_loss.backward() # update
|
||||||
learning_rate = 1.0 - 0.9*k/100 for p in model.parameters(): p.data -=
|
(sgd) learning_rate = 1.0 - 0.9*k/100 for p in model.parameters():
|
||||||
learning_rate * p.grad if k % 1 == 0: print(f"step {k} loss
|
p.data -= learning_rate * p.grad if k % 1 == 0: print(f"step {k}
|
||||||
{total_loss.data}, accuracy {acc*100}%") </py-repl
|
loss {total_loss.data}, accuracy {acc*100}%") </py-repl
|
||||||
><br />
|
><br />
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
Please wait for the training loop above to complete. It will not print
|
Please wait for the training loop above to complete. It will not
|
||||||
out stats until it has completely finished. This typically takes 1-2
|
print out stats until it has completely finished. This typically
|
||||||
min. <br /><br />
|
takes 1-2 min. <br /><br />
|
||||||
|
|
||||||
Line 9 has been changed from: <br />
|
Line 9 has been changed from: <br />
|
||||||
<code>Z = np.array([s.data > 0 for s in scores])</code><br />
|
<code>Z = np.array([s.data > 0 for s in scores])</code><br />
|
||||||
to: <br />
|
to: <br />
|
||||||
<code>Z = np.array([(s.data).__gt__(0) for s in scores])</code><br />
|
<code>Z = np.array([(s.data).__gt__(0) for s in scores])</code
|
||||||
</p>
|
><br />
|
||||||
</div>
|
</p>
|
||||||
<py-repl auto-generate="true">
|
</div>
|
||||||
h = 0.25 x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1 y_min, y_max
|
<py-repl auto-generate="true">
|
||||||
= X[:, 1].min() - 1, X[:, 1].max() + 1 xx, yy =
|
h = 0.25 x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1 y_min,
|
||||||
np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) Xmesh
|
y_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx, yy =
|
||||||
= np.c_[xx.ravel(), yy.ravel()] inputs = [list(map(Value, xrow)) for xrow
|
np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
|
||||||
in Xmesh] scores = list(map(model, inputs)) Z =
|
Xmesh = np.c_[xx.ravel(), yy.ravel()] inputs = [list(map(Value,
|
||||||
np.array([(s.data).__gt__(0) for s in scores]) Z = Z.reshape(xx.shape) fig
|
xrow)) for xrow in Xmesh] scores = list(map(model, inputs)) Z =
|
||||||
= plt.figure() plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral, alpha=0.8)
|
np.array([(s.data).__gt__(0) for s in scores]) Z =
|
||||||
plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.Spectral)
|
Z.reshape(xx.shape) fig = plt.figure() plt.contourf(xx, yy, Z,
|
||||||
plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) plt </py-repl
|
cmap=plt.cm.Spectral, alpha=0.8) plt.scatter(X[:, 0], X[:, 1], c=y,
|
||||||
><br />
|
s=40, cmap=plt.cm.Spectral) plt.xlim(xx.min(), xx.max())
|
||||||
<py-repl auto-generate="true"> 1+1 </py-repl><br />
|
plt.ylim(yy.min(), yy.max()) plt </py-repl
|
||||||
</body>
|
><br />
|
||||||
|
<py-repl auto-generate="true"> 1+1 </py-repl><br />
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
<!-- Adapted by Mat Miller -->
|
<!-- Adapted by Mat Miller -->
|
||||||
|
|||||||
@@ -1,385 +1,411 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>
|
<title>
|
||||||
Visualization of Mandelbrot, Julia and Newton sets with NumPy and HTML5
|
Visualization of Mandelbrot, Julia and Newton sets with NumPy and
|
||||||
canvas
|
HTML5 canvas
|
||||||
</title>
|
</title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
<style>
|
/>
|
||||||
.loading {
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
display: inline-block;
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
width: 50px;
|
<style>
|
||||||
height: 50px;
|
.loading {
|
||||||
border: 3px solid rgba(255, 255, 255, 0.3);
|
display: inline-block;
|
||||||
border-radius: 50%;
|
width: 50px;
|
||||||
border-top-color: black;
|
height: 50px;
|
||||||
animation: spin 1s ease-in-out infinite;
|
border: 3px solid rgba(255, 255, 255, 0.3);
|
||||||
}
|
border-radius: 50%;
|
||||||
|
border-top-color: black;
|
||||||
|
animation: spin 1s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
canvas {
|
canvas {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
to {
|
to {
|
||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" href="" style="color: #f0ab3c"
|
<a class="title" href="" style="color: #f0ab3c"
|
||||||
>Fractals with NumPy and canvas</a
|
>Fractals with NumPy and canvas</a
|
||||||
>
|
>
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<section class="pyscript">
|
|
||||||
<div
|
|
||||||
style="display: flex; flex-direction: column; gap: 1em; width: 600px"
|
|
||||||
>
|
|
||||||
<div id="mandelbrot">
|
|
||||||
<div style="text-align: center">Mandelbrot set</div>
|
|
||||||
<div>
|
|
||||||
<div class="loading"></div>
|
|
||||||
<canvas></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="julia">
|
|
||||||
<div style="text-align: center">Julia set</div>
|
|
||||||
<div>
|
|
||||||
<div class="loading"></div>
|
|
||||||
<canvas></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="newton">
|
|
||||||
<div style="text-align: center">Newton set</div>
|
|
||||||
<fieldset style="display: flex; flex-direction: row; gap: 1em">
|
|
||||||
<div>
|
|
||||||
<span style="white-space: pre">p(z) = </span
|
|
||||||
><input id="poly" type="text" value="z**3 - 2*z + 2" />
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
</nav>
|
||||||
<span style="white-space: pre">a = </span
|
<section class="pyscript">
|
||||||
><input id="coef" type="text" value="1" style="width: 40px" />
|
<div
|
||||||
|
style="
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1em;
|
||||||
|
width: 600px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div id="mandelbrot">
|
||||||
|
<div style="text-align: center">Mandelbrot set</div>
|
||||||
|
<div>
|
||||||
|
<div class="loading"></div>
|
||||||
|
<canvas></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="julia">
|
||||||
|
<div style="text-align: center">Julia set</div>
|
||||||
|
<div>
|
||||||
|
<div class="loading"></div>
|
||||||
|
<canvas></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="newton">
|
||||||
|
<div style="text-align: center">Newton set</div>
|
||||||
|
<fieldset
|
||||||
|
style="display: flex; flex-direction: row; gap: 1em"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<span style="white-space: pre">p(z) = </span
|
||||||
|
><input
|
||||||
|
id="poly"
|
||||||
|
type="text"
|
||||||
|
value="z**3 - 2*z + 2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span style="white-space: pre">a = </span
|
||||||
|
><input
|
||||||
|
id="coef"
|
||||||
|
type="text"
|
||||||
|
value="1"
|
||||||
|
style="width: 40px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; flex-direction: row">
|
||||||
|
<span style="white-space: pre">x = [</span>
|
||||||
|
<input
|
||||||
|
id="x0"
|
||||||
|
type="text"
|
||||||
|
value="-2.5"
|
||||||
|
style="width: 80px; text-align: right"
|
||||||
|
/>
|
||||||
|
<span style="white-space: pre">, </span>
|
||||||
|
<input
|
||||||
|
id="x1"
|
||||||
|
type="text"
|
||||||
|
value="2.5"
|
||||||
|
style="width: 80px; text-align: right"
|
||||||
|
/>
|
||||||
|
<span style="white-space: pre">]</span>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; flex-direction: row">
|
||||||
|
<span style="white-space: pre">y = [</span>
|
||||||
|
<input
|
||||||
|
id="y0"
|
||||||
|
type="text"
|
||||||
|
value="-5.0"
|
||||||
|
style="width: 80px; text-align: right"
|
||||||
|
/>
|
||||||
|
<span style="white-space: pre">, </span>
|
||||||
|
<input
|
||||||
|
id="y1"
|
||||||
|
type="text"
|
||||||
|
value="5.0"
|
||||||
|
style="width: 80px; text-align: right"
|
||||||
|
/>
|
||||||
|
<span style="white-space: pre">]</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="display: flex; flex-direction: row; gap: 1em"
|
||||||
|
>
|
||||||
|
<div style="white-space: pre">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
id="conv"
|
||||||
|
name="type"
|
||||||
|
value="convergence"
|
||||||
|
checked
|
||||||
|
/>
|
||||||
|
convergence
|
||||||
|
</div>
|
||||||
|
<div style="white-space: pre">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
id="iter"
|
||||||
|
name="type"
|
||||||
|
value="iterations"
|
||||||
|
/>
|
||||||
|
iterations
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<div>
|
||||||
|
<div class="loading"></div>
|
||||||
|
<canvas></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; flex-direction: row">
|
<py-tutor>
|
||||||
<span style="white-space: pre">x = [</span>
|
<py-config type="json">
|
||||||
<input
|
{
|
||||||
id="x0"
|
"packages": [
|
||||||
type="text"
|
"numpy",
|
||||||
value="-2.5"
|
"sympy"
|
||||||
style="width: 80px; text-align: right"
|
],
|
||||||
/>
|
"fetch": [
|
||||||
<span style="white-space: pre">, </span>
|
{
|
||||||
<input
|
"files": [
|
||||||
id="x1"
|
"./palettes.py",
|
||||||
type="text"
|
"./fractals.py"
|
||||||
value="2.5"
|
]
|
||||||
style="width: 80px; text-align: right"
|
}
|
||||||
/>
|
],
|
||||||
<span style="white-space: pre">]</span>
|
"plugins": [
|
||||||
</div>
|
"../build/plugins/python/py_tutor.py"
|
||||||
<div style="display: flex; flex-direction: row">
|
]
|
||||||
<span style="white-space: pre">y = [</span>
|
}
|
||||||
<input
|
</py-config>
|
||||||
id="y0"
|
|
||||||
type="text"
|
|
||||||
value="-5.0"
|
|
||||||
style="width: 80px; text-align: right"
|
|
||||||
/>
|
|
||||||
<span style="white-space: pre">, </span>
|
|
||||||
<input
|
|
||||||
id="y1"
|
|
||||||
type="text"
|
|
||||||
value="5.0"
|
|
||||||
style="width: 80px; text-align: right"
|
|
||||||
/>
|
|
||||||
<span style="white-space: pre">]</span>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; flex-direction: row; gap: 1em">
|
|
||||||
<div style="white-space: pre">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
id="conv"
|
|
||||||
name="type"
|
|
||||||
value="convergence"
|
|
||||||
checked
|
|
||||||
/>
|
|
||||||
convergence
|
|
||||||
</div>
|
|
||||||
<div style="white-space: pre">
|
|
||||||
<input type="radio" id="iter" name="type" value="iterations" />
|
|
||||||
iterations
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
<div>
|
|
||||||
<div class="loading"></div>
|
|
||||||
<canvas></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<py-tutor>
|
|
||||||
<py-config type="json">
|
|
||||||
{
|
|
||||||
"packages": [
|
|
||||||
"numpy",
|
|
||||||
"sympy"
|
|
||||||
],
|
|
||||||
"fetch": [
|
|
||||||
{
|
|
||||||
"files": [
|
|
||||||
"./palettes.py",
|
|
||||||
"./fractals.py"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"../build/plugins/python/py_tutor.py"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
</py-config>
|
|
||||||
|
|
||||||
<py-script>
|
<py-script>
|
||||||
from pyodide.ffi import to_js, create_proxy
|
from pyodide.ffi import to_js, create_proxy
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import sympy
|
import sympy
|
||||||
|
|
||||||
from palettes import Magma256
|
from palettes import Magma256
|
||||||
from fractals import mandelbrot, julia, newton
|
from fractals import mandelbrot, julia, newton
|
||||||
|
|
||||||
from js import (
|
from js import (
|
||||||
console,
|
console,
|
||||||
document,
|
document,
|
||||||
devicePixelRatio,
|
devicePixelRatio,
|
||||||
ImageData,
|
ImageData,
|
||||||
Uint8ClampedArray,
|
Uint8ClampedArray,
|
||||||
CanvasRenderingContext2D as Context2d,
|
CanvasRenderingContext2D as Context2d,
|
||||||
requestAnimationFrame,
|
requestAnimationFrame,
|
||||||
)
|
)
|
||||||
|
|
||||||
def prepare_canvas(width: int, height: int, canvas: Element) -> Context2d:
|
def prepare_canvas(width: int, height: int, canvas: Element) -> Context2d:
|
||||||
ctx = canvas.getContext("2d")
|
ctx = canvas.getContext("2d")
|
||||||
|
|
||||||
canvas.style.width = f"{width}px"
|
canvas.style.width = f"{width}px"
|
||||||
canvas.style.height = f"{height}px"
|
canvas.style.height = f"{height}px"
|
||||||
|
|
||||||
canvas.width = width
|
canvas.width = width
|
||||||
canvas.height = height
|
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:
|
def color_map(array: np.array, palette: np.array) -> np.array:
|
||||||
size, _ = palette.shape
|
size, _ = palette.shape
|
||||||
index = (array/array.max()*(size - 1)).round().astype("uint8")
|
index = (array/array.max()*(size - 1)).round().astype("uint8")
|
||||||
|
|
||||||
width, height = array.shape
|
width, height = array.shape
|
||||||
image = np.full((width, height, 4), 0xff, dtype=np.uint8)
|
image = np.full((width, height, 4), 0xff, dtype=np.uint8)
|
||||||
image[:, :, :3] = palette[index]
|
image[:, :, :3] = palette[index]
|
||||||
|
|
||||||
return image
|
return image
|
||||||
|
|
||||||
def draw_image(ctx: Context2d, image: np.array) -> None:
|
def draw_image(ctx: Context2d, image: np.array) -> None:
|
||||||
data = Uint8ClampedArray.new(to_js(image.tobytes()))
|
data = Uint8ClampedArray.new(to_js(image.tobytes()))
|
||||||
width, height, _ = image.shape
|
width, height, _ = image.shape
|
||||||
image_data = ImageData.new(data, width, height)
|
image_data = ImageData.new(data, width, height)
|
||||||
ctx.putImageData(image_data, 0, 0)
|
ctx.putImageData(image_data, 0, 0)
|
||||||
|
|
||||||
width, height = 600, 600
|
width, height = 600, 600
|
||||||
|
|
||||||
async def draw_mandelbrot() -> None:
|
async def draw_mandelbrot() -> None:
|
||||||
spinner = document.querySelector("#mandelbrot .loading")
|
spinner = document.querySelector("#mandelbrot .loading")
|
||||||
canvas = document.querySelector("#mandelbrot canvas")
|
canvas = document.querySelector("#mandelbrot canvas")
|
||||||
|
|
||||||
spinner.style.display = ""
|
spinner.style.display = ""
|
||||||
canvas.style.display = "none"
|
canvas.style.display = "none"
|
||||||
|
|
||||||
ctx = prepare_canvas(width, height, canvas)
|
ctx = prepare_canvas(width, height, canvas)
|
||||||
|
|
||||||
console.log("Computing Mandelbrot set ...")
|
console.log("Computing Mandelbrot set ...")
|
||||||
console.time("mandelbrot")
|
console.time("mandelbrot")
|
||||||
iters = mandelbrot(width, height)
|
iters = mandelbrot(width, height)
|
||||||
console.timeEnd("mandelbrot")
|
console.timeEnd("mandelbrot")
|
||||||
|
|
||||||
image = color_map(iters, Magma256)
|
image = color_map(iters, Magma256)
|
||||||
draw_image(ctx, image)
|
draw_image(ctx, image)
|
||||||
|
|
||||||
spinner.style.display = "none"
|
spinner.style.display = "none"
|
||||||
canvas.style.display = "block"
|
canvas.style.display = "block"
|
||||||
|
|
||||||
async def draw_julia() -> None:
|
async def draw_julia() -> None:
|
||||||
spinner = document.querySelector("#julia .loading")
|
spinner = document.querySelector("#julia .loading")
|
||||||
canvas = document.querySelector("#julia canvas")
|
canvas = document.querySelector("#julia canvas")
|
||||||
|
|
||||||
spinner.style.display = ""
|
spinner.style.display = ""
|
||||||
canvas.style.display = "none"
|
canvas.style.display = "none"
|
||||||
|
|
||||||
ctx = prepare_canvas(width, height, canvas)
|
ctx = prepare_canvas(width, height, canvas)
|
||||||
|
|
||||||
console.log("Computing Julia set ...")
|
console.log("Computing Julia set ...")
|
||||||
console.time("julia")
|
console.time("julia")
|
||||||
iters = julia(width, height)
|
iters = julia(width, height)
|
||||||
console.timeEnd("julia")
|
console.timeEnd("julia")
|
||||||
|
|
||||||
image = color_map(iters, Magma256)
|
image = color_map(iters, Magma256)
|
||||||
draw_image(ctx, image)
|
draw_image(ctx, image)
|
||||||
|
|
||||||
spinner.style.display = "none"
|
spinner.style.display = "none"
|
||||||
canvas.style.display = "block"
|
canvas.style.display = "block"
|
||||||
|
|
||||||
def ranges():
|
def ranges():
|
||||||
x0_in = document.querySelector("#x0")
|
x0_in = document.querySelector("#x0")
|
||||||
x1_in = document.querySelector("#x1")
|
x1_in = document.querySelector("#x1")
|
||||||
y0_in = document.querySelector("#y0")
|
y0_in = document.querySelector("#y0")
|
||||||
y1_in = document.querySelector("#y1")
|
y1_in = document.querySelector("#y1")
|
||||||
|
|
||||||
xr = (float(x0_in.value), float(x1_in.value))
|
xr = (float(x0_in.value), float(x1_in.value))
|
||||||
yr = (float(y0_in.value), float(y1_in.value))
|
yr = (float(y0_in.value), float(y1_in.value))
|
||||||
|
|
||||||
return xr, yr
|
return xr, yr
|
||||||
|
|
||||||
current_image = None
|
current_image = None
|
||||||
async def draw_newton() -> None:
|
async def draw_newton() -> None:
|
||||||
spinner = document.querySelector("#newton .loading")
|
spinner = document.querySelector("#newton .loading")
|
||||||
canvas = document.querySelector("#newton canvas")
|
canvas = document.querySelector("#newton canvas")
|
||||||
|
|
||||||
spinner.style.display = ""
|
spinner.style.display = ""
|
||||||
canvas.style.display = "none"
|
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")
|
poly_in = document.querySelector("#poly")
|
||||||
coef_in = document.querySelector("#coef")
|
coef_in = document.querySelector("#coef")
|
||||||
conv_in = document.querySelector("#conv")
|
conv_in = document.querySelector("#conv")
|
||||||
iter_in = document.querySelector("#iter")
|
iter_in = document.querySelector("#iter")
|
||||||
|
|
||||||
xr, yr = ranges()
|
xr, yr = ranges()
|
||||||
|
|
||||||
# z**3 - 1
|
# z**3 - 1
|
||||||
# z**8 + 15*z**4 - 16
|
# z**8 + 15*z**4 - 16
|
||||||
# z**3 - 2*z + 2
|
# z**3 - 2*z + 2
|
||||||
|
|
||||||
expr = sympy.parse_expr(poly_in.value)
|
expr = sympy.parse_expr(poly_in.value)
|
||||||
coeffs = [ complex(c) for c in reversed(sympy.Poly(expr, sympy.Symbol("z")).all_coeffs()) ]
|
coeffs = [ complex(c) for c in reversed(sympy.Poly(expr, sympy.Symbol("z")).all_coeffs()) ]
|
||||||
poly = np.polynomial.Polynomial(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")
|
console.time("newton")
|
||||||
iters, roots = newton(width, height, p=poly, a=coef, xr=xr, yr=yr)
|
iters, roots = newton(width, height, p=poly, a=coef, xr=xr, yr=yr)
|
||||||
console.timeEnd("newton")
|
console.timeEnd("newton")
|
||||||
|
|
||||||
if conv_in.checked:
|
if conv_in.checked:
|
||||||
n = poly.degree() + 1
|
n = poly.degree() + 1
|
||||||
k = int(len(Magma256)/n)
|
k = int(len(Magma256)/n)
|
||||||
|
|
||||||
colors = Magma256[::k, :][:n]
|
colors = Magma256[::k, :][:n]
|
||||||
colors[0, :] = [255, 0, 0] # red: no convergence
|
colors[0, :] = [255, 0, 0] # red: no convergence
|
||||||
|
|
||||||
image = color_map(roots, colors)
|
image = color_map(roots, colors)
|
||||||
else:
|
else:
|
||||||
image = color_map(iters, Magma256)
|
image = color_map(iters, Magma256)
|
||||||
|
|
||||||
global current_image
|
global current_image
|
||||||
current_image = image
|
current_image = image
|
||||||
draw_image(ctx, image)
|
draw_image(ctx, image)
|
||||||
|
|
||||||
spinner.style.display = "none"
|
spinner.style.display = "none"
|
||||||
canvas.style.display = "block"
|
canvas.style.display = "block"
|
||||||
|
|
||||||
handler = create_proxy(lambda _event: draw_newton())
|
handler = create_proxy(lambda _event: draw_newton())
|
||||||
document.querySelector("#newton fieldset").addEventListener("change", handler)
|
document.querySelector("#newton fieldset").addEventListener("change", handler)
|
||||||
|
|
||||||
canvas = document.querySelector("#newton canvas")
|
canvas = document.querySelector("#newton canvas")
|
||||||
|
|
||||||
is_selecting = False
|
is_selecting = False
|
||||||
init_sx, init_sy = None, None
|
init_sx, init_sy = None, None
|
||||||
sx, sy = None, None
|
sx, sy = None, None
|
||||||
async def mousemove(event):
|
async def mousemove(event):
|
||||||
global is_selecting
|
global is_selecting
|
||||||
global init_sx
|
global init_sx
|
||||||
global init_sy
|
global init_sy
|
||||||
global sx
|
global sx
|
||||||
global sy
|
global sy
|
||||||
|
|
||||||
def invert(sx, source_range, target_range):
|
def invert(sx, source_range, target_range):
|
||||||
source_start, source_end = source_range
|
source_start, source_end = source_range
|
||||||
target_start, target_end = target_range
|
target_start, target_end = target_range
|
||||||
factor = (target_end - target_start)/(source_end - source_start)
|
factor = (target_end - target_start)/(source_end - source_start)
|
||||||
offset = -(factor * source_start) + target_start
|
offset = -(factor * source_start) + target_start
|
||||||
return (sx - offset) / factor
|
return (sx - offset) / factor
|
||||||
|
|
||||||
bds = canvas.getBoundingClientRect()
|
bds = canvas.getBoundingClientRect()
|
||||||
event_sx, event_sy = event.clientX - bds.x, event.clientY - bds.y
|
event_sx, event_sy = event.clientX - bds.x, event.clientY - bds.y
|
||||||
|
|
||||||
ctx = canvas.getContext("2d")
|
ctx = canvas.getContext("2d")
|
||||||
|
|
||||||
pressed = event.buttons == 1
|
pressed = event.buttons == 1
|
||||||
if is_selecting:
|
if is_selecting:
|
||||||
if not pressed:
|
if not pressed:
|
||||||
xr, yr = ranges()
|
xr, yr = ranges()
|
||||||
|
|
||||||
x0 = invert(init_sx, xr, (0, width))
|
x0 = invert(init_sx, xr, (0, width))
|
||||||
x1 = invert(sx, xr, (0, width))
|
x1 = invert(sx, xr, (0, width))
|
||||||
y0 = invert(init_sy, yr, (0, height))
|
y0 = invert(init_sy, yr, (0, height))
|
||||||
y1 = invert(sy, yr, (0, height))
|
y1 = invert(sy, yr, (0, height))
|
||||||
|
|
||||||
document.querySelector("#x0").value = x0
|
document.querySelector("#x0").value = x0
|
||||||
document.querySelector("#x1").value = x1
|
document.querySelector("#x1").value = x1
|
||||||
document.querySelector("#y0").value = y0
|
document.querySelector("#y0").value = y0
|
||||||
document.querySelector("#y1").value = y1
|
document.querySelector("#y1").value = y1
|
||||||
|
|
||||||
is_selecting = False
|
is_selecting = False
|
||||||
init_sx, init_sy = None, None
|
init_sx, init_sy = None, None
|
||||||
sx, sy = init_sx, init_sy
|
sx, sy = init_sx, init_sy
|
||||||
|
|
||||||
await draw_newton()
|
await draw_newton()
|
||||||
else:
|
else:
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.clearRect(0, 0, width, height)
|
ctx.clearRect(0, 0, width, height)
|
||||||
draw_image(ctx, current_image)
|
draw_image(ctx, current_image)
|
||||||
sx, sy = event_sx, event_sy
|
sx, sy = event_sx, event_sy
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
ctx.rect(init_sx, init_sy, sx - init_sx, sy - init_sy)
|
ctx.rect(init_sx, init_sy, sx - init_sx, sy - init_sy)
|
||||||
ctx.fillStyle = "rgba(255, 255, 255, 0.4)"
|
ctx.fillStyle = "rgba(255, 255, 255, 0.4)"
|
||||||
ctx.strokeStyle = "rgba(255, 255, 255, 1.0)"
|
ctx.strokeStyle = "rgba(255, 255, 255, 1.0)"
|
||||||
ctx.fill()
|
ctx.fill()
|
||||||
ctx.stroke()
|
ctx.stroke()
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
else:
|
else:
|
||||||
if pressed:
|
if pressed:
|
||||||
is_selecting = True
|
is_selecting = True
|
||||||
init_sx, init_sy = event_sx, event_sy
|
init_sx, init_sy = event_sx, event_sy
|
||||||
sx, sy = init_sx, init_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():
|
async def main():
|
||||||
_ = await asyncio.gather(
|
_ = await asyncio.gather(
|
||||||
draw_mandelbrot(),
|
draw_mandelbrot(),
|
||||||
draw_julia(),
|
draw_julia(),
|
||||||
draw_newton(),
|
draw_newton(),
|
||||||
)
|
)
|
||||||
|
|
||||||
asyncio.ensure_future(main())
|
asyncio.ensure_future(main())
|
||||||
</py-script>
|
</py-script>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</section>
|
</section>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,124 +1,132 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title id="header-title"></title>
|
<title id="header-title"></title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
|
/>
|
||||||
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" id="page-title" href="" style="color: #f0ab3c"></a>
|
<a
|
||||||
</div>
|
class="title"
|
||||||
</nav>
|
id="page-title"
|
||||||
|
href=""
|
||||||
|
style="color: #f0ab3c"
|
||||||
|
></a>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<div id="page-message"></div>
|
<div id="page-message"></div>
|
||||||
|
|
||||||
<div id="pandas-source">
|
<div id="pandas-source">
|
||||||
<h3>Data Source</h3>
|
<h3>Data Source</h3>
|
||||||
<input type="text" id="txt-url" class="py-input" size="70" />
|
<input type="text" id="txt-url" class="py-input" size="70" />
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
id="btn-load"
|
id="btn-load"
|
||||||
class="py-button"
|
class="py-button"
|
||||||
py-click="loadFromURL()"
|
py-click="loadFromURL()"
|
||||||
>
|
>
|
||||||
Load CSV
|
Load CSV
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="pandas-repl" hidden>
|
<div id="pandas-repl" hidden>
|
||||||
<h3>Python REPL</h3>
|
<h3>Python REPL</h3>
|
||||||
<py-repl id="pandas-repl-inner" output="pandas-output-inner">
|
<py-repl id="pandas-repl-inner" output="pandas-output-inner">
|
||||||
# Hit SHIFT + ENTER to execute example code # Get all closed airports in
|
# Hit SHIFT + ENTER to execute example code # Get all closed
|
||||||
Great Britain df2 = df.query("type == 'closed' & iso_country == 'GB'")
|
airports in Great Britain df2 = df.query("type == 'closed' &
|
||||||
df2
|
iso_country == 'GB'") df2
|
||||||
</py-repl>
|
</py-repl>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="pandas-output" hidden>
|
<div id="pandas-output" hidden>
|
||||||
<h3>Output</h3>
|
<h3>Output</h3>
|
||||||
<div id="pandas-output-inner"></div>
|
<div id="pandas-output-inner"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="pandas-dev-console" hidden>
|
<div id="pandas-dev-console" hidden>
|
||||||
<h3>Dev Console</h3>
|
<h3>Dev Console</h3>
|
||||||
<py-terminal auto></py-terminal>
|
<py-terminal auto></py-terminal>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<py-tutor>
|
<py-tutor>
|
||||||
<py-config>
|
<py-config>
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
packages = ["pandas"]
|
packages = ["pandas"]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<section class="pyscript">
|
<section class="pyscript">
|
||||||
<py-script>
|
<py-script>
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
from pyodide.http import open_url
|
from pyodide.http import open_url
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
title = "Pandas (and basic DOM manipulation)"
|
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"
|
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("header-title").element.innerText = title
|
||||||
Element("page-title").element.innerText = title
|
Element("page-title").element.innerText = title
|
||||||
Element("page-message").element.innerText = page_message
|
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
|
# 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").write("example")
|
||||||
# Element("id-of-dom-element").innerText = "example"
|
# Element("id-of-dom-element").innerText = "example"
|
||||||
# Element("id-of-dom-element").value = "example"
|
# Element("id-of-dom-element").value = "example"
|
||||||
# Element("id-of-dom-element").element.innerText = "example"
|
# Element("id-of-dom-element").element.innerText = "example"
|
||||||
# Element("id-of-dom-element").element.value = "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").innerText = "example"
|
||||||
# js.document.getElementById("id-of-dom-element").value = "example"
|
# js.document.getElementById("id-of-dom-element").value = "example"
|
||||||
|
|
||||||
df = pd.DataFrame()
|
df = pd.DataFrame()
|
||||||
|
|
||||||
|
|
||||||
def loadFromURL(*ags, **kws):
|
def loadFromURL(*ags, **kws):
|
||||||
global df
|
global df
|
||||||
|
|
||||||
# clear dataframe & output
|
# clear dataframe & output
|
||||||
df = pd.DataFrame()
|
df = pd.DataFrame()
|
||||||
Element("pandas-output-inner").element.innerHTML = ""
|
Element("pandas-output-inner").element.innerHTML = ""
|
||||||
|
|
||||||
url = Element("txt-url").element.value
|
url = Element("txt-url").element.value
|
||||||
log ("Trying to fetch CSV from " + url)
|
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-repl").element.style.display = "block"
|
||||||
Element("pandas-output").element.style.display = "block"
|
Element("pandas-output").element.style.display = "block"
|
||||||
Element("pandas-dev-console").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):
|
def log(message):
|
||||||
# log to pyscript dev console
|
# log to pyscript dev console
|
||||||
print (message)
|
print (message)
|
||||||
|
|
||||||
# log to JS console
|
# log to JS console
|
||||||
js.console.log (message)
|
js.console.log (message)
|
||||||
</py-script>
|
</py-script>
|
||||||
</section>
|
</section>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,63 +1,68 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Panel Example</title>
|
<title>Panel Example</title>
|
||||||
<meta charset="iso-8859-1" />
|
<meta charset="iso-8859-1" />
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.jsdelivr.net/npm/@holoviz/panel@0.14.1/dist/panel.min.js"
|
src="https://cdn.jsdelivr.net/npm/@holoviz/panel@0.14.1/dist/panel.min.js"
|
||||||
></script>
|
></script>
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
</head>
|
/>
|
||||||
<body>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
<div class="app-header">
|
</head>
|
||||||
<a href="/">
|
<body>
|
||||||
<img src="./logo.png" class="logo" />
|
<nav class="navbar" style="background-color: #000000">
|
||||||
</a>
|
<div class="app-header">
|
||||||
<a class="title" href="" style="color: #f0ab3c">Panel Example</a>
|
<a href="/">
|
||||||
</div>
|
<img src="./logo.png" class="logo" />
|
||||||
</nav>
|
</a>
|
||||||
<section class="pyscript">
|
<a class="title" href="" style="color: #f0ab3c"
|
||||||
<div id="simple_app"></div>
|
>Panel Example</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<section class="pyscript">
|
||||||
|
<div id="simple_app"></div>
|
||||||
|
|
||||||
<py-tutor>
|
<py-tutor>
|
||||||
<py-config>
|
<py-config>
|
||||||
packages = [
|
packages = [
|
||||||
"https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
|
"https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
|
||||||
"numpy",
|
"numpy",
|
||||||
"panel==0.14.1"
|
"panel==0.14.1"
|
||||||
]
|
]
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<py-script>
|
<py-script>
|
||||||
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):
|
def callback(new):
|
||||||
return f'Amplitude is: {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');
|
||||||
</py-script>
|
</py-script>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</section>
|
</section>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,281 +1,284 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||||
<meta name="theme-color" content="#0072b5" />
|
<meta name="theme-color" content="#0072b5" />
|
||||||
<meta name="name" content="PyScript/Panel DeckGL Demo" />
|
<meta name="name" content="PyScript/Panel DeckGL Demo" />
|
||||||
|
|
||||||
<title>PyScript/Panel DeckGL Demo</title>
|
<title>PyScript/Panel DeckGL Demo</title>
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
|
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
|
||||||
type="text/css"
|
type="text/css"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css"
|
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css"
|
||||||
type="text/css"
|
type="text/css"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css"
|
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css"
|
||||||
type="text/css"
|
type="text/css"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://unpkg.com/h3-js@3.7.2/dist/h3-js.umd.js"
|
src="https://unpkg.com/h3-js@3.7.2/dist/h3-js.umd.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.jsdelivr.net/npm/deck.gl@8.6.7/dist.min.js"
|
src="https://cdn.jsdelivr.net/npm/deck.gl@8.6.7/dist.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.jsdelivr.net/npm/@deck.gl/json@8.6.7/dist.min.js"
|
src="https://cdn.jsdelivr.net/npm/@deck.gl/json@8.6.7/dist.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.jsdelivr.net/npm/@loaders.gl/csv@3.1.7/dist/dist.min.js"
|
src="https://cdn.jsdelivr.net/npm/@loaders.gl/csv@3.1.7/dist/dist.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.jsdelivr.net/npm/@loaders.gl/json@3.1.7/dist/dist.min.js"
|
src="https://cdn.jsdelivr.net/npm/@loaders.gl/json@3.1.7/dist/dist.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.jsdelivr.net/npm/@loaders.gl/3d-tiles@3.1.7/dist/dist.min.js"
|
src="https://cdn.jsdelivr.net/npm/@loaders.gl/3d-tiles@3.1.7/dist/dist.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://api.mapbox.com/mapbox-gl-js/v2.6.1/mapbox-gl.js"
|
src="https://api.mapbox.com/mapbox-gl-js/v2.6.1/mapbox-gl.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.js"
|
src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.js"
|
||||||
></script>
|
></script>
|
||||||
|
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"
|
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css"
|
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css"
|
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<style>
|
<style>
|
||||||
#sidebar {
|
#sidebar {
|
||||||
width: 400px;
|
width: 400px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
</head>
|
/>
|
||||||
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" href="" style="color: #f0ab3c"
|
<a class="title" href="" style="color: #f0ab3c"
|
||||||
>Panel DeckGL NYC Taxi Demo</a
|
>Panel DeckGL NYC Taxi Demo</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<section class="pyscript">
|
<section class="pyscript">
|
||||||
<div class="d-flex flex-nowrap" id="content">
|
<div class="d-flex flex-nowrap" id="content">
|
||||||
<div class="sidenav" id="sidebar">
|
<div class="sidenav" id="sidebar">
|
||||||
<ul class="nav flex-column">
|
<ul class="nav flex-column">
|
||||||
<div class="bk-root" id="widgets"></div>
|
<div class="bk-root" id="widgets"></div>
|
||||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col mh-100" style="padding: 0">
|
<div class="col mh-100" style="padding: 0">
|
||||||
<div class="bk-root" id="plot"></div>
|
<div class="bk-root" id="plot"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<py-tutor>
|
<py-tutor>
|
||||||
<py-config>
|
<py-config>
|
||||||
packages = [
|
packages = [
|
||||||
"https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
|
"https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
|
||||||
"numpy",
|
"numpy",
|
||||||
"pandas",
|
"pandas",
|
||||||
"panel==0.13.1"
|
"panel==0.13.1"
|
||||||
]
|
]
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<py-script>
|
<py-script>
|
||||||
import panel as pn
|
import panel as pn
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import param
|
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):
|
def __init__(self, **params):
|
||||||
self.deck_gl = None
|
self.deck_gl = None
|
||||||
super().__init__(**params)
|
super().__init__(**params)
|
||||||
self.deck_gl = pn.pane.DeckGL(
|
self.deck_gl = pn.pane.DeckGL(
|
||||||
dict(self.spec),
|
dict(self.spec),
|
||||||
mapbox_api_key=MAPBOX_KEY,
|
mapbox_api_key=MAPBOX_KEY,
|
||||||
throttle={'click': 10},
|
throttle={'click': 10},
|
||||||
sizing_mode='stretch_both',
|
sizing_mode='stretch_both',
|
||||||
margin=0
|
margin=0
|
||||||
)
|
)
|
||||||
self.deck_gl.param.watch(self._update_arc_view, 'click_state')
|
self.deck_gl.param.watch(self._update_arc_view, 'click_state')
|
||||||
self._playing = False
|
self._playing = False
|
||||||
self._cb = pn.state.add_periodic_callback(
|
self._cb = pn.state.add_periodic_callback(
|
||||||
self._update_hour, 1000//self.speed, start=False
|
self._update_hour, 1000//self.speed, start=False
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def spec(self):
|
def spec(self):
|
||||||
return {
|
return {
|
||||||
"initialViewState": {
|
"initialViewState": {
|
||||||
"bearing": 0,
|
"bearing": 0,
|
||||||
"latitude": 40.7,
|
"latitude": 40.7,
|
||||||
"longitude": -73.9,
|
"longitude": -73.9,
|
||||||
"maxZoom": 15,
|
"maxZoom": 15,
|
||||||
"minZoom": 5,
|
"minZoom": 5,
|
||||||
"pitch": 40.5,
|
"pitch": 40.5,
|
||||||
"zoom": 11
|
"zoom": 11
|
||||||
},
|
},
|
||||||
"layers": [self.hex_layer, self.arc_layer],
|
"layers": [self.hex_layer, self.arc_layer],
|
||||||
"mapStyle": "mapbox://styles/mapbox/dark-v9",
|
"mapStyle": "mapbox://styles/mapbox/dark-v9",
|
||||||
"views": [
|
"views": [
|
||||||
{"@@type": "MapView", "controller": True}
|
{"@@type": "MapView", "controller": True}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hex_layer(self):
|
def hex_layer(self):
|
||||||
return {
|
return {
|
||||||
"@@type": "HexagonLayer",
|
"@@type": "HexagonLayer",
|
||||||
"autoHighlight": True,
|
"autoHighlight": True,
|
||||||
"coverage": 1,
|
"coverage": 1,
|
||||||
"data": self.data if self.view is None else self.view,
|
"data": self.data if self.view is None else self.view,
|
||||||
"elevationRange": [0, 100],
|
"elevationRange": [0, 100],
|
||||||
"elevationScale": self.elevation,
|
"elevationScale": self.elevation,
|
||||||
"radius": self.radius,
|
"radius": self.radius,
|
||||||
"extruded": True,
|
"extruded": True,
|
||||||
"getPosition": "@@=[pickup_x, pickup_y]",
|
"getPosition": "@@=[pickup_x, pickup_y]",
|
||||||
"id": "8a553b25-ef3a-489c-bbe2-e102d18a3211"
|
"id": "8a553b25-ef3a-489c-bbe2-e102d18a3211"
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def arc_layer(self):
|
def arc_layer(self):
|
||||||
return {
|
return {
|
||||||
"@@type": "ArcLayer",
|
"@@type": "ArcLayer",
|
||||||
"id": 'arc-layer',
|
"id": 'arc-layer',
|
||||||
"data": self.arc_view,
|
"data": self.arc_view,
|
||||||
"pickable": True,
|
"pickable": True,
|
||||||
"getWidth": 1,
|
"getWidth": 1,
|
||||||
"getSourcePosition": "@@=[pickup_x, pickup_y]",
|
"getSourcePosition": "@@=[pickup_x, pickup_y]",
|
||||||
"getTargetPosition": "@@=[dropoff_x, dropoff_y]",
|
"getTargetPosition": "@@=[dropoff_x, dropoff_y]",
|
||||||
"getSourceColor": [0, 255, 0, 180],
|
"getSourceColor": [0, 255, 0, 180],
|
||||||
"getTargetColor": [240, 100, 0, 180]
|
"getTargetColor": [240, 100, 0, 180]
|
||||||
}
|
}
|
||||||
|
|
||||||
def _update_hour(self):
|
def _update_hour(self):
|
||||||
self.hour = (self.hour+1) % 24
|
self.hour = (self.hour+1) % 24
|
||||||
|
|
||||||
@param.depends('view', watch=True)
|
@param.depends('view', watch=True)
|
||||||
def _update_arc_view(self, event=None):
|
def _update_arc_view(self, event=None):
|
||||||
data = self.data if self.view is None else self.view
|
data = self.data if self.view is None else self.view
|
||||||
if not self.deck_gl or not self.deck_gl.click_state:
|
if not self.deck_gl or not self.deck_gl.click_state:
|
||||||
self.arc_view = data.iloc[:0]
|
self.arc_view = data.iloc[:0]
|
||||||
return
|
return
|
||||||
lon, lat = self.deck_gl.click_state['coordinate']
|
lon, lat = self.deck_gl.click_state['coordinate']
|
||||||
tol = 0.001
|
tol = 0.001
|
||||||
self.arc_view = data[
|
self.arc_view = data[
|
||||||
(df.pickup_x>=float(lon-tol)) &
|
(df.pickup_x>=float(lon-tol)) &
|
||||||
(df.pickup_x<=float(lon+tol)) &
|
(df.pickup_x<=float(lon+tol)) &
|
||||||
(df.pickup_y>=float(lat-tol)) &
|
(df.pickup_y>=float(lat-tol)) &
|
||||||
(df.pickup_y<=float(lat+tol))
|
(df.pickup_y<=float(lat+tol))
|
||||||
]
|
]
|
||||||
|
|
||||||
@param.depends('hour', watch=True, on_init=True)
|
@param.depends('hour', watch=True, on_init=True)
|
||||||
def _update_hourly_view(self):
|
def _update_hourly_view(self):
|
||||||
self.view = self.data[self.data.hour==self.hour]
|
self.view = self.data[self.data.hour==self.hour]
|
||||||
|
|
||||||
@param.depends('speed', watch=True)
|
@param.depends('speed', watch=True)
|
||||||
def _update_speed(self):
|
def _update_speed(self):
|
||||||
self._cb.period = 1000//self.speed
|
self._cb.period = 1000//self.speed
|
||||||
|
|
||||||
@param.depends('play', watch=True)
|
@param.depends('play', watch=True)
|
||||||
def _play_pause(self):
|
def _play_pause(self):
|
||||||
if self._playing:
|
if self._playing:
|
||||||
self._cb.stop()
|
self._cb.stop()
|
||||||
self.param.play.label = '▷'
|
self.param.play.label = '▷'
|
||||||
self.param.speed.precedence = -1
|
self.param.speed.precedence = -1
|
||||||
else:
|
else:
|
||||||
self._cb.start()
|
self._cb.start()
|
||||||
self.param.play.label = '❚❚'
|
self.param.play.label = '❚❚'
|
||||||
self.param.speed.precedence = 1
|
self.param.speed.precedence = 1
|
||||||
self._playing = not self._playing
|
self._playing = not self._playing
|
||||||
|
|
||||||
@param.depends('view', 'radius', 'elevation', 'arc_view', watch=True)
|
@param.depends('view', 'radius', 'elevation', 'arc_view', watch=True)
|
||||||
def update_spec(self):
|
def update_spec(self):
|
||||||
self.deck_gl.object = dict(self.spec)
|
self.deck_gl.object = dict(self.spec)
|
||||||
|
|
||||||
url = 'https://s3.eu-west-1.amazonaws.com/assets.holoviews.org/data/nyc_taxi_wide.csv'
|
url = 'https://s3.eu-west-1.amazonaws.com/assets.holoviews.org/data/nyc_taxi_wide.csv'
|
||||||
df = pd.read_csv(open_url(url))
|
df = pd.read_csv(open_url(url))
|
||||||
app = App(data=df)
|
app = App(data=df)
|
||||||
controls = pn.Param(app.param, sizing_mode='stretch_width', show_name=False)
|
controls = pn.Param(app.param, sizing_mode='stretch_width', show_name=False)
|
||||||
|
|
||||||
app.deck_gl.servable(target='plot')
|
app.deck_gl.servable(target='plot')
|
||||||
controls.servable(target='widgets');
|
controls.servable(target='widgets');
|
||||||
</py-script>
|
</py-script>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</section>
|
</section>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,226 +1,229 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta name="name" content="PyScript/Panel KMeans Demo" />
|
<meta name="name" content="PyScript/Panel KMeans Demo" />
|
||||||
|
|
||||||
<title>Pyscript/Panel KMeans Demo</title>
|
<title>Pyscript/Panel KMeans Demo</title>
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
|
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
|
||||||
type="text/css"
|
type="text/css"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css"
|
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css"
|
||||||
type="text/css"
|
type="text/css"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css"
|
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css"
|
||||||
type="text/css"
|
type="text/css"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.jsdelivr.net/npm/vega@5"
|
src="https://cdn.jsdelivr.net/npm/vega@5"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.jsdelivr.net/npm/vega-lite@5"
|
src="https://cdn.jsdelivr.net/npm/vega-lite@5"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.jsdelivr.net/npm/vega-embed@6"
|
src="https://cdn.jsdelivr.net/npm/vega-embed@6"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://unpkg.com/tabulator-tables@4.9.3/dist/js/tabulator.js"
|
src="https://unpkg.com/tabulator-tables@4.9.3/dist/js/tabulator.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js"
|
src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"
|
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css"
|
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css"
|
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#sidebar {
|
#sidebar {
|
||||||
width: 350px;
|
width: 350px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
</head>
|
/>
|
||||||
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" href="" style="color: #f0ab3c"
|
<a class="title" href="" style="color: #f0ab3c"
|
||||||
>Panel KMeans Clustering Demo</a
|
>Panel KMeans Clustering Demo</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<section class="pyscript">
|
<section class="pyscript">
|
||||||
<div class="row overflow-hidden" id="content">
|
<div class="row overflow-hidden" id="content">
|
||||||
<div class="sidenav" id="sidebar">
|
<div class="sidenav" id="sidebar">
|
||||||
<ul class="nav flex-column">
|
<ul class="nav flex-column">
|
||||||
<div class="bk-root" id="x-widget"></div>
|
<div class="bk-root" id="x-widget"></div>
|
||||||
<div class="bk-root" id="y-widget"></div>
|
<div class="bk-root" id="y-widget"></div>
|
||||||
<div class="bk-root" id="n-widget"></div>
|
<div class="bk-root" id="n-widget"></div>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col mh-100 float-left" id="main">
|
<div class="col mh-100 float-left" id="main">
|
||||||
<div class="bk-root" id="intro"></div>
|
<div class="bk-root" id="intro"></div>
|
||||||
<div class="bk-root" id="cluster-plot"></div>
|
<div class="bk-root" id="cluster-plot"></div>
|
||||||
<div class="bk-root" id="table"></div>
|
<div class="bk-root" id="table"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<py-tutor>
|
<py-tutor>
|
||||||
<py-config>
|
<py-config>
|
||||||
packages = [
|
packages = [
|
||||||
"https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
|
"https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
|
||||||
"altair",
|
"altair",
|
||||||
"numpy",
|
"numpy",
|
||||||
"pandas",
|
"pandas",
|
||||||
"scikit-learn",
|
"scikit-learn",
|
||||||
"panel==0.13.1"
|
"panel==0.13.1"
|
||||||
]
|
]
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<py-script>
|
<py-script>
|
||||||
import altair as alt
|
import altair as alt
|
||||||
import panel as pn
|
import panel as pn
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from sklearn.cluster import KMeans
|
from sklearn.cluster import KMeans
|
||||||
from pyodide.http import open_url
|
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'
|
url = 'https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-07-28/penguins.csv'
|
||||||
penguins = pd.read_csv(open_url(url)).dropna()
|
penguins = pd.read_csv(open_url(url)).dropna()
|
||||||
cols = list(penguins.columns)[2:6]
|
cols = list(penguins.columns)[2:6]
|
||||||
|
|
||||||
x = pn.widgets.Select(name='x', options=cols, value='bill_depth_mm').servable(target='x-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')
|
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')
|
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):
|
def get_clusters(n_clusters):
|
||||||
kmeans = KMeans(n_clusters=n_clusters)
|
kmeans = KMeans(n_clusters=n_clusters)
|
||||||
est = kmeans.fit(penguins[cols].values)
|
est = kmeans.fit(penguins[cols].values)
|
||||||
df = penguins.copy()
|
df = penguins.copy()
|
||||||
df['labels'] = est.labels_.astype('str')
|
df['labels'] = est.labels_.astype('str')
|
||||||
return df
|
return df
|
||||||
|
|
||||||
def get_chart(x, y, df):
|
def get_chart(x, y, df):
|
||||||
centers = df.groupby('labels').mean()
|
centers = df.groupby('labels').mean()
|
||||||
return (
|
return (
|
||||||
alt.Chart(df)
|
alt.Chart(df)
|
||||||
.mark_point(size=100)
|
.mark_point(size=100)
|
||||||
.encode(
|
.encode(
|
||||||
x=alt.X(x, scale=alt.Scale(zero=False)),
|
x=alt.X(x, scale=alt.Scale(zero=False)),
|
||||||
y=alt.Y(y, scale=alt.Scale(zero=False)),
|
y=alt.Y(y, scale=alt.Scale(zero=False)),
|
||||||
shape='labels',
|
shape='labels',
|
||||||
color='species'
|
color='species'
|
||||||
).add_selection(brush).properties(width=800) +
|
).add_selection(brush).properties(width=800) +
|
||||||
alt.Chart(centers)
|
alt.Chart(centers)
|
||||||
.mark_point(size=250, shape='cross', color='black')
|
.mark_point(size=250, shape='cross', color='black')
|
||||||
.encode(x=x+':Q', y=y+':Q')
|
.encode(x=x+':Q', y=y+':Q')
|
||||||
)
|
)
|
||||||
|
|
||||||
intro = pn.pane.Markdown("""
|
intro = pn.pane.Markdown("""
|
||||||
This app provides an example of **building a simple dashboard using
|
This app provides an example of **building a simple dashboard using
|
||||||
Panel**.\n\nIt demonstrates how to take the output of **k-means
|
Panel**.\n\nIt demonstrates how to take the output of **k-means
|
||||||
clustering on the Penguins dataset** using scikit-learn,
|
clustering on the Penguins dataset** using scikit-learn,
|
||||||
parameterizing the number of clusters and the variables to
|
parameterizing the number of clusters and the variables to
|
||||||
plot.\n\nThe plot and the table are linked, i.e. selecting on the plot
|
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
|
will filter the data in the table.\n\n The **`x` marks the center** of
|
||||||
the cluster.
|
the cluster.
|
||||||
""").servable(target='intro')
|
""").servable(target='intro')
|
||||||
|
|
||||||
chart = pn.pane.Vega().servable(target='cluster-plot')
|
chart = pn.pane.Vega().servable(target='cluster-plot')
|
||||||
table = pn.widgets.Tabulator(pagination='remote', page_size=10).servable(target='table')
|
table = pn.widgets.Tabulator(pagination='remote', page_size=10).servable(target='table')
|
||||||
|
|
||||||
def update_table(event=None):
|
def update_table(event=None):
|
||||||
table.value = get_clusters(n_clusters.value)
|
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)
|
@pn.depends(x, y, n_clusters, watch=True)
|
||||||
def update_chart(*events):
|
def update_chart(*events):
|
||||||
chart.object = get_chart(x.value, y.value, table.value)
|
chart.object = get_chart(x.value, y.value, table.value)
|
||||||
chart.selection.param.watch(update_filters, 'brush')
|
chart.selection.param.watch(update_filters, 'brush')
|
||||||
|
|
||||||
def update_filters(event=None):
|
def update_filters(event=None):
|
||||||
filters = []
|
filters = []
|
||||||
for k, v in (getattr(event, 'new') or {}).items():
|
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[0]))
|
||||||
filters.append(dict(field=k, type='<=', value=v[1]))
|
filters.append(dict(field=k, type='<=', value=v[1]))
|
||||||
table.filters = filters
|
table.filters = filters
|
||||||
|
|
||||||
update_table()
|
update_table()
|
||||||
update_chart()
|
update_chart()
|
||||||
</py-script>
|
</py-script>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</section>
|
</section>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$("#sidebarCollapse").on("click", function () {
|
$("#sidebarCollapse").on("click", function () {
|
||||||
$("#sidebar").toggleClass("active");
|
$("#sidebar").toggleClass("active");
|
||||||
$(this).toggleClass("active");
|
$(this).toggleClass("active");
|
||||||
var interval = setInterval(function () {
|
var interval = setInterval(function () {
|
||||||
window.dispatchEvent(new Event("resize"));
|
window.dispatchEvent(new Event("resize"));
|
||||||
}, 10);
|
}, 10);
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
}, 210);
|
}, 210);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,157 +1,162 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta name="name" content="PyScript/Panel Streaming Demo" />
|
<meta name="name" content="PyScript/Panel Streaming Demo" />
|
||||||
|
|
||||||
<title>PyScript/Panel Streaming Demo</title>
|
<title>PyScript/Panel Streaming Demo</title>
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.ico" />
|
<link rel="icon" type="image/x-icon" href="./favicon.ico" />
|
||||||
|
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
|
||||||
type="text/css"
|
type="text/css"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css"
|
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css"
|
||||||
type="text/css"
|
type="text/css"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css"
|
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css"
|
||||||
type="text/css"
|
type="text/css"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://unpkg.com/tabulator-tables@4.9.3/dist/js/tabulator.js"
|
src="https://unpkg.com/tabulator-tables@4.9.3/dist/js/tabulator.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js"
|
src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js"
|
||||||
></script>
|
></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"
|
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css"
|
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css"
|
href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
</head>
|
/>
|
||||||
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" href="" style="color: #f0ab3c">Panel Streaming Demo</a>
|
<a class="title" href="" style="color: #f0ab3c"
|
||||||
</div>
|
>Panel Streaming Demo</a
|
||||||
</nav>
|
>
|
||||||
<section class="pyscript">
|
</div>
|
||||||
<div class="row overflow-hidden" id="content">
|
</nav>
|
||||||
<div class="col mh-100 float-left" id="main">
|
<section class="pyscript">
|
||||||
<div class="bk-root" id="controls"></div>
|
<div class="row overflow-hidden" id="content">
|
||||||
<div class="row">
|
<div class="col mh-100 float-left" id="main">
|
||||||
<div class="bk-root" id="table"></div>
|
<div class="bk-root" id="controls"></div>
|
||||||
<div class="bk-root" id="plot"></div>
|
<div class="row">
|
||||||
</div>
|
<div class="bk-root" id="table"></div>
|
||||||
</div>
|
<div class="bk-root" id="plot"></div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<py-tutor>
|
<py-tutor>
|
||||||
<py-config>
|
<py-config>
|
||||||
packages = [
|
packages = [
|
||||||
"https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
|
"https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
|
||||||
"numpy",
|
"numpy",
|
||||||
"pandas",
|
"pandas",
|
||||||
"panel==0.13.1"
|
"panel==0.13.1"
|
||||||
]
|
]
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<py-script>
|
<py-script>
|
||||||
import panel as pn
|
import panel as pn
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from bokeh.models import ColumnDataSource
|
from bokeh.models import ColumnDataSource
|
||||||
from bokeh.plotting import figure
|
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)
|
rollover = pn.widgets.IntInput(name='Rollover', value=15)
|
||||||
follow = pn.widgets.Checkbox(name='Follow', value=True, align='end')
|
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):
|
def color_negative_red(val):
|
||||||
"""
|
"""
|
||||||
Takes a scalar and returns a string with
|
Takes a scalar and returns a string with
|
||||||
the css property `'color: red'` for negative
|
the css property `'color: red'` for negative
|
||||||
strings, black otherwise.
|
strings, black otherwise.
|
||||||
"""
|
"""
|
||||||
color = 'red' if val < 0 else 'green'
|
color = 'red' if val < 0 else 'green'
|
||||||
return 'color: %s' % color
|
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', 'A', source=cds, line_color='red')
|
||||||
p.line('index', 'B', source=cds, line_color='green')
|
p.line('index', 'B', source=cds, line_color='green')
|
||||||
p.line('index', 'C', source=cds, line_color='blue')
|
p.line('index', 'C', source=cds, line_color='blue')
|
||||||
p.line('index', 'D', source=cds, line_color='purple')
|
p.line('index', 'D', source=cds, line_color='purple')
|
||||||
|
|
||||||
def stream():
|
def stream():
|
||||||
data = df.iloc[-1] + np.random.randn(4)
|
data = df.iloc[-1] + np.random.randn(4)
|
||||||
tabulator.stream(data, rollover=rollover.value, follow=follow.value)
|
tabulator.stream(data, rollover=rollover.value, follow=follow.value)
|
||||||
value = {k: [v] for k, v in tabulator.value.iloc[-1].to_dict().items()}
|
value = {k: [v] for k, v in tabulator.value.iloc[-1].to_dict().items()}
|
||||||
value['index'] = [tabulator.value.index[-1]]
|
value['index'] = [tabulator.value.index[-1]]
|
||||||
cds.stream(value)
|
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.pane.Bokeh(p).servable(target='plot')
|
||||||
pn.Row(cb.param.period, rollover, follow, width=400).servable(target='controls')
|
pn.Row(cb.param.period, rollover, follow, width=400).servable(target='controls')
|
||||||
</py-script>
|
</py-script>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</section>
|
</section>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
#output > div {
|
#output > div {
|
||||||
font-family: "monospace";
|
font-family: "monospace";
|
||||||
background-color: #e5e5e5;
|
background-color: #e5e5e5;
|
||||||
border: 1px solid lightgray;
|
border: 1px solid lightgray;
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#output > div:first-child {
|
#output > div:first-child {
|
||||||
border-top: 1px solid lightgray;
|
border-top: 1px solid lightgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
#output > div:nth-child(even) {
|
#output > div:nth-child(even) {
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +1,47 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
|
|
||||||
<title>REPL</title>
|
<title>REPL</title>
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png" />
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
rel="stylesheet"
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
</head>
|
/>
|
||||||
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" href="" style="color: #f0ab3c">PyScript REPL</a>
|
<a class="title" href="" style="color: #f0ab3c"
|
||||||
</div>
|
>PyScript REPL</a
|
||||||
</nav>
|
>
|
||||||
<section class="pyscript">
|
</div>
|
||||||
<h1><b>PyScript REPL</b></h1>
|
</nav>
|
||||||
Tip: press Shift-ENTER to evaluate a cell
|
<section class="pyscript">
|
||||||
<br />
|
<h1><b>PyScript REPL</b></h1>
|
||||||
<py-tutor modules="antigravity.py">
|
Tip: press Shift-ENTER to evaluate a cell
|
||||||
<py-config>
|
<br />
|
||||||
plugins = [
|
<py-tutor modules="antigravity.py">
|
||||||
"../build/plugins/python/py_tutor.py"
|
<py-config>
|
||||||
]
|
plugins = [
|
||||||
[[fetch]]
|
"../build/plugins/python/py_tutor.py"
|
||||||
files = ["./antigravity.py"]
|
]
|
||||||
</py-config>
|
[[fetch]]
|
||||||
<div style="margin-right: 3rem">
|
files = ["./antigravity.py"]
|
||||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
</py-config>
|
||||||
</div>
|
<div style="margin-right: 3rem">
|
||||||
</py-tutor>
|
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||||
</section>
|
</div>
|
||||||
</body>
|
</py-tutor>
|
||||||
|
</section>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,47 +1,50 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
|
|
||||||
<title>Custom REPL Example</title>
|
<title>Custom REPL Example</title>
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png" />
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<link rel="stylesheet" href="repl.css" />
|
rel="stylesheet"
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
/>
|
||||||
</head>
|
<link rel="stylesheet" href="repl.css" />
|
||||||
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" href="" style="color: #f0ab3c">Custom REPL</a>
|
<a class="title" href="" style="color: #f0ab3c">Custom REPL</a>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<section class="pyscript">
|
<section class="pyscript">
|
||||||
<h1 class="font-semibold text-2xl ml-5">Custom REPL</h1>
|
<h1 class="font-semibold text-2xl ml-5">Custom REPL</h1>
|
||||||
<py-tutor modules="antigravity.py">
|
<py-tutor modules="antigravity.py">
|
||||||
<py-config>
|
<py-config>
|
||||||
packages = [
|
packages = [
|
||||||
"bokeh",
|
"bokeh",
|
||||||
"numpy"
|
"numpy"
|
||||||
]
|
]
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
|
|
||||||
[[fetch]]
|
[[fetch]]
|
||||||
files = ["./utils.py", "./antigravity.py"]
|
files = ["./utils.py", "./antigravity.py"]
|
||||||
</py-config>
|
</py-config>
|
||||||
<div style="margin-right: 3rem">
|
<div style="margin-right: 3rem">
|
||||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||||
<div id="output" class="p-4"></div>
|
<div id="output" class="p-4"></div>
|
||||||
</div>
|
</div>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</section>
|
</section>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,172 +1,179 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<title>PyScript — Simple Bioinformatics Example</title>
|
<title>PyScript — Simple Bioinformatics Example</title>
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
type="text/css"
|
type="text/css"
|
||||||
media="screen"
|
media="screen"
|
||||||
href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css"
|
href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="icon"
|
rel="icon"
|
||||||
type="image/png"
|
type="image/png"
|
||||||
href="https://user-images.githubusercontent.com/49681382/166738771-d0c26557-426c-4688-9641-8db5e6b08348.png"
|
href="https://user-images.githubusercontent.com/49681382/166738771-d0c26557-426c-4688-9641-8db5e6b08348.png"
|
||||||
/>
|
/>
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<section class="hero is-primary is-small">
|
<section class="hero is-primary is-small">
|
||||||
<div class="hero-body">
|
<div class="hero-body">
|
||||||
<p class="title is-3">
|
<p class="title is-3">
|
||||||
PyScript — Simple Bioinformatics Example
|
PyScript — Simple Bioinformatics Example
|
||||||
<span class="tag is-white">v.1</span>
|
<span class="tag is-white">v.1</span>
|
||||||
</p>
|
</p>
|
||||||
<p class="subtitle is-6">
|
<p class="subtitle is-6">
|
||||||
Demonstrates the simple use of
|
Demonstrates the simple use of
|
||||||
<a href="https://pyscript.net/" target="_blank"
|
<a href="https://pyscript.net/" target="_blank"
|
||||||
><code>PyScript</code></a
|
><code>PyScript</code></a
|
||||||
>
|
>
|
||||||
in <strong>Bioinformatics/Computational Biology</strong> fields!
|
in
|
||||||
</p>
|
<strong>Bioinformatics/Computational Biology</strong>
|
||||||
</div>
|
fields!
|
||||||
</section>
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<!-- Main Content -->
|
<!-- Main Content -->
|
||||||
<div class="container is-white is-fluid" style="margin-top: 45px">
|
<div class="container is-white is-fluid" style="margin-top: 45px">
|
||||||
<p class="title is-3">🧬 DNA Sequence Tool</p>
|
<p class="title is-3">🧬 DNA Sequence Tool</p>
|
||||||
|
|
||||||
<!--- DNA Sequence Input -->
|
<!--- DNA Sequence Input -->
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Input DNA Sequence</label>
|
<label class="label">Input DNA Sequence</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<textarea
|
<textarea
|
||||||
class="textarea"
|
class="textarea"
|
||||||
placeholder="GATTACA"
|
placeholder="GATTACA"
|
||||||
id="dna_seq"
|
id="dna_seq"
|
||||||
></textarea>
|
></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Operation Selection -->
|
||||||
|
<label class="label">Pick the operation to be applied</label>
|
||||||
|
<div class="field has-addons">
|
||||||
|
<div class="control is-expanded">
|
||||||
|
<div class="select is-fullwidth">
|
||||||
|
<select name="operation" id="operation">
|
||||||
|
<option value="Reverse">
|
||||||
|
Compute the reverse counterpart
|
||||||
|
</option>
|
||||||
|
<option value="Complement">
|
||||||
|
Compute the complement counterpart
|
||||||
|
</option>
|
||||||
|
<option value="ReverseComplement">
|
||||||
|
Compute the reverse complement counterpart
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<button
|
||||||
|
id="run"
|
||||||
|
type="button"
|
||||||
|
class="button is-primary"
|
||||||
|
py-onClick="run()"
|
||||||
|
>
|
||||||
|
Run!
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
id="clear"
|
||||||
|
type="button"
|
||||||
|
class="button is-danger"
|
||||||
|
py-onClick="clear()"
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<!--- DNA Sequence Output -->
|
||||||
|
<label class="label"
|
||||||
|
>Output for the
|
||||||
|
<code id="operation_name_output">given operation</code></label
|
||||||
|
>
|
||||||
|
<div id="output"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Operation Selection -->
|
<br /><br />
|
||||||
<label class="label">Pick the operation to be applied</label>
|
<!-- Footer -->
|
||||||
<div class="field has-addons">
|
<footer class="footer">
|
||||||
<div class="control is-expanded">
|
<div class="content has-text-centered">
|
||||||
<div class="select is-fullwidth">
|
<p>
|
||||||
<select name="operation" id="operation">
|
Developed by
|
||||||
<option value="Reverse">Compute the reverse counterpart</option>
|
<a href="mailto:furkanmtorun@gmail.com"
|
||||||
<option value="Complement">
|
><strong>Furkan M. Torun (@furkanmtorun)</strong></a
|
||||||
Compute the complement counterpart
|
>
|
||||||
</option>
|
<br />
|
||||||
<option value="ReverseComplement">
|
<a href="https://github.com/furkanmtorun">GitHub</a>
|
||||||
Compute the reverse complement counterpart
|
|
|
||||||
</option>
|
<a
|
||||||
</select>
|
href="https://scholar.google.com/citations?user=d5ZyOZ4AAAAJ"
|
||||||
</div>
|
>Google Scholar</a
|
||||||
</div>
|
>
|
||||||
<div class="control">
|
| <a href="https://twitter.com/furkanmtorun">Twitter</a> |
|
||||||
<button
|
<a href="https://www.linkedin.com/in/furkanmtorun/"
|
||||||
id="run"
|
>LinkedIn</a
|
||||||
type="button"
|
>
|
||||||
class="button is-primary"
|
</p>
|
||||||
py-onClick="run()"
|
</div>
|
||||||
>
|
</footer>
|
||||||
Run!
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
id="clear"
|
|
||||||
type="button"
|
|
||||||
class="button is-danger"
|
|
||||||
py-onClick="clear()"
|
|
||||||
>
|
|
||||||
Clear
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
<py-script>
|
||||||
|
# Define HTML elements and inputs
|
||||||
|
dna_alphabet = "ATGC"
|
||||||
|
output = Element("output")
|
||||||
|
dna_seq_element = Element("dna_seq")
|
||||||
|
operation_element = Element("operation")
|
||||||
|
operation_name_output_element = Element("operation_name_output")
|
||||||
|
|
||||||
<!--- DNA Sequence Output -->
|
# DNA Sequene Operations
|
||||||
<label class="label"
|
def return_reverse(dna_seq):
|
||||||
>Output for the
|
return dna_seq[::-1]
|
||||||
<code id="operation_name_output">given operation</code></label
|
def return_complement(dna_seq):
|
||||||
>
|
return dna_seq.translate(str.maketrans("ATCG", "TAGC"))
|
||||||
<div id="output"></div>
|
def return_reverse_complement(dna_seq):
|
||||||
</div>
|
return dna_seq.translate(str.maketrans("ATCG", "TAGC"))[::-1]
|
||||||
|
|
||||||
<br /><br />
|
# Check DNA seq is valid
|
||||||
<!-- Footer -->
|
def check_dna_seq(dna_seq):
|
||||||
<footer class="footer">
|
return all(letter in dna_alphabet for letter in dna_seq.upper())
|
||||||
<div class="content has-text-centered">
|
|
||||||
<p>
|
|
||||||
Developed by
|
|
||||||
<a href="mailto:furkanmtorun@gmail.com"
|
|
||||||
><strong>Furkan M. Torun (@furkanmtorun)</strong></a
|
|
||||||
>
|
|
||||||
<br />
|
|
||||||
<a href="https://github.com/furkanmtorun">GitHub</a>
|
|
||||||
|
|
|
||||||
<a href="https://scholar.google.com/citations?user=d5ZyOZ4AAAAJ"
|
|
||||||
>Google Scholar</a
|
|
||||||
>
|
|
||||||
| <a href="https://twitter.com/furkanmtorun">Twitter</a> |
|
|
||||||
<a href="https://www.linkedin.com/in/furkanmtorun/">LinkedIn</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<py-script>
|
# Clear the form and output
|
||||||
# Define HTML elements and inputs
|
def clear(*args, **kwargs):
|
||||||
dna_alphabet = "ATGC"
|
dna_seq_element.clear()
|
||||||
output = Element("output")
|
output.clear()
|
||||||
dna_seq_element = Element("dna_seq")
|
|
||||||
operation_element = Element("operation")
|
|
||||||
operation_name_output_element = Element("operation_name_output")
|
|
||||||
|
|
||||||
# DNA Sequene Operations
|
# Run
|
||||||
def return_reverse(dna_seq):
|
def run(*args, **kwargs):
|
||||||
return dna_seq[::-1]
|
dna_seq = dna_seq_element.value
|
||||||
def return_complement(dna_seq):
|
is_dna_seq_valid = check_dna_seq(dna_seq)
|
||||||
return dna_seq.translate(str.maketrans("ATCG", "TAGC"))
|
if is_dna_seq_valid:
|
||||||
def return_reverse_complement(dna_seq):
|
operation_name = operation_element.value
|
||||||
return dna_seq.translate(str.maketrans("ATCG", "TAGC"))[::-1]
|
operation_name_output_element.write(operation_name)
|
||||||
|
|
||||||
# Check DNA seq is valid
|
# Compute the desired outputs
|
||||||
def check_dna_seq(dna_seq):
|
if operation_name == "Reverse":
|
||||||
return all(letter in dna_alphabet for letter in dna_seq.upper())
|
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
|
# Output the result
|
||||||
def clear(*args, **kwargs):
|
output.write(output_dna_seq)
|
||||||
dna_seq_element.clear()
|
elif (dna_seq.strip() == "") or (dna_seq is None):
|
||||||
output.clear()
|
output.write("No DNA sequence provided")
|
||||||
|
else:
|
||||||
# Run
|
output.write("Invalid DNA sequence entered")
|
||||||
def run(*args, **kwargs):
|
</py-script>
|
||||||
dna_seq = dna_seq_element.value
|
</body>
|
||||||
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")
|
|
||||||
</py-script>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,64 +1,69 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
|
|
||||||
<title>Simple Clock Demo</title>
|
<title>Simple Clock Demo</title>
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png" />
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
|
/>
|
||||||
|
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" href="" style="color: #f0ab3c">Simple Clock</a>
|
<a class="title" href="" style="color: #f0ab3c">Simple Clock</a>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<section class="pyscript">
|
<section class="pyscript">
|
||||||
<div class="font-mono">start time: <label id="outputDiv"></label></div>
|
<div class="font-mono">
|
||||||
<div id="outputDiv2" class="font-mono"></div>
|
start time: <label id="outputDiv"></label>
|
||||||
<div id="outputDiv3" class="font-mono"></div>
|
</div>
|
||||||
|
<div id="outputDiv2" class="font-mono"></div>
|
||||||
|
<div id="outputDiv3" class="font-mono"></div>
|
||||||
|
|
||||||
<py-tutor modules="utils.py">
|
<py-tutor modules="utils.py">
|
||||||
<py-config>
|
<py-config>
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
[[fetch]]
|
[[fetch]]
|
||||||
files = ["./utils.py"]
|
files = ["./utils.py"]
|
||||||
</py-config>
|
</py-config>
|
||||||
<py-script>
|
<py-script>
|
||||||
import utils
|
import utils
|
||||||
display(utils.now())
|
display(utils.now())
|
||||||
</py-script>
|
</py-script>
|
||||||
|
|
||||||
<py-script>
|
<py-script>
|
||||||
from utils import now
|
from utils import now
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
async def foo():
|
async def foo():
|
||||||
while True:
|
while True:
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
output = now()
|
output = now()
|
||||||
Element("outputDiv2").write(output)
|
Element("outputDiv2").write(output)
|
||||||
|
|
||||||
out3 = Element("outputDiv3")
|
out3 = Element("outputDiv3")
|
||||||
if output[-1] in ["0", "4", "8"]:
|
if output[-1] in ["0", "4", "8"]:
|
||||||
out3.write("It's espresso time!")
|
out3.write("It's espresso time!")
|
||||||
else:
|
else:
|
||||||
out3.clear()
|
out3.clear()
|
||||||
|
|
||||||
pyscript.run_until_complete(foo())
|
pyscript.run_until_complete(foo())
|
||||||
</py-script>
|
</py-script>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</section>
|
</section>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,84 +1,91 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|
||||||
<title>Todo App</title>
|
<title>Todo App</title>
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png" />
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
|
/>
|
||||||
|
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" href="" style="color: #f0ab3c"
|
<a class="title" href="" style="color: #f0ab3c"
|
||||||
>Pyscript Native TODO App</a
|
>Pyscript Native TODO App</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<section class="pyscript">
|
<section class="pyscript">
|
||||||
<h1>To Do List</h1>
|
<h1>To Do List</h1>
|
||||||
<py-tutor modules="utils.py;pylist.py">
|
<py-tutor modules="utils.py;pylist.py">
|
||||||
<py-register-widget
|
<py-register-widget
|
||||||
src="./pylist.py"
|
src="./pylist.py"
|
||||||
name="py-list"
|
name="py-list"
|
||||||
klass="PyList"
|
klass="PyList"
|
||||||
></py-register-widget>
|
></py-register-widget>
|
||||||
|
|
||||||
<py-config>
|
<py-config>
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
[[fetch]]
|
[[fetch]]
|
||||||
files = ["./utils.py", "./pylist.py"]
|
files = ["./utils.py", "./pylist.py"]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<py-script>
|
<py-script>
|
||||||
from js import document
|
from js import document
|
||||||
from pyodide.ffi.wrappers import add_event_listener
|
from pyodide.ffi.wrappers import add_event_listener
|
||||||
|
|
||||||
def add_task(*ags, **kws):
|
def add_task(*ags, **kws):
|
||||||
# create a new dictionary representing the new task
|
# create a new dictionary representing the new task
|
||||||
new_task_content = Element("new-task-content")
|
new_task_content = Element("new-task-content")
|
||||||
task = { "content": new_task_content.value, "done": False, "created_at": dt.now() }
|
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
|
# 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
|
# and to use the key `done` to sync the task status with a checkbox element in the UI
|
||||||
myList.add(task)
|
myList.add(task)
|
||||||
|
|
||||||
# clear the inputbox element used to create the new task
|
# clear the inputbox element used to create the new task
|
||||||
new_task_content.clear()
|
new_task_content.clear()
|
||||||
|
|
||||||
def on_click(evt):
|
def on_click(evt):
|
||||||
add_task()
|
add_task()
|
||||||
|
|
||||||
def handle_keypress(evt):
|
def handle_keypress(evt):
|
||||||
if evt.key == "Enter":
|
if evt.key == "Enter":
|
||||||
add_task()
|
add_task()
|
||||||
|
|
||||||
add_event_listener(
|
add_event_listener(
|
||||||
document.getElementById("new-task-content"),
|
document.getElementById("new-task-content"),
|
||||||
"keypress",
|
"keypress",
|
||||||
handle_keypress
|
handle_keypress
|
||||||
)
|
)
|
||||||
</py-script>
|
</py-script>
|
||||||
<div class="py-box">
|
<div class="py-box">
|
||||||
<input id="new-task-content" />
|
<input id="new-task-content" />
|
||||||
<button py-click="add_task()" id="new-task-btn" class="py-button">
|
<button
|
||||||
Add Task!
|
py-click="add_task()"
|
||||||
</button>
|
id="new-task-btn"
|
||||||
</div>
|
class="py-button"
|
||||||
|
>
|
||||||
|
Add Task!
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<py-list id="myList"></py-list>
|
<py-list id="myList"></py-list>
|
||||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
</section>
|
</section>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,76 +1,83 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
|
|
||||||
<title>Todo App</title>
|
<title>Todo App</title>
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png" />
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
|
/>
|
||||||
|
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
<link rel="stylesheet" href="./assets/css/examples.css" />
|
<link rel="stylesheet" href="./assets/css/examples.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar" style="background-color: #000000">
|
<nav class="navbar" style="background-color: #000000">
|
||||||
<div class="app-header">
|
<div class="app-header">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="./logo.png" class="logo" />
|
<img src="./logo.png" class="logo" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" href="" style="color: #f0ab3c">Todo App</a>
|
<a class="title" href="" style="color: #f0ab3c">Todo App</a>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<section class="pyscript">
|
<section class="pyscript">
|
||||||
<py-tutor modules="./utils.py;./todo.py">
|
<py-tutor modules="./utils.py;./todo.py">
|
||||||
<py-config>
|
<py-config>
|
||||||
plugins = [
|
plugins = [
|
||||||
"../build/plugins/python/py_tutor.py"
|
"../build/plugins/python/py_tutor.py"
|
||||||
]
|
]
|
||||||
[[fetch]]
|
[[fetch]]
|
||||||
files = ["./utils.py", "./todo.py"]
|
files = ["./utils.py", "./todo.py"]
|
||||||
</py-config>
|
</py-config>
|
||||||
|
|
||||||
<py-script src="./todo.py"></py-script>
|
<py-script src="./todo.py"></py-script>
|
||||||
</py-tutor>
|
</py-tutor>
|
||||||
<main>
|
<main>
|
||||||
<section>
|
<section>
|
||||||
<div class="text-center w-full mb-8">
|
<div class="text-center w-full mb-8">
|
||||||
<h1
|
<h1
|
||||||
class="text-3xl font-bold text-gray-800 uppercase tracking-tight"
|
class="text-3xl font-bold text-gray-800 uppercase tracking-tight"
|
||||||
>
|
>
|
||||||
To Do List
|
To Do List
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input id="new-task-content" class="py-input" type="text" />
|
<input
|
||||||
<button
|
id="new-task-content"
|
||||||
id="new-task-btn"
|
class="py-input"
|
||||||
class="py-button"
|
type="text"
|
||||||
type="submit"
|
/>
|
||||||
py-click="add_task()"
|
<button
|
||||||
>
|
id="new-task-btn"
|
||||||
Add task
|
class="py-button"
|
||||||
</button>
|
type="submit"
|
||||||
</div>
|
py-click="add_task()"
|
||||||
|
>
|
||||||
|
Add task
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<py-list id="myList"></py-list>
|
<py-list id="myList"></py-list>
|
||||||
<div
|
<div
|
||||||
id="list-tasks-container"
|
id="list-tasks-container"
|
||||||
class="flex flex-col-reverse mt-4"
|
class="flex flex-col-reverse mt-4"
|
||||||
></div>
|
></div>
|
||||||
|
|
||||||
<template id="task-template">
|
<template id="task-template">
|
||||||
<section class="task py-li-element">
|
<section class="task py-li-element">
|
||||||
<label for="flex items-center p-2 ">
|
<label for="flex items-center p-2 ">
|
||||||
<input class="mr-2" type="checkbox" />
|
<input class="mr-2" type="checkbox" />
|
||||||
<p class="m-0 inline"></p>
|
<p class="m-0 inline"></p>
|
||||||
</label>
|
</label>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</body>
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ It can be served as a Single Page App from a static web server.
|
|||||||
1. Create and activate a virtual environment, and move into the `freedom`
|
1. Create and activate a virtual environment, and move into the `freedom`
|
||||||
project directory:
|
project directory:
|
||||||
|
|
||||||
$ python -m venv venv
|
$ python -m venv venv
|
||||||
$ . ./venv/bin/activate
|
$ . ./venv/bin/activate
|
||||||
$ cd freedom
|
$ cd freedom
|
||||||
|
|
||||||
2. Install Briefcase:
|
2. Install Briefcase:
|
||||||
|
|
||||||
$ pip install briefcase
|
$ pip install briefcase
|
||||||
|
|
||||||
## Web app
|
## Web app
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +1,62 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta
|
<meta
|
||||||
name="viewport"
|
name="viewport"
|
||||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||||
/>
|
/>
|
||||||
<title>Freedom Units</title>
|
<title>Freedom Units</title>
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="/static/logo-32.png" />
|
<link rel="icon" type="image/png" href="/static/logo-32.png" />
|
||||||
|
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
|
/>
|
||||||
|
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
|
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
|
||||||
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N"
|
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N"
|
||||||
crossorigin="anonymous"
|
crossorigin="anonymous"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<link rel="stylesheet" href="/static/css/briefcase.css" />
|
<link rel="stylesheet" href="/static/css/briefcase.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app-placeholder"></div>
|
<div id="app-placeholder"></div>
|
||||||
|
|
||||||
<script
|
<script
|
||||||
src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"
|
src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"
|
||||||
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
|
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
|
||||||
crossorigin="anonymous"
|
crossorigin="anonymous"
|
||||||
></script>
|
></script>
|
||||||
<script
|
<script
|
||||||
src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"
|
src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"
|
||||||
integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct"
|
integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct"
|
||||||
crossorigin="anonymous"
|
crossorigin="anonymous"
|
||||||
></script>
|
></script>
|
||||||
|
|
||||||
<py-config>
|
<py-config>
|
||||||
name = "Freedom Units"
|
name = "Freedom Units"
|
||||||
description = "A testing app"
|
description = "A testing app"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
terminal = false
|
terminal = false
|
||||||
packages = [
|
packages = [
|
||||||
"./static/wheels/freedom-0.0.1-py3-none-any.whl",
|
"./static/wheels/freedom-0.0.1-py3-none-any.whl",
|
||||||
"toga_core==0.3.0",
|
"toga_core==0.3.0",
|
||||||
"toga_web==0.3.0",
|
"toga_web==0.3.0",
|
||||||
"travertino==0.1.3",
|
"travertino==0.1.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[splashscreen]
|
[splashscreen]
|
||||||
autoclose = true
|
autoclose = true
|
||||||
</py-config>
|
</py-config>
|
||||||
<py-script>
|
<py-script>
|
||||||
import runpy
|
import runpy
|
||||||
result = runpy.run_module("freedom", run_name="__main__", alter_sys=True)
|
result = runpy.run_module("freedom", run_name="__main__", alter_sys=True)
|
||||||
</py-script>
|
</py-script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
/* Unset the overly generic pyscript .label style */
|
/* Unset the overly generic pyscript .label style */
|
||||||
#app-placeholder .label {
|
#app-placeholder .label {
|
||||||
margin-top: inherit;
|
margin-top: inherit;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-align: inherit;
|
text-align: inherit;
|
||||||
width: inherit;
|
width: inherit;
|
||||||
display: inherit;
|
display: inherit;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
margin-top: inherit;
|
margin-top: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
@@ -21,15 +21,15 @@
|
|||||||
*******************************************************/
|
*******************************************************/
|
||||||
|
|
||||||
main.toga.window {
|
main.toga.window {
|
||||||
margin-top: 5em;
|
margin-top: 5em;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.toga.box {
|
div.toga.box {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.toga.label {
|
span.toga.label {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,192 +1,195 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>Raycaster</title>
|
<title>Raycaster</title>
|
||||||
<link rel="icon" type="image/png" href="../favicon.png" />
|
<link rel="icon" type="image/png" href="../favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link rel="stylesheet" href="./style.css" />
|
<link rel="stylesheet" href="./style.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container-fluid fixed-top header disable-selection">
|
<div class="container-fluid fixed-top header disable-selection">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col"></div>
|
<div class="col"></div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col"></div>
|
<div class="col"></div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col"></div>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.147.0/three.min.js"></script>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.147.0/three.min.js"></script>
|
|
||||||
|
|
||||||
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
|
||||||
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
|
<link
|
||||||
<py-script>
|
rel="stylesheet"
|
||||||
from pyodide.ffi import create_proxy, to_js
|
href="https://pyscript.net/latest/pyscript.css"
|
||||||
from js import window
|
/>
|
||||||
from js import Math
|
<py-script>
|
||||||
from js import THREE
|
from pyodide.ffi import create_proxy, to_js
|
||||||
from js import performance
|
from js import window
|
||||||
from js import Object
|
from js import Math
|
||||||
from js import document
|
from js import THREE
|
||||||
import asyncio
|
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 = THREE.WebGLRenderer.new({"antialias":True})
|
||||||
renderer.setSize(1000, 1000)
|
renderer.setSize(1000, 1000)
|
||||||
renderer.shadowMap.enabled = False
|
renderer.shadowMap.enabled = False
|
||||||
renderer.shadowMap.type = THREE.PCFSoftShadowMap
|
renderer.shadowMap.type = THREE.PCFSoftShadowMap
|
||||||
renderer.shadowMap.needsUpdate = True
|
renderer.shadowMap.needsUpdate = True
|
||||||
|
|
||||||
document.body.appendChild( renderer.domElement )
|
document.body.appendChild( renderer.domElement )
|
||||||
|
|
||||||
import js, pyodide
|
import js, pyodide
|
||||||
def onMouseMove(event):
|
def onMouseMove(event):
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
|
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
|
||||||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
||||||
js.document.addEventListener('mousemove', pyodide.ffi.create_proxy(onMouseMove))
|
js.document.addEventListener('mousemove', pyodide.ffi.create_proxy(onMouseMove))
|
||||||
|
|
||||||
camera = THREE.PerspectiveCamera.new( 35, window.innerWidth / window.innerHeight, 1, 500 )
|
camera = THREE.PerspectiveCamera.new( 35, window.innerWidth / window.innerHeight, 1, 500 )
|
||||||
scene = THREE.Scene.new()
|
scene = THREE.Scene.new()
|
||||||
cameraRange = 3
|
cameraRange = 3
|
||||||
|
|
||||||
camera.aspect = window.innerWidth / window.innerHeight
|
camera.aspect = window.innerWidth / window.innerHeight
|
||||||
camera.updateProjectionMatrix()
|
camera.updateProjectionMatrix()
|
||||||
renderer.setSize( window.innerWidth, window.innerHeight )
|
renderer.setSize( window.innerWidth, window.innerHeight )
|
||||||
|
|
||||||
setcolor = "#000000"
|
setcolor = "#000000"
|
||||||
|
|
||||||
scene.background = THREE.Color.new(setcolor)
|
scene.background = THREE.Color.new(setcolor)
|
||||||
scene.fog = THREE.Fog.new(setcolor, 2.5, 3.5);
|
scene.fog = THREE.Fog.new(setcolor, 2.5, 3.5);
|
||||||
|
|
||||||
sceneGroup = THREE.Object3D.new();
|
sceneGroup = THREE.Object3D.new();
|
||||||
particularGroup = THREE.Object3D.new();
|
particularGroup = THREE.Object3D.new();
|
||||||
|
|
||||||
def mathRandom(num = 1):
|
def mathRandom(num = 1):
|
||||||
setNumber = - Math.random() * num + Math.random() * num
|
setNumber = - Math.random() * num + Math.random() * num
|
||||||
return setNumber
|
return setNumber
|
||||||
|
|
||||||
particularGroup = THREE.Object3D.new();
|
particularGroup = THREE.Object3D.new();
|
||||||
modularGroup = THREE.Object3D.new();
|
modularGroup = THREE.Object3D.new();
|
||||||
|
|
||||||
perms = {"flatShading":True, "color":"#111111", "transparent":False, "opacity":1, "wireframe":False}
|
perms = {"flatShading":True, "color":"#111111", "transparent":False, "opacity":1, "wireframe":False}
|
||||||
perms = Object.fromEntries(to_js(perms))
|
perms = Object.fromEntries(to_js(perms))
|
||||||
|
|
||||||
particle_perms = {"color":"#FFFFFF", "side":THREE.DoubleSide}
|
particle_perms = {"color":"#FFFFFF", "side":THREE.DoubleSide}
|
||||||
particle_perms = Object.fromEntries(to_js(particle_perms))
|
particle_perms = Object.fromEntries(to_js(particle_perms))
|
||||||
|
|
||||||
def create_cubes(mathRandom, modularGroup):
|
def create_cubes(mathRandom, modularGroup):
|
||||||
i = 0
|
i = 0
|
||||||
while i < 30:
|
while i < 30:
|
||||||
geometry = THREE.IcosahedronGeometry.new();
|
geometry = THREE.IcosahedronGeometry.new();
|
||||||
material = THREE.MeshStandardMaterial.new(perms);
|
material = THREE.MeshStandardMaterial.new(perms);
|
||||||
cube = THREE.Mesh.new(geometry, material);
|
cube = THREE.Mesh.new(geometry, material);
|
||||||
cube.speedRotation = Math.random() * 0.1;
|
cube.speedRotation = Math.random() * 0.1;
|
||||||
cube.positionX = mathRandom();
|
cube.positionX = mathRandom();
|
||||||
cube.positionY = mathRandom();
|
cube.positionY = mathRandom();
|
||||||
cube.positionZ = mathRandom();
|
cube.positionZ = mathRandom();
|
||||||
cube.castShadow = True;
|
cube.castShadow = True;
|
||||||
cube.receiveShadow = True;
|
cube.receiveShadow = True;
|
||||||
newScaleValue = mathRandom(0.3);
|
newScaleValue = mathRandom(0.3);
|
||||||
cube.scale.set(newScaleValue,newScaleValue,newScaleValue);
|
cube.scale.set(newScaleValue,newScaleValue,newScaleValue);
|
||||||
cube.rotation.x = mathRandom(180 * Math.PI / 180);
|
cube.rotation.x = mathRandom(180 * Math.PI / 180);
|
||||||
cube.rotation.y = mathRandom(180 * Math.PI / 180);
|
cube.rotation.y = mathRandom(180 * Math.PI / 180);
|
||||||
cube.rotation.z = mathRandom(180 * Math.PI / 180);
|
cube.rotation.z = mathRandom(180 * Math.PI / 180);
|
||||||
cube.position.set(cube.positionX, cube.positionY, cube.positionZ);
|
cube.position.set(cube.positionX, cube.positionY, cube.positionZ);
|
||||||
modularGroup.add(cube);
|
modularGroup.add(cube);
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
create_cubes(mathRandom, modularGroup)
|
create_cubes(mathRandom, modularGroup)
|
||||||
|
|
||||||
|
|
||||||
def generateParticle(mathRandom, particularGroup, num, amp = 2):
|
def generateParticle(mathRandom, particularGroup, num, amp = 2):
|
||||||
gmaterial = THREE.MeshPhysicalMaterial.new(particle_perms);
|
gmaterial = THREE.MeshPhysicalMaterial.new(particle_perms);
|
||||||
gparticular = THREE.CircleGeometry.new(0.2,5);
|
gparticular = THREE.CircleGeometry.new(0.2,5);
|
||||||
i = 0
|
i = 0
|
||||||
while i < num:
|
while i < num:
|
||||||
pscale = 0.001+Math.abs(mathRandom(0.03));
|
pscale = 0.001+Math.abs(mathRandom(0.03));
|
||||||
particular = THREE.Mesh.new(gparticular, gmaterial);
|
particular = THREE.Mesh.new(gparticular, gmaterial);
|
||||||
particular.position.set(mathRandom(amp),mathRandom(amp),mathRandom(amp));
|
particular.position.set(mathRandom(amp),mathRandom(amp),mathRandom(amp));
|
||||||
particular.rotation.set(mathRandom(),mathRandom(),mathRandom());
|
particular.rotation.set(mathRandom(),mathRandom(),mathRandom());
|
||||||
particular.scale.set(pscale,pscale,pscale);
|
particular.scale.set(pscale,pscale,pscale);
|
||||||
particular.speedValue = mathRandom(1);
|
particular.speedValue = mathRandom(1);
|
||||||
particularGroup.add(particular);
|
particularGroup.add(particular);
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
generateParticle(mathRandom, particularGroup, 200, 2)
|
generateParticle(mathRandom, particularGroup, 200, 2)
|
||||||
|
|
||||||
sceneGroup.add(particularGroup);
|
sceneGroup.add(particularGroup);
|
||||||
scene.add(modularGroup);
|
scene.add(modularGroup);
|
||||||
scene.add(sceneGroup);
|
scene.add(sceneGroup);
|
||||||
|
|
||||||
camera.position.set(0, 0, cameraRange);
|
camera.position.set(0, 0, cameraRange);
|
||||||
cameraValue = False;
|
cameraValue = False;
|
||||||
|
|
||||||
ambientLight = THREE.AmbientLight.new(0xFFFFFF, 0.1);
|
ambientLight = THREE.AmbientLight.new(0xFFFFFF, 0.1);
|
||||||
|
|
||||||
light = THREE.SpotLight.new(0xFFFFFF, 3);
|
light = THREE.SpotLight.new(0xFFFFFF, 3);
|
||||||
light.position.set(5, 5, 2);
|
light.position.set(5, 5, 2);
|
||||||
light.castShadow = True;
|
light.castShadow = True;
|
||||||
light.shadow.mapSize.width = 10000;
|
light.shadow.mapSize.width = 10000;
|
||||||
light.shadow.mapSize.height = light.shadow.mapSize.width;
|
light.shadow.mapSize.height = light.shadow.mapSize.width;
|
||||||
light.penumbra = 0.5;
|
light.penumbra = 0.5;
|
||||||
|
|
||||||
lightBack = THREE.PointLight.new(0x0FFFFF, 1);
|
lightBack = THREE.PointLight.new(0x0FFFFF, 1);
|
||||||
lightBack.position.set(0, -3, -1);
|
lightBack.position.set(0, -3, -1);
|
||||||
|
|
||||||
scene.add(sceneGroup);
|
scene.add(sceneGroup);
|
||||||
scene.add(light);
|
scene.add(light);
|
||||||
scene.add(lightBack);
|
scene.add(lightBack);
|
||||||
|
|
||||||
rectSize = 2
|
rectSize = 2
|
||||||
intensity = 14
|
intensity = 14
|
||||||
rectLight = THREE.RectAreaLight.new( 0x0FFFFF, intensity, rectSize, rectSize )
|
rectLight = THREE.RectAreaLight.new( 0x0FFFFF, intensity, rectSize, rectSize )
|
||||||
rectLight.position.set( 0, 0, 1 )
|
rectLight.position.set( 0, 0, 1 )
|
||||||
rectLight.lookAt( 0, 0, 0 )
|
rectLight.lookAt( 0, 0, 0 )
|
||||||
scene.add( rectLight )
|
scene.add( rectLight )
|
||||||
|
|
||||||
raycaster = THREE.Raycaster.new();
|
raycaster = THREE.Raycaster.new();
|
||||||
uSpeed = 0.1
|
uSpeed = 0.1
|
||||||
|
|
||||||
time = 0.0003;
|
time = 0.0003;
|
||||||
camera.lookAt(scene.position)
|
camera.lookAt(scene.position)
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
while True:
|
while True:
|
||||||
time = performance.now() * 0.0003;
|
time = performance.now() * 0.0003;
|
||||||
i = 0
|
i = 0
|
||||||
while i < particularGroup.children.length:
|
while i < particularGroup.children.length:
|
||||||
newObject = particularGroup.children[i];
|
newObject = particularGroup.children[i];
|
||||||
newObject.rotation.x += newObject.speedValue/10;
|
newObject.rotation.x += newObject.speedValue/10;
|
||||||
newObject.rotation.y += newObject.speedValue/10;
|
newObject.rotation.y += newObject.speedValue/10;
|
||||||
newObject.rotation.z += newObject.speedValue/10;
|
newObject.rotation.z += newObject.speedValue/10;
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
while i < modularGroup.children.length:
|
while i < modularGroup.children.length:
|
||||||
newCubes = modularGroup.children[i];
|
newCubes = modularGroup.children[i];
|
||||||
newCubes.rotation.x += 0.008;
|
newCubes.rotation.x += 0.008;
|
||||||
newCubes.rotation.y += 0.005;
|
newCubes.rotation.y += 0.005;
|
||||||
newCubes.rotation.z += 0.003;
|
newCubes.rotation.z += 0.003;
|
||||||
|
|
||||||
newCubes.position.x = Math.sin(time * newCubes.positionZ) * newCubes.positionY;
|
newCubes.position.x = Math.sin(time * newCubes.positionZ) * newCubes.positionY;
|
||||||
newCubes.position.y = Math.cos(time * newCubes.positionX) * newCubes.positionZ;
|
newCubes.position.y = Math.cos(time * newCubes.positionX) * newCubes.positionZ;
|
||||||
newCubes.position.z = Math.sin(time * newCubes.positionY) * newCubes.positionX;
|
newCubes.position.z = Math.sin(time * newCubes.positionY) * newCubes.positionX;
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
particularGroup.rotation.y += 0.005;
|
particularGroup.rotation.y += 0.005;
|
||||||
|
|
||||||
modularGroup.rotation.y -= ((mouse.x * 4) + modularGroup.rotation.y) * uSpeed;
|
modularGroup.rotation.y -= ((mouse.x * 4) + modularGroup.rotation.y) * uSpeed;
|
||||||
modularGroup.rotation.x -= ((-mouse.y * 4) + modularGroup.rotation.x) * uSpeed;
|
modularGroup.rotation.x -= ((-mouse.y * 4) + modularGroup.rotation.x) * uSpeed;
|
||||||
|
|
||||||
renderer.render( scene, camera )
|
renderer.render( scene, camera )
|
||||||
await asyncio.sleep(0.02)
|
await asyncio.sleep(0.02)
|
||||||
|
|
||||||
asyncio.ensure_future(main())
|
asyncio.ensure_future(main())
|
||||||
</py-script>
|
</py-script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,55 +1,55 @@
|
|||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
cursor: crosshair;
|
cursor: crosshair;
|
||||||
}
|
}
|
||||||
canvas {
|
canvas {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
.header {
|
.header {
|
||||||
/*top:45%;*/
|
/*top:45%;*/
|
||||||
top: 45%;
|
top: 45%;
|
||||||
color: #dddddd;
|
color: #dddddd;
|
||||||
}
|
}
|
||||||
.footer {
|
.footer {
|
||||||
bottom: 3%;
|
bottom: 3%;
|
||||||
}
|
}
|
||||||
.description {
|
.description {
|
||||||
color: gray;
|
color: gray;
|
||||||
padding-top: 50px;
|
padding-top: 50px;
|
||||||
}
|
}
|
||||||
.btn {
|
.btn {
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
padding: 10px 30px;
|
padding: 10px 30px;
|
||||||
}
|
}
|
||||||
a,
|
a,
|
||||||
a:hover,
|
a:hover,
|
||||||
a:visited {
|
a:visited {
|
||||||
color: red;
|
color: red;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.disable-selection {
|
.disable-selection {
|
||||||
-moz-user-select: none; /* Firefox */
|
-moz-user-select: none; /* Firefox */
|
||||||
-ms-user-select: none; /* Internet Explorer */
|
-ms-user-select: none; /* Internet Explorer */
|
||||||
-khtml-user-select: none; /* KHTML browsers (e.g. Konqueror) */
|
-khtml-user-select: none; /* KHTML browsers (e.g. Konqueror) */
|
||||||
-webkit-user-select: none; /* Chrome, Safari, and Opera */
|
-webkit-user-select: none; /* Chrome, Safari, and Opera */
|
||||||
-webkit-touch-callout: none; /* Disable Android and iOS callouts*/
|
-webkit-touch-callout: none; /* Disable Android and iOS callouts*/
|
||||||
}
|
}
|
||||||
h1::after {
|
h1::after {
|
||||||
content: " V 2.0";
|
content: " V 2.0";
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 3px;
|
top: 3px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
h2::after {
|
h2::after {
|
||||||
content: "2";
|
content: "2";
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 14px;
|
top: 14px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user