├── .github
└── workflows
│ └── deploy.yml
├── .gitignore
├── .karma.conf.js
├── .travis.yml
├── README.md
├── assets
├── Graphics
│ ├── Bosses
│ │ ├── Airman.psd
│ │ ├── Crashman.psd
│ │ ├── Flashman.psd
│ │ ├── Heatman.psd
│ │ └── Metalman.psd
│ ├── Cog.ai
│ ├── Deco
│ │ ├── Headlight Lensflare prepared.psd
│ │ └── Lens flare.psd
│ ├── Defullscreen.ai
│ ├── Enemies
│ │ ├── ChangkeyMaker.psd
│ │ ├── Sillycanon.psd
│ │ ├── SniperArmor.psd
│ │ ├── SniperJoe.psd
│ │ └── Telly.psd
│ ├── Explosions.psd
│ ├── Font.psd
│ ├── Fullscreen.ai
│ ├── Hud.psd
│ ├── Intro.psd
│ ├── Levels
│ │ ├── Airman.psd
│ │ ├── Bubbleman.psd
│ │ ├── Crashman.psd
│ │ ├── DrWily1.psd
│ │ ├── DrWily2.psd
│ │ ├── DrWily3.psd
│ │ ├── DrWily4.psd
│ │ ├── DrWilyAlien.psd
│ │ ├── DrWilyTeleport.psd
│ │ ├── Flashman.psd
│ │ ├── Heatman.psd
│ │ ├── Metalman.psd
│ │ ├── Quickman.psd
│ │ └── Woodman.psd
│ ├── Megaman
│ │ ├── Megaman.act
│ │ ├── Megaman.psd
│ │ └── Metalman.act
│ ├── Meters.psd
│ ├── Nes Controller.svg
│ ├── Obstacles.psd
│ ├── Play.ai
│ ├── PowerUp.psd
│ ├── Projectiles.psd
│ ├── StageSelect.psd
│ └── Tool
│ │ └── LevelEditor.psd
└── jnes save states
│ ├── Bubbleman-pre-boss.jst
│ ├── Bubbleman-start.jst
│ ├── Heatman-lower-high-jump.jst
│ ├── Heatman-lower-start.jst
│ ├── Heatman-vertical-1.jst
│ ├── SniperArmor.jst
│ └── Woodman before boss.jst
├── package.json
├── public
├── favicon.ico
├── index.html
└── resource
│ ├── Decorations.xml
│ ├── Intro.xml
│ ├── Megaman2.xml
│ ├── Powerup.xml
│ ├── Projectiles.xml
│ ├── StageSelect.xml
│ ├── characters
│ ├── Airman.xml
│ ├── ChangkeyMaker.xml
│ ├── Crashman.xml
│ ├── Flashman.xml
│ ├── Heatman.xml
│ ├── Megaman.xml
│ ├── Metalman.xml
│ ├── Shotman.xml
│ ├── SniperArmor.xml
│ ├── SniperJoe.xml
│ ├── Telly.xml
│ ├── airman.png
│ ├── changkey.png
│ ├── crashman.png
│ ├── enemies
│ │ ├── shotman.png
│ │ ├── sniperarmor.png
│ │ └── sniperjoe.png
│ ├── flashman.png
│ ├── heatman.png
│ ├── megaman
│ │ ├── airshot.ogg
│ │ ├── damage.ogg
│ │ ├── death.ogg
│ │ ├── jump-land.ogg
│ │ ├── megaman.png
│ │ ├── metalblade.ogg
│ │ ├── plasma.ogg
│ │ ├── teleport-in.ogg
│ │ └── teleport-out.ogg
│ ├── metalman.png
│ └── telly.png
│ ├── cog.svg
│ ├── crash-bomb-attach.ogg
│ ├── deco
│ └── headlight_lensflare.png
│ ├── energy-fill.ogg
│ ├── explosion.ogg
│ ├── explosions.png
│ ├── font.png
│ ├── hit.ogg
│ ├── intro
│ ├── intro.ogg
│ └── intro.png
│ ├── levels
│ ├── Airman.xml
│ ├── Bubbleman.xml
│ ├── Crashman.xml
│ ├── DrWily1.xml
│ ├── DrWily2.xml
│ ├── DrWily3.xml
│ ├── DrWily4.xml
│ ├── DrWilyAlien.xml
│ ├── DrWilyTeleport.xml
│ ├── Flashman.xml
│ ├── Heatman.xml
│ ├── Metalman.xml
│ ├── Quickman.xml
│ ├── Woodman.xml
│ ├── airman
│ │ ├── music.ogg
│ │ └── tiles.png
│ ├── bubbleman
│ │ ├── music.ogg
│ │ └── tiles.png
│ ├── crashman
│ │ ├── music.ogg
│ │ └── tiles.png
│ ├── debug
│ │ ├── DestructibleWall.xml
│ │ ├── DisappearingBlock.xml
│ │ ├── Doors.xml
│ │ ├── Elevator.xml
│ │ ├── Enemies.xml
│ │ ├── JumpHeight.xml
│ │ ├── Ladder.xml
│ │ ├── OnePlatform.xml
│ │ ├── Per.xml
│ │ ├── Physics.xml
│ │ ├── Powerups.xml
│ │ └── sunset.png
│ ├── drwily1
│ │ └── tiles.png
│ ├── drwily2
│ │ └── tiles.png
│ ├── drwily3
│ │ └── tiles.png
│ ├── drwily4
│ │ └── tiles.png
│ ├── drwilyalien
│ │ └── tiles.png
│ ├── drwilyteleport
│ │ └── tiles.png
│ ├── flashman
│ │ ├── music.ogg
│ │ └── tiles.png
│ ├── heatman
│ │ ├── music.ogg
│ │ └── tiles.png
│ ├── metalman
│ │ ├── music.ogg
│ │ └── tiles.png
│ ├── quickman
│ │ ├── music.ogg
│ │ └── tiles.png
│ └── woodman
│ │ ├── music.ogg
│ │ └── tiles.png
│ ├── meters.png
│ ├── nes-controller.svg
│ ├── objects
│ └── obstacles.png
│ ├── powerup.png
│ ├── projectiles.png
│ └── stage-select
│ ├── boss-reveal.ogg
│ ├── change-selection.ogg
│ ├── make-selection.ogg
│ ├── stageselect.png
│ └── wait-music.ogg
├── src
├── App.css
├── App.js
├── __tests__
│ └── bootstrap-test.js
├── bootstrap.js
├── index.css
└── index.js
├── test
├── browser-env.js
├── browser-support
│ ├── TestEnv.js
│ ├── bootstrap.js
│ ├── context.html
│ ├── lib
│ │ ├── expect.js
│ │ ├── mocha.css
│ │ ├── mocha.js
│ │ └── sinon.js
│ ├── style.css
│ ├── ui.js
│ └── webgl-mock.js
├── env.js
├── fixtures
│ ├── animations.xml
│ ├── character.xml
│ ├── level.xml
│ └── textures.xml
├── integration
│ ├── fixtures
│ │ ├── jump.xml
│ │ └── ladder.xml
│ ├── index.html
│ └── tests
│ │ ├── jump.js
│ │ ├── ladder.js
│ │ └── megaman-colors.js
├── system
│ ├── index.html
│ ├── input
│ │ ├── level-bubbleman.json
│ │ ├── level-crashman.json
│ │ ├── level-flashman.json
│ │ └── level-quickman.json
│ └── tests
│ │ ├── game.js
│ │ ├── intro.js
│ │ ├── level-1-airman.js
│ │ ├── level-2-bubbleman.js
│ │ ├── level-3-crashman.js
│ │ ├── level-4-flashman.js
│ │ ├── level-5-heatman.js
│ │ ├── level-6-metalman.js
│ │ ├── level-7-quickman.js
│ │ ├── level-8-woodman.js
│ │ ├── level-9-drwily1.js
│ │ └── stage-select.js
└── webpack.config.js
└── yarn.lock
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Build and Deploy
2 | on:
3 | push:
4 | branches:
5 | - master
6 | jobs:
7 | build-and-deploy:
8 | concurrency: ci-${{ github.ref }} # Recommended if you intend to make multiple deployments in quick succession.
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout 🛎️
12 | uses: actions/checkout@v2
13 |
14 | - name: Install
15 | run: yarn install
16 |
17 | - name: Build
18 | run: yarn run build
19 |
20 | - name: Deploy 🚀
21 | uses: JamesIves/github-pages-deploy-action@v4.2.5
22 | with:
23 | branch: gh-pages
24 | folder: build
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /coverage
3 | /build
4 | /test/browser-test-build.js
--------------------------------------------------------------------------------
/.karma.conf.js:
--------------------------------------------------------------------------------
1 | module.exports = function(_config) {
2 |
3 | const dependencies = [];
4 | dependencies.push('./test/browser-test-build.js');
5 | dependencies.push('./test/browser-support/webgl-mock.js');
6 |
7 | const testFiles = [
8 | {pattern: 'public/resource/**', watched: true, included: false},
9 | {pattern: 'test/integration/fixtures/**', watched: true, included: false},
10 | {pattern: 'test/system/input/**', watched: true, included: false},
11 | 'test/browser-support/lib/expect.js',
12 | 'test/browser-support/lib/sinon.js',
13 | 'test/browser-support/TestEnv.js',
14 | 'test/browser-support/bootstrap.js',
15 | 'test/integration/tests/*.js',
16 | 'test/system/tests/*.js',
17 | ];
18 |
19 | const config = {
20 |
21 | // base path that will be used to resolve all patterns (eg. files, exclude)
22 | basePath: '',
23 |
24 | browserNoActivityTimeout: 20000,
25 |
26 | // frameworks to use
27 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
28 | frameworks: [
29 | 'mocha'
30 | ],
31 |
32 | // list of files / patterns to load in the browser
33 | files: dependencies.concat(testFiles),
34 |
35 |
36 | // list of files to exclude
37 | exclude: [
38 | ],
39 |
40 | customLaunchers: {
41 | Chrome_travis_ci: {
42 | base: 'Chrome',
43 | flags: ['--no-sandbox'],
44 | }
45 | },
46 |
47 | customContextFile: 'test/browser-support/context.html',
48 |
49 | proxies: {
50 | '/public/': '/base/public/',
51 | '/test/': '/base/test/',
52 | },
53 |
54 | // test results reporter to use
55 | // possible values: 'dots', 'progress'
56 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
57 | reporters: [
58 | 'mocha',
59 | ],
60 |
61 | // web server port
62 | port: 9876,
63 |
64 | // enable / disable colors in the output (reporters and logs)
65 | colors: true,
66 |
67 | // level of logging
68 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
69 | logLevel: _config.LOG_DEBUG,
70 |
71 | // enable / disable watching file and executing tests whenever any file changes
72 | autoWatch: true,
73 |
74 | // start these browsers
75 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
76 | browsers: [
77 | 'Chrome',
78 | //'Firefox',
79 | ],
80 |
81 | // Continuous Integration mode
82 | // if true, Karma captures browsers, runs the tests and exits
83 | singleRun: false,
84 |
85 | // Concurrency level
86 | // how many browser should be started simultaneous
87 | concurrency: Infinity,
88 |
89 | coverageReporter: {
90 | dir : 'test/coverage/integration',
91 | reporters: [
92 | {type: 'html', subdir: 'lcov-report'},
93 | {type: 'json', subdir: './', file: 'coverage.json'}
94 | ]
95 | },
96 | };
97 |
98 | if (process.env.TRAVIS) {
99 | config.browsers = ['Chrome_travis_ci'];
100 | config.singleRun = true;
101 | /*
102 | config.files = [
103 | 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r70/three.min.js',
104 | './test/browser-support/webgl-mock.js',
105 | 'build/megaman.es5.js',
106 | ].concat(testFiles);
107 | */
108 | }
109 |
110 | _config.set(config);
111 | }
112 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | dist: trusty
2 | sudo: required
3 | language: node_js
4 | before_install:
5 | - export CHROME_BIN=chromium-browser
6 | - export DISPLAY=:99.0
7 | - sh -e /etc/init.d/xvfb start
8 | - wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
9 | - sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
10 | - sudo apt-get update
11 | - sudo apt-get install google-chrome-stable
12 | branches:
13 | only:
14 | - master
15 | node_js:
16 | - '7'
17 | - '8'
18 | - '9'
19 | script:
20 | - yarn test
21 | - echo "megaman.pomle.com" > build/CNAME
22 | after_success:
23 | - yarn run upload-coverage
24 | deploy:
25 | provider: pages
26 | skip_cleanup: true
27 | github_token: $GITHUB_TOKEN # Set in travis-ci.org dashboard
28 | local_dir: build
29 | on:
30 | branch: master
31 | node: '8'
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # megamanjs
2 | [][1]
3 | [](https://codecov.io/github/pomle/megamanjs?branch=master)
4 |
5 | Project that aims at creating a game engine in JavaScript using Megaman 2 on NES as guide. WebGL is used as renderer and despite Megaman 2 being a 2D game it is run in 3D space using [THREE.js](https://github.com/mrdoob/three.js/) as 3D lib.
6 |
7 | Deployed at http://megaman.pomle.com/
8 |
9 | This project have generated the SnakeSilk Game Engine and the following libraries:
10 | * [snakesilk-engine](https://github.com/snakesilk/snakesilk-engine)
11 | Simple game engine providing game Entity, Timer, Scene, etc.
12 |
13 | * [snakesilk-xml-loader](https://github.com/snakesilk/snakesilk-xml-loader)
14 | Loader creating entities and scenes from XML.
15 |
16 | * [megaman-kit](https://github.com/snakesilk/megaman-kit)
17 | Components for creating Megaman games.
18 |
19 | Follow the project blog at https://medium.com/recreating-megaman-2-using-js-webgl
20 |
21 | ## Running
22 |
23 | * Clone repo.
24 |
25 | git clone https://github.com/pomle/megamanjs.git
26 | cd megamanjs
27 |
28 | * Install dependencies
29 |
30 | yarn install
31 |
32 | * Start; should open game in a browser.
33 |
34 | yarn start
35 |
36 |
37 | ## Developing
38 |
39 | ### Prerequisites
40 |
41 | * Make sure you are running Node.js `>= 7`. Installation instructions for your platform can be found at https://nodejs.org/en/download/package-manager/.
42 |
43 | node --version
44 |
45 | * Install dev dependencies.
46 |
47 | cd megamanjs
48 | yarn install
49 |
50 | * Run test suite.
51 |
52 | yarn test
53 |
54 | The test suite begins with running a Mocha unit test in Node. After that a Chrome window should open and run a browser test.
55 |
56 |
57 | ## Contributing
58 |
59 | Contributions are welcome.
60 |
61 | [1]: https://travis-ci.org/pomle/megamanjs
62 |
--------------------------------------------------------------------------------
/assets/Graphics/Bosses/Airman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Bosses/Airman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Bosses/Crashman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Bosses/Crashman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Bosses/Flashman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Bosses/Flashman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Bosses/Heatman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Bosses/Heatman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Bosses/Metalman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Bosses/Metalman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Cog.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Cog.ai
--------------------------------------------------------------------------------
/assets/Graphics/Deco/Headlight Lensflare prepared.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Deco/Headlight Lensflare prepared.psd
--------------------------------------------------------------------------------
/assets/Graphics/Deco/Lens flare.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Deco/Lens flare.psd
--------------------------------------------------------------------------------
/assets/Graphics/Defullscreen.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Defullscreen.ai
--------------------------------------------------------------------------------
/assets/Graphics/Enemies/ChangkeyMaker.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Enemies/ChangkeyMaker.psd
--------------------------------------------------------------------------------
/assets/Graphics/Enemies/Sillycanon.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Enemies/Sillycanon.psd
--------------------------------------------------------------------------------
/assets/Graphics/Enemies/SniperArmor.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Enemies/SniperArmor.psd
--------------------------------------------------------------------------------
/assets/Graphics/Enemies/SniperJoe.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Enemies/SniperJoe.psd
--------------------------------------------------------------------------------
/assets/Graphics/Enemies/Telly.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Enemies/Telly.psd
--------------------------------------------------------------------------------
/assets/Graphics/Explosions.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Explosions.psd
--------------------------------------------------------------------------------
/assets/Graphics/Font.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Font.psd
--------------------------------------------------------------------------------
/assets/Graphics/Fullscreen.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Fullscreen.ai
--------------------------------------------------------------------------------
/assets/Graphics/Hud.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Hud.psd
--------------------------------------------------------------------------------
/assets/Graphics/Intro.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Intro.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/Airman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/Airman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/Bubbleman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/Bubbleman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/Crashman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/Crashman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/DrWily1.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/DrWily1.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/DrWily2.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/DrWily2.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/DrWily3.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/DrWily3.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/DrWily4.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/DrWily4.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/DrWilyAlien.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/DrWilyAlien.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/DrWilyTeleport.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/DrWilyTeleport.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/Flashman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/Flashman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/Heatman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/Heatman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/Metalman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/Metalman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/Quickman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/Quickman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Levels/Woodman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Levels/Woodman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Megaman/Megaman.act:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Megaman/Megaman.act
--------------------------------------------------------------------------------
/assets/Graphics/Megaman/Megaman.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Megaman/Megaman.psd
--------------------------------------------------------------------------------
/assets/Graphics/Megaman/Metalman.act:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Megaman/Metalman.act
--------------------------------------------------------------------------------
/assets/Graphics/Meters.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Meters.psd
--------------------------------------------------------------------------------
/assets/Graphics/Obstacles.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Obstacles.psd
--------------------------------------------------------------------------------
/assets/Graphics/Play.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Play.ai
--------------------------------------------------------------------------------
/assets/Graphics/PowerUp.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/PowerUp.psd
--------------------------------------------------------------------------------
/assets/Graphics/Projectiles.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Projectiles.psd
--------------------------------------------------------------------------------
/assets/Graphics/StageSelect.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/StageSelect.psd
--------------------------------------------------------------------------------
/assets/Graphics/Tool/LevelEditor.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/Graphics/Tool/LevelEditor.psd
--------------------------------------------------------------------------------
/assets/jnes save states/Bubbleman-pre-boss.jst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/jnes save states/Bubbleman-pre-boss.jst
--------------------------------------------------------------------------------
/assets/jnes save states/Bubbleman-start.jst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/jnes save states/Bubbleman-start.jst
--------------------------------------------------------------------------------
/assets/jnes save states/Heatman-lower-high-jump.jst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/jnes save states/Heatman-lower-high-jump.jst
--------------------------------------------------------------------------------
/assets/jnes save states/Heatman-lower-start.jst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/jnes save states/Heatman-lower-start.jst
--------------------------------------------------------------------------------
/assets/jnes save states/Heatman-vertical-1.jst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/jnes save states/Heatman-vertical-1.jst
--------------------------------------------------------------------------------
/assets/jnes save states/SniperArmor.jst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/jnes save states/SniperArmor.jst
--------------------------------------------------------------------------------
/assets/jnes save states/Woodman before boss.jst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/assets/jnes save states/Woodman before boss.jst
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "megaman2-js",
3 | "version": "0.2.2",
4 | "license": "MIT",
5 | "repository": "https://github.com/pomle/megamanjs",
6 | "homepage": ".",
7 | "scripts": {
8 | "autoformat": "prettier --trailing-comma es5 --write './src/**/*.{js,jsx}'",
9 | "build": "react-scripts build",
10 | "build:test": "webpack --config ./test/webpack.config.js",
11 | "eject": "react-scripts eject",
12 | "heroku-postbuild": "yarn run build",
13 | "start": "react-scripts start",
14 | "start:prod": "serve ./build -C --port $PORT",
15 | "test": "yarn run test:unit && yarn run build && yarn run build:test && yarn run test:browser",
16 | "test:browser": "karma start .karma.conf --single-run --reporters mocha",
17 | "test:unit": "mocha 'src/**/*-test.js'"
18 | },
19 | "dependencies": {
20 | "@snakesilk/engine": "^0.12.0",
21 | "@snakesilk/megaman-kit": "^0.7.2",
22 | "@snakesilk/platform-kit": "^0.2.1",
23 | "@snakesilk/react-loader-progress": "^0.0.1",
24 | "@snakesilk/react-presenter": "0.2.0",
25 | "@snex/react-connect": "0.3.2",
26 | "@snex/react-input-mapper": "^0.3.0",
27 | "desensitize-mousemove": "^0.1.3",
28 | "react": "^15.6.1",
29 | "react-dom": "^15.6.1",
30 | "react-scripts": "^5.0.0",
31 | "serve": "^6.0.6"
32 | },
33 | "devDependencies": {
34 | "@snakesilk/testing": "^0.2.1",
35 | "babel-core": "^6.26.0",
36 | "babel-loader": "^7.1.2",
37 | "expect.js": "^0.3.1",
38 | "karma": "^1.7.0",
39 | "karma-chrome-launcher": "^2.2.0",
40 | "karma-coverage": "^1.1.1",
41 | "karma-mocha": "^1.3.0",
42 | "karma-mocha-reporter": "^2.2.3",
43 | "mocha": "^3.5.0",
44 | "prettier": "^1.5.3",
45 | "sinon": "^3.2.0",
46 | "webpack": "^3.5.4"
47 | },
48 | "browserslist": {
49 | "production": [
50 | ">0.2%",
51 | "not dead",
52 | "not op_mini all"
53 | ],
54 | "development": [
55 | "last 1 chrome version",
56 | "last 1 firefox version",
57 | "last 1 safari version"
58 | ]
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | Megaman 2 JS
23 |
24 |
25 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/public/resource/Decorations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | READY
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/public/resource/Megaman2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/public/resource/Powerup.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/public/resource/Projectiles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/public/resource/StageSelect.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
241 |
242 |
243 |
247 |
248 |
249 |
253 |
254 |
255 |
259 |
260 |
261 |
265 |
266 |
267 |
271 |
272 |
273 |
277 |
278 |
279 |
283 |
284 |
285 |
289 |
290 |
291 |
292 |
293 |
--------------------------------------------------------------------------------
/public/resource/characters/Airman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/public/resource/characters/ChangkeyMaker.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/public/resource/characters/Crashman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/public/resource/characters/Flashman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/public/resource/characters/Heatman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/public/resource/characters/Megaman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | this.climber.bounds.climbable.top - 5) {
94 | return 'bent-over';
95 | }
96 | if (this.velocity.y !== 0) {
97 | return 'climbing';
98 | }
99 | return 'hang';
100 | }
101 |
102 | if (!this.jump._ready) {
103 | if (this.weapon._firing) {
104 | return 'jump-fire';
105 | }
106 | return 'jump';
107 | }
108 |
109 | if (this.move._interimSpeed) {
110 | if (this.move._interimSpeed < this.move.speed * .8) {
111 | if (this.weapon._firing) {
112 | return 'fire';
113 | }
114 | return 'lean';
115 | }
116 | if (this.weapon._firing) {
117 | return 'run-fire';
118 | }
119 | return 'run';
120 | }
121 |
122 | if (this.weapon._firing) {
123 | return 'fire';
124 | }
125 |
126 | return 'idle';
127 | }
128 | ]]>
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
--------------------------------------------------------------------------------
/public/resource/characters/Metalman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/public/resource/characters/Shotman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/public/resource/characters/SniperArmor.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/public/resource/characters/SniperJoe.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/public/resource/characters/Telly.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/public/resource/characters/airman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/airman.png
--------------------------------------------------------------------------------
/public/resource/characters/changkey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/changkey.png
--------------------------------------------------------------------------------
/public/resource/characters/crashman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/crashman.png
--------------------------------------------------------------------------------
/public/resource/characters/enemies/shotman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/enemies/shotman.png
--------------------------------------------------------------------------------
/public/resource/characters/enemies/sniperarmor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/enemies/sniperarmor.png
--------------------------------------------------------------------------------
/public/resource/characters/enemies/sniperjoe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/enemies/sniperjoe.png
--------------------------------------------------------------------------------
/public/resource/characters/flashman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/flashman.png
--------------------------------------------------------------------------------
/public/resource/characters/heatman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/heatman.png
--------------------------------------------------------------------------------
/public/resource/characters/megaman/airshot.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/megaman/airshot.ogg
--------------------------------------------------------------------------------
/public/resource/characters/megaman/damage.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/megaman/damage.ogg
--------------------------------------------------------------------------------
/public/resource/characters/megaman/death.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/megaman/death.ogg
--------------------------------------------------------------------------------
/public/resource/characters/megaman/jump-land.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/megaman/jump-land.ogg
--------------------------------------------------------------------------------
/public/resource/characters/megaman/megaman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/megaman/megaman.png
--------------------------------------------------------------------------------
/public/resource/characters/megaman/metalblade.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/megaman/metalblade.ogg
--------------------------------------------------------------------------------
/public/resource/characters/megaman/plasma.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/megaman/plasma.ogg
--------------------------------------------------------------------------------
/public/resource/characters/megaman/teleport-in.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/megaman/teleport-in.ogg
--------------------------------------------------------------------------------
/public/resource/characters/megaman/teleport-out.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/megaman/teleport-out.ogg
--------------------------------------------------------------------------------
/public/resource/characters/metalman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/metalman.png
--------------------------------------------------------------------------------
/public/resource/characters/telly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/characters/telly.png
--------------------------------------------------------------------------------
/public/resource/cog.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/public/resource/crash-bomb-attach.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/crash-bomb-attach.ogg
--------------------------------------------------------------------------------
/public/resource/deco/headlight_lensflare.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/deco/headlight_lensflare.png
--------------------------------------------------------------------------------
/public/resource/energy-fill.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/energy-fill.ogg
--------------------------------------------------------------------------------
/public/resource/explosion.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/explosion.ogg
--------------------------------------------------------------------------------
/public/resource/explosions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/explosions.png
--------------------------------------------------------------------------------
/public/resource/font.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/font.png
--------------------------------------------------------------------------------
/public/resource/hit.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/hit.ogg
--------------------------------------------------------------------------------
/public/resource/intro/intro.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/intro/intro.ogg
--------------------------------------------------------------------------------
/public/resource/intro/intro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/intro/intro.png
--------------------------------------------------------------------------------
/public/resource/levels/DrWilyTeleport.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
--------------------------------------------------------------------------------
/public/resource/levels/airman/music.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/airman/music.ogg
--------------------------------------------------------------------------------
/public/resource/levels/airman/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/airman/tiles.png
--------------------------------------------------------------------------------
/public/resource/levels/bubbleman/music.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/bubbleman/music.ogg
--------------------------------------------------------------------------------
/public/resource/levels/bubbleman/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/bubbleman/tiles.png
--------------------------------------------------------------------------------
/public/resource/levels/crashman/music.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/crashman/music.ogg
--------------------------------------------------------------------------------
/public/resource/levels/crashman/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/crashman/tiles.png
--------------------------------------------------------------------------------
/public/resource/levels/debug/DestructibleWall.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/public/resource/levels/debug/DisappearingBlock.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/public/resource/levels/debug/Doors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/public/resource/levels/debug/Elevator.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/public/resource/levels/debug/Enemies.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/public/resource/levels/debug/JumpHeight.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/public/resource/levels/debug/Ladder.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/public/resource/levels/debug/OnePlatform.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/public/resource/levels/debug/Per.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/public/resource/levels/debug/Physics.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/public/resource/levels/debug/Powerups.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/public/resource/levels/debug/sunset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/debug/sunset.png
--------------------------------------------------------------------------------
/public/resource/levels/drwily1/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/drwily1/tiles.png
--------------------------------------------------------------------------------
/public/resource/levels/drwily2/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/drwily2/tiles.png
--------------------------------------------------------------------------------
/public/resource/levels/drwily3/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/drwily3/tiles.png
--------------------------------------------------------------------------------
/public/resource/levels/drwily4/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/drwily4/tiles.png
--------------------------------------------------------------------------------
/public/resource/levels/drwilyalien/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/drwilyalien/tiles.png
--------------------------------------------------------------------------------
/public/resource/levels/drwilyteleport/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/drwilyteleport/tiles.png
--------------------------------------------------------------------------------
/public/resource/levels/flashman/music.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/flashman/music.ogg
--------------------------------------------------------------------------------
/public/resource/levels/flashman/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/flashman/tiles.png
--------------------------------------------------------------------------------
/public/resource/levels/heatman/music.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/heatman/music.ogg
--------------------------------------------------------------------------------
/public/resource/levels/heatman/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/heatman/tiles.png
--------------------------------------------------------------------------------
/public/resource/levels/metalman/music.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/metalman/music.ogg
--------------------------------------------------------------------------------
/public/resource/levels/metalman/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/metalman/tiles.png
--------------------------------------------------------------------------------
/public/resource/levels/quickman/music.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/quickman/music.ogg
--------------------------------------------------------------------------------
/public/resource/levels/quickman/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/quickman/tiles.png
--------------------------------------------------------------------------------
/public/resource/levels/woodman/music.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/woodman/music.ogg
--------------------------------------------------------------------------------
/public/resource/levels/woodman/tiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/levels/woodman/tiles.png
--------------------------------------------------------------------------------
/public/resource/meters.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/meters.png
--------------------------------------------------------------------------------
/public/resource/objects/obstacles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/objects/obstacles.png
--------------------------------------------------------------------------------
/public/resource/powerup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/powerup.png
--------------------------------------------------------------------------------
/public/resource/projectiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/projectiles.png
--------------------------------------------------------------------------------
/public/resource/stage-select/boss-reveal.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/stage-select/boss-reveal.ogg
--------------------------------------------------------------------------------
/public/resource/stage-select/change-selection.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/stage-select/change-selection.ogg
--------------------------------------------------------------------------------
/public/resource/stage-select/make-selection.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/stage-select/make-selection.ogg
--------------------------------------------------------------------------------
/public/resource/stage-select/stageselect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/stage-select/stageselect.png
--------------------------------------------------------------------------------
/public/resource/stage-select/wait-music.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pomle/megamanjs/03392276d378922ddf56e086e895cf2da49567d6/public/resource/stage-select/wait-music.ogg
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | height: 100%;
3 | }
4 |
5 | .App .snakesilk-presenter .snex-connect {
6 | font-size: 2vh;
7 | height: 7vh;
8 | margin: 0 auto;
9 | width: 14vw;
10 | }
11 |
12 | .App .snakesilk-presenter .video .overlay {
13 | align-items: center;
14 | display: flex;
15 | flex-flow: column;
16 | justify-content: center;
17 | }
18 |
19 | .App .snakesilk-presenter .fullscreen {
20 | background: #000;
21 | height: 100%;
22 | }
23 |
24 | .App .snex-input-mapper {
25 | font-size: 2vh;
26 | margin: 0 auto;
27 | width: 30vw;
28 | }
29 |
30 | .App .snex-input-mapper .key-map {
31 | background: rgba(0,0,0,.5);
32 | border-radius: .2em;
33 | padding: 1em;
34 | text-align: left;
35 | }
36 |
37 | .App .snex-input-mapper button {
38 | background: transparent;
39 | border: none;
40 | color: inherit;
41 | margin-left: auto;
42 | }
43 |
44 | .App .snakesilk-progress-bar {
45 | border: solid 3px #fff;
46 | width: 50%;
47 | }
48 |
49 | .App .snakesilk-progress-bar.idle {
50 | display: none;
51 | }
52 |
53 | .App .snakesilk-progress-bar .progress {
54 | background: #fff;
55 | height: 10px;
56 | width: 50%;
57 | }
58 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import Presenter from "@snakesilk/react-presenter";
3 | import { ProgressBar } from "@snakesilk/react-loader-progress";
4 | import SNEXConnect from "@snex/react-connect";
5 | import SNEXMapper from "@snex/react-input-mapper";
6 | import {createLoader} from './bootstrap';
7 | import "./App.css";
8 |
9 | class App extends Component {
10 | constructor(props) {
11 | super(props);
12 | this.loader = createLoader();
13 | this.game = this.loader.game;
14 | window.megaman2 = this.loader;
15 | }
16 |
17 | componentDidMount() {
18 | this.loader.loadGame("./resource/Megaman2.xml");
19 | }
20 |
21 | attachSNEXController(controller) {
22 | controller.on("data", ({ key, state }) => {
23 | this.routeInput(key, state);
24 | });
25 | }
26 |
27 | routeInput(key, state) {
28 | this.game.input.trigger(key.toLowerCase(), state ? "keydown" : "keyup");
29 | }
30 |
31 | render() {
32 | return (
33 |
34 |
}
39 | >
40 |
this.routeInput(key, state)}
42 | svgURL="/resource/nes-controller.svg"
43 | />
44 |
45 | this.attachSNEXController(cont)}
48 | />
49 |
50 |
51 | );
52 | }
53 | }
54 |
55 | export default App;
56 |
--------------------------------------------------------------------------------
/src/__tests__/bootstrap-test.js:
--------------------------------------------------------------------------------
1 | const expect = require('expect.js');
2 |
3 | const mocks = require('@snakesilk/testing/mocks');
4 | const {createNode} = require('@snakesilk/testing/xml');
5 | const {createLoader} = require('../bootstrap');
6 | const {Parser: {EntityParser}} = require('@snakesilk/xml-loader');
7 |
8 | describe('createLoader()', () => {
9 | let loader;
10 |
11 | beforeEach(() => {
12 | mocks.AudioContext.mock();
13 | mocks.requestAnimationFrame.mock();
14 | mocks.THREE.WebGLRenderer.mock();
15 |
16 | loader = createLoader();
17 | });
18 |
19 | afterEach(() => {
20 | mocks.AudioContext.restore();
21 | mocks.requestAnimationFrame.restore();
22 | mocks.THREE.WebGLRenderer.restore();
23 | });
24 |
25 | [
26 | 'Airman',
27 | 'Crashman',
28 | 'Flashman',
29 | 'Heatman',
30 | 'Megaman',
31 | 'Metalman',
32 |
33 | 'ChangkeyMaker',
34 | 'Shotman',
35 | 'SniperArmor',
36 | 'SniperJoe',
37 | 'Telly',
38 | ].forEach(name => {
39 | const id = name + '-id';
40 | const xmlString = `
41 |
42 | `;
43 |
44 | describe(`when parsing ${xmlString}`, () => {
45 | let parser, Entity;
46 |
47 | beforeEach(() => {
48 | const node = createNode(xmlString);
49 | parser = new EntityParser(loader);
50 | return parser.getObjects(node)
51 | .then(objects => {
52 | Entity = objects[id].constructor;
53 | });
54 | });
55 |
56 | it(`produces a ${name} entity`, () => {
57 | expect(Entity).to.be.a(Function);
58 | });
59 |
60 | it.skip(`produces a ${name} entity`, () => {
61 | expect(new Entity()).to.be.a(Objects[name]);
62 | });
63 | });
64 | });
65 | });
66 |
--------------------------------------------------------------------------------
/src/bootstrap.js:
--------------------------------------------------------------------------------
1 | const {Game} = require('@snakesilk/engine');
2 | const {Traits: PlatformTraits} = require('@snakesilk/platform-kit');
3 | const {
4 | Entities,
5 | Loaders: {MegamanLoader},
6 | Traits: MegamanTraits,
7 | } = require('@snakesilk/megaman-kit');
8 |
9 | function createLoader() {
10 | const game = new Game();
11 | const loader = new MegamanLoader(game);
12 |
13 | loader.entities.add(Entities);
14 |
15 | loader.traits.add(PlatformTraits);
16 | loader.traits.add(MegamanTraits);
17 |
18 | return loader;
19 | }
20 |
21 | module.exports = {
22 | createLoader,
23 | };
24 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | font-family: "Saira", sans-serif;
3 | }
4 |
5 | body {
6 | background: #222;
7 | color: #fff;
8 | margin: 0;
9 | padding: 0;
10 | }
11 |
12 | a {
13 | color: #fff;
14 | font-weight: bold;
15 | text-decoration: none;
16 | }
17 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import App from "./App";
4 | import "./index.css";
5 |
6 | ReactDOM.render(, document.getElementById("root"));
7 |
--------------------------------------------------------------------------------
/test/browser-env.js:
--------------------------------------------------------------------------------
1 | const THREE = require('three');
2 | const Engine = require('@snakesilk/engine');
3 | const {createLoader} = require('../src/bootstrap');
4 |
5 | window.THREE = THREE;
6 | window.Engine = Engine;
7 | window.createLoader = createLoader;
8 |
--------------------------------------------------------------------------------
/test/browser-support/TestEnv.js:
--------------------------------------------------------------------------------
1 | class TestEnv
2 | {
3 | constructor(gameXML)
4 | {
5 | this.renderInterval = 0;
6 | this.tickDelay = -1;
7 |
8 | this.paused = false;
9 | this._resume = null;
10 |
11 | this._running = false;
12 | this._screen = document.querySelector('#screen');
13 |
14 | this.loader = createLoader();
15 | this.game = this.loader.game;
16 |
17 | if (this._screen) {
18 | this.game.attachToElement(this._screen);
19 | this.game.setResolution(640, 480);
20 | this.game.adjustResolution();
21 | }
22 | this.ready = this.loader.loadGame(gameXML);
23 | }
24 | destroy()
25 | {
26 | this.game.destroy();
27 | this._screen.innerHTML = '';
28 | }
29 | load(nameOrUrl)
30 | {
31 | const method = nameOrUrl.indexOf('.xml') === -1 ? 'loadSceneByName' : 'loadScene';
32 | return this.loader[method](nameOrUrl).then(scene => {
33 | scene.camera.smoothing = 0;
34 | return scene;
35 | });
36 | }
37 | loadInput(url)
38 | {
39 | return fetch(url).then(response => response.json());
40 | }
41 | pauseToggle()
42 | {
43 | if (this.paused) {
44 | this.paused = false;
45 | if (this._resume) {
46 | this._resume();
47 | }
48 | } else {
49 | this.paused = true;
50 | }
51 | }
52 | scene(scene)
53 | {
54 | this.game.setScene(scene);
55 | }
56 | tap(keys)
57 | {
58 | const inp = this.game.input;
59 | inp.enable();
60 | keys.split(' ').forEach(key => {
61 | inp.trigger(key, inp.ENGAGE);
62 | inp.trigger(key, inp.RELEASE);
63 | });
64 | }
65 | toggle(keys, state)
66 | {
67 | const inp = this.game.input;
68 | inp.enable();
69 | keys.split(' ').forEach(key => {
70 | inp.trigger(key, state ? inp.ENGAGE : inp.RELEASE);
71 | });
72 | }
73 | release()
74 | {
75 | this.game.input.release();
76 | }
77 | settle()
78 | {
79 | this.game.scene.world.simulateTime(0);
80 | }
81 | playInput(log)
82 | {
83 | this.game.input.enable();
84 | const player = new Engine.InputPlayer(this.game.scene.world,
85 | this.game.input);
86 | player.play(log);
87 | return player;
88 | }
89 | goToTick(tick)
90 | {
91 | /* When the game is paused and the tick retrieved
92 | current tick is returned but the simulation event
93 | for that tick will happen on the next iteration. */
94 | const goal = (tick - 1) | 0;
95 | return this.waitUntil(data => data.tick === goal);
96 | }
97 | goToTime(time)
98 | {
99 | return this.waitUntil(data => data.totalTime > time);
100 | }
101 | waitTicks(ticks)
102 | {
103 | const tick = this.game.scene.world._tick + ticks;
104 | return this.waitUntil(data => data.tick >= tick);
105 | }
106 | waitTime(time)
107 | {
108 | const goal = this.game.scene.world._timeTotal + time;
109 | return this.waitUntil(data => data.totalTime >= goal);
110 | }
111 | waitUntil(condition)
112 | {
113 | if (this._running) {
114 | throw new Error('Progress already running. Make sure last wait*() call was waiting to be resolved.');
115 | }
116 | this._running = true;
117 |
118 | return new Promise(resolve => {
119 | const scene = this.game.scene;
120 | const world = scene.world;
121 |
122 | const simCallback = (dt, t, tick) => {
123 | if (this.renderInterval > 0 && tick % this.renderInterval === 0) {
124 | this.game.render();
125 | }
126 |
127 | const data = {
128 | scene,
129 | world,
130 | tick,
131 | deltaTime: dt,
132 | totalTime: t,
133 | };
134 |
135 | if (condition(data)) {
136 | world.events.unbind(world.EVENT_SIMULATE, simCallback);
137 | this._running = false;
138 | this._resume = null;
139 | resolve();
140 | }
141 | };
142 |
143 | world.events.bind(world.EVENT_SIMULATE, simCallback);
144 |
145 | const next = this._resume = () => {
146 | if (!this.paused) {
147 | if (this.tickDelay >= 0) {
148 | scene.updateTime(scene.world.timeStep);
149 | } else {
150 | /* Relieve occasionally to let Async operations run.
151 | In the game environment everything is sync, but
152 | the loader is async when loading resources so in
153 | order to be able to test that a level is loaded
154 | at some time, we need to back off. */
155 | let maxTicks = 1200;
156 | while (maxTicks-- && this._running) {
157 | scene.updateTime(scene.world.timeStep);
158 | }
159 | }
160 |
161 | if (this._running) {
162 | setTimeout(next, this.tickDelay);
163 | }
164 | }
165 | };
166 |
167 | next();
168 | });
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/test/browser-support/bootstrap.js:
--------------------------------------------------------------------------------
1 | mocha.setup({
2 | ui: 'bdd',
3 | enableTimeouts: false,
4 | });
5 |
6 | const env = new TestEnv('/public/resource/Megaman2.xml');
7 | env.renderInterval = 0;
8 | env.tickDelay = -1;
9 |
--------------------------------------------------------------------------------
/test/browser-support/context.html:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
21 |
22 |
30 |
31 | %SCRIPTS%
32 |
35 |
36 |
--------------------------------------------------------------------------------
/test/browser-support/lib/mocha.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | body {
4 | margin:0;
5 | }
6 |
7 | #mocha {
8 | font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
9 | margin: 60px 50px;
10 | }
11 |
12 | #mocha ul,
13 | #mocha li {
14 | margin: 0;
15 | padding: 0;
16 | }
17 |
18 | #mocha ul {
19 | list-style: none;
20 | }
21 |
22 | #mocha h1,
23 | #mocha h2 {
24 | margin: 0;
25 | }
26 |
27 | #mocha h1 {
28 | margin-top: 15px;
29 | font-size: 1em;
30 | font-weight: 200;
31 | }
32 |
33 | #mocha h1 a {
34 | text-decoration: none;
35 | color: inherit;
36 | }
37 |
38 | #mocha h1 a:hover {
39 | text-decoration: underline;
40 | }
41 |
42 | #mocha .suite .suite h1 {
43 | margin-top: 0;
44 | font-size: .8em;
45 | }
46 |
47 | #mocha .hidden {
48 | display: none;
49 | }
50 |
51 | #mocha h2 {
52 | font-size: 12px;
53 | font-weight: normal;
54 | cursor: pointer;
55 | }
56 |
57 | #mocha .suite {
58 | margin-left: 15px;
59 | }
60 |
61 | #mocha .test {
62 | margin-left: 15px;
63 | overflow: hidden;
64 | }
65 |
66 | #mocha .test.pending:hover h2::after {
67 | content: '(pending)';
68 | font-family: arial, sans-serif;
69 | }
70 |
71 | #mocha .test.pass.medium .duration {
72 | background: #c09853;
73 | }
74 |
75 | #mocha .test.pass.slow .duration {
76 | background: #b94a48;
77 | }
78 |
79 | #mocha .test.pass::before {
80 | content: '✓';
81 | font-size: 12px;
82 | display: block;
83 | float: left;
84 | margin-right: 5px;
85 | color: #00d6b2;
86 | }
87 |
88 | #mocha .test.pass .duration {
89 | font-size: 9px;
90 | margin-left: 5px;
91 | padding: 2px 5px;
92 | color: #fff;
93 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
94 | -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
95 | box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
96 | -webkit-border-radius: 5px;
97 | -moz-border-radius: 5px;
98 | -ms-border-radius: 5px;
99 | -o-border-radius: 5px;
100 | border-radius: 5px;
101 | }
102 |
103 | #mocha .test.pass.fast .duration {
104 | display: none;
105 | }
106 |
107 | #mocha .test.pending {
108 | color: #0b97c4;
109 | }
110 |
111 | #mocha .test.pending::before {
112 | content: '◦';
113 | color: #0b97c4;
114 | }
115 |
116 | #mocha .test.fail {
117 | color: #c00;
118 | }
119 |
120 | #mocha .test.fail pre {
121 | color: black;
122 | }
123 |
124 | #mocha .test.fail::before {
125 | content: '✖';
126 | font-size: 12px;
127 | display: block;
128 | float: left;
129 | margin-right: 5px;
130 | color: #c00;
131 | }
132 |
133 | #mocha .test pre.error {
134 | color: #c00;
135 | max-height: 300px;
136 | overflow: auto;
137 | }
138 |
139 | /**
140 | * (1): approximate for browsers not supporting calc
141 | * (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)
142 | * ^^ seriously
143 | */
144 | #mocha .test pre {
145 | display: block;
146 | float: left;
147 | clear: left;
148 | font: 12px/1.5 monaco, monospace;
149 | margin: 5px;
150 | padding: 15px;
151 | border: 1px solid #eee;
152 | max-width: 85%; /*(1)*/
153 | max-width: calc(100% - 42px); /*(2)*/
154 | word-wrap: break-word;
155 | border-bottom-color: #ddd;
156 | -webkit-border-radius: 3px;
157 | -webkit-box-shadow: 0 1px 3px #eee;
158 | -moz-border-radius: 3px;
159 | -moz-box-shadow: 0 1px 3px #eee;
160 | border-radius: 3px;
161 | }
162 |
163 | #mocha .test h2 {
164 | position: relative;
165 | }
166 |
167 | #mocha .test a.replay {
168 | position: absolute;
169 | top: 3px;
170 | right: 0;
171 | text-decoration: none;
172 | vertical-align: middle;
173 | display: block;
174 | width: 15px;
175 | height: 15px;
176 | line-height: 15px;
177 | text-align: center;
178 | background: #eee;
179 | font-size: 15px;
180 | -moz-border-radius: 15px;
181 | border-radius: 15px;
182 | -webkit-transition: opacity 200ms;
183 | -moz-transition: opacity 200ms;
184 | transition: opacity 200ms;
185 | opacity: 0.3;
186 | color: #888;
187 | }
188 |
189 | #mocha .test:hover a.replay {
190 | opacity: 1;
191 | }
192 |
193 | #mocha-report.pass .test.fail {
194 | display: none;
195 | }
196 |
197 | #mocha-report.fail .test.pass {
198 | display: none;
199 | }
200 |
201 | #mocha-report.pending .test.pass,
202 | #mocha-report.pending .test.fail {
203 | display: none;
204 | }
205 | #mocha-report.pending .test.pass.pending {
206 | display: block;
207 | }
208 |
209 | #mocha-error {
210 | color: #c00;
211 | font-size: 1.5em;
212 | font-weight: 100;
213 | letter-spacing: 1px;
214 | }
215 |
216 | #mocha-stats {
217 | position: fixed;
218 | top: 15px;
219 | right: 10px;
220 | font-size: 12px;
221 | margin: 0;
222 | color: #888;
223 | z-index: 1;
224 | }
225 |
226 | #mocha-stats .progress {
227 | float: right;
228 | padding-top: 0;
229 | }
230 |
231 | #mocha-stats em {
232 | color: black;
233 | }
234 |
235 | #mocha-stats a {
236 | text-decoration: none;
237 | color: inherit;
238 | }
239 |
240 | #mocha-stats a:hover {
241 | border-bottom: 1px solid #eee;
242 | }
243 |
244 | #mocha-stats li {
245 | display: inline-block;
246 | margin: 0 5px;
247 | list-style: none;
248 | padding-top: 11px;
249 | }
250 |
251 | #mocha-stats canvas {
252 | width: 40px;
253 | height: 40px;
254 | }
255 |
256 | #mocha code .comment { color: #ddd; }
257 | #mocha code .init { color: #2f6fad; }
258 | #mocha code .string { color: #5890ad; }
259 | #mocha code .keyword { color: #8a6343; }
260 | #mocha code .number { color: #2f6fad; }
261 |
262 | @media screen and (max-device-width: 480px) {
263 | #mocha {
264 | margin: 60px 0px;
265 | }
266 |
267 | #mocha #stats {
268 | position: absolute;
269 | }
270 | }
271 |
--------------------------------------------------------------------------------
/test/browser-support/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | display: flex;
3 | font-family: sans-serif;
4 | }
5 |
6 | fieldset {
7 | border: none;
8 | font-size: .8em;
9 | }
10 |
11 | #control {
12 | margin: .5em;
13 | }
14 |
15 | #mocha {
16 | flex: 1;
17 | height: 100%;
18 | margin: 0;
19 | overflow: auto;
20 | }
21 |
22 | #mocha-report {
23 | margin: 1em 0;
24 | }
25 |
--------------------------------------------------------------------------------
/test/browser-support/ui.js:
--------------------------------------------------------------------------------
1 | ['tickDelay', 'renderInterval'].forEach(prop => {
2 | const element = document.querySelector('[name=' + prop + ']');
3 | let value;
4 | if (value = localStorage.getItem(prop)) {
5 | element.value = value;
6 | } else {
7 | value = element.value;
8 | }
9 |
10 | if (env.hasOwnProperty(prop)) {
11 | env[prop] = value|0;
12 | }
13 | });
14 |
15 | document.addEventListener('click', e => {
16 | const name = e.target.getAttribute('name');
17 | if (name === 'pauseToggle') {
18 | env.pauseToggle();
19 | } else if (name === 'exposeTick') {
20 | if (env.game.scene) {
21 | console.info('Tick', env.game.scene.world._tick);
22 | } else {
23 | console.error('No active scene');
24 | }
25 | }
26 | });
27 |
28 | document.addEventListener('change', e => {
29 | if (e.target.matches('[name=tickDelay]')) {
30 | env.tickDelay = e.target.value|0;
31 | localStorage.setItem('tickDelay', e.target.value);
32 | } else if (e.target.matches('[name=renderInterval]')) {
33 | env.renderInterval = e.target.value|0;
34 | localStorage.setItem('renderInterval', e.target.value);
35 | }
36 | });
37 |
--------------------------------------------------------------------------------
/test/browser-support/webgl-mock.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This file overrides the renderer part of THREE.js's WebGLRenderer
3 | * and can be used to run THREE.js when no graphics card is available.
4 | *
5 | * Include after THREE.js and it will overwrite relevant parts of THREE.js.
6 | */
7 |
8 | window.THREE.WebGLRenderer = function() {
9 | this.domElement = document.createElement('canvas');
10 | this.render = function() {}
11 | this.setSize = function() {}
12 | }
13 |
--------------------------------------------------------------------------------
/test/env.js:
--------------------------------------------------------------------------------
1 | global.self = global;
2 |
--------------------------------------------------------------------------------
/test/fixtures/animations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/test/fixtures/character.xml:
--------------------------------------------------------------------------------
1 |
2 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/test/fixtures/textures.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/test/integration/fixtures/jump.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/test/integration/fixtures/ladder.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/test/integration/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
25 |
26 |
36 |
37 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
68 |
69 |
--------------------------------------------------------------------------------
/test/integration/tests/jump.js:
--------------------------------------------------------------------------------
1 | describe('Jump', () => {
2 | let player;
3 |
4 | before(done => {
5 | env.ready.then(() => {
6 | return env.load('/test/integration/fixtures/jump.xml');
7 | }).then(scene => {
8 | env.scene(scene);
9 | player = env.game.player.character;
10 | done();
11 | }).catch(done);
12 | });
13 |
14 | after(() => {
15 | env.game.unsetScene();
16 | });
17 |
18 | beforeEach(() => {
19 | env.release();
20 | player.reset();
21 | });
22 |
23 | describe('when jumping without obstruction', () => {
24 | let maxHeight = -Infinity;
25 | before(done => {
26 | player.position.x = -56;
27 | player.position.y = 0;
28 | env.settle();
29 | player.jump.engage();
30 | env.waitUntil(data => {
31 | if (player.position.y < maxHeight) {
32 | return true;
33 | }
34 | maxHeight = player.position.y;
35 | }).then(done);
36 | });
37 |
38 | it('max height should be between 64 and 65', () => {
39 | expect(maxHeight).to.be.within(64, 65);
40 | });
41 | });
42 |
43 | describe('when jumping into obstruction', () => {
44 | let maxHeight = -Infinity;
45 | before(done => {
46 | player.position.x = 0;
47 | player.position.y = 0;
48 | env.settle();
49 | player.jump.engage();
50 | env.waitUntil(data => {
51 | if (player.position.y < maxHeight) {
52 | return true;
53 | }
54 | maxHeight = player.position.y;
55 | }).then(done);
56 | });
57 |
58 | it('jump should be cancelled', () => {
59 | expect(maxHeight).to.be.within(30, 30.2);
60 | });
61 | });
62 | });
63 |
--------------------------------------------------------------------------------
/test/integration/tests/ladder.js:
--------------------------------------------------------------------------------
1 | describe('Ladder', () => {
2 | let player;
3 |
4 | before(done => {
5 | env.ready.then(() => {
6 | return env.load('/test/integration/fixtures/ladder.xml');
7 | }).then(scene => {
8 | env.scene(scene);
9 | player = env.game.player.character;
10 | done();
11 | }).catch(done);
12 | });
13 |
14 | after(() => {
15 | env.game.unsetScene();
16 | });
17 |
18 | beforeEach(() => {
19 | env.release();
20 | player.reset();
21 | });
22 |
23 | describe('when jumping against a ladder from below', () => {
24 | describe('and not aiming', () => {
25 | before(done => {
26 | player.position.x = -48;
27 | player.position.y = -69;
28 | env.waitTime(.1).then(() => {
29 | env.toggle('a', 1);
30 | return env.waitTime(.4);
31 | }).then(done);
32 | });
33 |
34 | it('player passes thru ladder', () => {
35 | expect(player.position.y).to.be.within(-12, -11);
36 | });
37 |
38 | it('player does not grab ladder', () => {
39 | expect(player.climber.attached).to.be(null);
40 | });
41 | });
42 |
43 | describe('while aiming up', () => {
44 | before(done => {
45 | player.position.x = -48;
46 | player.position.y = -69;
47 | env.toggle('a up', 1);
48 | env.waitTime(.4).then(done);
49 | });
50 |
51 | it('player grabs ladder', () => {
52 | expect(player.position.x).to.be(-48);
53 | expect(player.position.y).to.be.within(-26, -25);
54 | });
55 | });
56 | });
57 |
58 | describe('when falling on ladder from above', () => {
59 | describe('and not aiming', () => {
60 | before(done => {
61 | player.position.x = -48;
62 | player.position.y = 120;
63 | env.waitTime(.5).then(done);
64 | });
65 |
66 | it('player is supported by ladder', () => {
67 | expect(player.position.x).to.be(-48);
68 | expect(player.position.y).to.be(107);
69 | });
70 | });
71 |
72 | describe('and aiming down', () => {
73 | before(done => {
74 | player.position.x = -48;
75 | player.position.y = 120;
76 | env.toggle('down', 1);
77 | env.waitTime(.4).then(done);
78 | });
79 |
80 | it('player grabs ladder and climbs down', () => {
81 | expect(player.position.x).to.be(-48);
82 | expect(player.position.y).to.be.within(80, 82);
83 | });
84 | });
85 | });
86 |
87 | describe('when walking past ladder from left', () => {
88 | describe('and not aiming', () => {
89 | before(done => {
90 | player.position.x = 80;
91 | player.position.y = -150;
92 | env.toggle('right', 1);
93 | env.waitTime(.5).then(done);
94 | });
95 |
96 | it('player ignores ladder', () => {
97 | expect(player.position.x).to.be.within(117, 118);
98 | expect(player.position.y).to.be(-149);
99 | });
100 | });
101 |
102 | describe('while aiming up', () => {
103 | before(done => {
104 | player.position.x = 80;
105 | player.position.y = -150;
106 | env.toggle('right up', 1);
107 | env.waitTime(.5).then(done);
108 | });
109 |
110 | it('player grabs ladder', () => {
111 | expect(player.position.x).to.be.within(96, 97);
112 | expect(player.position.y).to.be.within(-135, -134);
113 | });
114 | });
115 | });
116 |
117 | describe('when walking past ladder from right', () => {
118 | describe('and not aiming', () => {
119 | before(done => {
120 | player.position.x = 112;
121 | player.position.y = -150;
122 | env.toggle('left', 1);
123 | env.waitTime(.5).then(done);
124 | });
125 |
126 | it('player ignores ladder', () => {
127 | expect(player.position.x).to.be.within(66, 67);
128 | expect(player.position.y).to.be(-149);
129 | });
130 | });
131 |
132 | describe('while aiming up', () => {
133 | before(done => {
134 | player.position.x = 112;
135 | player.position.y = -150;
136 | env.toggle('left up', 1);
137 | env.waitTime(.5).then(done);
138 | });
139 |
140 | it('player grabs ladder', () => {
141 | expect(player.position.x).to.be.within(95, 96);
142 | expect(player.position.y).to.be.within(-135, -134);
143 | });
144 | });
145 | });
146 |
147 | describe('when falling along a ladder', () => {
148 | describe('and pressing down', () => {
149 | before(done => {
150 | player.position.x = -48;
151 | player.position.y = 60;
152 | env.toggle('down', 1);
153 | env.waitTime(.2).then(done);
154 | });
155 |
156 | it('nothing happens', () => {
157 | expect(player.climber.attached).to.be(null);
158 | });
159 | });
160 |
161 | describe('and pressing up', () => {
162 | before(done => {
163 | player.position.x = -48;
164 | player.position.y = 0;
165 | env.toggle('up', 1);
166 | env.waitTime(.2).then(done);
167 | });
168 |
169 | it('ladder is grabbed', () => {
170 | expect(player.position.y).to.be.within(9, 11);
171 | //expect(player.climber.attached).to.not.be(null);
172 | });
173 | });
174 | });
175 |
176 | describe('when on ladder', () => {
177 | beforeEach(done => {
178 | player.position.x = -48;
179 | player.position.y = 0;
180 | env.toggle('up', 1);
181 | env.waitTicks(1).then(() => {
182 | env.release();
183 | }).then(done);
184 | });
185 |
186 | describe('and reaching bottom when climbing down', () => {
187 | beforeEach(done => {
188 | env.toggle('down', 1);
189 | env.waitTime(1).then(done);
190 | });
191 |
192 | it('player releases ladder', () => {
193 | expect(player.position.y).to.be.within(-55, -52);
194 | expect(player.position.x).to.be(-48);
195 | });
196 |
197 | /* The test above is contaminated by the full test suite
198 | when running on different speeds. I have not been able
199 | to figure out why. Hopefully this test is still valid
200 | but ideally the "it" from below should be used. */
201 | it.skip('player releases ladder (exact)', () => {
202 | expect(player.position.y).to.be.within(-55, -54);
203 | expect(player.position.x).to.be(-48);
204 | });
205 | });
206 |
207 | describe('and player is reset', () => {
208 | beforeEach(done => {
209 | player.reset();
210 | env.waitTime(.5).then(done);
211 | });
212 |
213 | it('player releases ladder', () => {
214 | expect(player.position.y).to.be(-69);
215 | expect(player.position.x).to.be(-48);
216 | });
217 | });
218 | });
219 | });
220 |
--------------------------------------------------------------------------------
/test/integration/tests/megaman-colors.js:
--------------------------------------------------------------------------------
1 | describe('Megaman Colors', () => {
2 | let player, weapons;
3 |
4 | before(done => {
5 | env.ready.then(() => {
6 | player = env.game.player.character;
7 | weapons = env.game.player.weapons;
8 |
9 | const scene = new Engine.Scene();
10 | scene.camera.position.z = 100;
11 | scene.world.gravityForce.set(0, 0);
12 | scene.world.addObject(player);
13 | scene.world.updateTime(0.1);
14 | env.scene(scene);
15 |
16 | done();
17 | }).catch(done);
18 | });
19 |
20 | after(() => {
21 | player.weapon.equip(weapons.p);
22 | env.game.unsetScene();
23 | });
24 |
25 | function getPixel(x, y) {
26 | const scale = env.loader.textureScale;
27 | return player.model.material.map.image
28 | .getContext('2d')
29 | .getImageData(x * scale, y * scale, 1, 1);
30 | }
31 |
32 | describe('when changing weapon', () => {
33 | describe('to Plasma (default)', () => {
34 | before(() => {
35 | player.weapon.equip(weapons.p);
36 | env.game.render();
37 | });
38 |
39 | it('palette is blue shaded', () => {
40 | expect(getPixel(26, 26).data).to.eql([0, 255, 255, 255]);
41 | expect(getPixel(26, 29).data).to.eql([0, 115, 247, 255]);
42 | });
43 | });
44 |
45 | describe('to Air Shooter', () => {
46 | before(() => {
47 | player.weapon.equip(weapons.a);
48 | env.game.render();
49 | });
50 |
51 | it('palette is white and blue', () => {
52 | expect(getPixel(26, 26).data).to.eql([248, 248, 248, 255]);
53 | expect(getPixel(26, 29).data).to.eql([0, 120, 248, 255]);
54 | });
55 | });
56 |
57 | describe('to Crash Bomber', () => {
58 | before(() => {
59 | player.weapon.equip(weapons.c);
60 | env.game.render();
61 | });
62 |
63 | it('palette is white and red', () => {
64 | expect(getPixel(26, 26).data).to.eql([248, 248, 248, 255]);
65 | expect(getPixel(26, 29).data).to.eql([248, 120, 88, 255]);
66 | });
67 | });
68 |
69 | describe('to Metal Blade', () => {
70 | before(() => {
71 | player.weapon.equip(weapons.m);
72 | env.game.render();
73 | });
74 |
75 | it('palette is green shaded', () => {
76 | expect(getPixel(26, 26).data).to.eql([255, 224, 168, 255]);
77 | expect(getPixel(26, 29).data).to.eql([172, 175, 0, 255]);
78 | });
79 | });
80 |
81 | describe('to Time Stopper', () => {
82 | before(() => {
83 | player.weapon.equip(weapons.f);
84 | env.game.render();
85 | });
86 |
87 | it('palette is purple shaded', () => {
88 | expect(getPixel(26, 26).data).to.eql([248, 184, 248, 255]);
89 | expect(getPixel(26, 29).data).to.eql([216, 0, 204, 255]);
90 | });
91 | });
92 | });
93 | });
94 |
--------------------------------------------------------------------------------
/test/system/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
25 |
26 |
36 |
37 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
77 |
78 |
--------------------------------------------------------------------------------
/test/system/input/level-bubbleman.json:
--------------------------------------------------------------------------------
1 | [{"tick":320,"key":"right","type":"keydown"},{"tick":362,"key":"a","type":"keydown"},{"tick":376,"key":"a","type":"keyup"},{"tick":536,"key":"a","type":"keydown"},{"tick":584,"key":"a","type":"keyup"},{"tick":708,"key":"a","type":"keydown"},{"tick":760,"key":"a","type":"keyup"},{"tick":888,"key":"a","type":"keydown"},{"tick":938,"key":"a","type":"keyup"},{"tick":1100,"key":"a","type":"keydown"},{"tick":1120,"key":"a","type":"keyup"},{"tick":1168,"key":"right","type":"keyup"},{"tick":1174,"key":"right","type":"keydown"},{"tick":1194,"key":"a","type":"keydown"},{"tick":1212,"key":"a","type":"keyup"},{"tick":1266,"key":"a","type":"keydown"},{"tick":1294,"key":"a","type":"keyup"},{"tick":1348,"key":"a","type":"keydown"},{"tick":1370,"key":"a","type":"keyup"},{"tick":1444,"key":"a","type":"keydown"},{"tick":1462,"key":"a","type":"keyup"},{"tick":1516,"key":"a","type":"keydown"},{"tick":1538,"key":"a","type":"keyup"},{"tick":1830,"key":"right","type":"keyup"},{"tick":1834,"key":"left","type":"keydown"},{"tick":1900,"key":"left","type":"keyup"},{"tick":1904,"key":"right","type":"keydown"},{"tick":1980,"key":"right","type":"keyup"},{"tick":1982,"key":"left","type":"keydown"},{"tick":2096,"key":"right","type":"keydown"},{"tick":2096,"key":"left","type":"keyup"},{"tick":2218,"key":"left","type":"keydown"},{"tick":2220,"key":"right","type":"keyup"},{"tick":2428,"key":"left","type":"keyup"},{"tick":2430,"key":"right","type":"keydown"},{"tick":2442,"key":"right","type":"keyup"},{"tick":2510,"key":"right","type":"keydown"},{"tick":2666,"key":"right","type":"keyup"},{"tick":2668,"key":"left","type":"keydown"},{"tick":2872,"key":"left","type":"keyup"},{"tick":2876,"key":"right","type":"keydown"},{"tick":3744,"key":"a","type":"keydown"},{"tick":3766,"key":"a","type":"keyup"},{"tick":3832,"key":"a","type":"keydown"},{"tick":3848,"key":"a","type":"keyup"},{"tick":3912,"key":"a","type":"keydown"},{"tick":3932,"key":"a","type":"keyup"},{"tick":4008,"key":"right","type":"keyup"}]
--------------------------------------------------------------------------------
/test/system/input/level-crashman.json:
--------------------------------------------------------------------------------
1 | [{"tick":316,"key":"left","type":"keydown"},{"tick":334,"key":"left","type":"keyup"},{"tick":334,"key":"a","type":"keydown"},{"tick":336,"key":"up","type":"keydown"},{"tick":368,"key":"a","type":"keyup"},{"tick":562,"key":"left","type":"keydown"},{"tick":568,"key":"up","type":"keyup"},{"tick":596,"key":"a","type":"keydown"},{"tick":632,"key":"up","type":"keydown"},{"tick":634,"key":"a","type":"keyup"},{"tick":650,"key":"left","type":"keyup"},{"tick":748,"key":"right","type":"keydown"},{"tick":752,"key":"up","type":"keyup"},{"tick":804,"key":"a","type":"keydown"},{"tick":824,"key":"a","type":"keyup"},{"tick":836,"key":"up","type":"keydown"},{"tick":848,"key":"right","type":"keyup"},{"tick":944,"key":"left","type":"keydown"},{"tick":946,"key":"up","type":"keyup"},{"tick":976,"key":"a","type":"keydown"},{"tick":1010,"key":"up","type":"keydown"},{"tick":1016,"key":"a","type":"keyup"},{"tick":1028,"key":"left","type":"keyup"},{"tick":1410,"key":"right","type":"keydown"},{"tick":1420,"key":"up","type":"keyup"},{"tick":1532,"key":"a","type":"keydown"},{"tick":1550,"key":"a","type":"keyup"},{"tick":1706,"key":"a","type":"keydown"},{"tick":1718,"key":"a","type":"keyup"},{"tick":1796,"key":"a","type":"keydown"},{"tick":1804,"key":"a","type":"keyup"},{"tick":1890,"key":"a","type":"keydown"},{"tick":1920,"key":"up","type":"keydown"},{"tick":1922,"key":"a","type":"keyup"},{"tick":1924,"key":"right","type":"keyup"},{"tick":2200,"key":"a","type":"keydown"},{"tick":2206,"key":"up","type":"keyup"},{"tick":2212,"key":"left","type":"keydown"},{"tick":2222,"key":"a","type":"keyup"},{"tick":2250,"key":"left","type":"keyup"},{"tick":2320,"key":"left","type":"keydown"},{"tick":2350,"key":"left","type":"keyup"},{"tick":2372,"key":"right","type":"keydown"},{"tick":2388,"key":"right","type":"keyup"},{"tick":2784,"key":"right","type":"keydown"},{"tick":2812,"key":"right","type":"keyup"},{"tick":3044,"key":"up","type":"keydown"},{"tick":3306,"key":"a","type":"keydown"},{"tick":3306,"key":"left","type":"keydown"},{"tick":3308,"key":"up","type":"keyup"},{"tick":3328,"key":"a","type":"keyup"},{"tick":3338,"key":"left","type":"keyup"},{"tick":3376,"key":"left","type":"keydown"},{"tick":3396,"key":"left","type":"keyup"},{"tick":3744,"key":"right","type":"keydown"},{"tick":3762,"key":"right","type":"keyup"},{"tick":4234,"key":"a","type":"keydown"},{"tick":4244,"key":"up","type":"keydown"},{"tick":4258,"key":"a","type":"keyup"},{"tick":4502,"key":"right","type":"keydown"},{"tick":4508,"key":"up","type":"keyup"},{"tick":4600,"key":"a","type":"keydown"},{"tick":4600,"key":"right","type":"keyup"},{"tick":4612,"key":"right","type":"keydown"},{"tick":4658,"key":"right","type":"keyup"},{"tick":4666,"key":"a","type":"keyup"},{"tick":4696,"key":"a","type":"keydown"},{"tick":4722,"key":"left","type":"keydown"},{"tick":4740,"key":"left","type":"keyup"},{"tick":4756,"key":"a","type":"keyup"},{"tick":6442,"key":"right","type":"keydown"},{"tick":6480,"key":"right","type":"keyup"},{"tick":6644,"key":"right","type":"keydown"},{"tick":6698,"key":"right","type":"keyup"},{"tick":6770,"key":"a","type":"keydown"},{"tick":6776,"key":"right","type":"keydown"},{"tick":6792,"key":"a","type":"keyup"},{"tick":6814,"key":"right","type":"keyup"},{"tick":6830,"key":"left","type":"keydown"},{"tick":6852,"key":"left","type":"keyup"},{"tick":8250,"key":"right","type":"keydown"},{"tick":8260,"key":"right","type":"keyup"},{"tick":8640,"key":"right","type":"keydown"},{"tick":8650,"key":"right","type":"keyup"},{"tick":9428,"key":"up","type":"keydown"},{"tick":9752,"key":"right","type":"keydown"},{"tick":9754,"key":"up","type":"keyup"},{"tick":10274,"key":"a","type":"keydown"},{"tick":10284,"key":"right","type":"keyup"},{"tick":10292,"key":"up","type":"keydown"},{"tick":10306,"key":"a","type":"keyup"},{"tick":10348,"key":"right","type":"keydown"},{"tick":10388,"key":"right","type":"keyup"},{"tick":11749,"key":"up","type":"keyup"},{"tick":11751,"key":"left","type":"keydown"},{"tick":11789,"key":"a","type":"keydown"},{"tick":11817,"key":"a","type":"keyup"},{"tick":11851,"key":"left","type":"keyup"},{"tick":11889,"key":"left","type":"keydown"},{"tick":11905,"key":"a","type":"keydown"},{"tick":11937,"key":"up","type":"keydown"},{"tick":11961,"key":"a","type":"keyup"},{"tick":11983,"key":"left","type":"keyup"},{"tick":12151,"key":"right","type":"keydown"},{"tick":12159,"key":"up","type":"keyup"},{"tick":12207,"key":"a","type":"keydown"},{"tick":12227,"key":"up","type":"keydown"},{"tick":12235,"key":"right","type":"keyup"},{"tick":12241,"key":"a","type":"keyup"},{"tick":12281,"key":"right","type":"keydown"},{"tick":12315,"key":"right","type":"keyup"},{"tick":13549,"key":"up","type":"keyup"},{"tick":13589,"key":"up","type":"keydown"},{"tick":14001,"key":"up","type":"keyup"},{"tick":14017,"key":"down","type":"keydown"},{"tick":14173,"key":"a","type":"keydown"},{"tick":14175,"key":"down","type":"keyup"},{"tick":14185,"key":"a","type":"keyup"},{"tick":14223,"key":"up","type":"keydown"},{"tick":14253,"key":"up","type":"keyup"},{"tick":14269,"key":"down","type":"keydown"},{"tick":14309,"key":"down","type":"keyup"},{"tick":14319,"key":"right","type":"keydown"},{"tick":14331,"key":"a","type":"keydown"},{"tick":14341,"key":"a","type":"keyup"},{"tick":14359,"key":"up","type":"keydown"},{"tick":14421,"key":"right","type":"keyup"},{"tick":15727,"key":"left","type":"keydown"},{"tick":15727,"key":"up","type":"keyup"},{"tick":15779,"key":"a","type":"keydown"},{"tick":15809,"key":"up","type":"keydown"},{"tick":15817,"key":"a","type":"keyup"},{"tick":15829,"key":"left","type":"keyup"},{"tick":16155,"key":"right","type":"keydown"},{"tick":16157,"key":"up","type":"keyup"},{"tick":16237,"key":"a","type":"keydown"},{"tick":16259,"key":"a","type":"keyup"},{"tick":16317,"key":"a","type":"keydown"},{"tick":16337,"key":"a","type":"keyup"},{"tick":16431,"key":"a","type":"keydown"},{"tick":16519,"key":"a","type":"keyup"},{"tick":16545,"key":"a","type":"keydown"},{"tick":16563,"key":"a","type":"keyup"},{"tick":16627,"key":"a","type":"keydown"},{"tick":16651,"key":"a","type":"keyup"},{"tick":16723,"key":"a","type":"keydown"},{"tick":16735,"key":"a","type":"keyup"},{"tick":16799,"key":"right","type":"keyup"},{"tick":17019,"key":"right","type":"keydown"},{"tick":17345,"key":"a","type":"keydown"},{"tick":17355,"key":"a","type":"keyup"},{"tick":17411,"key":"right","type":"keyup"},{"tick":17831,"key":"right","type":"keydown"},{"tick":17963,"key":"right","type":"keyup"}]
--------------------------------------------------------------------------------
/test/system/input/level-flashman.json:
--------------------------------------------------------------------------------
1 | [{"tick":372,"key":"right","type":"keydown"},{"tick":1012,"key":"right","type":"keyup"},{"tick":1036,"key":"right","type":"keydown"},{"tick":1042,"key":"right","type":"keyup"},{"tick":1046,"key":"right","type":"keydown"},{"tick":1058,"key":"a","type":"keydown"},{"tick":1106,"key":"a","type":"keyup"},{"tick":1550,"key":"b","type":"keydown"},{"tick":1560,"key":"b","type":"keyup"},{"tick":1590,"key":"right","type":"keyup"},{"tick":1632,"key":"left","type":"keydown"},{"tick":2156,"key":"right","type":"keydown"},{"tick":2158,"key":"left","type":"keyup"},{"tick":2906,"key":"right","type":"keyup"},{"tick":2908,"key":"left","type":"keydown"},{"tick":2948,"key":"a","type":"keydown"},{"tick":2948,"key":"left","type":"keyup"},{"tick":2952,"key":"right","type":"keydown"},{"tick":2996,"key":"a","type":"keyup"},{"tick":3080,"key":"a","type":"keydown"},{"tick":3122,"key":"a","type":"keyup"},{"tick":3308,"key":"right","type":"keyup"},{"tick":3326,"key":"right","type":"keydown"},{"tick":3694,"key":"a","type":"keydown"},{"tick":3698,"key":"right","type":"keyup"},{"tick":3702,"key":"left","type":"keydown"},{"tick":3746,"key":"a","type":"keyup"},{"tick":3800,"key":"a","type":"keydown"},{"tick":3808,"key":"right","type":"keydown"},{"tick":3810,"key":"left","type":"keyup"},{"tick":3850,"key":"a","type":"keyup"},{"tick":3982,"key":"right","type":"keyup"},{"tick":3988,"key":"left","type":"keydown"},{"tick":4006,"key":"left","type":"keyup"},{"tick":4082,"key":"left","type":"keydown"},{"tick":4278,"key":"right","type":"keydown"},{"tick":4280,"key":"left","type":"keyup"},{"tick":4516,"key":"right","type":"keyup"},{"tick":4558,"key":"left","type":"keydown"},{"tick":4708,"key":"left","type":"keyup"},{"tick":4716,"key":"right","type":"keydown"},{"tick":4740,"key":"right","type":"keyup"},{"tick":4790,"key":"right","type":"keydown"},{"tick":5026,"key":"right","type":"keyup"},{"tick":5090,"key":"left","type":"keydown"},{"tick":5110,"key":"left","type":"keyup"},{"tick":5138,"key":"left","type":"keydown"},{"tick":5166,"key":"a","type":"keydown"},{"tick":5186,"key":"a","type":"keyup"},{"tick":5236,"key":"a","type":"keydown"},{"tick":5238,"key":"a","type":"keyup"},{"tick":5322,"key":"left","type":"keyup"},{"tick":5322,"key":"right","type":"keydown"},{"tick":5702,"key":"a","type":"keydown"},{"tick":5736,"key":"a","type":"keyup"},{"tick":5794,"key":"a","type":"keydown"},{"tick":5820,"key":"a","type":"keyup"},{"tick":5882,"key":"a","type":"keydown"},{"tick":5898,"key":"a","type":"keyup"},{"tick":5936,"key":"right","type":"keyup"},{"tick":5948,"key":"right","type":"keydown"},{"tick":5962,"key":"a","type":"keydown"},{"tick":5980,"key":"a","type":"keyup"},{"tick":6026,"key":"right","type":"keyup"},{"tick":6036,"key":"right","type":"keydown"},{"tick":6046,"key":"a","type":"keydown"},{"tick":6060,"key":"a","type":"keyup"},{"tick":6120,"key":"a","type":"keydown"},{"tick":6130,"key":"a","type":"keyup"},{"tick":6166,"key":"right","type":"keyup"},{"tick":6172,"key":"right","type":"keydown"},{"tick":6186,"key":"a","type":"keydown"},{"tick":6280,"key":"a","type":"keyup"},{"tick":6300,"key":"a","type":"keydown"},{"tick":6316,"key":"a","type":"keyup"},{"tick":6406,"key":"left","type":"keydown"},{"tick":6410,"key":"right","type":"keyup"},{"tick":6506,"key":"right","type":"keydown"},{"tick":6508,"key":"left","type":"keyup"},{"tick":6598,"key":"a","type":"keydown"},{"tick":6652,"key":"a","type":"keyup"},{"tick":6964,"key":"a","type":"keydown"},{"tick":7014,"key":"right","type":"keyup"},{"tick":7020,"key":"left","type":"keydown"},{"tick":7020,"key":"a","type":"keyup"},{"tick":7044,"key":"left","type":"keyup"},{"tick":7062,"key":"a","type":"keydown"},{"tick":7066,"key":"left","type":"keydown"},{"tick":7096,"key":"a","type":"keyup"},{"tick":7120,"key":"left","type":"keyup"},{"tick":7134,"key":"right","type":"keydown"},{"tick":7166,"key":"a","type":"keydown"},{"tick":7200,"key":"a","type":"keyup"},{"tick":7206,"key":"right","type":"keyup"},{"tick":7210,"key":"left","type":"keydown"},{"tick":7222,"key":"a","type":"keydown"},{"tick":7276,"key":"a","type":"keyup"},{"tick":7298,"key":"left","type":"keyup"},{"tick":7300,"key":"right","type":"keydown"},{"tick":7348,"key":"a","type":"keydown"},{"tick":7386,"key":"a","type":"keyup"},{"tick":7392,"key":"left","type":"keydown"},{"tick":7392,"key":"right","type":"keyup"},{"tick":7416,"key":"a","type":"keydown"},{"tick":7458,"key":"a","type":"keyup"},{"tick":7488,"key":"right","type":"keydown"},{"tick":7488,"key":"left","type":"keyup"},{"tick":7536,"key":"a","type":"keydown"},{"tick":7602,"key":"a","type":"keyup"},{"tick":7696,"key":"a","type":"keydown"},{"tick":7744,"key":"a","type":"keyup"},{"tick":7796,"key":"right","type":"keyup"},{"tick":8102,"key":"right","type":"keydown"},{"tick":8366,"key":"a","type":"keydown"},{"tick":8380,"key":"a","type":"keyup"},{"tick":8440,"key":"right","type":"keyup"},{"tick":8798,"key":"right","type":"keydown"},{"tick":8816,"key":"a","type":"keydown"},{"tick":8828,"key":"a","type":"keyup"},{"tick":8858,"key":"right","type":"keyup"},{"tick":8958,"key":"right","type":"keydown"},{"tick":8972,"key":"a","type":"keydown"},{"tick":8982,"key":"a","type":"keyup"},{"tick":9016,"key":"right","type":"keyup"},{"tick":9020,"key":"right","type":"keydown"},{"tick":9034,"key":"a","type":"keydown"},{"tick":9046,"key":"a","type":"keyup"},{"tick":9078,"key":"right","type":"keyup"},{"tick":9102,"key":"right","type":"keydown"},{"tick":9114,"key":"right","type":"keyup"}]
--------------------------------------------------------------------------------
/test/system/input/level-quickman.json:
--------------------------------------------------------------------------------
1 | [{"tick":306,"key":"right","type":"keydown"},{"tick":380,"key":"right","type":"keyup"},{"tick":412,"key":"left","type":"keydown"},{"tick":442,"key":"left","type":"keyup"},{"tick":460,"key":"left","type":"keydown"},{"tick":582,"key":"left","type":"keyup"},{"tick":598,"key":"left","type":"keydown"},{"tick":656,"key":"left","type":"keyup"},{"tick":676,"key":"right","type":"keydown"},{"tick":906,"key":"right","type":"keyup"},{"tick":906,"key":"left","type":"keydown"},{"tick":1112,"key":"left","type":"keyup"},{"tick":1134,"key":"right","type":"keydown"},{"tick":1292,"key":"right","type":"keyup"},{"tick":1298,"key":"left","type":"keydown"},{"tick":1438,"key":"left","type":"keyup"},{"tick":1438,"key":"right","type":"keydown"},{"tick":1528,"key":"left","type":"keydown"},{"tick":1532,"key":"right","type":"keyup"},{"tick":1574,"key":"right","type":"keydown"},{"tick":1576,"key":"left","type":"keyup"},{"tick":1638,"key":"left","type":"keydown"},{"tick":1638,"key":"right","type":"keyup"},{"tick":1800,"key":"left","type":"keyup"},{"tick":1808,"key":"right","type":"keydown"},{"tick":1822,"key":"right","type":"keyup"},{"tick":1866,"key":"right","type":"keydown"},{"tick":2098,"key":"right","type":"keyup"},{"tick":2156,"key":"right","type":"keydown"},{"tick":2170,"key":"a","type":"keydown"},{"tick":2186,"key":"a","type":"keyup"},{"tick":2210,"key":"right","type":"keyup"},{"tick":2222,"key":"right","type":"keydown"},{"tick":2260,"key":"a","type":"keydown"},{"tick":2282,"key":"a","type":"keyup"},{"tick":2426,"key":"right","type":"keyup"},{"tick":2466,"key":"right","type":"keydown"},{"tick":2556,"key":"a","type":"keydown"},{"tick":2582,"key":"a","type":"keyup"},{"tick":2654,"key":"a","type":"keydown"},{"tick":2674,"key":"a","type":"keyup"},{"tick":2934,"key":"a","type":"keydown"},{"tick":2960,"key":"a","type":"keyup"},{"tick":3192,"key":"a","type":"keydown"},{"tick":3202,"key":"a","type":"keyup"},{"tick":3544,"key":"right","type":"keyup"},{"tick":3552,"key":"left","type":"keydown"},{"tick":3568,"key":"left","type":"keyup"},{"tick":3634,"key":"left","type":"keydown"},{"tick":3718,"key":"a","type":"keydown"},{"tick":3742,"key":"a","type":"keyup"},{"tick":3818,"key":"right","type":"keydown"},{"tick":3822,"key":"left","type":"keyup"},{"tick":3932,"key":"right","type":"keyup"},{"tick":3934,"key":"left","type":"keydown"},{"tick":4128,"key":"left","type":"keyup"},{"tick":4128,"key":"right","type":"keydown"},{"tick":4246,"key":"right","type":"keyup"},{"tick":4252,"key":"left","type":"keydown"},{"tick":4364,"key":"left","type":"keyup"},{"tick":4370,"key":"right","type":"keydown"},{"tick":4416,"key":"right","type":"keyup"},{"tick":4444,"key":"right","type":"keydown"},{"tick":4616,"key":"right","type":"keyup"},{"tick":4618,"key":"left","type":"keydown"},{"tick":4726,"key":"left","type":"keyup"},{"tick":4792,"key":"left","type":"keydown"},{"tick":4850,"key":"left","type":"keyup"},{"tick":4854,"key":"right","type":"keydown"},{"tick":4870,"key":"right","type":"keyup"},{"tick":4898,"key":"right","type":"keydown"},{"tick":4994,"key":"right","type":"keyup"},{"tick":5004,"key":"left","type":"keydown"},{"tick":5088,"key":"left","type":"keyup"},{"tick":5090,"key":"right","type":"keydown"},{"tick":5186,"key":"right","type":"keyup"},{"tick":5206,"key":"left","type":"keydown"},{"tick":5358,"key":"left","type":"keyup"},{"tick":5358,"key":"right","type":"keydown"},{"tick":5736,"key":"a","type":"keydown"},{"tick":5812,"key":"a","type":"keyup"},{"tick":5872,"key":"a","type":"keydown"},{"tick":5924,"key":"a","type":"keyup"},{"tick":5996,"key":"a","type":"keydown"},{"tick":6024,"key":"a","type":"keyup"},{"tick":6120,"key":"a","type":"keydown"},{"tick":6154,"key":"a","type":"keyup"},{"tick":6256,"key":"a","type":"keydown"},{"tick":6280,"key":"a","type":"keyup"},{"tick":6318,"key":"a","type":"keydown"},{"tick":6336,"key":"a","type":"keyup"},{"tick":6396,"key":"right","type":"keyup"},{"tick":6698,"key":"right","type":"keydown"},{"tick":6964,"key":"a","type":"keydown"},{"tick":6974,"key":"a","type":"keyup"},{"tick":7018,"key":"right","type":"keyup"},{"tick":7410,"key":"right","type":"keydown"},{"tick":7428,"key":"a","type":"keydown"},{"tick":7442,"key":"a","type":"keyup"},{"tick":7494,"key":"a","type":"keydown"},{"tick":7506,"key":"a","type":"keyup"},{"tick":7586,"key":"right","type":"keyup"}]
--------------------------------------------------------------------------------
/test/system/tests/game.js:
--------------------------------------------------------------------------------
1 | describe('Megaman 2', function() {
2 | describe.skip('when loading game XML', () => {
3 | let game, loader, entrypoint;
4 | before(done => {
5 | game = new Engine.Game;
6 | loader = new XMLLoader(game);
7 | loader.loadGame('/resource/Megaman2.xml').then(_entrypoint => {
8 | entrypoint = _entrypoint;
9 | done();
10 | });
11 | });
12 |
13 | it('entrypoint is Intro', () => {
14 | expect(entrypoint).to.be('Intro');
15 | });
16 |
17 | it('player has 28 health max', () => {
18 | expect(game.player.character.health.energy.max).to.be(28);
19 | });
20 |
21 | it('player has 0 health min', () => {
22 | expect(game.player.character.health.energy.min).to.be(0);
23 | });
24 |
25 | describe('Loader', () => {
26 | it('should load a scene by name', function(done) {
27 | const game = new Engine.Game;
28 | const loader = new XMLLoader(game);
29 | loader.loadGame('/dist/resource/Megaman2.xml')
30 | .then(() => {
31 | return loader.loadSceneByName('Intro');
32 | })
33 | .then(scene => {
34 | expect(scene.name).to.be('Intro');
35 | done();
36 | });
37 | });
38 | });
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/test/system/tests/intro.js:
--------------------------------------------------------------------------------
1 | describe('Intro', function() {
2 | before(function(done) {
3 | env.load('Intro').then(scene => {
4 | env.scene(scene);
5 | done();
6 | });
7 | });
8 |
9 | after(function() {
10 | env.game.unsetScene();
11 | });
12 |
13 | it('should have an invisible logo', function() {
14 | const logo = env.game.scene.world.getObject('logo');
15 | expect(logo.model.material.opacity).to.be(0);
16 | expect(logo.position.z).to.be(-800);
17 | });
18 |
19 | it('should have three invisible text layers', function() {
20 | const world = env.game.scene.world;
21 | const objects = [
22 | world.getObject('story1'),
23 | world.getObject('story2'),
24 | world.getObject('story3'),
25 | ];
26 |
27 | objects.forEach(o => {
28 | expect(o.model.material.opacity).to.be(0);
29 | });
30 |
31 | this.objects = objects;
32 | });
33 |
34 | it('layer 1 should be visible after 2.5 seconds', function(done) {
35 | env.goToTick(300).then(() => {
36 | expect(this.objects[0].model.material.opacity).to.be(1);
37 | expect(this.objects[1].model.material.opacity).to.be(0);
38 | done();
39 | });
40 | });
41 |
42 | it('layer 2 should be visible after 8 seconds', function(done) {
43 | env.goToTick(1260).then(() => {
44 | expect(this.objects[0].model.material.opacity).to.be(0);
45 | expect(this.objects[1].model.material.opacity).to.be(1);
46 | done();
47 | });
48 | });
49 |
50 | it('layer 3 should be visible after 8 seconds', function(done) {
51 | env.goToTick(2220).then(() => {
52 | expect(this.objects[1].model.material.opacity).to.be(0);
53 | expect(this.objects[2].model.material.opacity).to.be(1);
54 | done();
55 | });
56 | });
57 |
58 | it('layer 3 should be hidden after 5 seconds', function(done) {
59 | env.goToTick(2820).then(() => {
60 | expect(this.objects[2].model.material.opacity).to.be(0);
61 | done();
62 | });
63 | });
64 |
65 | it('camera should be scrolled after 12 seconds', function(done) {
66 | env.goToTick(4260).then(() => {
67 | expect(env.game.scene.camera.position.y).to.be.within(400, 500);
68 | done();
69 | });
70 | });
71 |
72 | it('camera should reach top of skyscraper', function(done) {
73 | env.goToTick(4500).then(() => {
74 | expect(env.game.scene.camera.position.y).to.be.within(570, 580);
75 | done();
76 | });
77 | });
78 |
79 | it('logo should still be invisible', function() {
80 | const logo = env.game.scene.world.getObject('logo');
81 | expect(logo.model.material.opacity).to.be(0);
82 | expect(logo.position.z).to.be(-800);
83 | });
84 |
85 | it('logotype should be revealed', function(done) {
86 | env.goToTick(4800).then(() => {
87 | const logo = env.game.scene.world.getObject('logo');
88 | expect(logo.model.material.opacity).to.be(1);
89 | expect(logo.position.z).to.be(0);
90 | done();
91 | });
92 | });
93 |
94 | it('should go to scene select when pressing start', function(done) {
95 | env.game.events.once(env.game.EVENT_SCENE_SET, scene => {
96 | done();
97 | });
98 | env.tap('start');
99 | });
100 | });
101 |
--------------------------------------------------------------------------------
/test/system/tests/level-1-airman.js:
--------------------------------------------------------------------------------
1 | describe('Airman Level', function() {
2 | context('StageSelect', function() {
3 | before(function(done) {
4 | env.load('StageSelect').then(scene => {
5 | env.scene(scene);
6 | done();
7 | });
8 | });
9 |
10 | after(function() {
11 | env.game.unsetScene();
12 | });
13 |
14 | it('starts Airman stage when pressing up + start', function(done) {
15 | let started = false;
16 | env.game.events.once(env.game.EVENT_SCENE_SET, scene => {
17 | expect(scene.name).to.be('Airman');
18 | started = true;
19 | });
20 | env.tap('up start');
21 | env.waitUntil(() => started).then(done);
22 | });
23 | });
24 |
25 | context('Level', function() {
26 | let player;
27 |
28 | before(function(done) {
29 | Promise.all([
30 | env.load('Airman'),
31 | ]).then(([scene]) => {
32 | env.scene(scene);
33 | player = env.game.player.character;
34 | done();
35 | });
36 | });
37 |
38 | after(function() {
39 | env.game.unsetScene();
40 | });
41 |
42 | describe('at start of stage', function() {
43 | it('player should be off screen', function() {
44 | expect(player.position)
45 | .to.eql({ x: 128, y: 80, z: 0});
46 | });
47 | });
48 |
49 | describe('after ready text', function() {
50 | before(() => env.goToTime(2.5));
51 |
52 | it('player should be at start position', function() {
53 | expect(player.position)
54 | .to.eql({x: 128, y: -120, z: 0});
55 | });
56 | });
57 | });
58 | });
59 |
--------------------------------------------------------------------------------
/test/system/tests/level-2-bubbleman.js:
--------------------------------------------------------------------------------
1 | describe('Bubbleman Level', function() {
2 | context('StageSelect', function() {
3 | before(function(done) {
4 | env.load('StageSelect').then(scene => {
5 | env.scene(scene);
6 | done();
7 | });
8 | });
9 |
10 | after(function() {
11 | env.game.unsetScene();
12 | });
13 |
14 | it('starts Bubbleman stage when pressing up + left + start', function(done) {
15 | let started = false;
16 | env.game.events.once(env.game.EVENT_SCENE_SET, scene => {
17 | expect(scene.name).to.be('Bubbleman');
18 | started = true;
19 | });
20 | env.tap('up left start');
21 | env.waitUntil(() => started).then(done);
22 | });
23 | });
24 |
25 | context('Level', function() {
26 | before(function(done) {
27 | Promise.all([
28 | env.load('Bubbleman'),
29 | env.loadInput('/test/system/input/level-bubbleman.json'),
30 | ]).then(([scene, log]) => {
31 | env.scene(scene);
32 | env.playInput(log);
33 | done();
34 | });
35 | });
36 |
37 | after(function() {
38 | env.game.unsetScene();
39 | });
40 |
41 | it('should hide player off screen on start', function() {
42 | expect(env.game.player.character.position.y)
43 | .to.be.above(env.game.scene.camera.position.y + 120);
44 | });
45 |
46 | it('should teleport player to first checkpoint', function(done) {
47 | env.goToTime(2.5).then(() => {
48 | expect(env.game.player.character.position)
49 | .to.eql({x: 128, y: -101, z: 0});
50 | done();
51 | });
52 | });
53 |
54 | it('should have blocks that are solid and can be jumped from', function(done) {
55 | env.goToTick(1221).then(() => {
56 | expect(env.game.player.character.position)
57 | .to.eql({x: 772.7280559184165, y: -54.61095471377428, z: 0});
58 | done();
59 | });
60 | });
61 |
62 | it('enables player to get to other side of falling blocks', function(done) {
63 | env.goToTick(1609).then(() => {
64 | expect(env.game.player.character.position)
65 | .to.eql({x: 1054.7769542709652, y: -69, z: 0});
66 | done();
67 | });
68 | });
69 |
70 | it('falling blocks should have fallen away', function() {
71 | const blocks = env.game.scene.world.getObjects('falling-block');
72 | expect(blocks[0].position.y).to.be.below(-1000);
73 | expect(blocks[4].position.y).to.be.below(-300);
74 | });
75 | });
76 | });
77 |
--------------------------------------------------------------------------------
/test/system/tests/level-3-crashman.js:
--------------------------------------------------------------------------------
1 | describe('Crashman Level', function() {
2 | context('StageSelect', function() {
3 | before(function(done) {
4 | env.load('StageSelect').then(scene => {
5 | env.scene(scene);
6 | done();
7 | });
8 | });
9 |
10 | after(function() {
11 | env.game.unsetScene();
12 | });
13 |
14 | it('starts Crashman stage when pressing down + right + start', function(done) {
15 | let started = false;
16 | env.game.events.once(env.game.EVENT_SCENE_SET, scene => {
17 | expect(scene.name).to.be('Crashman');
18 | started = true;
19 | });
20 | env.tap('down right start');
21 | env.waitUntil(() => started).then(done);
22 | });
23 | });
24 |
25 | context('Level', function() {
26 | let player;
27 |
28 | before(function(done) {
29 | Promise.all([
30 | env.load('Crashman'),
31 | env.loadInput('/test/system/input/level-crashman.json'),
32 | ]).then(([scene, log]) => {
33 | env.scene(scene);
34 | env.playInput(log);
35 | player = env.game.player.character;
36 | done();
37 | }).catch(done);
38 | });
39 |
40 | describe('at start of level', () => {
41 | it('player is off screen', function() {
42 | expect(player.position).to.eql({x: 128, y: 256, z: 0});
43 | });
44 |
45 | it('camera is at start of level', function() {
46 | expect(env.game.scene.camera.position)
47 | .to.eql({x: 128, y: 120, z: 150});
48 | });
49 | });
50 |
51 | describe('after 2.1 seconds', () => {
52 | before(done => {
53 | env.goToTime(2.2).then(done);
54 | });
55 |
56 | it('player teleport is active', () => {
57 | expect(player.teleport.state).to.be(player.teleport.STATE_GO);
58 | });
59 |
60 | it('player is teleporting down', () => {
61 | expect(player.position.y).to.be.within(218, 219);
62 | });
63 | });
64 |
65 | describe('after 2.5 seconds', () => {
66 | before(done => {
67 | env.goToTime(2.6).then(done);
68 | });
69 |
70 | it('player is on the ground', () => {
71 | expect(player.position).to.eql({x: 128, y: 59, z: 0});
72 | });
73 | });
74 |
75 | describe.skip('after 90 seconds', () => {
76 | before(done => {
77 | env.goToTime(90).then(done);
78 | });
79 |
80 | it('player has reached end', () => {
81 | const pos = env.game.player.character.position;
82 | expect(pos.x).to.be.within(1288, 1536);
83 | expect(pos.y).to.be.within(3392, 3528);
84 | });
85 | });
86 | });
87 | });
88 |
--------------------------------------------------------------------------------
/test/system/tests/level-4-flashman.js:
--------------------------------------------------------------------------------
1 | describe('Flashman Level', function() {
2 | context('StageSelect', function() {
3 | before(function(done) {
4 | env.load('StageSelect').then(scene => {
5 | env.scene(scene);
6 | done();
7 | });
8 | });
9 |
10 | after(function() {
11 | env.game.unsetScene();
12 | });
13 |
14 | it('starts Flashman stage when pressing down + start', function(done) {
15 | let started = false;
16 | env.game.events.once(env.game.EVENT_SCENE_SET, scene => {
17 | expect(scene.name).to.be('Flashman');
18 | started = true;
19 | });
20 | env.tap('down start');
21 | env.waitUntil(() => started).then(done);
22 | });
23 | });
24 |
25 | describe('Level', function() {
26 | before(function(done) {
27 | Promise.all([
28 | env.load('Flashman'),
29 | env.loadInput('/test/system/input/level-flashman.json'),
30 | ]).then(([scene, log]) => {
31 | env.scene(scene);
32 | env.playInput(log);
33 | done();
34 | }).catch(done);
35 | });
36 |
37 | after(function() {
38 | env.game.unsetScene();
39 | });
40 |
41 | describe('at start of stage', function() {
42 | it('player should be off screen', function() {
43 | expect(env.game.player.character.position)
44 | .to.eql({x: 136, y: 48, z: 0});
45 | });
46 | });
47 |
48 | describe('after ready text', function() {
49 | before(() => env.goToTime(2.5));
50 |
51 | it('player should be at start position', function() {
52 | expect(env.game.player.character.position)
53 | .to.eql({x: 136, y: -152, z: 0});
54 | });
55 | });
56 |
57 | describe.skip('after 78 seconds', function() {
58 | before(done => env.goToTime(80).then(done));
59 |
60 | it('player should reach a position', function() {
61 | const pos = env.game.player.character.position;
62 | expect(pos.x).to.be.within(3100, 3300);
63 | expect(pos.y).to.be.within(-1840, -1800);
64 | });
65 | });
66 | });
67 | });
68 |
--------------------------------------------------------------------------------
/test/system/tests/level-5-heatman.js:
--------------------------------------------------------------------------------
1 | describe('Heatman Level', function() {
2 | context('StageSelect', function() {
3 | before(function(done) {
4 | env.load('StageSelect').then(scene => {
5 | env.scene(scene);
6 | done();
7 | });
8 | });
9 |
10 | after(function() {
11 | env.game.unsetScene();
12 | });
13 |
14 | it('starts Heatman stage when pressing left + start', function(done) {
15 | let started = false;
16 | env.game.events.once(env.game.EVENT_SCENE_SET, scene => {
17 | expect(scene.name).to.be('Heatman');
18 | started = true;
19 | });
20 | env.tap('left start');
21 | env.waitUntil(() => started).then(done);
22 | });
23 | });
24 |
25 | context('Level', function() {
26 | let player;
27 |
28 | before(function(done) {
29 | Promise.all([
30 | env.load('Heatman'),
31 | ]).then(([scene]) => {
32 | env.scene(scene);
33 | player = env.game.player.character;
34 | done();
35 | });
36 | });
37 |
38 | after(function() {
39 | env.game.unsetScene();
40 | });
41 |
42 | describe('at start of level', () => {
43 | it('player is off screen', function() {
44 | expect(player.position).to.eql({x: 136, y: 35, z: 0});
45 | });
46 |
47 | it('camera is at start of level', function() {
48 | expect(env.game.scene.camera.position)
49 | .to.eql({x: 180, y: -120, z: 150});
50 | });
51 | });
52 |
53 | describe('after 2.2 seconds', () => {
54 | before(done => {
55 | env.goToTime(2.2).then(done);
56 | });
57 |
58 | it('player teleport is active', () => {
59 | expect(player.teleport.state).to.be(player.teleport.STATE_GO);
60 | });
61 |
62 | it('player is teleporting down', () => {
63 | expect(player.position.y).to.be.within(-3, -2);
64 | });
65 | });
66 |
67 | describe('after 2.6 seconds', () => {
68 | before(done => {
69 | env.goToTime(2.6).then(done);
70 | });
71 |
72 | it('player is on the ground', () => {
73 | expect(player.position)
74 | .to.eql({ x: 136, y: -165, z: 0 });
75 | });
76 | });
77 |
78 | describe('Level succession', function() {
79 | it.skip('disappearing blocks part 1 should be solvable', function() {
80 | });
81 |
82 | it.skip('disappearing blocks part 2 should be solvable', function() {
83 | });
84 | });
85 | });
86 | });
87 |
--------------------------------------------------------------------------------
/test/system/tests/level-6-metalman.js:
--------------------------------------------------------------------------------
1 | describe('Metalman Level', function() {
2 | context('StageSelect', function() {
3 | before(function(done) {
4 | env.load('StageSelect').then(scene => {
5 | env.scene(scene);
6 | done();
7 | });
8 | });
9 |
10 | after(function() {
11 | env.game.unsetScene();
12 | });
13 |
14 | it('starts Metalman stage when pressing down + left + start', function(done) {
15 | let started = false;
16 | env.game.events.once(env.game.EVENT_SCENE_SET, scene => {
17 | expect(scene.name).to.be('Metalman');
18 | started = true;
19 | });
20 | env.tap('down left start');
21 | env.waitUntil(() => started).then(done);
22 | });
23 | });
24 |
25 | context('Level', function() {
26 | let player;
27 |
28 | before(function(done) {
29 | Promise.all([
30 | env.load('Metalman'),
31 | ]).then(([scene]) => {
32 | env.scene(scene);
33 | player = env.game.player.character;
34 | done();
35 | });
36 | });
37 |
38 | after(function() {
39 | env.game.unsetScene();
40 | });
41 |
42 | describe('at start of stage', function() {
43 | it('player should be off screen', function() {
44 | expect(player.position)
45 | .to.eql({x: 128, y: 32, z: 0});
46 | });
47 | });
48 |
49 | describe('after ready text', function() {
50 | before(() => env.goToTime(2.5));
51 |
52 | it('player should be at start position', function() {
53 | expect(player.position)
54 | .to.eql({x: 128, y: -168, z: 0});
55 | });
56 | });
57 |
58 | describe.skip('one second after start', function() {
59 | before(done => env.waitTime(1).then(done));
60 |
61 | it('player should have been moved by conveyor', function() {
62 | expect(player.position)
63 | .to.eql({x: 128, y: -168, z: 0});
64 | });
65 | });
66 | });
67 | });
68 |
--------------------------------------------------------------------------------
/test/system/tests/level-7-quickman.js:
--------------------------------------------------------------------------------
1 | describe('Quickman Level', function() {
2 | this.timeout(120000);
3 |
4 | context('StageSelect', function() {
5 | before(function(done) {
6 | env.load('StageSelect').then(scene => {
7 | env.scene(scene);
8 | done();
9 | });
10 | });
11 |
12 | after(function() {
13 | env.game.unsetScene();
14 | });
15 |
16 | it('starts Quickman stage when pressing up + right + start', function(done) {
17 | let started = false;
18 | env.game.events.once(env.game.EVENT_SCENE_SET, scene => {
19 | expect(scene.name).to.be('Quickman');
20 | started = true;
21 | });
22 | env.tap('up right start');
23 | env.waitUntil(() => started).then(done);
24 | });
25 | });
26 |
27 | context('Level', function() {
28 | before(function(done) {
29 | Promise.all([
30 | env.load('Quickman'),
31 | env.loadInput('/test/system/input/level-quickman.json'),
32 | ]).then(([scene, log]) => {
33 | env.scene(scene);
34 | env.playInput(log);
35 | done();
36 | });
37 | });
38 |
39 | after(function() {
40 | env.game.unsetScene();
41 | });
42 |
43 | it('camera placed correctly', function() {
44 | expect(env.game.scene.camera.position)
45 | .to.eql({x: 128, y: -120, z: 150});
46 | });
47 |
48 | it('should hide player off screen on start', function() {
49 | expect(env.game.player.character.position)
50 | .to.eql({x: 128, y: 48, z: 0});
51 | });
52 |
53 | it('should teleport player to first checkpoint', function(done) {
54 | env.goToTime(2.5).then(() => {
55 | expect(env.game.player.character.position)
56 | .to.eql({x: 128, y: -152, z: 0});
57 | done();
58 | });
59 | });
60 |
61 | it('scene should go dark when entering dark area', function(done) {
62 | env.goToTime(19).then(() => {
63 | expect(env.game.scene.world.ambientLight.color)
64 | .to.eql({r: 0.1, g: 0.03, b: 0.03});
65 | done();
66 | });
67 | });
68 |
69 | it('scene should go light when exiting dark area', function(done) {
70 | env.goToTime(31).then(() => {
71 | expect(env.game.scene.world.ambientLight.color)
72 | .to.eql({r: 1, g: 1, b: 1});
73 | done();
74 | });
75 | });
76 |
77 | it('player should reach end', function(done) {
78 | env.goToTime(64).then(() => {
79 | const pos = env.game.player.character.position;
80 | expect(pos.x).to.be.within(2120, 2180);
81 | expect(pos.y).to.be.within(-3780, -3720);
82 | done();
83 | });
84 | });
85 | });
86 | });
87 |
--------------------------------------------------------------------------------
/test/system/tests/level-8-woodman.js:
--------------------------------------------------------------------------------
1 | describe('Woodman Level', function() {
2 | context('StageSelect', function() {
3 | before(function(done) {
4 | env.load('StageSelect').then(scene => {
5 | env.scene(scene);
6 | done();
7 | });
8 | });
9 |
10 | after(function() {
11 | env.game.unsetScene();
12 | });
13 |
14 | it('starts Woodman stage when pressing right + start', function(done) {
15 | let started = false;
16 | env.game.events.once(env.game.EVENT_SCENE_SET, scene => {
17 | expect(scene.name).to.be('Woodman');
18 | started = true;
19 | });
20 | env.tap('right start');
21 | env.waitUntil(() => started).then(done);
22 | });
23 | });
24 |
25 | context('Level', function() {
26 | let player;
27 |
28 | before(function(done) {
29 | Promise.all([
30 | env.load('Woodman'),
31 | ]).then(([scene]) => {
32 | env.scene(scene);
33 | player = env.game.player.character;
34 | done();
35 | });
36 | });
37 |
38 | after(function() {
39 | env.game.unsetScene();
40 | });
41 |
42 | describe('at start of stage', function() {
43 | it('player should be off screen', function() {
44 | expect(player.position)
45 | .to.eql({x: 128, y: 16, z: 0});
46 | });
47 | });
48 |
49 | describe('after ready text', function() {
50 | before(() => env.goToTime(2.5));
51 |
52 | it('player should be at start position', function() {
53 | expect(player.position)
54 | .to.eql({x: 128, y: -184, z: 0});
55 | });
56 | });
57 | });
58 | });
59 |
--------------------------------------------------------------------------------
/test/system/tests/level-9-drwily1.js:
--------------------------------------------------------------------------------
1 | describe('Dr Wily Level 1', function() {
2 | let player;
3 |
4 | context('Level', function() {
5 | before(function(done) {
6 | Promise.all([
7 | env.load('DrWily1'),
8 | ]).then(([scene]) => {
9 | env.scene(scene);
10 | player = env.game.player.character;
11 | done();
12 | });
13 | });
14 |
15 | after(function() {
16 | env.game.unsetScene();
17 | });
18 |
19 | after(function() {
20 | env.game.unsetScene();
21 | });
22 |
23 | describe('at start of stage', function() {
24 | it('player should be off screen', function() {
25 | expect(player.position)
26 | .to.eql({x: 128, y: 248, z: 0});
27 | });
28 |
29 | it('camera is at start of level', function() {
30 | expect(env.game.scene.camera.position)
31 | .to.eql({x: 128, y: 112, z: 150});
32 | });
33 | });
34 |
35 | describe('after ready text', function() {
36 | before(() => env.goToTime(2.5));
37 |
38 | it('player should be at start position', function() {
39 | expect(player.position)
40 | .to.eql({x: 128, y: 48, z: 0});
41 | });
42 | });
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/test/system/tests/stage-select.js:
--------------------------------------------------------------------------------
1 | describe('Stage Select', function() {
2 | let camera, scene;
3 |
4 | beforeEach(done => {
5 | env.load('StageSelect').then(_scene => {
6 | scene = _scene;
7 | env.scene(_scene);
8 | camera = env.game.scene.camera;
9 | done();
10 | });
11 | });
12 |
13 | afterEach(() => {
14 | env.game.unsetScene();
15 | });
16 |
17 | describe('At start', () => {
18 | it('is zoomed in', () => {
19 | expect(camera.position.z).to.be(40);
20 | });
21 |
22 | it('indicator is in center', () => {
23 | expect(scene.world.getObject('indicator').position).to.eql({
24 | x: 0,
25 | y: 8,
26 | z: 0.1
27 | });
28 | });
29 |
30 | describe('after 1 second', () => {
31 | beforeEach(() => env.waitTime(1));
32 |
33 | it('is zoomed out', () => {
34 | expect(camera.position.z).to.be(140);
35 | });
36 | });
37 | });
38 |
39 | describe('Indicator', () => {
40 | it('has blink trait', () => {
41 | const indicator = scene.world.getObject('indicator');
42 | expect(indicator.blink.interval).to.be(0.25);
43 | });
44 | });
45 |
46 | const bosses = [
47 | {
48 | keys: 'up',
49 | name: 'Airman',
50 | },
51 | {
52 | keys: 'down',
53 | name: 'Flashman',
54 | },
55 | {
56 | keys: 'left',
57 | name: 'Heatman',
58 | },
59 | {
60 | keys: 'down left',
61 | name: 'Metalman',
62 | },
63 | ];
64 |
65 | bosses.forEach(boss => {
66 | describe(`when pressing ${boss.keys} and start`, () => {
67 | let spy = sinon.spy();
68 | beforeEach(() => {
69 | const scene = env.game.scene;
70 | scene.events.once('stage-selected', spy);
71 | env.tap(boss.keys);
72 | env.tap('start');
73 | });
74 |
75 | it(`selects ${boss.name} stage`, () => {
76 | expect(spy.callCount).to.be(1);
77 | const stage = spy.lastCall.args[0];
78 | expect(stage.scene).to.be(boss.name);
79 | });
80 |
81 | describe('immediately after', () => {
82 | beforeEach(() => env.waitTime(0.1));
83 |
84 | it('removes indicator', () => {
85 | expect(scene.world.getObject('indicator')).to.be(false);
86 | });
87 | });
88 |
89 | describe('after 2.5 seconds', () => {
90 | beforeEach(() => env.waitTime(2.5));
91 |
92 | it('camera has moved to reveal boss', () => {
93 | expect(env.game.scene.camera.position).to.eql({
94 | x: 0,
95 | y: 512,
96 | z: 140,
97 | });
98 | });
99 |
100 | it.skip('stars are behind podium');
101 |
102 | it(`${boss.name} has been spawned in scene`, () => {
103 | const Boss = env.loader.resourceManager.get('entity', boss.name);
104 | const instance = env.game.scene.world.getObjects(boss.name)[0];
105 | expect(instance).to.be.a(Boss);
106 | expect(instance.position.x).to.be(0);
107 | expect(instance.position.y).to.be.within(516, 518);
108 | });
109 |
110 | describe('after 5 seconds', () => {
111 | let spy;
112 |
113 | beforeEach(done => {
114 | spy = sinon.spy();
115 | env.game.events.once(env.game.EVENT_SCENE_SET, spy);
116 | env.waitUntil(() => spy.called).then(done);
117 | });
118 |
119 | it(`has loaded ${boss.name} level`, () => {
120 | expect(spy.callCount).to.be(1);
121 | expect(spy.lastCall.args[0].name).to.be(boss.name);
122 | });
123 | });
124 | });
125 | });
126 | });
127 | });
128 |
--------------------------------------------------------------------------------
/test/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack');
3 |
4 | function resolve(...args) {
5 | return path.resolve(__dirname, ...args);
6 | }
7 |
8 | const config = {
9 | entry: {
10 | 'browser-env': resolve('browser-env.js'),
11 | },
12 | output: {
13 | path: resolve('.'),
14 | filename: 'browser-test-build.js',
15 | },
16 | module: {
17 | rules: [
18 | {
19 | test: /\.js$/,
20 | include: [
21 | resolve('../src'),
22 | ],
23 | use: {
24 | loader: 'babel-loader',
25 | options: {
26 | presets: ['env'],
27 | /*plugins: [
28 | require('transform-runtime'),
29 | require('transform-class-properties'),
30 | ],*/
31 | },
32 | },
33 | },
34 | ],
35 | },
36 | };
37 |
38 | module.exports = config;
39 |
--------------------------------------------------------------------------------