├── static
├── favicon.ico
├── phase00
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ ├── bullet.png
│ │ ├── earth.png
│ │ ├── sentry.png
│ │ ├── explosion.png
│ │ └── alien-explosion.png
│ ├── audio
│ │ ├── bullet.mp3
│ │ ├── alien_boom.mp3
│ │ └── bullet_boom.mp3
│ ├── swf
│ │ ├── soundmanager2_flash9.swf
│ │ └── soundmanager2_flash9_debug.swf
│ ├── manifest.appcache
│ ├── index.html
│ └── scripts
│ │ └── stats.js
├── phase01
│ ├── favicon.ico
│ └── index.html
├── phase02
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ ├── bullet.png
│ │ ├── earth.png
│ │ ├── sentry.png
│ │ ├── explosion.png
│ │ └── alien-explosion.png
│ ├── index.html
│ └── scripts
│ │ └── app.js
├── phase03
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ └── earth.png
│ ├── index.html
│ └── scripts
│ │ └── app.js
├── phase04
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ └── earth.png
│ ├── index.html
│ └── scripts
│ │ └── app.js
├── phase05
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ └── earth.png
│ ├── index.html
│ └── scripts
│ │ └── app.js
├── phase06
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ └── earth.png
│ ├── index.html
│ └── scripts
│ │ └── app.js
├── phase07
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ ├── bullet.png
│ │ ├── earth.png
│ │ ├── sentry.png
│ │ ├── explosion.png
│ │ └── alien-explosion.png
│ ├── index.html
│ └── scripts
│ │ └── app.js
├── phase08
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ ├── bullet.png
│ │ ├── earth.png
│ │ ├── sentry.png
│ │ └── bullet-single.png
│ ├── index.html
│ └── scripts
│ │ └── app.js
├── phase09
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ ├── bullet.png
│ │ ├── earth.png
│ │ ├── sentry.png
│ │ └── explosion.png
│ ├── index.html
│ └── scripts
│ │ └── app.js
├── phase10
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ ├── bullet.png
│ │ ├── earth.png
│ │ ├── sentry.png
│ │ └── explosion.png
│ ├── audio
│ │ ├── bullet.mp3
│ │ ├── alien_boom.mp3
│ │ └── bullet_boom.mp3
│ ├── swf
│ │ ├── soundmanager2_flash9.swf
│ │ └── soundmanager2_flash9_debug.swf
│ ├── index.html
│ └── scripts
│ │ ├── stats.js
│ │ └── app.js
├── phase11
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ ├── bullet.png
│ │ ├── earth.png
│ │ ├── sentry.png
│ │ ├── explosion.png
│ │ └── alien-explosion.png
│ ├── audio
│ │ ├── bullet.mp3
│ │ ├── alien_boom.mp3
│ │ └── bullet_boom.mp3
│ ├── swf
│ │ ├── soundmanager2_flash9.swf
│ │ └── soundmanager2_flash9_debug.swf
│ ├── index.html
│ └── scripts
│ │ └── app.js
├── phase12
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ ├── bullet.png
│ │ ├── earth.png
│ │ ├── sentry.png
│ │ ├── explosion.png
│ │ └── alien-explosion.png
│ ├── audio
│ │ ├── bullet.mp3
│ │ ├── alien_boom.mp3
│ │ └── bullet_boom.mp3
│ ├── swf
│ │ ├── soundmanager2_flash9.swf
│ │ └── soundmanager2_flash9_debug.swf
│ ├── index.html
│ └── scripts
│ │ └── app.js
├── phase13
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ ├── bullet.png
│ │ ├── earth.png
│ │ ├── sentry.png
│ │ ├── explosion.png
│ │ └── alien-explosion.png
│ ├── audio
│ │ ├── bullet.mp3
│ │ ├── alien_boom.mp3
│ │ └── bullet_boom.mp3
│ ├── swf
│ │ ├── soundmanager2_flash9.swf
│ │ └── soundmanager2_flash9_debug.swf
│ ├── index.html
│ └── scripts
│ │ ├── stats.js
│ │ └── app.js
├── phase14
│ ├── favicon.ico
│ ├── img
│ │ ├── alien.png
│ │ ├── bullet.png
│ │ ├── earth.png
│ │ ├── sentry.png
│ │ ├── explosion.png
│ │ └── alien-explosion.png
│ ├── audio
│ │ ├── bullet.mp3
│ │ ├── alien_boom.mp3
│ │ └── bullet_boom.mp3
│ ├── swf
│ │ ├── soundmanager2_flash9.swf
│ │ └── soundmanager2_flash9_debug.swf
│ ├── manifest.appcache
│ ├── index.html
│ └── scripts
│ │ └── stats.js
├── .gitignore
├── img
│ ├── alien.png
│ ├── bullet.png
│ ├── earth.png
│ ├── sentry.png
│ ├── explosion.png
│ └── alien-explosion.png
├── audio
│ ├── bullet.mp3
│ ├── alien_boom.mp3
│ └── bullet_boom.mp3
├── swf
│ ├── soundmanager2_flash9.swf
│ └── soundmanager2_flash9_debug.swf
├── manifest.appcache
├── index.html
└── scripts
│ └── stats.js
├── .gitignore
├── TODO
├── app.yaml
├── index.yaml
├── README
└── LICENSE
/static/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
--------------------------------------------------------------------------------
/static/phase00/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase01/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase02/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase03/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase04/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase05/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase06/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase07/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase08/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase09/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase10/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase11/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase12/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase13/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/phase14/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
--------------------------------------------------------------------------------
/static/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/img/alien.png
--------------------------------------------------------------------------------
/static/img/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/img/bullet.png
--------------------------------------------------------------------------------
/static/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/img/earth.png
--------------------------------------------------------------------------------
/static/img/sentry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/img/sentry.png
--------------------------------------------------------------------------------
/static/audio/bullet.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/audio/bullet.mp3
--------------------------------------------------------------------------------
/static/img/explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/img/explosion.png
--------------------------------------------------------------------------------
/static/audio/alien_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/audio/alien_boom.mp3
--------------------------------------------------------------------------------
/static/audio/bullet_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/audio/bullet_boom.mp3
--------------------------------------------------------------------------------
/static/phase00/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase00/img/alien.png
--------------------------------------------------------------------------------
/static/phase00/img/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase00/img/bullet.png
--------------------------------------------------------------------------------
/static/phase00/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase00/img/earth.png
--------------------------------------------------------------------------------
/static/phase00/img/sentry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase00/img/sentry.png
--------------------------------------------------------------------------------
/static/phase02/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase02/img/alien.png
--------------------------------------------------------------------------------
/static/phase02/img/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase02/img/bullet.png
--------------------------------------------------------------------------------
/static/phase02/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase02/img/earth.png
--------------------------------------------------------------------------------
/static/phase02/img/sentry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase02/img/sentry.png
--------------------------------------------------------------------------------
/static/phase03/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase03/img/alien.png
--------------------------------------------------------------------------------
/static/phase03/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase03/img/earth.png
--------------------------------------------------------------------------------
/static/phase04/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase04/img/alien.png
--------------------------------------------------------------------------------
/static/phase04/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase04/img/earth.png
--------------------------------------------------------------------------------
/static/phase05/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase05/img/alien.png
--------------------------------------------------------------------------------
/static/phase05/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase05/img/earth.png
--------------------------------------------------------------------------------
/static/phase06/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase06/img/alien.png
--------------------------------------------------------------------------------
/static/phase06/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase06/img/earth.png
--------------------------------------------------------------------------------
/static/phase07/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase07/img/alien.png
--------------------------------------------------------------------------------
/static/phase07/img/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase07/img/bullet.png
--------------------------------------------------------------------------------
/static/phase07/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase07/img/earth.png
--------------------------------------------------------------------------------
/static/phase07/img/sentry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase07/img/sentry.png
--------------------------------------------------------------------------------
/static/phase08/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase08/img/alien.png
--------------------------------------------------------------------------------
/static/phase08/img/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase08/img/bullet.png
--------------------------------------------------------------------------------
/static/phase08/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase08/img/earth.png
--------------------------------------------------------------------------------
/static/phase08/img/sentry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase08/img/sentry.png
--------------------------------------------------------------------------------
/static/phase09/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase09/img/alien.png
--------------------------------------------------------------------------------
/static/phase09/img/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase09/img/bullet.png
--------------------------------------------------------------------------------
/static/phase09/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase09/img/earth.png
--------------------------------------------------------------------------------
/static/phase09/img/sentry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase09/img/sentry.png
--------------------------------------------------------------------------------
/static/phase10/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase10/img/alien.png
--------------------------------------------------------------------------------
/static/phase10/img/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase10/img/bullet.png
--------------------------------------------------------------------------------
/static/phase10/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase10/img/earth.png
--------------------------------------------------------------------------------
/static/phase10/img/sentry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase10/img/sentry.png
--------------------------------------------------------------------------------
/static/phase11/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase11/img/alien.png
--------------------------------------------------------------------------------
/static/phase11/img/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase11/img/bullet.png
--------------------------------------------------------------------------------
/static/phase11/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase11/img/earth.png
--------------------------------------------------------------------------------
/static/phase11/img/sentry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase11/img/sentry.png
--------------------------------------------------------------------------------
/static/phase12/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase12/img/alien.png
--------------------------------------------------------------------------------
/static/phase12/img/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase12/img/bullet.png
--------------------------------------------------------------------------------
/static/phase12/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase12/img/earth.png
--------------------------------------------------------------------------------
/static/phase12/img/sentry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase12/img/sentry.png
--------------------------------------------------------------------------------
/static/phase13/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase13/img/alien.png
--------------------------------------------------------------------------------
/static/phase13/img/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase13/img/bullet.png
--------------------------------------------------------------------------------
/static/phase13/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase13/img/earth.png
--------------------------------------------------------------------------------
/static/phase13/img/sentry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase13/img/sentry.png
--------------------------------------------------------------------------------
/static/phase14/img/alien.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase14/img/alien.png
--------------------------------------------------------------------------------
/static/phase14/img/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase14/img/bullet.png
--------------------------------------------------------------------------------
/static/phase14/img/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase14/img/earth.png
--------------------------------------------------------------------------------
/static/phase14/img/sentry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase14/img/sentry.png
--------------------------------------------------------------------------------
/static/img/alien-explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/img/alien-explosion.png
--------------------------------------------------------------------------------
/static/phase00/audio/bullet.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase00/audio/bullet.mp3
--------------------------------------------------------------------------------
/static/phase10/audio/bullet.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase10/audio/bullet.mp3
--------------------------------------------------------------------------------
/static/phase11/audio/bullet.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase11/audio/bullet.mp3
--------------------------------------------------------------------------------
/static/phase12/audio/bullet.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase12/audio/bullet.mp3
--------------------------------------------------------------------------------
/static/phase13/audio/bullet.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase13/audio/bullet.mp3
--------------------------------------------------------------------------------
/static/phase14/audio/bullet.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase14/audio/bullet.mp3
--------------------------------------------------------------------------------
/static/phase00/img/explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase00/img/explosion.png
--------------------------------------------------------------------------------
/static/phase02/img/explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase02/img/explosion.png
--------------------------------------------------------------------------------
/static/phase07/img/explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase07/img/explosion.png
--------------------------------------------------------------------------------
/static/phase09/img/explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase09/img/explosion.png
--------------------------------------------------------------------------------
/static/phase10/img/explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase10/img/explosion.png
--------------------------------------------------------------------------------
/static/phase11/img/explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase11/img/explosion.png
--------------------------------------------------------------------------------
/static/phase12/img/explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase12/img/explosion.png
--------------------------------------------------------------------------------
/static/phase13/img/explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase13/img/explosion.png
--------------------------------------------------------------------------------
/static/phase14/img/explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase14/img/explosion.png
--------------------------------------------------------------------------------
/static/phase00/audio/alien_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase00/audio/alien_boom.mp3
--------------------------------------------------------------------------------
/static/phase00/audio/bullet_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase00/audio/bullet_boom.mp3
--------------------------------------------------------------------------------
/static/phase08/img/bullet-single.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase08/img/bullet-single.png
--------------------------------------------------------------------------------
/static/phase10/audio/alien_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase10/audio/alien_boom.mp3
--------------------------------------------------------------------------------
/static/phase10/audio/bullet_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase10/audio/bullet_boom.mp3
--------------------------------------------------------------------------------
/static/phase11/audio/alien_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase11/audio/alien_boom.mp3
--------------------------------------------------------------------------------
/static/phase11/audio/bullet_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase11/audio/bullet_boom.mp3
--------------------------------------------------------------------------------
/static/phase12/audio/alien_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase12/audio/alien_boom.mp3
--------------------------------------------------------------------------------
/static/phase12/audio/bullet_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase12/audio/bullet_boom.mp3
--------------------------------------------------------------------------------
/static/phase13/audio/alien_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase13/audio/alien_boom.mp3
--------------------------------------------------------------------------------
/static/phase13/audio/bullet_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase13/audio/bullet_boom.mp3
--------------------------------------------------------------------------------
/static/phase14/audio/alien_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase14/audio/alien_boom.mp3
--------------------------------------------------------------------------------
/static/phase14/audio/bullet_boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase14/audio/bullet_boom.mp3
--------------------------------------------------------------------------------
/static/swf/soundmanager2_flash9.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/swf/soundmanager2_flash9.swf
--------------------------------------------------------------------------------
/static/phase00/img/alien-explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase00/img/alien-explosion.png
--------------------------------------------------------------------------------
/static/phase02/img/alien-explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase02/img/alien-explosion.png
--------------------------------------------------------------------------------
/static/phase07/img/alien-explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase07/img/alien-explosion.png
--------------------------------------------------------------------------------
/static/phase11/img/alien-explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase11/img/alien-explosion.png
--------------------------------------------------------------------------------
/static/phase12/img/alien-explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase12/img/alien-explosion.png
--------------------------------------------------------------------------------
/static/phase13/img/alien-explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase13/img/alien-explosion.png
--------------------------------------------------------------------------------
/static/phase14/img/alien-explosion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase14/img/alien-explosion.png
--------------------------------------------------------------------------------
/static/swf/soundmanager2_flash9_debug.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/swf/soundmanager2_flash9_debug.swf
--------------------------------------------------------------------------------
/static/phase00/swf/soundmanager2_flash9.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase00/swf/soundmanager2_flash9.swf
--------------------------------------------------------------------------------
/static/phase10/swf/soundmanager2_flash9.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase10/swf/soundmanager2_flash9.swf
--------------------------------------------------------------------------------
/static/phase11/swf/soundmanager2_flash9.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase11/swf/soundmanager2_flash9.swf
--------------------------------------------------------------------------------
/static/phase12/swf/soundmanager2_flash9.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase12/swf/soundmanager2_flash9.swf
--------------------------------------------------------------------------------
/static/phase13/swf/soundmanager2_flash9.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase13/swf/soundmanager2_flash9.swf
--------------------------------------------------------------------------------
/static/phase14/swf/soundmanager2_flash9.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase14/swf/soundmanager2_flash9.swf
--------------------------------------------------------------------------------
/static/phase00/swf/soundmanager2_flash9_debug.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase00/swf/soundmanager2_flash9_debug.swf
--------------------------------------------------------------------------------
/static/phase10/swf/soundmanager2_flash9_debug.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase10/swf/soundmanager2_flash9_debug.swf
--------------------------------------------------------------------------------
/static/phase11/swf/soundmanager2_flash9_debug.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase11/swf/soundmanager2_flash9_debug.swf
--------------------------------------------------------------------------------
/static/phase12/swf/soundmanager2_flash9_debug.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase12/swf/soundmanager2_flash9_debug.swf
--------------------------------------------------------------------------------
/static/phase13/swf/soundmanager2_flash9_debug.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase13/swf/soundmanager2_flash9_debug.swf
--------------------------------------------------------------------------------
/static/phase14/swf/soundmanager2_flash9_debug.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sethladd/Bad-Aliens/HEAD/static/phase14/swf/soundmanager2_flash9_debug.swf
--------------------------------------------------------------------------------
/static/phase01/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/static/phase02/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/static/phase03/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/static/phase04/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/static/phase05/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/static/phase06/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/static/phase07/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/static/phase08/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/static/phase09/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/TODO:
--------------------------------------------------------------------------------
1 | * Finish refactoring into screens
2 | * Game Over Screen
3 | * Refactor entities from Game Engine over to EntitiesScreen
4 | * Record high scores
5 | * Display high scores on Game Over screen
6 | * Display "Play Again?" on Game Over screen, handle button clicks for Yes or No
7 | * Create New Game screen
8 | * Display "start" on New Game screen
9 | * Display high scores on New Game screen
10 | * Refactor into multiple files
--------------------------------------------------------------------------------
/app.yaml:
--------------------------------------------------------------------------------
1 | application: bad-aliens
2 | version: 1
3 | runtime: python
4 | api_version: 1
5 |
6 | #default_expiration: "30d"
7 |
8 | handlers:
9 |
10 | - url: /(.*\.appcache)
11 | static_files: static/\1
12 | mime_type: text/cache-manifest
13 | upload: static/(.*\.appcache)
14 |
15 | - url: (.*)/
16 | static_files: static\1/index.html
17 | upload: static/index.html
18 |
19 | - url: /
20 | static_dir: static
21 |
22 |
--------------------------------------------------------------------------------
/static/manifest.appcache:
--------------------------------------------------------------------------------
1 | CACHE MANIFEST
2 |
3 | # version 16
4 |
5 | CACHE:
6 | scripts/app.js
7 | scripts/soundmanager2-nodebug-jsmin.js
8 | scripts/stats.js
9 |
10 | swf/soundmanager2_flash9.swf
11 |
12 | audio/alien_boom.mp3
13 | audio/bullet.mp3
14 | audio/bullet_boom.mp3
15 |
16 | img/alien-explosion.png
17 | img/alien.png
18 | img/bullet.png
19 | img/earth.png
20 | img/explosion.png
21 | img/sentry.png
22 |
23 | favicon.ico
24 | index.html
--------------------------------------------------------------------------------
/static/phase00/manifest.appcache:
--------------------------------------------------------------------------------
1 | CACHE MANIFEST
2 |
3 | # version 5
4 |
5 | CACHE:
6 | scripts/app.js
7 | scripts/soundmanager2-nodebug-jsmin.js
8 | scripts/stats.js
9 |
10 | swf/soundmanager2_flash9.swf
11 |
12 | audio/alien_boom.mp3
13 | audio/bullet.mp3
14 | audio/bullet_boom.mp3
15 |
16 | img/alien-explosion.png
17 | img/alien.png
18 | img/bullet.png
19 | img/earth.png
20 | img/explosion.png
21 | img/sentry.png
22 |
23 | favicon.ico
24 | index.html
--------------------------------------------------------------------------------
/static/phase14/manifest.appcache:
--------------------------------------------------------------------------------
1 | CACHE MANIFEST
2 |
3 | # version 5
4 |
5 | CACHE:
6 | scripts/app.js
7 | scripts/soundmanager2-nodebug-jsmin.js
8 | scripts/stats.js
9 |
10 | swf/soundmanager2_flash9.swf
11 |
12 | audio/alien_boom.mp3
13 | audio/bullet.mp3
14 | audio/bullet_boom.mp3
15 |
16 | img/alien-explosion.png
17 | img/alien.png
18 | img/bullet.png
19 | img/earth.png
20 | img/explosion.png
21 | img/sentry.png
22 |
23 | favicon.ico
24 | index.html
--------------------------------------------------------------------------------
/static/phase10/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/static/phase11/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/static/phase12/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/index.yaml:
--------------------------------------------------------------------------------
1 | indexes:
2 |
3 | # AUTOGENERATED
4 |
5 | # This index.yaml is automatically updated whenever the dev_appserver
6 | # detects that a new type of query is run. If you want to manage the
7 | # index.yaml file manually, remove the above marker line (the line
8 | # saying "# AUTOGENERATED"). If you want to manage some indexes
9 | # manually, move them above the marker line. The index.yaml file is
10 | # automatically uploaded to the admin console when you next deploy
11 | # your application using appcfg.py.
12 |
--------------------------------------------------------------------------------
/static/phase13/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | WARNING: THIS GAME IS DEPRECATED.
2 |
3 | This code is no longer maintained. Certain aspects of it (like, using SoundManager2) are no longer
4 | the right way to do it. This code is left here for posterity only.
5 |
6 | Example HTML5 Game for Google IO Presentation.
7 |
8 | # Credits
9 |
10 | Images:
11 | * http://www.lostgarden.com/2005/03/download-complete-set-of-sweet-8-bit.html
12 |
13 | Sounds:
14 | * http://www.freesound.org/samplesViewSingle.php?id=18397
15 | * http://www.freesound.org/samplesViewSingle.php?id=47252
16 | * http://www.freesound.org/samplesViewSingle.php?id=35643
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2011 Seth Ladd
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/static/phase00/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/static/phase14/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bad Aliens
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/static/phase02/scripts/app.js:
--------------------------------------------------------------------------------
1 | function AssetManager() {
2 | this.successCount = 0;
3 | this.errorCount = 0;
4 | this.cache = {};
5 | this.downloadQueue = [];
6 | }
7 |
8 | AssetManager.prototype.queueDownload = function(path) {
9 | this.downloadQueue.push(path);
10 | }
11 |
12 | AssetManager.prototype.downloadAll = function(callback) {
13 | if (this.downloadQueue.length === 0 && this.soundsQueue.length === 0) {
14 | callback();
15 | }
16 |
17 | for (var i = 0; i < this.downloadQueue.length; i++) {
18 | var path = this.downloadQueue[i];
19 | var img = new Image();
20 | var that = this;
21 | img.addEventListener("load", function() {
22 | console.log(this.src + ' is loaded');
23 | that.successCount += 1;
24 | if (that.isDone()) {
25 | callback();
26 | }
27 | }, false);
28 | img.addEventListener("error", function() {
29 | that.errorCount += 1;
30 | if (that.isDone()) {
31 | callback();
32 | }
33 | }, false);
34 | img.src = path;
35 | this.cache[path] = img;
36 | }
37 | }
38 |
39 | AssetManager.prototype.getAsset = function(path) {
40 | return this.cache[path];
41 | }
42 |
43 | AssetManager.prototype.isDone = function() {
44 | return (this.downloadQueue.length == this.successCount + this.errorCount);
45 | }
46 |
47 | var canvas = document.getElementById('surface');
48 | var ctx = canvas.getContext('2d');
49 | var ASSET_MANAGER = new AssetManager();
50 |
51 | ASSET_MANAGER.queueDownload('img/earth.png');
52 |
53 | ASSET_MANAGER.downloadAll(function() {
54 | var x = 0, y = 0;
55 | var sprite = ASSET_MANAGER.getAsset('img/earth.png');
56 | ctx.save();
57 | ctx.translate(canvas.width/2, canvas.height/2);
58 | ctx.drawImage(sprite, x - sprite.width/2, y - sprite.height/2);
59 | ctx.restore();
60 | });
--------------------------------------------------------------------------------
/static/scripts/stats.js:
--------------------------------------------------------------------------------
1 | // stats.js r5 - http://github.com/mrdoob/stats.js
2 | var Stats=function(){function w(d,K,n){var u,f,c;for(f=0;f<30;f++)for(u=0;u<73;u++){c=(u+f*74)*4;d[c]=d[c+4];d[c+1]=d[c+5];d[c+2]=d[c+6]}for(f=0;f<30;f++){c=(73+f*74)*4;if(fFPS';m.appendChild(g);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";m.appendChild(a);
5 | p=a.getContext("2d");p.fillStyle="rgb("+b.fps.bg.r+","+b.fps.bg.g+","+b.fps.bg.b+")";p.fillRect(0,0,a.width,a.height);C=p.getImageData(0,0,a.width,a.height);h=document.createElement("div");h.style.backgroundColor="rgb("+Math.floor(b.ms.bg.r/2)+","+Math.floor(b.ms.bg.g/2)+","+Math.floor(b.ms.bg.b/2)+")";h.style.padding="2px 0px 3px 0px";h.style.display="none";e.appendChild(h);i=document.createElement("div");i.style.fontFamily="Helvetica, Arial, sans-serif";i.style.textAlign="left";i.style.fontSize=
6 | "9px";i.style.color="rgb("+b.ms.fg.r+","+b.ms.fg.g+","+b.ms.fg.b+")";i.style.margin="0px 0px 1px 3px";i.innerHTML='MS';h.appendChild(i);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";h.appendChild(a);r=a.getContext("2d");r.fillStyle="rgb("+b.ms.bg.r+","+b.ms.bg.g+","+b.ms.bg.b+")";r.fillRect(0,0,a.width,a.height);F=r.getImageData(0,0,a.width,a.height);try{if(webkitPerformance&&webkitPerformance.memory.totalJSHeapSize)x=
7 | 3}catch(L){}j=document.createElement("div");j.style.backgroundColor="rgb("+Math.floor(b.mem.bg.r/2)+","+Math.floor(b.mem.bg.g/2)+","+Math.floor(b.mem.bg.b/2)+")";j.style.padding="2px 0px 3px 0px";j.style.display="none";e.appendChild(j);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.textAlign="left";k.style.fontSize="9px";k.style.color="rgb("+b.mem.fg.r+","+b.mem.fg.g+","+b.mem.fg.b+")";k.style.margin="0px 0px 1px 3px";k.innerHTML='MEM';
8 | j.appendChild(k);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";j.appendChild(a);t=a.getContext("2d");t.fillStyle="#301010";t.fillRect(0,0,a.width,a.height);I=t.getImageData(0,0,a.width,a.height);return{domElement:e,update:function(){y++;l=(new Date).getTime();q=l-J;D=Math.min(D,q);E=Math.max(E,q);w(F.data,Math.min(30,30-q/200*30),"ms");i.innerHTML=''+q+" MS ("+D+"-"+E+")";r.putImageData(F,0,0);J=l;if(l>
9 | z+1E3){o=Math.round(y*1E3/(l-z));A=Math.min(A,o);B=Math.max(B,o);w(C.data,Math.min(30,30-o/100*30),"fps");g.innerHTML=''+o+" FPS ("+A+"-"+B+")";p.putImageData(C,0,0);if(x==3){s=webkitPerformance.memory.usedJSHeapSize*9.54E-7;G=Math.min(G,s);H=Math.max(H,s);w(I.data,Math.min(30,30-s/2),"mem");k.innerHTML=''+Math.round(s)+" MEM ("+Math.round(G)+"-"+Math.round(H)+")";t.putImageData(I,0,0)}z=l;y=0}}}};
10 |
--------------------------------------------------------------------------------
/static/phase00/scripts/stats.js:
--------------------------------------------------------------------------------
1 | // stats.js r5 - http://github.com/mrdoob/stats.js
2 | var Stats=function(){function w(d,K,n){var u,f,c;for(f=0;f<30;f++)for(u=0;u<73;u++){c=(u+f*74)*4;d[c]=d[c+4];d[c+1]=d[c+5];d[c+2]=d[c+6]}for(f=0;f<30;f++){c=(73+f*74)*4;if(fFPS';m.appendChild(g);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";m.appendChild(a);
5 | p=a.getContext("2d");p.fillStyle="rgb("+b.fps.bg.r+","+b.fps.bg.g+","+b.fps.bg.b+")";p.fillRect(0,0,a.width,a.height);C=p.getImageData(0,0,a.width,a.height);h=document.createElement("div");h.style.backgroundColor="rgb("+Math.floor(b.ms.bg.r/2)+","+Math.floor(b.ms.bg.g/2)+","+Math.floor(b.ms.bg.b/2)+")";h.style.padding="2px 0px 3px 0px";h.style.display="none";e.appendChild(h);i=document.createElement("div");i.style.fontFamily="Helvetica, Arial, sans-serif";i.style.textAlign="left";i.style.fontSize=
6 | "9px";i.style.color="rgb("+b.ms.fg.r+","+b.ms.fg.g+","+b.ms.fg.b+")";i.style.margin="0px 0px 1px 3px";i.innerHTML='MS';h.appendChild(i);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";h.appendChild(a);r=a.getContext("2d");r.fillStyle="rgb("+b.ms.bg.r+","+b.ms.bg.g+","+b.ms.bg.b+")";r.fillRect(0,0,a.width,a.height);F=r.getImageData(0,0,a.width,a.height);try{if(webkitPerformance&&webkitPerformance.memory.totalJSHeapSize)x=
7 | 3}catch(L){}j=document.createElement("div");j.style.backgroundColor="rgb("+Math.floor(b.mem.bg.r/2)+","+Math.floor(b.mem.bg.g/2)+","+Math.floor(b.mem.bg.b/2)+")";j.style.padding="2px 0px 3px 0px";j.style.display="none";e.appendChild(j);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.textAlign="left";k.style.fontSize="9px";k.style.color="rgb("+b.mem.fg.r+","+b.mem.fg.g+","+b.mem.fg.b+")";k.style.margin="0px 0px 1px 3px";k.innerHTML='MEM';
8 | j.appendChild(k);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";j.appendChild(a);t=a.getContext("2d");t.fillStyle="#301010";t.fillRect(0,0,a.width,a.height);I=t.getImageData(0,0,a.width,a.height);return{domElement:e,update:function(){y++;l=(new Date).getTime();q=l-J;D=Math.min(D,q);E=Math.max(E,q);w(F.data,Math.min(30,30-q/200*30),"ms");i.innerHTML=''+q+" MS ("+D+"-"+E+")";r.putImageData(F,0,0);J=l;if(l>
9 | z+1E3){o=Math.round(y*1E3/(l-z));A=Math.min(A,o);B=Math.max(B,o);w(C.data,Math.min(30,30-o/100*30),"fps");g.innerHTML=''+o+" FPS ("+A+"-"+B+")";p.putImageData(C,0,0);if(x==3){s=webkitPerformance.memory.usedJSHeapSize*9.54E-7;G=Math.min(G,s);H=Math.max(H,s);w(I.data,Math.min(30,30-s/2),"mem");k.innerHTML=''+Math.round(s)+" MEM ("+Math.round(G)+"-"+Math.round(H)+")";t.putImageData(I,0,0)}z=l;y=0}}}};
10 |
--------------------------------------------------------------------------------
/static/phase10/scripts/stats.js:
--------------------------------------------------------------------------------
1 | // stats.js r5 - http://github.com/mrdoob/stats.js
2 | var Stats=function(){function w(d,K,n){var u,f,c;for(f=0;f<30;f++)for(u=0;u<73;u++){c=(u+f*74)*4;d[c]=d[c+4];d[c+1]=d[c+5];d[c+2]=d[c+6]}for(f=0;f<30;f++){c=(73+f*74)*4;if(fFPS';m.appendChild(g);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";m.appendChild(a);
5 | p=a.getContext("2d");p.fillStyle="rgb("+b.fps.bg.r+","+b.fps.bg.g+","+b.fps.bg.b+")";p.fillRect(0,0,a.width,a.height);C=p.getImageData(0,0,a.width,a.height);h=document.createElement("div");h.style.backgroundColor="rgb("+Math.floor(b.ms.bg.r/2)+","+Math.floor(b.ms.bg.g/2)+","+Math.floor(b.ms.bg.b/2)+")";h.style.padding="2px 0px 3px 0px";h.style.display="none";e.appendChild(h);i=document.createElement("div");i.style.fontFamily="Helvetica, Arial, sans-serif";i.style.textAlign="left";i.style.fontSize=
6 | "9px";i.style.color="rgb("+b.ms.fg.r+","+b.ms.fg.g+","+b.ms.fg.b+")";i.style.margin="0px 0px 1px 3px";i.innerHTML='MS';h.appendChild(i);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";h.appendChild(a);r=a.getContext("2d");r.fillStyle="rgb("+b.ms.bg.r+","+b.ms.bg.g+","+b.ms.bg.b+")";r.fillRect(0,0,a.width,a.height);F=r.getImageData(0,0,a.width,a.height);try{if(webkitPerformance&&webkitPerformance.memory.totalJSHeapSize)x=
7 | 3}catch(L){}j=document.createElement("div");j.style.backgroundColor="rgb("+Math.floor(b.mem.bg.r/2)+","+Math.floor(b.mem.bg.g/2)+","+Math.floor(b.mem.bg.b/2)+")";j.style.padding="2px 0px 3px 0px";j.style.display="none";e.appendChild(j);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.textAlign="left";k.style.fontSize="9px";k.style.color="rgb("+b.mem.fg.r+","+b.mem.fg.g+","+b.mem.fg.b+")";k.style.margin="0px 0px 1px 3px";k.innerHTML='MEM';
8 | j.appendChild(k);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";j.appendChild(a);t=a.getContext("2d");t.fillStyle="#301010";t.fillRect(0,0,a.width,a.height);I=t.getImageData(0,0,a.width,a.height);return{domElement:e,update:function(){y++;l=(new Date).getTime();q=l-J;D=Math.min(D,q);E=Math.max(E,q);w(F.data,Math.min(30,30-q/200*30),"ms");i.innerHTML=''+q+" MS ("+D+"-"+E+")";r.putImageData(F,0,0);J=l;if(l>
9 | z+1E3){o=Math.round(y*1E3/(l-z));A=Math.min(A,o);B=Math.max(B,o);w(C.data,Math.min(30,30-o/100*30),"fps");g.innerHTML=''+o+" FPS ("+A+"-"+B+")";p.putImageData(C,0,0);if(x==3){s=webkitPerformance.memory.usedJSHeapSize*9.54E-7;G=Math.min(G,s);H=Math.max(H,s);w(I.data,Math.min(30,30-s/2),"mem");k.innerHTML=''+Math.round(s)+" MEM ("+Math.round(G)+"-"+Math.round(H)+")";t.putImageData(I,0,0)}z=l;y=0}}}};
10 |
--------------------------------------------------------------------------------
/static/phase13/scripts/stats.js:
--------------------------------------------------------------------------------
1 | // stats.js r5 - http://github.com/mrdoob/stats.js
2 | var Stats=function(){function w(d,K,n){var u,f,c;for(f=0;f<30;f++)for(u=0;u<73;u++){c=(u+f*74)*4;d[c]=d[c+4];d[c+1]=d[c+5];d[c+2]=d[c+6]}for(f=0;f<30;f++){c=(73+f*74)*4;if(fFPS';m.appendChild(g);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";m.appendChild(a);
5 | p=a.getContext("2d");p.fillStyle="rgb("+b.fps.bg.r+","+b.fps.bg.g+","+b.fps.bg.b+")";p.fillRect(0,0,a.width,a.height);C=p.getImageData(0,0,a.width,a.height);h=document.createElement("div");h.style.backgroundColor="rgb("+Math.floor(b.ms.bg.r/2)+","+Math.floor(b.ms.bg.g/2)+","+Math.floor(b.ms.bg.b/2)+")";h.style.padding="2px 0px 3px 0px";h.style.display="none";e.appendChild(h);i=document.createElement("div");i.style.fontFamily="Helvetica, Arial, sans-serif";i.style.textAlign="left";i.style.fontSize=
6 | "9px";i.style.color="rgb("+b.ms.fg.r+","+b.ms.fg.g+","+b.ms.fg.b+")";i.style.margin="0px 0px 1px 3px";i.innerHTML='MS';h.appendChild(i);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";h.appendChild(a);r=a.getContext("2d");r.fillStyle="rgb("+b.ms.bg.r+","+b.ms.bg.g+","+b.ms.bg.b+")";r.fillRect(0,0,a.width,a.height);F=r.getImageData(0,0,a.width,a.height);try{if(webkitPerformance&&webkitPerformance.memory.totalJSHeapSize)x=
7 | 3}catch(L){}j=document.createElement("div");j.style.backgroundColor="rgb("+Math.floor(b.mem.bg.r/2)+","+Math.floor(b.mem.bg.g/2)+","+Math.floor(b.mem.bg.b/2)+")";j.style.padding="2px 0px 3px 0px";j.style.display="none";e.appendChild(j);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.textAlign="left";k.style.fontSize="9px";k.style.color="rgb("+b.mem.fg.r+","+b.mem.fg.g+","+b.mem.fg.b+")";k.style.margin="0px 0px 1px 3px";k.innerHTML='MEM';
8 | j.appendChild(k);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";j.appendChild(a);t=a.getContext("2d");t.fillStyle="#301010";t.fillRect(0,0,a.width,a.height);I=t.getImageData(0,0,a.width,a.height);return{domElement:e,update:function(){y++;l=(new Date).getTime();q=l-J;D=Math.min(D,q);E=Math.max(E,q);w(F.data,Math.min(30,30-q/200*30),"ms");i.innerHTML=''+q+" MS ("+D+"-"+E+")";r.putImageData(F,0,0);J=l;if(l>
9 | z+1E3){o=Math.round(y*1E3/(l-z));A=Math.min(A,o);B=Math.max(B,o);w(C.data,Math.min(30,30-o/100*30),"fps");g.innerHTML=''+o+" FPS ("+A+"-"+B+")";p.putImageData(C,0,0);if(x==3){s=webkitPerformance.memory.usedJSHeapSize*9.54E-7;G=Math.min(G,s);H=Math.max(H,s);w(I.data,Math.min(30,30-s/2),"mem");k.innerHTML=''+Math.round(s)+" MEM ("+Math.round(G)+"-"+Math.round(H)+")";t.putImageData(I,0,0)}z=l;y=0}}}};
10 |
--------------------------------------------------------------------------------
/static/phase14/scripts/stats.js:
--------------------------------------------------------------------------------
1 | // stats.js r5 - http://github.com/mrdoob/stats.js
2 | var Stats=function(){function w(d,K,n){var u,f,c;for(f=0;f<30;f++)for(u=0;u<73;u++){c=(u+f*74)*4;d[c]=d[c+4];d[c+1]=d[c+5];d[c+2]=d[c+6]}for(f=0;f<30;f++){c=(73+f*74)*4;if(fFPS';m.appendChild(g);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";m.appendChild(a);
5 | p=a.getContext("2d");p.fillStyle="rgb("+b.fps.bg.r+","+b.fps.bg.g+","+b.fps.bg.b+")";p.fillRect(0,0,a.width,a.height);C=p.getImageData(0,0,a.width,a.height);h=document.createElement("div");h.style.backgroundColor="rgb("+Math.floor(b.ms.bg.r/2)+","+Math.floor(b.ms.bg.g/2)+","+Math.floor(b.ms.bg.b/2)+")";h.style.padding="2px 0px 3px 0px";h.style.display="none";e.appendChild(h);i=document.createElement("div");i.style.fontFamily="Helvetica, Arial, sans-serif";i.style.textAlign="left";i.style.fontSize=
6 | "9px";i.style.color="rgb("+b.ms.fg.r+","+b.ms.fg.g+","+b.ms.fg.b+")";i.style.margin="0px 0px 1px 3px";i.innerHTML='MS';h.appendChild(i);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";h.appendChild(a);r=a.getContext("2d");r.fillStyle="rgb("+b.ms.bg.r+","+b.ms.bg.g+","+b.ms.bg.b+")";r.fillRect(0,0,a.width,a.height);F=r.getImageData(0,0,a.width,a.height);try{if(webkitPerformance&&webkitPerformance.memory.totalJSHeapSize)x=
7 | 3}catch(L){}j=document.createElement("div");j.style.backgroundColor="rgb("+Math.floor(b.mem.bg.r/2)+","+Math.floor(b.mem.bg.g/2)+","+Math.floor(b.mem.bg.b/2)+")";j.style.padding="2px 0px 3px 0px";j.style.display="none";e.appendChild(j);k=document.createElement("div");k.style.fontFamily="Helvetica, Arial, sans-serif";k.style.textAlign="left";k.style.fontSize="9px";k.style.color="rgb("+b.mem.fg.r+","+b.mem.fg.g+","+b.mem.fg.b+")";k.style.margin="0px 0px 1px 3px";k.innerHTML='MEM';
8 | j.appendChild(k);a=document.createElement("canvas");a.width=74;a.height=30;a.style.display="block";a.style.marginLeft="3px";j.appendChild(a);t=a.getContext("2d");t.fillStyle="#301010";t.fillRect(0,0,a.width,a.height);I=t.getImageData(0,0,a.width,a.height);return{domElement:e,update:function(){y++;l=(new Date).getTime();q=l-J;D=Math.min(D,q);E=Math.max(E,q);w(F.data,Math.min(30,30-q/200*30),"ms");i.innerHTML=''+q+" MS ("+D+"-"+E+")";r.putImageData(F,0,0);J=l;if(l>
9 | z+1E3){o=Math.round(y*1E3/(l-z));A=Math.min(A,o);B=Math.max(B,o);w(C.data,Math.min(30,30-o/100*30),"fps");g.innerHTML=''+o+" FPS ("+A+"-"+B+")";p.putImageData(C,0,0);if(x==3){s=webkitPerformance.memory.usedJSHeapSize*9.54E-7;G=Math.min(G,s);H=Math.max(H,s);w(I.data,Math.min(30,30-s/2),"mem");k.innerHTML=''+Math.round(s)+" MEM ("+Math.round(G)+"-"+Math.round(H)+")";t.putImageData(I,0,0)}z=l;y=0}}}};
10 |
--------------------------------------------------------------------------------
/static/phase03/scripts/app.js:
--------------------------------------------------------------------------------
1 | window.requestAnimFrame = (function(){
2 | return window.requestAnimationFrame ||
3 | window.webkitRequestAnimationFrame ||
4 | window.mozRequestAnimationFrame ||
5 | window.oRequestAnimationFrame ||
6 | window.msRequestAnimationFrame ||
7 | function(/* function */ callback, /* DOMElement */ element){
8 | window.setTimeout(callback, 1000 / 60);
9 | };
10 | })();
11 |
12 | function AssetManager() {
13 | this.successCount = 0;
14 | this.errorCount = 0;
15 | this.cache = {};
16 | this.downloadQueue = [];
17 | }
18 |
19 | AssetManager.prototype.queueDownload = function(path) {
20 | this.downloadQueue.push(path);
21 | }
22 |
23 | AssetManager.prototype.downloadAll = function(callback) {
24 | if (this.downloadQueue.length === 0 && this.soundsQueue.length === 0) {
25 | callback();
26 | }
27 |
28 | for (var i = 0; i < this.downloadQueue.length; i++) {
29 | var path = this.downloadQueue[i];
30 | var img = new Image();
31 | var that = this;
32 | img.addEventListener("load", function() {
33 | console.log(this.src + ' is loaded');
34 | that.successCount += 1;
35 | if (that.isDone()) {
36 | callback();
37 | }
38 | }, false);
39 | img.addEventListener("error", function() {
40 | that.errorCount += 1;
41 | if (that.isDone()) {
42 | callback();
43 | }
44 | }, false);
45 | img.src = path;
46 | this.cache[path] = img;
47 | }
48 | }
49 |
50 | AssetManager.prototype.getAsset = function(path) {
51 | return this.cache[path];
52 | }
53 |
54 | AssetManager.prototype.isDone = function() {
55 | return (this.downloadQueue.length == this.successCount + this.errorCount);
56 | }
57 |
58 | function GameEngine() {
59 | this.entities = [];
60 | this.ctx = null;
61 |
62 | this.lastUpdateTimestamp = null;
63 | this.deltaTime = null;
64 |
65 | this.surfaceWidth = null;
66 | this.surfaceHeight = null;
67 | this.halfSurfaceWidth = null;
68 | this.halfSurfaceHeight = null;
69 | }
70 |
71 | GameEngine.prototype.init = function(ctx) {
72 | console.log('game initialized');
73 | this.ctx = ctx;
74 | this.surfaceWidth = this.ctx.canvas.width;
75 | this.surfaceHeight = this.ctx.canvas.height;
76 | this.halfSurfaceWidth = this.surfaceWidth/2;
77 | this.halfSurfaceHeight = this.surfaceHeight/2;
78 | }
79 |
80 | GameEngine.prototype.start = function() {
81 | console.log("starting game");
82 | this.lastUpdateTimestamp = Date.now();
83 | var that = this;
84 | (function gameLoop() {
85 | that.loop();
86 | requestAnimFrame(gameLoop, that.ctx.canvas);
87 | })();
88 | }
89 |
90 | GameEngine.prototype.addEntity = function(entity) {
91 | this.entities.push(entity);
92 | }
93 |
94 | GameEngine.prototype.draw = function(callback) {
95 | this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
96 | this.ctx.save();
97 | this.ctx.translate(this.ctx.canvas.width/2, this.ctx.canvas.height/2);
98 | for (var i = 0; i < this.entities.length; i++) {
99 | this.entities[i].draw(this.ctx);
100 | }
101 | if (callback) {
102 | callback(this);
103 | }
104 | this.ctx.restore();
105 | }
106 |
107 | GameEngine.prototype.update = function() {
108 | var entitiesCount = this.entities.length;
109 |
110 | for (var i = 0; i < entitiesCount; i++) {
111 | var entity = this.entities[i];
112 |
113 | if (!entity.removeFromWorld) {
114 | entity.update();
115 | }
116 | }
117 |
118 | for (var i = this.entities.length-1; i >= 0; --i) {
119 | if (this.entities[i].removeFromWorld) {
120 | this.entities.splice(i, 1);
121 | }
122 | }
123 | }
124 |
125 | GameEngine.prototype.loop = function() {
126 | var now = Date.now();
127 | this.deltaTime = now - this.lastUpdateTimestamp;
128 | this.update();
129 | this.draw();
130 | this.lastUpdateTimestamp = now;
131 | }
132 |
133 | function Entity(game, x, y) {
134 | this.game = game;
135 | this.x = x;
136 | this.y = y;
137 | this.removeFromWorld = false;
138 | }
139 |
140 | Entity.prototype.update = function() {
141 | }
142 |
143 | Entity.prototype.draw = function(ctx) {
144 | if (this.game.showOutlines && this.radius) {
145 | ctx.beginPath();
146 | ctx.strokeStyle = "green";
147 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
148 | ctx.stroke();
149 | ctx.closePath();
150 | }
151 | }
152 |
153 | Entity.prototype.drawSpriteCentered = function(ctx) {
154 | if (this.sprite && this.x && this.y) {
155 | var x = this.x - this.sprite.width/2;
156 | var y = this.y - this.sprite.height/2;
157 | ctx.drawImage(this.sprite, x, y);
158 | }
159 | }
160 |
161 | Entity.prototype.outsideScreen = function() {
162 | return (this.x > this.game.halfSurfaceWidth || this.x < -(this.game.halfSurfaceWidth) ||
163 | this.y > this.game.halfSurfaceHeight || this.y < -(this.game.halfSurfaceHeight));
164 | }
165 |
166 | function Alien(game, radial_distance, angle) {
167 | Entity.call(this, game);
168 | this.radial_distance = radial_distance;
169 | this.angle = angle;
170 | this.speed = 0.2;
171 | this.sprite = ASSET_MANAGER.getAsset('img/alien.png');
172 | this.radius = this.sprite.height/2;
173 | this.setCoords();
174 | }
175 | Alien.prototype = new Entity();
176 | Alien.prototype.constructor = Alien;
177 |
178 | Alien.prototype.setCoords = function() {
179 | this.x = this.radial_distance * Math.cos(this.angle);
180 | this.y = this.radial_distance * Math.sin(this.angle);
181 | }
182 |
183 | Alien.prototype.update = function() {
184 | this.setCoords();
185 | this.radial_distance -= this.speed * this.game.deltaTime;
186 |
187 | Entity.prototype.update.call(this);
188 | }
189 |
190 | Alien.prototype.draw = function(ctx) {
191 | this.drawSpriteCentered(ctx);
192 | Entity.prototype.draw.call(this, ctx);
193 | }
194 |
195 | function Earth(game) {
196 | Entity.call(this, game, 0, 0);
197 | this.sprite = ASSET_MANAGER.getAsset('img/earth.png');
198 | }
199 | Earth.prototype = new Entity();
200 | Earth.prototype.constructor = Earth;
201 |
202 | Earth.RADIUS = 67;
203 |
204 | Earth.prototype.draw = function(ctx) {
205 | ctx.drawImage(this.sprite, this.x - this.sprite.width/2, this.y - this.sprite.height/2);
206 | }
207 |
208 | function EvilAliens() {
209 | GameEngine.call(this);
210 | }
211 | EvilAliens.prototype = new GameEngine();
212 | EvilAliens.prototype.constructor = EvilAliens;
213 |
214 | EvilAliens.prototype.start = function() {
215 | this.earth = new Earth(this);
216 | this.addEntity(this.earth);
217 | GameEngine.prototype.start.call(this);
218 | }
219 |
220 | EvilAliens.prototype.update = function() {
221 | if (this.lastAlienAddedAt == null || (this.lastUpdateTimestamp - this.lastAlienAddedAt) > 1000) {
222 | this.addEntity(new Alien(this, this.ctx.canvas.width, Math.random() * Math.PI * 180));
223 | this.lastAlienAddedAt = this.lastUpdateTimestamp;
224 | }
225 |
226 | GameEngine.prototype.update.call(this);
227 | }
228 |
229 | EvilAliens.prototype.draw = function() {
230 | GameEngine.prototype.draw.call(this);
231 | }
232 |
233 | var canvas = document.getElementById('surface');
234 | var ctx = canvas.getContext('2d');
235 | var game = new EvilAliens();
236 | var ASSET_MANAGER = new AssetManager();
237 |
238 | ASSET_MANAGER.queueDownload('img/alien.png');
239 | ASSET_MANAGER.queueDownload('img/earth.png');
240 |
241 | ASSET_MANAGER.downloadAll(function() {
242 | game.init(ctx);
243 | game.start();
244 | });
--------------------------------------------------------------------------------
/static/phase04/scripts/app.js:
--------------------------------------------------------------------------------
1 | window.requestAnimFrame = (function(){
2 | return window.requestAnimationFrame ||
3 | window.webkitRequestAnimationFrame ||
4 | window.mozRequestAnimationFrame ||
5 | window.oRequestAnimationFrame ||
6 | window.msRequestAnimationFrame ||
7 | function(/* function */ callback, /* DOMElement */ element){
8 | window.setTimeout(callback, 1000 / 60);
9 | };
10 | })();
11 |
12 | function AssetManager() {
13 | this.successCount = 0;
14 | this.errorCount = 0;
15 | this.cache = {};
16 | this.downloadQueue = [];
17 | }
18 |
19 | AssetManager.prototype.queueDownload = function(path) {
20 | this.downloadQueue.push(path);
21 | }
22 |
23 | AssetManager.prototype.downloadAll = function(callback) {
24 | if (this.downloadQueue.length === 0 && this.soundsQueue.length === 0) {
25 | callback();
26 | }
27 |
28 | for (var i = 0; i < this.downloadQueue.length; i++) {
29 | var path = this.downloadQueue[i];
30 | var img = new Image();
31 | var that = this;
32 | img.addEventListener("load", function() {
33 | console.log(this.src + ' is loaded');
34 | that.successCount += 1;
35 | if (that.isDone()) {
36 | callback();
37 | }
38 | }, false);
39 | img.addEventListener("error", function() {
40 | that.errorCount += 1;
41 | if (that.isDone()) {
42 | callback();
43 | }
44 | }, false);
45 | img.src = path;
46 | this.cache[path] = img;
47 | }
48 | }
49 |
50 | AssetManager.prototype.getAsset = function(path) {
51 | return this.cache[path];
52 | }
53 |
54 | AssetManager.prototype.isDone = function() {
55 | return (this.downloadQueue.length == this.successCount + this.errorCount);
56 | }
57 |
58 | function Timer() {
59 | this.gameTime = 0;
60 | this.maxStep = 0.05;
61 | this.wallLastTimestamp = 0;
62 | }
63 |
64 | Timer.prototype.tick = function() {
65 | var wallCurrent = Date.now();
66 | var wallDelta = (wallCurrent - this.wallLastTimestamp) / 1000;
67 | this.wallLastTimestamp = wallCurrent;
68 |
69 | var gameDelta = Math.min(wallDelta, this.maxStep);
70 | this.gameTime += gameDelta;
71 | return gameDelta;
72 | }
73 |
74 | function GameEngine() {
75 | this.entities = [];
76 | this.ctx = null;
77 | this.timer = new Timer();
78 | this.surfaceWidth = null;
79 | this.surfaceHeight = null;
80 | this.halfSurfaceWidth = null;
81 | this.halfSurfaceHeight = null;
82 | }
83 |
84 | GameEngine.prototype.init = function(ctx) {
85 | console.log('game initialized');
86 | this.ctx = ctx;
87 | this.surfaceWidth = this.ctx.canvas.width;
88 | this.surfaceHeight = this.ctx.canvas.height;
89 | this.halfSurfaceWidth = this.surfaceWidth/2;
90 | this.halfSurfaceHeight = this.surfaceHeight/2;
91 | }
92 |
93 | GameEngine.prototype.start = function() {
94 | console.log("starting game");
95 | var that = this;
96 | (function gameLoop() {
97 | that.loop();
98 | requestAnimFrame(gameLoop, that.ctx.canvas);
99 | })();
100 | }
101 |
102 | GameEngine.prototype.addEntity = function(entity) {
103 | this.entities.push(entity);
104 | }
105 |
106 | GameEngine.prototype.draw = function(callback) {
107 | this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
108 | this.ctx.save();
109 | this.ctx.translate(this.ctx.canvas.width/2, this.ctx.canvas.height/2);
110 | for (var i = 0; i < this.entities.length; i++) {
111 | this.entities[i].draw(this.ctx);
112 | }
113 | if (callback) {
114 | callback(this);
115 | }
116 | this.ctx.restore();
117 | }
118 |
119 | GameEngine.prototype.update = function() {
120 | var entitiesCount = this.entities.length;
121 |
122 | for (var i = 0; i < entitiesCount; i++) {
123 | var entity = this.entities[i];
124 |
125 | if (!entity.removeFromWorld) {
126 | entity.update();
127 | }
128 | }
129 |
130 | for (var i = this.entities.length-1; i >= 0; --i) {
131 | if (this.entities[i].removeFromWorld) {
132 | this.entities.splice(i, 1);
133 | }
134 | }
135 | }
136 |
137 | GameEngine.prototype.loop = function() {
138 | this.clockTick = this.timer.tick();
139 | this.update();
140 | this.draw();
141 | }
142 |
143 | function Entity(game, x, y) {
144 | this.game = game;
145 | this.x = x;
146 | this.y = y;
147 | this.removeFromWorld = false;
148 | }
149 |
150 | Entity.prototype.update = function() {
151 | }
152 |
153 | Entity.prototype.draw = function(ctx) {
154 | if (this.game.showOutlines && this.radius) {
155 | ctx.beginPath();
156 | ctx.strokeStyle = "green";
157 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
158 | ctx.stroke();
159 | ctx.closePath();
160 | }
161 | }
162 |
163 | Entity.prototype.drawSpriteCentered = function(ctx) {
164 | if (this.sprite && this.x && this.y) {
165 | var x = this.x - this.sprite.width/2;
166 | var y = this.y - this.sprite.height/2;
167 | ctx.drawImage(this.sprite, x, y);
168 | }
169 | }
170 |
171 | Entity.prototype.outsideScreen = function() {
172 | return (this.x > this.game.halfSurfaceWidth || this.x < -(this.game.halfSurfaceWidth) ||
173 | this.y > this.game.halfSurfaceHeight || this.y < -(this.game.halfSurfaceHeight));
174 | }
175 |
176 | function Alien(game, radial_distance, angle) {
177 | Entity.call(this, game);
178 | this.radial_distance = radial_distance;
179 | this.angle = angle;
180 | this.speed = 100;
181 | this.sprite = ASSET_MANAGER.getAsset('img/alien.png');
182 | this.radius = this.sprite.height/2;
183 | this.setCoords();
184 | }
185 | Alien.prototype = new Entity();
186 | Alien.prototype.constructor = Alien;
187 |
188 | Alien.prototype.setCoords = function() {
189 | this.x = this.radial_distance * Math.cos(this.angle);
190 | this.y = this.radial_distance * Math.sin(this.angle);
191 | }
192 |
193 | Alien.prototype.update = function() {
194 | this.setCoords();
195 | this.radial_distance -= this.speed * this.game.clockTick;
196 |
197 | Entity.prototype.update.call(this);
198 | }
199 |
200 | Alien.prototype.draw = function(ctx) {
201 | this.drawSpriteCentered(ctx);
202 | Entity.prototype.draw.call(this, ctx);
203 | }
204 |
205 | function Earth(game) {
206 | Entity.call(this, game, 0, 0);
207 | this.sprite = ASSET_MANAGER.getAsset('img/earth.png');
208 | }
209 | Earth.prototype = new Entity();
210 | Earth.prototype.constructor = Earth;
211 |
212 | Earth.RADIUS = 67;
213 |
214 | Earth.prototype.draw = function(ctx) {
215 | ctx.drawImage(this.sprite, this.x - this.sprite.width/2, this.y - this.sprite.height/2);
216 | }
217 |
218 | function EvilAliens() {
219 | GameEngine.call(this);
220 | }
221 | EvilAliens.prototype = new GameEngine();
222 | EvilAliens.prototype.constructor = EvilAliens;
223 |
224 | EvilAliens.prototype.start = function() {
225 | this.earth = new Earth(this);
226 | this.addEntity(this.earth);
227 | GameEngine.prototype.start.call(this);
228 | }
229 |
230 | EvilAliens.prototype.update = function() {
231 | if (this.lastAlienAddedAt == null || (this.timer.gameTime - this.lastAlienAddedAt) > 1) {
232 | this.addEntity(new Alien(this, this.ctx.canvas.width, Math.random() * Math.PI * 180));
233 | this.lastAlienAddedAt = this.timer.gameTime;
234 | }
235 |
236 | GameEngine.prototype.update.call(this);
237 | }
238 |
239 | EvilAliens.prototype.draw = function() {
240 | GameEngine.prototype.draw.call(this);
241 | }
242 |
243 | var canvas = document.getElementById('surface');
244 | var ctx = canvas.getContext('2d');
245 | var game = new EvilAliens();
246 | var ASSET_MANAGER = new AssetManager();
247 |
248 | ASSET_MANAGER.queueDownload('img/alien.png');
249 | ASSET_MANAGER.queueDownload('img/earth.png');
250 |
251 | ASSET_MANAGER.downloadAll(function() {
252 | game.init(ctx);
253 | game.start();
254 | });
--------------------------------------------------------------------------------
/static/phase05/scripts/app.js:
--------------------------------------------------------------------------------
1 | window.requestAnimFrame = (function(){
2 | return window.requestAnimationFrame ||
3 | window.webkitRequestAnimationFrame ||
4 | window.mozRequestAnimationFrame ||
5 | window.oRequestAnimationFrame ||
6 | window.msRequestAnimationFrame ||
7 | function(/* function */ callback, /* DOMElement */ element){
8 | window.setTimeout(callback, 1000 / 60);
9 | };
10 | })();
11 |
12 | function AssetManager() {
13 | this.successCount = 0;
14 | this.errorCount = 0;
15 | this.cache = {};
16 | this.downloadQueue = [];
17 | }
18 |
19 | AssetManager.prototype.queueDownload = function(path) {
20 | this.downloadQueue.push(path);
21 | }
22 |
23 | AssetManager.prototype.downloadAll = function(callback) {
24 | if (this.downloadQueue.length === 0 && this.soundsQueue.length === 0) {
25 | callback();
26 | }
27 |
28 | for (var i = 0; i < this.downloadQueue.length; i++) {
29 | var path = this.downloadQueue[i];
30 | var img = new Image();
31 | var that = this;
32 | img.addEventListener("load", function() {
33 | console.log(this.src + ' is loaded');
34 | that.successCount += 1;
35 | if (that.isDone()) {
36 | callback();
37 | }
38 | }, false);
39 | img.addEventListener("error", function() {
40 | that.errorCount += 1;
41 | if (that.isDone()) {
42 | callback();
43 | }
44 | }, false);
45 | img.src = path;
46 | this.cache[path] = img;
47 | }
48 | }
49 |
50 | AssetManager.prototype.getAsset = function(path) {
51 | return this.cache[path];
52 | }
53 |
54 | AssetManager.prototype.isDone = function() {
55 | return (this.downloadQueue.length == this.successCount + this.errorCount);
56 | }
57 |
58 | function Timer() {
59 | this.gameTime = 0;
60 | this.maxStep = 0.05;
61 | this.wallLastTimestamp = 0;
62 | }
63 |
64 | Timer.prototype.tick = function() {
65 | var wallCurrent = Date.now();
66 | var wallDelta = (wallCurrent - this.wallLastTimestamp) / 1000;
67 | this.wallLastTimestamp = wallCurrent;
68 |
69 | var gameDelta = Math.min(wallDelta, this.maxStep);
70 | this.gameTime += gameDelta;
71 | return gameDelta;
72 | }
73 |
74 | function GameEngine() {
75 | this.entities = [];
76 | this.ctx = null;
77 | this.timer = new Timer();
78 | this.surfaceWidth = null;
79 | this.surfaceHeight = null;
80 | this.halfSurfaceWidth = null;
81 | this.halfSurfaceHeight = null;
82 | }
83 |
84 | GameEngine.prototype.init = function(ctx) {
85 | console.log('game initialized');
86 | this.ctx = ctx;
87 | this.surfaceWidth = this.ctx.canvas.width;
88 | this.surfaceHeight = this.ctx.canvas.height;
89 | this.halfSurfaceWidth = this.surfaceWidth/2;
90 | this.halfSurfaceHeight = this.surfaceHeight/2;
91 | }
92 |
93 | GameEngine.prototype.start = function() {
94 | console.log("starting game");
95 | var that = this;
96 | (function gameLoop() {
97 | that.loop();
98 | requestAnimFrame(gameLoop, that.ctx.canvas);
99 | })();
100 | }
101 |
102 | GameEngine.prototype.addEntity = function(entity) {
103 | this.entities.push(entity);
104 | }
105 |
106 | GameEngine.prototype.draw = function(callback) {
107 | this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
108 | this.ctx.save();
109 | this.ctx.translate(this.ctx.canvas.width/2, this.ctx.canvas.height/2);
110 | for (var i = 0; i < this.entities.length; i++) {
111 | this.entities[i].draw(this.ctx);
112 | }
113 | if (callback) {
114 | callback(this);
115 | }
116 | this.ctx.restore();
117 | }
118 |
119 | GameEngine.prototype.update = function() {
120 | var entitiesCount = this.entities.length;
121 |
122 | for (var i = 0; i < entitiesCount; i++) {
123 | var entity = this.entities[i];
124 |
125 | if (!entity.removeFromWorld) {
126 | entity.update();
127 | }
128 | }
129 |
130 | for (var i = this.entities.length-1; i >= 0; --i) {
131 | if (this.entities[i].removeFromWorld) {
132 | this.entities.splice(i, 1);
133 | }
134 | }
135 | }
136 |
137 | GameEngine.prototype.loop = function() {
138 | this.clockTick = this.timer.tick();
139 | this.update();
140 | this.draw();
141 | this.click = null;
142 | }
143 |
144 | function Entity(game, x, y) {
145 | this.game = game;
146 | this.x = x;
147 | this.y = y;
148 | this.removeFromWorld = false;
149 | }
150 |
151 | Entity.prototype.update = function() {
152 | }
153 |
154 | Entity.prototype.draw = function(ctx) {
155 | if (this.game.showOutlines && this.radius) {
156 | ctx.beginPath();
157 | ctx.strokeStyle = "green";
158 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
159 | ctx.stroke();
160 | ctx.closePath();
161 | }
162 | }
163 |
164 | Entity.prototype.drawSpriteCentered = function(ctx) {
165 | if (this.sprite && this.x && this.y) {
166 | var x = this.x - this.sprite.width/2;
167 | var y = this.y - this.sprite.height/2;
168 | ctx.drawImage(this.sprite, x, y);
169 | }
170 | }
171 |
172 | Entity.prototype.outsideScreen = function() {
173 | return (this.x > this.game.halfSurfaceWidth || this.x < -(this.game.halfSurfaceWidth) ||
174 | this.y > this.game.halfSurfaceHeight || this.y < -(this.game.halfSurfaceHeight));
175 | }
176 |
177 | function Alien(game, radial_distance, angle) {
178 | Entity.call(this, game);
179 | this.radial_distance = radial_distance;
180 | this.angle = angle;
181 | this.speed = 100;
182 | this.sprite = ASSET_MANAGER.getAsset('img/alien.png');
183 | this.radius = this.sprite.height/2;
184 | this.setCoords();
185 | }
186 | Alien.prototype = new Entity();
187 | Alien.prototype.constructor = Alien;
188 |
189 | Alien.prototype.setCoords = function() {
190 | this.x = this.radial_distance * Math.cos(this.angle);
191 | this.y = this.radial_distance * Math.sin(this.angle);
192 | }
193 |
194 | Alien.prototype.update = function() {
195 | this.setCoords();
196 | this.radial_distance -= this.speed * this.game.clockTick;
197 |
198 | Entity.prototype.update.call(this);
199 | }
200 |
201 | Alien.prototype.draw = function(ctx) {
202 | ctx.save();
203 | ctx.translate(this.x, this.y);
204 | ctx.rotate(this.angle + Math.PI/2);
205 | ctx.drawImage(this.sprite, -this.sprite.width/2, -this.sprite.height/2);
206 | ctx.restore();
207 |
208 | Entity.prototype.draw.call(this, ctx);
209 | }
210 |
211 | function Earth(game) {
212 | Entity.call(this, game, 0, 0);
213 | this.sprite = ASSET_MANAGER.getAsset('img/earth.png');
214 | }
215 | Earth.prototype = new Entity();
216 | Earth.prototype.constructor = Earth;
217 |
218 | Earth.RADIUS = 67;
219 |
220 | Earth.prototype.draw = function(ctx) {
221 | ctx.drawImage(this.sprite, this.x - this.sprite.width/2, this.y - this.sprite.height/2);
222 | }
223 |
224 | function EvilAliens() {
225 | GameEngine.call(this);
226 | }
227 | EvilAliens.prototype = new GameEngine();
228 | EvilAliens.prototype.constructor = EvilAliens;
229 |
230 | EvilAliens.prototype.start = function() {
231 | this.earth = new Earth(this);
232 | this.addEntity(this.earth);
233 | GameEngine.prototype.start.call(this);
234 | }
235 |
236 | EvilAliens.prototype.update = function() {
237 | if (this.lastAlienAddedAt == null || (this.timer.gameTime - this.lastAlienAddedAt) > 1) {
238 | this.addEntity(new Alien(this, this.ctx.canvas.width, Math.floor(Math.random() * Math.PI * 2)));
239 | this.lastAlienAddedAt = this.timer.gameTime;
240 | }
241 |
242 | GameEngine.prototype.update.call(this);
243 | }
244 |
245 | EvilAliens.prototype.draw = function() {
246 | GameEngine.prototype.draw.call(this);
247 | }
248 |
249 | var canvas = document.getElementById('surface');
250 | var ctx = canvas.getContext('2d');
251 | var game = new EvilAliens();
252 | var ASSET_MANAGER = new AssetManager();
253 |
254 | ASSET_MANAGER.queueDownload('img/alien.png');
255 | ASSET_MANAGER.queueDownload('img/earth.png');
256 |
257 | ASSET_MANAGER.downloadAll(function() {
258 | game.init(ctx);
259 | game.start();
260 | });
--------------------------------------------------------------------------------
/static/phase06/scripts/app.js:
--------------------------------------------------------------------------------
1 | window.requestAnimFrame = (function(){
2 | return window.requestAnimationFrame ||
3 | window.webkitRequestAnimationFrame ||
4 | window.mozRequestAnimationFrame ||
5 | window.oRequestAnimationFrame ||
6 | window.msRequestAnimationFrame ||
7 | function(/* function */ callback, /* DOMElement */ element){
8 | window.setTimeout(callback, 1000 / 60);
9 | };
10 | })();
11 |
12 | function AssetManager() {
13 | this.successCount = 0;
14 | this.errorCount = 0;
15 | this.cache = {};
16 | this.downloadQueue = [];
17 | }
18 |
19 | AssetManager.prototype.queueDownload = function(path) {
20 | this.downloadQueue.push(path);
21 | }
22 |
23 | AssetManager.prototype.downloadAll = function(callback) {
24 | if (this.downloadQueue.length === 0 && this.soundsQueue.length === 0) {
25 | callback();
26 | }
27 |
28 | for (var i = 0; i < this.downloadQueue.length; i++) {
29 | var path = this.downloadQueue[i];
30 | var img = new Image();
31 | var that = this;
32 | img.addEventListener("load", function() {
33 | console.log(this.src + ' is loaded');
34 | that.successCount += 1;
35 | if (that.isDone()) {
36 | callback();
37 | }
38 | }, false);
39 | img.addEventListener("error", function() {
40 | that.errorCount += 1;
41 | if (that.isDone()) {
42 | callback();
43 | }
44 | }, false);
45 | img.src = path;
46 | this.cache[path] = img;
47 | }
48 | }
49 |
50 | AssetManager.prototype.getAsset = function(path) {
51 | return this.cache[path];
52 | }
53 |
54 | AssetManager.prototype.isDone = function() {
55 | return (this.downloadQueue.length == this.successCount + this.errorCount);
56 | }
57 |
58 | function Timer() {
59 | this.gameTime = 0;
60 | this.maxStep = 0.05;
61 | this.wallLastTimestamp = 0;
62 | }
63 |
64 | Timer.prototype.tick = function() {
65 | var wallCurrent = Date.now();
66 | var wallDelta = (wallCurrent - this.wallLastTimestamp) / 1000;
67 | this.wallLastTimestamp = wallCurrent;
68 |
69 | var gameDelta = Math.min(wallDelta, this.maxStep);
70 | this.gameTime += gameDelta;
71 | return gameDelta;
72 | }
73 |
74 | function GameEngine() {
75 | this.entities = [];
76 | this.ctx = null;
77 | this.timer = new Timer();
78 | this.surfaceWidth = null;
79 | this.surfaceHeight = null;
80 | this.halfSurfaceWidth = null;
81 | this.halfSurfaceHeight = null;
82 |
83 | //this.showOutlines = true;
84 | }
85 |
86 | GameEngine.prototype.init = function(ctx) {
87 | console.log('game initialized');
88 | this.ctx = ctx;
89 | this.surfaceWidth = this.ctx.canvas.width;
90 | this.surfaceHeight = this.ctx.canvas.height;
91 | this.halfSurfaceWidth = this.surfaceWidth/2;
92 | this.halfSurfaceHeight = this.surfaceHeight/2;
93 | }
94 |
95 | GameEngine.prototype.start = function() {
96 | console.log("starting game");
97 | var that = this;
98 | (function gameLoop() {
99 | that.loop();
100 | requestAnimFrame(gameLoop, that.ctx.canvas);
101 | })();
102 | }
103 |
104 | GameEngine.prototype.addEntity = function(entity) {
105 | this.entities.push(entity);
106 | }
107 |
108 | GameEngine.prototype.draw = function(callback) {
109 | this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
110 | this.ctx.save();
111 | this.ctx.translate(this.ctx.canvas.width/2, this.ctx.canvas.height/2);
112 | for (var i = 0; i < this.entities.length; i++) {
113 | this.entities[i].draw(this.ctx);
114 | }
115 | if (callback) {
116 | callback(this);
117 | }
118 | this.ctx.restore();
119 | }
120 |
121 | GameEngine.prototype.update = function() {
122 | var entitiesCount = this.entities.length;
123 |
124 | for (var i = 0; i < entitiesCount; i++) {
125 | var entity = this.entities[i];
126 |
127 | if (!entity.removeFromWorld) {
128 | entity.update();
129 | }
130 | }
131 |
132 | for (var i = this.entities.length-1; i >= 0; --i) {
133 | if (this.entities[i].removeFromWorld) {
134 | this.entities.splice(i, 1);
135 | }
136 | }
137 | }
138 |
139 | GameEngine.prototype.loop = function() {
140 | this.clockTick = this.timer.tick();
141 | this.update();
142 | this.draw();
143 | this.click = null;
144 | }
145 |
146 | function Entity(game, x, y) {
147 | this.game = game;
148 | this.x = x;
149 | this.y = y;
150 | this.removeFromWorld = false;
151 | }
152 |
153 | Entity.prototype.update = function() {
154 | }
155 |
156 | Entity.prototype.draw = function(ctx) {
157 | if (this.game.showOutlines && this.radius) {
158 | ctx.beginPath();
159 | ctx.strokeStyle = "green";
160 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
161 | ctx.stroke();
162 | ctx.closePath();
163 | }
164 | }
165 |
166 | Entity.prototype.drawSpriteCentered = function(ctx) {
167 | if (this.sprite && this.x && this.y) {
168 | var x = this.x - this.sprite.width/2;
169 | var y = this.y - this.sprite.height/2;
170 | ctx.drawImage(this.sprite, x, y);
171 | }
172 | }
173 |
174 | Entity.prototype.outsideScreen = function() {
175 | return (this.x > this.game.halfSurfaceWidth || this.x < -(this.game.halfSurfaceWidth) ||
176 | this.y > this.game.halfSurfaceHeight || this.y < -(this.game.halfSurfaceHeight));
177 | }
178 |
179 | Entity.prototype.rotateAndCache = function(image) {
180 | var offscreenCanvas = document.createElement('canvas');
181 | var size = Math.max(image.width, image.height);
182 | offscreenCanvas.width = size;
183 | offscreenCanvas.height = size;
184 | var offscreenCtx = offscreenCanvas.getContext('2d');
185 | offscreenCtx.translate(size/2, size/2);
186 | offscreenCtx.rotate(this.angle + Math.PI/2);
187 | offscreenCtx.drawImage(image, -(image.width/2), -(image.height/2));
188 | return offscreenCanvas;
189 | }
190 |
191 | function Alien(game, radial_distance, angle) {
192 | Entity.call(this, game);
193 | this.radial_distance = radial_distance;
194 | this.angle = angle;
195 | this.speed = 100;
196 | this.sprite = this.rotateAndCache(ASSET_MANAGER.getAsset('img/alien.png'));
197 | this.radius = this.sprite.height/2;
198 | this.setCoords();
199 | }
200 | Alien.prototype = new Entity();
201 | Alien.prototype.constructor = Alien;
202 |
203 | Alien.prototype.setCoords = function() {
204 | this.x = this.radial_distance * Math.cos(this.angle);
205 | this.y = this.radial_distance * Math.sin(this.angle);
206 | }
207 |
208 | Alien.prototype.update = function() {
209 | this.setCoords();
210 | this.radial_distance -= this.speed * this.game.clockTick;
211 |
212 | Entity.prototype.update.call(this);
213 | }
214 |
215 | Alien.prototype.draw = function(ctx) {
216 | this.drawSpriteCentered(ctx);
217 |
218 | Entity.prototype.draw.call(this, ctx);
219 | }
220 |
221 | function Earth(game) {
222 | Entity.call(this, game, 0, 0);
223 | this.sprite = ASSET_MANAGER.getAsset('img/earth.png');
224 | }
225 | Earth.prototype = new Entity();
226 | Earth.prototype.constructor = Earth;
227 |
228 | Earth.RADIUS = 67;
229 |
230 | Earth.prototype.draw = function(ctx) {
231 | ctx.drawImage(this.sprite, this.x - this.sprite.width/2, this.y - this.sprite.height/2);
232 | }
233 |
234 | function EvilAliens() {
235 | GameEngine.call(this);
236 | }
237 | EvilAliens.prototype = new GameEngine();
238 | EvilAliens.prototype.constructor = EvilAliens;
239 |
240 | EvilAliens.prototype.start = function() {
241 | this.earth = new Earth(this);
242 | this.addEntity(this.earth);
243 | GameEngine.prototype.start.call(this);
244 | }
245 |
246 | EvilAliens.prototype.update = function() {
247 | if (this.lastAlienAddedAt == null || (this.timer.gameTime - this.lastAlienAddedAt) > 1) {
248 | this.addEntity(new Alien(this, this.ctx.canvas.width, Math.floor(Math.random() * Math.PI * 2)));
249 | this.lastAlienAddedAt = this.timer.gameTime;
250 | }
251 |
252 | GameEngine.prototype.update.call(this);
253 | }
254 |
255 | EvilAliens.prototype.draw = function() {
256 | GameEngine.prototype.draw.call(this);
257 | }
258 |
259 | var canvas = document.getElementById('surface');
260 | var ctx = canvas.getContext('2d');
261 | var game = new EvilAliens();
262 | var ASSET_MANAGER = new AssetManager();
263 |
264 | ASSET_MANAGER.queueDownload('img/alien.png');
265 | ASSET_MANAGER.queueDownload('img/earth.png');
266 |
267 | ASSET_MANAGER.downloadAll(function() {
268 | game.init(ctx);
269 | game.start();
270 | });
--------------------------------------------------------------------------------
/static/phase07/scripts/app.js:
--------------------------------------------------------------------------------
1 | window.requestAnimFrame = (function(){
2 | return window.requestAnimationFrame ||
3 | window.webkitRequestAnimationFrame ||
4 | window.mozRequestAnimationFrame ||
5 | window.oRequestAnimationFrame ||
6 | window.msRequestAnimationFrame ||
7 | function(/* function */ callback, /* DOMElement */ element){
8 | window.setTimeout(callback, 1000 / 60);
9 | };
10 | })();
11 |
12 | function AssetManager() {
13 | this.successCount = 0;
14 | this.errorCount = 0;
15 | this.cache = {};
16 | this.downloadQueue = [];
17 | }
18 |
19 | AssetManager.prototype.queueDownload = function(path) {
20 | this.downloadQueue.push(path);
21 | }
22 |
23 | AssetManager.prototype.downloadAll = function(callback) {
24 | if (this.downloadQueue.length === 0 && this.soundsQueue.length === 0) {
25 | callback();
26 | }
27 |
28 | for (var i = 0; i < this.downloadQueue.length; i++) {
29 | var path = this.downloadQueue[i];
30 | var img = new Image();
31 | var that = this;
32 | img.addEventListener("load", function() {
33 | console.log(this.src + ' is loaded');
34 | that.successCount += 1;
35 | if (that.isDone()) {
36 | callback();
37 | }
38 | }, false);
39 | img.addEventListener("error", function() {
40 | that.errorCount += 1;
41 | if (that.isDone()) {
42 | callback();
43 | }
44 | }, false);
45 | img.src = path;
46 | this.cache[path] = img;
47 | }
48 | }
49 |
50 | AssetManager.prototype.getAsset = function(path) {
51 | return this.cache[path];
52 | }
53 |
54 | AssetManager.prototype.isDone = function() {
55 | return (this.downloadQueue.length == this.successCount + this.errorCount);
56 | }
57 |
58 | function Timer() {
59 | this.gameTime = 0;
60 | this.maxStep = 0.05;
61 | this.wallLastTimestamp = 0;
62 | }
63 |
64 | Timer.prototype.tick = function() {
65 | var wallCurrent = Date.now();
66 | var wallDelta = (wallCurrent - this.wallLastTimestamp) / 1000;
67 | this.wallLastTimestamp = wallCurrent;
68 |
69 | var gameDelta = Math.min(wallDelta, this.maxStep);
70 | this.gameTime += gameDelta;
71 | return gameDelta;
72 | }
73 |
74 | function GameEngine() {
75 | this.entities = [];
76 | this.ctx = null;
77 | this.click = null;
78 | this.mouse = null;
79 | this.timer = new Timer();
80 | this.surfaceWidth = null;
81 | this.surfaceHeight = null;
82 | this.halfSurfaceWidth = null;
83 | this.halfSurfaceHeight = null;
84 | }
85 |
86 | GameEngine.prototype.init = function(ctx) {
87 | console.log('game initialized');
88 | this.ctx = ctx;
89 | this.surfaceWidth = this.ctx.canvas.width;
90 | this.surfaceHeight = this.ctx.canvas.height;
91 | this.halfSurfaceWidth = this.surfaceWidth/2;
92 | this.halfSurfaceHeight = this.surfaceHeight/2;
93 | this.startInput();
94 | }
95 |
96 | GameEngine.prototype.start = function() {
97 | console.log("starting game");
98 | var that = this;
99 | (function gameLoop() {
100 | that.loop();
101 | requestAnimFrame(gameLoop, that.ctx.canvas);
102 | })();
103 | }
104 |
105 | GameEngine.prototype.startInput = function() {
106 | var getXandY = function(e) {
107 | var x = e.clientX - that.ctx.canvas.getBoundingClientRect().left - (that.ctx.canvas.width/2);
108 | var y = e.clientY - that.ctx.canvas.getBoundingClientRect().top - (that.ctx.canvas.height/2);
109 | return {x: x, y: y};
110 | }
111 |
112 | var that = this;
113 |
114 | this.ctx.canvas.addEventListener("click", function(e) {
115 | that.click = getXandY(e);
116 | e.stopPropagation();
117 | e.preventDefault();
118 | }, false);
119 |
120 | this.ctx.canvas.addEventListener("mousemove", function(e) {
121 | that.mouse = getXandY(e);
122 | }, false);
123 | }
124 |
125 | GameEngine.prototype.addEntity = function(entity) {
126 | this.entities.push(entity);
127 | }
128 |
129 | GameEngine.prototype.draw = function(callback) {
130 | this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
131 | this.ctx.save();
132 | this.ctx.translate(this.ctx.canvas.width/2, this.ctx.canvas.height/2);
133 | for (var i = 0; i < this.entities.length; i++) {
134 | this.entities[i].draw(this.ctx);
135 | }
136 | if (callback) {
137 | callback(this);
138 | }
139 | this.ctx.restore();
140 | }
141 |
142 | GameEngine.prototype.update = function() {
143 | var entitiesCount = this.entities.length;
144 |
145 | for (var i = 0; i < entitiesCount; i++) {
146 | var entity = this.entities[i];
147 |
148 | if (!entity.removeFromWorld) {
149 | entity.update();
150 | }
151 | }
152 |
153 | for (var i = this.entities.length-1; i >= 0; --i) {
154 | if (this.entities[i].removeFromWorld) {
155 | this.entities.splice(i, 1);
156 | }
157 | }
158 | }
159 |
160 | GameEngine.prototype.loop = function() {
161 | this.clockTick = this.timer.tick();
162 | this.update();
163 | this.draw();
164 | this.click = null;
165 | }
166 |
167 | function Entity(game, x, y) {
168 | this.game = game;
169 | this.x = x;
170 | this.y = y;
171 | this.removeFromWorld = false;
172 | }
173 |
174 | Entity.prototype.update = function() {
175 | }
176 |
177 | Entity.prototype.draw = function(ctx) {
178 | if (this.game.showOutlines && this.radius) {
179 | ctx.beginPath();
180 | ctx.strokeStyle = "green";
181 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
182 | ctx.stroke();
183 | ctx.closePath();
184 | }
185 | }
186 |
187 | Entity.prototype.drawSpriteCentered = function(ctx) {
188 | if (this.sprite && this.x && this.y) {
189 | var x = this.x - this.sprite.width/2;
190 | var y = this.y - this.sprite.height/2;
191 | ctx.drawImage(this.sprite, x, y);
192 | }
193 | }
194 |
195 | Entity.prototype.outsideScreen = function() {
196 | return (this.x > this.game.halfSurfaceWidth || this.x < -(this.game.halfSurfaceWidth) ||
197 | this.y > this.game.halfSurfaceHeight || this.y < -(this.game.halfSurfaceHeight));
198 | }
199 |
200 | Entity.prototype.rotateAndCache = function(image) {
201 | var offscreenCanvas = document.createElement('canvas');
202 | var size = Math.max(image.width, image.height);
203 | offscreenCanvas.width = size;
204 | offscreenCanvas.height = size;
205 | var offscreenCtx = offscreenCanvas.getContext('2d');
206 | offscreenCtx.save();
207 | offscreenCtx.translate(size/2, size/2);
208 | offscreenCtx.rotate(this.angle + Math.PI/2);
209 | offscreenCtx.drawImage(image, -(image.width/2), -(image.height/2));
210 | offscreenCtx.restore();
211 | //offscreenCtx.strokeStyle = "red";
212 | //offscreenCtx.strokeRect(0,0,size,size);
213 | return offscreenCanvas;
214 | }
215 |
216 | function Alien(game, radial_distance, angle) {
217 | Entity.call(this, game);
218 | this.radial_distance = radial_distance;
219 | this.angle = angle;
220 | this.speed = 100;
221 | this.sprite = this.rotateAndCache(ASSET_MANAGER.getAsset('img/alien.png'));
222 | this.radius = this.sprite.height/2;
223 | this.setCoords();
224 | }
225 | Alien.prototype = new Entity();
226 | Alien.prototype.constructor = Alien;
227 |
228 | Alien.prototype.setCoords = function() {
229 | this.x = this.radial_distance * Math.cos(this.angle);
230 | this.y = this.radial_distance * Math.sin(this.angle);
231 | }
232 |
233 | Alien.prototype.update = function() {
234 | this.setCoords();
235 | this.radial_distance -= this.speed * this.game.clockTick;
236 |
237 | Entity.prototype.update.call(this);
238 | }
239 |
240 | Alien.prototype.draw = function(ctx) {
241 | this.drawSpriteCentered(ctx);
242 |
243 | Entity.prototype.draw.call(this, ctx);
244 | }
245 |
246 | function Sentry(game) {
247 | this.distanceFromEarthCenter = 85;
248 | Entity.call(this, game, 0, this.distanceFromEarthCenter);
249 | this.sprite = ASSET_MANAGER.getAsset('img/sentry.png');
250 | this.radius = this.sprite.width / 2;
251 | this.angle = 0;
252 | }
253 | Sentry.prototype = new Entity();
254 | Sentry.prototype.constructor = Sentry;
255 |
256 | Sentry.prototype.update = function() {
257 | if (this.game.mouse) {
258 | this.angle = Math.atan2(this.game.mouse.y, this.game.mouse.x);
259 | if (this.angle < 0) {
260 | this.angle += Math.PI * 2;
261 | }
262 | this.x = (Math.cos(this.angle) * this.distanceFromEarthCenter);
263 | this.y = (Math.sin(this.angle) * this.distanceFromEarthCenter);
264 | }
265 | Entity.prototype.update.call(this);
266 | }
267 |
268 | Sentry.prototype.draw = function(ctx) {
269 | ctx.save();
270 | ctx.translate(this.x, this.y);
271 | ctx.rotate(this.angle + Math.PI/2);
272 | ctx.drawImage(this.sprite, -this.sprite.width/2, -this.sprite.height/2);
273 | ctx.restore();
274 |
275 | Entity.prototype.draw.call(this, ctx);
276 | }
277 |
278 | function Earth(game) {
279 | Entity.call(this, game, 0, 0);
280 | this.sprite = ASSET_MANAGER.getAsset('img/earth.png');
281 | }
282 | Earth.prototype = new Entity();
283 | Earth.prototype.constructor = Earth;
284 |
285 | Earth.RADIUS = 67;
286 |
287 | Earth.prototype.draw = function(ctx) {
288 | ctx.drawImage(this.sprite, this.x - this.sprite.width/2, this.y - this.sprite.height/2);
289 | }
290 |
291 | function EvilAliens() {
292 | GameEngine.call(this);
293 | //this.showOutlines = true;
294 | }
295 | EvilAliens.prototype = new GameEngine();
296 | EvilAliens.prototype.constructor = EvilAliens;
297 |
298 | EvilAliens.prototype.start = function() {
299 | this.sentry = new Sentry(this);
300 | this.earth = new Earth(this);
301 | this.addEntity(this.earth);
302 | this.addEntity(this.sentry);
303 | GameEngine.prototype.start.call(this);
304 | }
305 |
306 | EvilAliens.prototype.update = function() {
307 | if (this.lastAlienAddedAt == null || (this.timer.gameTime - this.lastAlienAddedAt) > 1) {
308 | this.addEntity(new Alien(this, this.ctx.canvas.width, Math.floor(Math.random() * Math.PI * 2)));
309 | this.lastAlienAddedAt = this.timer.gameTime;
310 | }
311 |
312 | GameEngine.prototype.update.call(this);
313 | }
314 |
315 | EvilAliens.prototype.draw = function() {
316 | GameEngine.prototype.draw.call(this);
317 | }
318 |
319 | var canvas = document.getElementById('surface');
320 | var ctx = canvas.getContext('2d');
321 | var game = new EvilAliens();
322 | var ASSET_MANAGER = new AssetManager();
323 |
324 | ASSET_MANAGER.queueDownload('img/alien.png');
325 | ASSET_MANAGER.queueDownload('img/earth.png');
326 | ASSET_MANAGER.queueDownload('img/sentry.png');
327 |
328 | ASSET_MANAGER.downloadAll(function() {
329 | game.init(ctx);
330 | game.start();
331 | });
--------------------------------------------------------------------------------
/static/phase08/scripts/app.js:
--------------------------------------------------------------------------------
1 | window.requestAnimFrame = (function(){
2 | return window.requestAnimationFrame ||
3 | window.webkitRequestAnimationFrame ||
4 | window.mozRequestAnimationFrame ||
5 | window.oRequestAnimationFrame ||
6 | window.msRequestAnimationFrame ||
7 | function(/* function */ callback, /* DOMElement */ element){
8 | window.setTimeout(callback, 1000 / 60);
9 | };
10 | })();
11 |
12 | function AssetManager() {
13 | this.successCount = 0;
14 | this.errorCount = 0;
15 | this.cache = {};
16 | this.downloadQueue = [];
17 | }
18 |
19 | AssetManager.prototype.queueDownload = function(path) {
20 | this.downloadQueue.push(path);
21 | }
22 | AssetManager.prototype.downloadAll = function(callback) {
23 | if (this.downloadQueue.length === 0 && this.soundsQueue.length === 0) {
24 | callback();
25 | }
26 |
27 | for (var i = 0; i < this.downloadQueue.length; i++) {
28 | var path = this.downloadQueue[i];
29 | var img = new Image();
30 | var that = this;
31 | img.addEventListener("load", function() {
32 | console.log(this.src + ' is loaded');
33 | that.successCount += 1;
34 | if (that.isDone()) {
35 | callback();
36 | }
37 | }, false);
38 | img.addEventListener("error", function() {
39 | that.errorCount += 1;
40 | if (that.isDone()) {
41 | callback();
42 | }
43 | }, false);
44 | img.src = path;
45 | this.cache[path] = img;
46 | }
47 | }
48 |
49 | AssetManager.prototype.getAsset = function(path) {
50 | return this.cache[path];
51 | }
52 |
53 | AssetManager.prototype.isDone = function() {
54 | return (this.downloadQueue.length == this.successCount + this.errorCount);
55 | }
56 |
57 | function Timer() {
58 | this.gameTime = 0;
59 | this.maxStep = 0.05;
60 | this.wallLastTimestamp = 0;
61 | }
62 |
63 | Timer.prototype.tick = function() {
64 | var wallCurrent = Date.now();
65 | var wallDelta = (wallCurrent - this.wallLastTimestamp) / 1000;
66 | this.wallLastTimestamp = wallCurrent;
67 |
68 | var gameDelta = Math.min(wallDelta, this.maxStep);
69 | this.gameTime += gameDelta;
70 | return gameDelta;
71 | }
72 |
73 | function GameEngine() {
74 | this.entities = [];
75 | this.ctx = null;
76 | this.click = null;
77 | this.mouse = null;
78 | this.timer = new Timer();
79 | this.surfaceWidth = null;
80 | this.surfaceHeight = null;
81 | this.halfSurfaceWidth = null;
82 | this.halfSurfaceHeight = null;
83 | }
84 |
85 | GameEngine.prototype.init = function(ctx) {
86 | console.log('game initialized');
87 | this.ctx = ctx;
88 | this.surfaceWidth = this.ctx.canvas.width;
89 | this.surfaceHeight = this.ctx.canvas.height;
90 | this.halfSurfaceWidth = this.surfaceWidth/2;
91 | this.halfSurfaceHeight = this.surfaceHeight/2;
92 | this.startInput();
93 | }
94 |
95 | GameEngine.prototype.start = function() {
96 | console.log("starting game");
97 | var that = this;
98 | (function gameLoop() {
99 | that.loop();
100 | requestAnimFrame(gameLoop, that.ctx.canvas);
101 | })();
102 | }
103 |
104 | GameEngine.prototype.startInput = function() {
105 | var getXandY = function(e) {
106 | var x = e.clientX - that.ctx.canvas.getBoundingClientRect().left - (that.ctx.canvas.width/2);
107 | var y = e.clientY - that.ctx.canvas.getBoundingClientRect().top - (that.ctx.canvas.height/2);
108 | return {x: x, y: y};
109 | }
110 |
111 | var that = this;
112 |
113 | this.ctx.canvas.addEventListener("click", function(e) {
114 | that.click = getXandY(e);
115 | e.stopPropagation();
116 | e.preventDefault();
117 | }, false);
118 |
119 | this.ctx.canvas.addEventListener("mousemove", function(e) {
120 | that.mouse = getXandY(e);
121 | }, false);
122 | }
123 |
124 | GameEngine.prototype.addEntity = function(entity) {
125 | this.entities.push(entity);
126 | }
127 |
128 | GameEngine.prototype.draw = function(callback) {
129 | this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
130 | this.ctx.save();
131 | this.ctx.translate(this.ctx.canvas.width/2, this.ctx.canvas.height/2);
132 | for (var i = 0; i < this.entities.length; i++) {
133 | this.entities[i].draw(this.ctx);
134 | }
135 | if (callback) {
136 | callback(this);
137 | }
138 | this.ctx.restore();
139 | }
140 |
141 | GameEngine.prototype.update = function() {
142 | var entitiesCount = this.entities.length;
143 |
144 | for (var i = 0; i < entitiesCount; i++) {
145 | var entity = this.entities[i];
146 |
147 | if (!entity.removeFromWorld) {
148 | entity.update();
149 | }
150 | }
151 |
152 | for (var i = this.entities.length-1; i >= 0; --i) {
153 | if (this.entities[i].removeFromWorld) {
154 | this.entities.splice(i, 1);
155 | }
156 | }
157 | }
158 |
159 | GameEngine.prototype.loop = function() {
160 | this.clockTick = this.timer.tick();
161 | this.update();
162 | this.draw();
163 | this.click = null;
164 | }
165 |
166 | function Entity(game, x, y) {
167 | this.game = game;
168 | this.x = x;
169 | this.y = y;
170 | this.removeFromWorld = false;
171 | }
172 |
173 | Entity.prototype.update = function() {
174 | }
175 |
176 | Entity.prototype.draw = function(ctx) {
177 | if (this.game.showOutlines && this.radius) {
178 | ctx.beginPath();
179 | ctx.strokeStyle = "green";
180 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
181 | ctx.stroke();
182 | ctx.closePath();
183 | }
184 | }
185 |
186 | Entity.prototype.drawSpriteCentered = function(ctx) {
187 | if (this.sprite && this.x && this.y) {
188 | var x = this.x - this.sprite.width/2;
189 | var y = this.y - this.sprite.height/2;
190 | ctx.drawImage(this.sprite, x, y);
191 | }
192 | }
193 |
194 | Entity.prototype.outsideScreen = function() {
195 | return (this.x > this.game.halfSurfaceWidth || this.x < -(this.game.halfSurfaceWidth) ||
196 | this.y > this.game.halfSurfaceHeight || this.y < -(this.game.halfSurfaceHeight));
197 | }
198 |
199 | Entity.prototype.rotateAndCache = function(image, angle) {
200 | var offscreenCanvas = document.createElement('canvas');
201 | var size = Math.max(image.width, image.height);
202 | offscreenCanvas.width = size;
203 | offscreenCanvas.height = size;
204 | var offscreenCtx = offscreenCanvas.getContext('2d');
205 | offscreenCtx.save();
206 | offscreenCtx.translate(size/2, size/2);
207 | offscreenCtx.rotate(angle + Math.PI/2);
208 | offscreenCtx.drawImage(image, -(image.width/2), -(image.height/2));
209 | offscreenCtx.restore();
210 | //offscreenCtx.strokeStyle = "red";
211 | //offscreenCtx.strokeRect(0,0,size,size);
212 | return offscreenCanvas;
213 | }
214 |
215 | function Alien(game, radial_distance, angle) {
216 | Entity.call(this, game);
217 | this.radial_distance = radial_distance;
218 | this.angle = angle;
219 | this.speed = 100;
220 | this.sprite = this.rotateAndCache(ASSET_MANAGER.getAsset('img/alien.png'), this.angle);
221 | this.radius = this.sprite.height/2;
222 | this.setCoords();
223 | }
224 | Alien.prototype = new Entity();
225 | Alien.prototype.constructor = Alien;
226 |
227 | Alien.prototype.setCoords = function() {
228 | this.x = this.radial_distance * Math.cos(this.angle);
229 | this.y = this.radial_distance * Math.sin(this.angle);
230 | }
231 |
232 | Alien.prototype.update = function() {
233 | this.setCoords();
234 | this.radial_distance -= this.speed * this.game.clockTick;
235 |
236 | Entity.prototype.update.call(this);
237 | }
238 |
239 | Alien.prototype.draw = function(ctx) {
240 | this.drawSpriteCentered(ctx);
241 |
242 | Entity.prototype.draw.call(this, ctx);
243 | }
244 |
245 | function Sentry(game) {
246 | this.distanceFromEarthCenter = 85;
247 | Entity.call(this, game, 0, this.distanceFromEarthCenter);
248 | this.sprite = ASSET_MANAGER.getAsset('img/sentry.png');
249 | this.radius = this.sprite.width / 2;
250 | this.angle = 0;
251 | }
252 | Sentry.prototype = new Entity();
253 | Sentry.prototype.constructor = Sentry;
254 |
255 | Sentry.prototype.update = function() {
256 | if (this.game.mouse) {
257 | this.angle = Math.atan2(this.game.mouse.y, this.game.mouse.x);
258 | if (this.angle < 0) {
259 | this.angle += Math.PI * 2;
260 | }
261 | this.x = (Math.cos(this.angle) * this.distanceFromEarthCenter);
262 | this.y = (Math.sin(this.angle) * this.distanceFromEarthCenter);
263 | }
264 | if (this.game.click) {
265 | this.shoot();
266 | }
267 | Entity.prototype.update.call(this);
268 | }
269 |
270 | Sentry.prototype.draw = function(ctx) {
271 | ctx.save();
272 | ctx.translate(this.x, this.y);
273 | ctx.rotate(this.angle + Math.PI/2);
274 | ctx.drawImage(this.sprite, -this.sprite.width/2, -this.sprite.height/2);
275 | ctx.restore();
276 |
277 | Entity.prototype.draw.call(this, ctx);
278 | }
279 |
280 | Sentry.prototype.shoot = function() {
281 | var bullet = new Bullet(this.game, this.x, this.y, this.angle, this.game.click);
282 | this.game.addEntity(bullet);
283 | }
284 |
285 | function Bullet(game, x, y, angle, explodesAt) {
286 | Entity.call(this, game, x, y);
287 | this.angle = angle;
288 | this.explodesAt = explodesAt;
289 | this.speed = 250;
290 | this.radial_distance = 95;
291 | this.sprite = this.rotateAndCache(ASSET_MANAGER.getAsset('img/bullet-single.png'), this.angle);
292 | }
293 | Bullet.prototype = new Entity();
294 | Bullet.prototype.constructor = Bullet;
295 |
296 | Bullet.prototype.update = function() {
297 | if (this.outsideScreen()) {
298 | this.removeFromWorld = true;
299 | } else {
300 | this.x = this.radial_distance * Math.cos(this.angle);
301 | this.y = this.radial_distance * Math.sin(this.angle);
302 | this.radial_distance += this.speed * this.game.clockTick;
303 | }
304 | }
305 |
306 | Bullet.prototype.draw = function(ctx) {
307 | this.drawSpriteCentered(ctx);
308 |
309 | Entity.prototype.draw.call(this, ctx);
310 | }
311 |
312 | function Earth(game) {
313 | Entity.call(this, game, 0, 0);
314 | this.sprite = ASSET_MANAGER.getAsset('img/earth.png');
315 | }
316 | Earth.prototype = new Entity();
317 | Earth.prototype.constructor = Earth;
318 |
319 | Earth.RADIUS = 67;
320 |
321 | Earth.prototype.draw = function(ctx) {
322 | ctx.drawImage(this.sprite, this.x - this.sprite.width/2, this.y - this.sprite.height/2);
323 | }
324 |
325 | function EvilAliens() {
326 | GameEngine.call(this);
327 | //this.showOutlines = true;
328 | }
329 | EvilAliens.prototype = new GameEngine();
330 | EvilAliens.prototype.constructor = EvilAliens;
331 |
332 | EvilAliens.prototype.start = function() {
333 | this.sentry = new Sentry(this);
334 | this.earth = new Earth(this);
335 | this.addEntity(this.earth);
336 | this.addEntity(this.sentry);
337 | GameEngine.prototype.start.call(this);
338 | }
339 |
340 | EvilAliens.prototype.update = function() {
341 | if (this.lastAlienAddedAt == null || (this.timer.gameTime - this.lastAlienAddedAt) > 1) {
342 | this.addEntity(new Alien(this, this.ctx.canvas.width, Math.floor(Math.random() * Math.PI * 2)));
343 | this.lastAlienAddedAt = this.timer.gameTime;
344 | }
345 |
346 | GameEngine.prototype.update.call(this);
347 | }
348 |
349 | EvilAliens.prototype.draw = function() {
350 | GameEngine.prototype.draw.call(this);
351 | }
352 |
353 | var canvas = document.getElementById('surface');
354 | var ctx = canvas.getContext('2d');
355 | var game = new EvilAliens();
356 | var ASSET_MANAGER = new AssetManager();
357 |
358 | ASSET_MANAGER.queueDownload('img/alien.png');
359 | ASSET_MANAGER.queueDownload('img/bullet-single.png');
360 | ASSET_MANAGER.queueDownload('img/earth.png');
361 | ASSET_MANAGER.queueDownload('img/sentry.png');
362 |
363 | ASSET_MANAGER.downloadAll(function() {
364 | game.init(ctx);
365 | game.start();
366 | });
--------------------------------------------------------------------------------
/static/phase09/scripts/app.js:
--------------------------------------------------------------------------------
1 | window.requestAnimFrame = (function(){
2 | return window.requestAnimationFrame ||
3 | window.webkitRequestAnimationFrame ||
4 | window.mozRequestAnimationFrame ||
5 | window.oRequestAnimationFrame ||
6 | window.msRequestAnimationFrame ||
7 | function(/* function */ callback, /* DOMElement */ element){
8 | window.setTimeout(callback, 1000 / 60);
9 | };
10 | })();
11 |
12 | function AssetManager() {
13 | this.successCount = 0;
14 | this.errorCount = 0;
15 | this.cache = {};
16 | this.downloadQueue = [];
17 | }
18 |
19 | AssetManager.prototype.queueDownload = function(path) {
20 | this.downloadQueue.push(path);
21 | }
22 |
23 | AssetManager.prototype.downloadAll = function(callback) {
24 | if (this.downloadQueue.length === 0 && this.soundsQueue.length === 0) {
25 | callback();
26 | }
27 |
28 | for (var i = 0; i < this.downloadQueue.length; i++) {
29 | var path = this.downloadQueue[i];
30 | var img = new Image();
31 | var that = this;
32 | img.addEventListener("load", function() {
33 | console.log(this.src + ' is loaded');
34 | that.successCount += 1;
35 | if (that.isDone()) {
36 | callback();
37 | }
38 | }, false);
39 | img.addEventListener("error", function() {
40 | that.errorCount += 1;
41 | if (that.isDone()) {
42 | callback();
43 | }
44 | }, false);
45 | img.src = path;
46 | this.cache[path] = img;
47 | }
48 | }
49 |
50 | AssetManager.prototype.getAsset = function(path) {
51 | return this.cache[path];
52 | }
53 |
54 | AssetManager.prototype.isDone = function() {
55 | return (this.downloadQueue.length == this.successCount + this.errorCount);
56 | }
57 |
58 | function Animation(spriteSheet, frameWidth, frameDuration, loop) {
59 | this.spriteSheet = spriteSheet;
60 | this.frameWidth = frameWidth;
61 | this.frameDuration = frameDuration;
62 | this.frameHeight= this.spriteSheet.height;
63 | this.totalTime = (this.spriteSheet.width / this.frameWidth) * this.frameDuration;
64 | this.elapsedTime = 0;
65 | this.loop = loop;
66 | }
67 |
68 | Animation.prototype.drawFrame = function(tick, ctx, x, y, scaleBy) {
69 | var scaleBy = scaleBy || 1;
70 | this.elapsedTime += tick;
71 | if (this.loop) {
72 | if (this.isDone()) {
73 | this.elapsedTime = 0;
74 | }
75 | } else if (this.isDone()) {
76 | return;
77 | }
78 | var index = this.currentFrame();
79 | var locX = x - (this.frameWidth/2) * scaleBy;
80 | var locY = y - (this.frameHeight/2) * scaleBy;
81 | ctx.drawImage(this.spriteSheet,
82 | index*this.frameWidth, 0, // source from sheet
83 | this.frameWidth, this.frameHeight,
84 | locX, locY,
85 | this.frameWidth*scaleBy,
86 | this.frameHeight*scaleBy);
87 | }
88 |
89 | Animation.prototype.currentFrame = function() {
90 | return Math.floor(this.elapsedTime / this.frameDuration);
91 | }
92 |
93 | Animation.prototype.isDone = function() {
94 | return (this.elapsedTime >= this.totalTime);
95 | }
96 |
97 | function Timer() {
98 | this.gameTime = 0;
99 | this.maxStep = 0.05;
100 | this.wallLastTimestamp = 0;
101 | }
102 |
103 | Timer.prototype.tick = function() {
104 | var wallCurrent = Date.now();
105 | var wallDelta = (wallCurrent - this.wallLastTimestamp) / 1000;
106 | this.wallLastTimestamp = wallCurrent;
107 |
108 | var gameDelta = Math.min(wallDelta, this.maxStep);
109 | this.gameTime += gameDelta;
110 | return gameDelta;
111 | }
112 |
113 | function GameEngine() {
114 | this.entities = [];
115 | this.ctx = null;
116 | this.click = null;
117 | this.mouse = null;
118 | this.timer = new Timer();
119 | this.surfaceWidth = null;
120 | this.surfaceHeight = null;
121 | this.halfSurfaceWidth = null;
122 | this.halfSurfaceHeight = null;
123 | }
124 |
125 | GameEngine.prototype.init = function(ctx) {
126 | console.log('game initialized');
127 | this.ctx = ctx;
128 | this.surfaceWidth = this.ctx.canvas.width;
129 | this.surfaceHeight = this.ctx.canvas.height;
130 | this.halfSurfaceWidth = this.surfaceWidth/2;
131 | this.halfSurfaceHeight = this.surfaceHeight/2;
132 | this.startInput();
133 | }
134 |
135 | GameEngine.prototype.start = function() {
136 | console.log("starting game");
137 | var that = this;
138 | (function gameLoop() {
139 | that.loop();
140 | requestAnimFrame(gameLoop, that.ctx.canvas);
141 | })();
142 | }
143 |
144 | GameEngine.prototype.startInput = function() {
145 | var getXandY = function(e) {
146 | var x = e.clientX - that.ctx.canvas.getBoundingClientRect().left - (that.ctx.canvas.width/2);
147 | var y = e.clientY - that.ctx.canvas.getBoundingClientRect().top - (that.ctx.canvas.height/2);
148 | return {x: x, y: y};
149 | }
150 |
151 | var that = this;
152 |
153 | this.ctx.canvas.addEventListener("click", function(e) {
154 | that.click = getXandY(e);
155 | e.stopPropagation();
156 | e.preventDefault();
157 | }, false);
158 |
159 | this.ctx.canvas.addEventListener("mousemove", function(e) {
160 | that.mouse = getXandY(e);
161 | }, false);
162 | }
163 |
164 | GameEngine.prototype.addEntity = function(entity) {
165 | this.entities.push(entity);
166 | }
167 |
168 | GameEngine.prototype.draw = function(callback) {
169 | this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
170 | this.ctx.save();
171 | this.ctx.translate(this.ctx.canvas.width/2, this.ctx.canvas.height/2);
172 | for (var i = 0; i < this.entities.length; i++) {
173 | this.entities[i].draw(this.ctx);
174 | }
175 | if (callback) {
176 | callback(this);
177 | }
178 | this.ctx.restore();
179 | }
180 |
181 | GameEngine.prototype.update = function() {
182 | var entitiesCount = this.entities.length;
183 |
184 | for (var i = 0; i < entitiesCount; i++) {
185 | var entity = this.entities[i];
186 |
187 | if (!entity.removeFromWorld) {
188 | entity.update();
189 | }
190 | }
191 |
192 | for (var i = this.entities.length-1; i >= 0; --i) {
193 | if (this.entities[i].removeFromWorld) {
194 | this.entities.splice(i, 1);
195 | }
196 | }
197 | }
198 |
199 | GameEngine.prototype.loop = function() {
200 | this.clockTick = this.timer.tick();
201 | this.update();
202 | this.draw();
203 | this.click = null;
204 | }
205 |
206 | function Entity(game, x, y) {
207 | this.game = game;
208 | this.x = x;
209 | this.y = y;
210 | this.removeFromWorld = false;
211 | }
212 |
213 | Entity.prototype.update = function() {
214 | }
215 |
216 | Entity.prototype.draw = function(ctx) {
217 | if (this.game.showOutlines && this.radius) {
218 | ctx.beginPath();
219 | ctx.strokeStyle = "green";
220 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
221 | ctx.stroke();
222 | ctx.closePath();
223 | }
224 | }
225 |
226 | Entity.prototype.drawSpriteCentered = function(ctx) {
227 | if (this.sprite && this.x && this.y) {
228 | var x = this.x - this.sprite.width/2;
229 | var y = this.y - this.sprite.height/2;
230 | ctx.drawImage(this.sprite, x, y);
231 | }
232 | }
233 |
234 | Entity.prototype.outsideScreen = function() {
235 | return (this.x > this.game.halfSurfaceWidth || this.x < -(this.game.halfSurfaceWidth) ||
236 | this.y > this.game.halfSurfaceHeight || this.y < -(this.game.halfSurfaceHeight));
237 | }
238 |
239 | Entity.prototype.rotateAndCache = function(image, angle) {
240 | var offscreenCanvas = document.createElement('canvas');
241 | var size = Math.max(image.width, image.height);
242 | offscreenCanvas.width = size;
243 | offscreenCanvas.height = size;
244 | var offscreenCtx = offscreenCanvas.getContext('2d');
245 | offscreenCtx.save();
246 | offscreenCtx.translate(size/2, size/2);
247 | offscreenCtx.rotate(angle + Math.PI/2);
248 | offscreenCtx.drawImage(image, -(image.width/2), -(image.height/2));
249 | offscreenCtx.restore();
250 | //offscreenCtx.strokeStyle = "red";
251 | //offscreenCtx.strokeRect(0,0,size,size);
252 | return offscreenCanvas;
253 | }
254 |
255 | function Alien(game, radial_distance, angle) {
256 | Entity.call(this, game);
257 | this.radial_distance = radial_distance;
258 | this.angle = angle;
259 | this.speed = 100;
260 | this.sprite = this.rotateAndCache(ASSET_MANAGER.getAsset('img/alien.png'), this.angle);
261 | this.radius = this.sprite.height/2;
262 | this.setCoords();
263 | }
264 | Alien.prototype = new Entity();
265 | Alien.prototype.constructor = Alien;
266 |
267 | Alien.prototype.setCoords = function() {
268 | this.x = this.radial_distance * Math.cos(this.angle);
269 | this.y = this.radial_distance * Math.sin(this.angle);
270 | }
271 |
272 | Alien.prototype.update = function() {
273 | this.setCoords();
274 | this.radial_distance -= this.speed * this.game.clockTick;
275 |
276 | Entity.prototype.update.call(this);
277 | }
278 |
279 | Alien.prototype.draw = function(ctx) {
280 | this.drawSpriteCentered(ctx);
281 |
282 | Entity.prototype.draw.call(this, ctx);
283 | }
284 |
285 | function Sentry(game) {
286 | this.distanceFromEarthCenter = 85;
287 | Entity.call(this, game, 0, this.distanceFromEarthCenter);
288 | this.sprite = ASSET_MANAGER.getAsset('img/sentry.png');
289 | this.radius = this.sprite.width / 2;
290 | this.angle = 0;
291 | }
292 | Sentry.prototype = new Entity();
293 | Sentry.prototype.constructor = Sentry;
294 |
295 | Sentry.prototype.update = function() {
296 | if (this.game.mouse) {
297 | this.angle = Math.atan2(this.game.mouse.y, this.game.mouse.x);
298 | if (this.angle < 0) {
299 | this.angle += Math.PI * 2;
300 | }
301 | this.x = (Math.cos(this.angle) * this.distanceFromEarthCenter);
302 | this.y = (Math.sin(this.angle) * this.distanceFromEarthCenter);
303 | }
304 | if (this.game.click) {
305 | this.shoot();
306 | }
307 | Entity.prototype.update.call(this);
308 | }
309 |
310 | Sentry.prototype.draw = function(ctx) {
311 | ctx.save();
312 | ctx.translate(this.x, this.y);
313 | ctx.rotate(this.angle + Math.PI/2);
314 | ctx.drawImage(this.sprite, -this.sprite.width/2, -this.sprite.height/2);
315 | ctx.restore();
316 |
317 | Entity.prototype.draw.call(this, ctx);
318 | }
319 |
320 | Sentry.prototype.shoot = function() {
321 | var bullet = new Bullet(this.game, this.x, this.y, this.angle, this.game.click);
322 | this.game.addEntity(bullet);
323 | }
324 |
325 | function Bullet(game, x, y, angle, explodesAt) {
326 | Entity.call(this, game, x, y);
327 | this.angle = angle;
328 | this.explodesAt = explodesAt;
329 | this.speed = 250;
330 | this.radial_distance = 95;
331 | this.sprite = ASSET_MANAGER.getAsset('img/bullet.png');
332 | this.animation = new Animation(this.sprite, 7, 0.05, true);
333 | }
334 | Bullet.prototype = new Entity();
335 | Bullet.prototype.constructor = Bullet;
336 |
337 | Bullet.prototype.update = function() {
338 | if (this.outsideScreen()) {
339 | this.removeFromWorld = true;
340 | } else if (Math.abs(this.x) >= Math.abs(this.explodesAt.x) || Math.abs(this.y) >= Math.abs(this.explodesAt.y)) {
341 | this.game.addEntity(new BulletExplosion(this.game, this.explodesAt.x, this.explodesAt.y));
342 | this.removeFromWorld = true;
343 | } else {
344 | this.x = this.radial_distance * Math.cos(this.angle);
345 | this.y = this.radial_distance * Math.sin(this.angle);
346 | this.radial_distance += this.speed * this.game.clockTick;
347 | }
348 | }
349 |
350 | Bullet.prototype.draw = function(ctx) {
351 | ctx.save();
352 | ctx.translate(this.x, this.y);
353 | ctx.rotate(this.angle + Math.PI/2);
354 | ctx.translate(-this.x, -this.y);
355 | this.animation.drawFrame(this.game.clockTick, ctx, this.x, this.y);
356 | ctx.restore();
357 |
358 | Entity.prototype.draw.call(this, ctx);
359 | }
360 |
361 | function BulletExplosion(game, x, y) {
362 | Entity.call(this, game, x, y);
363 | this.sprite = ASSET_MANAGER.getAsset('img/explosion.png');
364 | this.animation = new Animation(this.sprite, 34, 0.05);
365 | this.radius = this.animation.frameWidth / 2;
366 | }
367 | BulletExplosion.prototype = new Entity();
368 | BulletExplosion.prototype.constructor = BulletExplosion;
369 |
370 | BulletExplosion.prototype.update = function() {
371 | Entity.prototype.update.call(this);
372 |
373 | if (this.animation.isDone()) {
374 | this.removeFromWorld = true;
375 | return;
376 | }
377 |
378 | this.radius = (this.animation.frameWidth/2) * this.scaleFactor();
379 | }
380 |
381 | BulletExplosion.prototype.scaleFactor = function() {
382 | return 1 + (this.animation.currentFrame() / 3);
383 | }
384 |
385 | BulletExplosion.prototype.draw = function(ctx) {
386 | this.animation.drawFrame(this.game.clockTick, ctx, this.x, this.y, this.scaleFactor());
387 |
388 | Entity.prototype.draw.call(this, ctx);
389 | }
390 |
391 | function Earth(game) {
392 | Entity.call(this, game, 0, 0);
393 | this.sprite = ASSET_MANAGER.getAsset('img/earth.png');
394 | }
395 | Earth.prototype = new Entity();
396 | Earth.prototype.constructor = Earth;
397 |
398 | Earth.RADIUS = 67;
399 |
400 | Earth.prototype.draw = function(ctx) {
401 | ctx.drawImage(this.sprite, this.x - this.sprite.width/2, this.y - this.sprite.height/2);
402 | }
403 |
404 | function EvilAliens() {
405 | GameEngine.call(this);
406 | //this.showOutlines = true;
407 | }
408 | EvilAliens.prototype = new GameEngine();
409 | EvilAliens.prototype.constructor = EvilAliens;
410 |
411 | EvilAliens.prototype.start = function() {
412 | this.sentry = new Sentry(this);
413 | this.earth = new Earth(this);
414 | this.addEntity(this.earth);
415 | this.addEntity(this.sentry);
416 | GameEngine.prototype.start.call(this);
417 | }
418 |
419 | EvilAliens.prototype.update = function() {
420 | if (this.lastAlienAddedAt == null || (this.timer.gameTime - this.lastAlienAddedAt) > 1) {
421 | this.addEntity(new Alien(this, this.ctx.canvas.width, Math.floor(Math.random() * Math.PI * 2)));
422 | this.lastAlienAddedAt = this.timer.gameTime;
423 | }
424 |
425 | GameEngine.prototype.update.call(this);
426 | }
427 |
428 | EvilAliens.prototype.draw = function() {
429 | GameEngine.prototype.draw.call(this);
430 | }
431 |
432 |
433 | var canvas = document.getElementById('surface');
434 | var ctx = canvas.getContext('2d');
435 | var game = new EvilAliens();
436 | var ASSET_MANAGER = new AssetManager();
437 |
438 | ASSET_MANAGER.queueDownload('img/alien.png');
439 | ASSET_MANAGER.queueDownload('img/bullet.png');
440 | ASSET_MANAGER.queueDownload('img/earth.png');
441 | ASSET_MANAGER.queueDownload('img/sentry.png');
442 | ASSET_MANAGER.queueDownload('img/explosion.png');
443 |
444 | ASSET_MANAGER.downloadAll(function() {
445 | game.init(ctx);
446 | game.start();
447 | });
--------------------------------------------------------------------------------
/static/phase10/scripts/app.js:
--------------------------------------------------------------------------------
1 | soundManager.url = 'swf/';
2 | soundManager.flashVersion = 9;
3 | soundManager.debugFlash = false;
4 | soundManager.debugMode = false;
5 |
6 | window.requestAnimFrame = (function(){
7 | return window.requestAnimationFrame ||
8 | window.webkitRequestAnimationFrame ||
9 | window.mozRequestAnimationFrame ||
10 | window.oRequestAnimationFrame ||
11 | window.msRequestAnimationFrame ||
12 | function(/* function */ callback, /* DOMElement */ element){
13 | window.setTimeout(callback, 1000 / 60);
14 | };
15 | })();
16 |
17 | function AssetManager() {
18 | this.successCount = 0;
19 | this.errorCount = 0;
20 | this.cache = {};
21 | this.downloadQueue = [];
22 | this.soundsQueue = [];
23 | }
24 |
25 | AssetManager.prototype.queueDownload = function(path) {
26 | this.downloadQueue.push(path);
27 | }
28 |
29 | AssetManager.prototype.queueSound = function(id, path) {
30 | this.soundsQueue.push({id: id, path: path});
31 | }
32 |
33 | AssetManager.prototype.downloadAll = function(callback) {
34 | if (this.downloadQueue.length === 0 && this.soundsQueue.length === 0) {
35 | callback();
36 | }
37 |
38 | this.downloadSounds(callback);
39 |
40 | for (var i = 0; i < this.downloadQueue.length; i++) {
41 | var path = this.downloadQueue[i];
42 | var img = new Image();
43 | var that = this;
44 | img.addEventListener("load", function() {
45 | console.log(this.src + ' is loaded');
46 | that.successCount += 1;
47 | if (that.isDone()) {
48 | callback();
49 | }
50 | }, false);
51 | img.addEventListener("error", function() {
52 | that.errorCount += 1;
53 | if (that.isDone()) {
54 | callback();
55 | }
56 | }, false);
57 | img.src = path;
58 | this.cache[path] = img;
59 | }
60 | }
61 |
62 | AssetManager.prototype.downloadSounds = function(callback) {
63 | var that = this;
64 | soundManager.onready(function() {
65 | console.log('soundManager ready');
66 | for (var i = 0; i < that.soundsQueue.length; i++) {
67 | that.downloadSound(that.soundsQueue[i].id, that.soundsQueue[i].path, callback);
68 | }
69 | });
70 | soundManager.ontimeout(function() {
71 | console.log('SM2 did not start');
72 | });
73 | }
74 |
75 | AssetManager.prototype.downloadSound = function(id, path, callback) {
76 | var that = this;
77 | this.cache[path] = soundManager.createSound({
78 | id: id,
79 | autoLoad: true,
80 | url: path,
81 | onload: function() {
82 | console.log(this.url + ' is loaded');
83 | that.successCount += 1;
84 | if (that.isDone()) {
85 | callback();
86 | }
87 | }
88 | });
89 | }
90 |
91 | AssetManager.prototype.getSound = function(path) {
92 | return this.cache[path];
93 | }
94 |
95 | AssetManager.prototype.getAsset = function(path) {
96 | return this.cache[path];
97 | }
98 |
99 | AssetManager.prototype.isDone = function() {
100 | return ((this.downloadQueue.length + this.soundsQueue.length) == this.successCount + this.errorCount);
101 | }
102 |
103 | function Animation(spriteSheet, frameWidth, frameDuration, loop) {
104 | this.spriteSheet = spriteSheet;
105 | this.frameWidth = frameWidth;
106 | this.frameDuration = frameDuration;
107 | this.frameHeight= this.spriteSheet.height;
108 | this.totalTime = (this.spriteSheet.width / this.frameWidth) * this.frameDuration;
109 | this.elapsedTime = 0;
110 | this.loop = loop;
111 | }
112 |
113 | Animation.prototype.drawFrame = function(tick, ctx, x, y, scaleBy) {
114 | var scaleBy = scaleBy || 1;
115 | this.elapsedTime += tick;
116 | if (this.loop) {
117 | if (this.isDone()) {
118 | this.elapsedTime = 0;
119 | }
120 | } else if (this.isDone()) {
121 | return;
122 | }
123 | var index = this.currentFrame();
124 | var locX = x - (this.frameWidth/2) * scaleBy;
125 | var locY = y - (this.frameHeight/2) * scaleBy;
126 | ctx.drawImage(this.spriteSheet,
127 | index*this.frameWidth, 0, // source from sheet
128 | this.frameWidth, this.frameHeight,
129 | locX, locY,
130 | this.frameWidth*scaleBy,
131 | this.frameHeight*scaleBy);
132 | }
133 |
134 | Animation.prototype.currentFrame = function() {
135 | return Math.floor(this.elapsedTime / this.frameDuration);
136 | }
137 |
138 | Animation.prototype.isDone = function() {
139 | return (this.elapsedTime >= this.totalTime);
140 | }
141 |
142 | function Timer() {
143 | this.gameTime = 0;
144 | this.maxStep = 0.05;
145 | this.wallLastTimestamp = 0;
146 | }
147 |
148 | Timer.prototype.tick = function() {
149 | var wallCurrent = Date.now();
150 | var wallDelta = (wallCurrent - this.wallLastTimestamp) / 1000;
151 | this.wallLastTimestamp = wallCurrent;
152 |
153 | var gameDelta = Math.min(wallDelta, this.maxStep);
154 | this.gameTime += gameDelta;
155 | return gameDelta;
156 | }
157 |
158 | function GameEngine() {
159 | this.entities = [];
160 | this.ctx = null;
161 | this.click = null;
162 | this.mouse = null;
163 | this.timer = new Timer();
164 | this.surfaceWidth = null;
165 | this.surfaceHeight = null;
166 | this.halfSurfaceWidth = null;
167 | this.halfSurfaceHeight = null;
168 | }
169 |
170 | GameEngine.prototype.init = function(ctx) {
171 | console.log('game initialized');
172 | this.ctx = ctx;
173 | this.surfaceWidth = this.ctx.canvas.width;
174 | this.surfaceHeight = this.ctx.canvas.height;
175 | this.halfSurfaceWidth = this.surfaceWidth/2;
176 | this.halfSurfaceHeight = this.surfaceHeight/2;
177 | this.startInput();
178 | }
179 |
180 | GameEngine.prototype.start = function() {
181 | console.log("starting game");
182 | var that = this;
183 | (function gameLoop() {
184 | that.loop();
185 | requestAnimFrame(gameLoop, that.ctx.canvas);
186 | })();
187 | }
188 |
189 | GameEngine.prototype.startInput = function() {
190 | var getXandY = function(e) {
191 | var x = e.clientX - that.ctx.canvas.getBoundingClientRect().left - (that.ctx.canvas.width/2);
192 | var y = e.clientY - that.ctx.canvas.getBoundingClientRect().top - (that.ctx.canvas.height/2);
193 | return {x: x, y: y};
194 | }
195 |
196 | var that = this;
197 |
198 | this.ctx.canvas.addEventListener("click", function(e) {
199 | that.click = getXandY(e);
200 | e.stopPropagation();
201 | e.preventDefault();
202 | }, false);
203 |
204 | this.ctx.canvas.addEventListener("mousemove", function(e) {
205 | that.mouse = getXandY(e);
206 | }, false);
207 | }
208 |
209 | GameEngine.prototype.addEntity = function(entity) {
210 | this.entities.push(entity);
211 | }
212 |
213 | GameEngine.prototype.draw = function(callback) {
214 | this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
215 | this.ctx.save();
216 | this.ctx.translate(this.ctx.canvas.width/2, this.ctx.canvas.height/2);
217 | for (var i = 0; i < this.entities.length; i++) {
218 | this.entities[i].draw(this.ctx);
219 | }
220 | if (callback) {
221 | callback(this);
222 | }
223 | this.ctx.restore();
224 | }
225 |
226 | GameEngine.prototype.update = function() {
227 | var entitiesCount = this.entities.length;
228 |
229 | for (var i = 0; i < entitiesCount; i++) {
230 | var entity = this.entities[i];
231 |
232 | if (!entity.removeFromWorld) {
233 | entity.update();
234 | }
235 | }
236 |
237 | for (var i = this.entities.length-1; i >= 0; --i) {
238 | if (this.entities[i].removeFromWorld) {
239 | this.entities.splice(i, 1);
240 | }
241 | }
242 | }
243 |
244 | GameEngine.prototype.loop = function() {
245 | this.clockTick = this.timer.tick();
246 | this.update();
247 | this.draw();
248 | this.click = null;
249 | }
250 |
251 | function Entity(game, x, y) {
252 | this.game = game;
253 | this.x = x;
254 | this.y = y;
255 | this.removeFromWorld = false;
256 | }
257 |
258 | Entity.prototype.update = function() {
259 | }
260 |
261 | Entity.prototype.draw = function(ctx) {
262 | if (this.game.showOutlines && this.radius) {
263 | ctx.beginPath();
264 | ctx.strokeStyle = "green";
265 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
266 | ctx.stroke();
267 | ctx.closePath();
268 | }
269 | }
270 |
271 | Entity.prototype.drawSpriteCentered = function(ctx) {
272 | if (this.sprite && this.x && this.y) {
273 | var x = this.x - this.sprite.width/2;
274 | var y = this.y - this.sprite.height/2;
275 | ctx.drawImage(this.sprite, x, y);
276 | }
277 | }
278 |
279 | Entity.prototype.outsideScreen = function() {
280 | return (this.x > this.game.halfSurfaceWidth || this.x < -(this.game.halfSurfaceWidth) ||
281 | this.y > this.game.halfSurfaceHeight || this.y < -(this.game.halfSurfaceHeight));
282 | }
283 |
284 | Entity.prototype.rotateAndCache = function(image, angle) {
285 | var offscreenCanvas = document.createElement('canvas');
286 | var size = Math.max(image.width, image.height);
287 | offscreenCanvas.width = size;
288 | offscreenCanvas.height = size;
289 | var offscreenCtx = offscreenCanvas.getContext('2d');
290 | offscreenCtx.save();
291 | offscreenCtx.translate(size/2, size/2);
292 | offscreenCtx.rotate(angle + Math.PI/2);
293 | offscreenCtx.drawImage(image, -(image.width/2), -(image.height/2));
294 | offscreenCtx.restore();
295 | //offscreenCtx.strokeStyle = "red";
296 | //offscreenCtx.strokeRect(0,0,size,size);
297 | return offscreenCanvas;
298 | }
299 |
300 | function Alien(game, radial_distance, angle) {
301 | Entity.call(this, game);
302 | this.radial_distance = radial_distance;
303 | this.angle = angle;
304 | this.speed = 100;
305 | this.sprite = this.rotateAndCache(ASSET_MANAGER.getAsset('img/alien.png'), this.angle);
306 | this.radius = this.sprite.height/2;
307 | this.setCoords();
308 | }
309 | Alien.prototype = new Entity();
310 | Alien.prototype.constructor = Alien;
311 |
312 | Alien.prototype.setCoords = function() {
313 | this.x = this.radial_distance * Math.cos(this.angle);
314 | this.y = this.radial_distance * Math.sin(this.angle);
315 | }
316 |
317 | Alien.prototype.update = function() {
318 | this.setCoords();
319 | this.radial_distance -= this.speed * this.game.clockTick;
320 |
321 | Entity.prototype.update.call(this);
322 | }
323 |
324 | Alien.prototype.draw = function(ctx) {
325 | this.drawSpriteCentered(ctx);
326 |
327 | Entity.prototype.draw.call(this, ctx);
328 | }
329 |
330 | function Sentry(game) {
331 | this.distanceFromEarthCenter = 85;
332 | Entity.call(this, game, 0, this.distanceFromEarthCenter);
333 | this.sprite = ASSET_MANAGER.getAsset('img/sentry.png');
334 | this.radius = this.sprite.width / 2;
335 | this.angle = 0;
336 | }
337 | Sentry.prototype = new Entity();
338 | Sentry.prototype.constructor = Sentry;
339 |
340 | Sentry.prototype.update = function() {
341 | if (this.game.mouse) {
342 | this.angle = Math.atan2(this.game.mouse.y, this.game.mouse.x);
343 | if (this.angle < 0) {
344 | this.angle += Math.PI * 2;
345 | }
346 | this.x = (Math.cos(this.angle) * this.distanceFromEarthCenter);
347 | this.y = (Math.sin(this.angle) * this.distanceFromEarthCenter);
348 | }
349 | if (this.game.click) {
350 | this.shoot();
351 | }
352 | Entity.prototype.update.call(this);
353 | }
354 |
355 | Sentry.prototype.draw = function(ctx) {
356 | ctx.save();
357 | ctx.translate(this.x, this.y);
358 | ctx.rotate(this.angle + Math.PI/2);
359 | ctx.drawImage(this.sprite, -this.sprite.width/2, -this.sprite.height/2);
360 | ctx.restore();
361 |
362 | Entity.prototype.draw.call(this, ctx);
363 | }
364 |
365 | Sentry.prototype.shoot = function() {
366 | var bullet = new Bullet(this.game, this.x, this.y, this.angle, this.game.click);
367 | this.game.addEntity(bullet);
368 | ASSET_MANAGER.getSound('audio/bullet.mp3').play();
369 | }
370 |
371 | function Bullet(game, x, y, angle, explodesAt) {
372 | Entity.call(this, game, x, y);
373 | this.angle = angle;
374 | this.explodesAt = explodesAt;
375 | this.speed = 250;
376 | this.radial_distance = 95;
377 | this.sprite = ASSET_MANAGER.getAsset('img/bullet.png');
378 | this.animation = new Animation(this.sprite, 7, 0.05, true);
379 | }
380 | Bullet.prototype = new Entity();
381 | Bullet.prototype.constructor = Bullet;
382 |
383 | Bullet.prototype.update = function() {
384 | if (this.outsideScreen()) {
385 | this.removeFromWorld = true;
386 | } else if (Math.abs(this.x) >= Math.abs(this.explodesAt.x) || Math.abs(this.y) >= Math.abs(this.explodesAt.y)) {
387 | ASSET_MANAGER.getSound('audio/bullet_boom.mp3').play();
388 | this.game.addEntity(new BulletExplosion(this.game, this.explodesAt.x, this.explodesAt.y));
389 | this.removeFromWorld = true;
390 | } else {
391 | this.x = this.radial_distance * Math.cos(this.angle);
392 | this.y = this.radial_distance * Math.sin(this.angle);
393 | this.radial_distance += this.speed * this.game.clockTick;
394 | }
395 | }
396 |
397 | Bullet.prototype.draw = function(ctx) {
398 | ctx.save();
399 | ctx.translate(this.x, this.y);
400 | ctx.rotate(this.angle + Math.PI/2);
401 | ctx.translate(-this.x, -this.y);
402 | this.animation.drawFrame(this.game.clockTick, ctx, this.x, this.y);
403 | ctx.restore();
404 |
405 | Entity.prototype.draw.call(this, ctx);
406 | }
407 |
408 | function BulletExplosion(game, x, y) {
409 | Entity.call(this, game, x, y);
410 | this.sprite = ASSET_MANAGER.getAsset('img/explosion.png');
411 | this.animation = new Animation(this.sprite, 34, 0.05);
412 | this.radius = this.animation.frameWidth / 2;
413 | }
414 | BulletExplosion.prototype = new Entity();
415 | BulletExplosion.prototype.constructor = BulletExplosion;
416 |
417 | BulletExplosion.prototype.update = function() {
418 | Entity.prototype.update.call(this);
419 |
420 | if (this.animation.isDone()) {
421 | this.removeFromWorld = true;
422 | return;
423 | }
424 |
425 | this.radius = (this.animation.frameWidth/2) * this.scaleFactor();
426 | }
427 |
428 | BulletExplosion.prototype.scaleFactor = function() {
429 | return 1 + (this.animation.currentFrame() / 3);
430 | }
431 |
432 | BulletExplosion.prototype.draw = function(ctx) {
433 | this.animation.drawFrame(this.game.clockTick, ctx, this.x, this.y, this.scaleFactor());
434 |
435 | Entity.prototype.draw.call(this, ctx);
436 | }
437 |
438 | function Earth(game) {
439 | Entity.call(this, game, 0, 0);
440 | this.sprite = ASSET_MANAGER.getAsset('img/earth.png');
441 | }
442 | Earth.prototype = new Entity();
443 | Earth.prototype.constructor = Earth;
444 |
445 | Earth.RADIUS = 67;
446 |
447 | Earth.prototype.draw = function(ctx) {
448 | ctx.drawImage(this.sprite, this.x - this.sprite.width/2, this.y - this.sprite.height/2);
449 | }
450 |
451 | function EvilAliens() {
452 | GameEngine.call(this);
453 | //this.showOutlines = true;
454 | }
455 | EvilAliens.prototype = new GameEngine();
456 | EvilAliens.prototype.constructor = EvilAliens;
457 |
458 | EvilAliens.prototype.start = function() {
459 | this.sentry = new Sentry(this);
460 | this.earth = new Earth(this);
461 | this.addEntity(this.earth);
462 | this.addEntity(this.sentry);
463 | GameEngine.prototype.start.call(this);
464 | }
465 |
466 | EvilAliens.prototype.update = function() {
467 | if (this.lastAlienAddedAt == null || (this.timer.gameTime - this.lastAlienAddedAt) > 1) {
468 | this.addEntity(new Alien(this, this.ctx.canvas.width, Math.floor(Math.random() * Math.PI * 2)));
469 | this.lastAlienAddedAt = this.timer.gameTime;
470 | }
471 |
472 | GameEngine.prototype.update.call(this);
473 | }
474 |
475 | EvilAliens.prototype.draw = function() {
476 | GameEngine.prototype.draw.call(this);
477 | }
478 |
479 | var canvas = document.getElementById('surface');
480 | var ctx = canvas.getContext('2d');
481 | var game = new EvilAliens();
482 | var ASSET_MANAGER = new AssetManager();
483 |
484 | ASSET_MANAGER.queueDownload('img/alien.png');
485 | ASSET_MANAGER.queueDownload('img/bullet.png');
486 | ASSET_MANAGER.queueDownload('img/earth.png');
487 | ASSET_MANAGER.queueDownload('img/sentry.png');
488 | ASSET_MANAGER.queueDownload('img/explosion.png');
489 | ASSET_MANAGER.queueSound('alien-boom', 'audio/alien_boom.mp3');
490 | ASSET_MANAGER.queueSound('bullet-boom', 'audio/bullet_boom.mp3');
491 | ASSET_MANAGER.queueSound('bullet', 'audio/bullet.mp3');
492 |
493 | ASSET_MANAGER.downloadAll(function() {
494 | game.init(ctx);
495 | game.start();
496 | });
--------------------------------------------------------------------------------
/static/phase11/scripts/app.js:
--------------------------------------------------------------------------------
1 | soundManager.url = 'swf/';
2 | soundManager.flashVersion = 9;
3 | soundManager.debugFlash = false;
4 | soundManager.debugMode = false;
5 |
6 | window.requestAnimFrame = (function(){
7 | return window.requestAnimationFrame ||
8 | window.webkitRequestAnimationFrame ||
9 | window.mozRequestAnimationFrame ||
10 | window.oRequestAnimationFrame ||
11 | window.msRequestAnimationFrame ||
12 | function(/* function */ callback, /* DOMElement */ element){
13 | window.setTimeout(callback, 1000 / 60);
14 | };
15 | })();
16 |
17 | function AssetManager() {
18 | this.successCount = 0;
19 | this.errorCount = 0;
20 | this.cache = {};
21 | this.downloadQueue = [];
22 | this.soundsQueue = [];
23 | }
24 |
25 | AssetManager.prototype.queueDownload = function(path) {
26 | this.downloadQueue.push(path);
27 | }
28 |
29 | AssetManager.prototype.queueSound = function(id, path) {
30 | this.soundsQueue.push({id: id, path: path});
31 | }
32 |
33 | AssetManager.prototype.downloadAll = function(callback) {
34 | if (this.downloadQueue.length === 0 && this.soundsQueue.length === 0) {
35 | callback();
36 | }
37 |
38 | this.downloadSounds(callback);
39 |
40 | for (var i = 0; i < this.downloadQueue.length; i++) {
41 | var path = this.downloadQueue[i];
42 | var img = new Image();
43 | var that = this;
44 | img.addEventListener("load", function() {
45 | console.log(this.src + ' is loaded');
46 | that.successCount += 1;
47 | if (that.isDone()) {
48 | callback();
49 | }
50 | }, false);
51 | img.addEventListener("error", function() {
52 | that.errorCount += 1;
53 | if (that.isDone()) {
54 | callback();
55 | }
56 | }, false);
57 | img.src = path;
58 | this.cache[path] = img;
59 | }
60 | }
61 |
62 | AssetManager.prototype.downloadSounds = function(callback) {
63 | var that = this;
64 | soundManager.onready(function() {
65 | console.log('soundManager ready');
66 | for (var i = 0; i < that.soundsQueue.length; i++) {
67 | that.downloadSound(that.soundsQueue[i].id, that.soundsQueue[i].path, callback);
68 | }
69 | });
70 | soundManager.ontimeout(function() {
71 | console.log('SM2 did not start');
72 | });
73 | }
74 |
75 | AssetManager.prototype.downloadSound = function(id, path, callback) {
76 | var that = this;
77 | this.cache[path] = soundManager.createSound({
78 | id: id,
79 | autoLoad: true,
80 | url: path,
81 | onload: function() {
82 | console.log(this.url + ' is loaded');
83 | that.successCount += 1;
84 | if (that.isDone()) {
85 | callback();
86 | }
87 | }
88 | });
89 | }
90 |
91 | AssetManager.prototype.getSound = function(path) {
92 | return this.cache[path];
93 | }
94 |
95 | AssetManager.prototype.getAsset = function(path) {
96 | return this.cache[path];
97 | }
98 |
99 | AssetManager.prototype.isDone = function() {
100 | return ((this.downloadQueue.length + this.soundsQueue.length) == this.successCount + this.errorCount);
101 | }
102 |
103 | function Animation(spriteSheet, frameWidth, frameDuration, loop) {
104 | this.spriteSheet = spriteSheet;
105 | this.frameWidth = frameWidth;
106 | this.frameDuration = frameDuration;
107 | this.frameHeight= this.spriteSheet.height;
108 | this.totalTime = (this.spriteSheet.width / this.frameWidth) * this.frameDuration;
109 | this.elapsedTime = 0;
110 | this.loop = loop;
111 | }
112 |
113 | Animation.prototype.drawFrame = function(tick, ctx, x, y, scaleBy) {
114 | var scaleBy = scaleBy || 1;
115 | this.elapsedTime += tick;
116 | if (this.loop) {
117 | if (this.isDone()) {
118 | this.elapsedTime = 0;
119 | }
120 | } else if (this.isDone()) {
121 | return;
122 | }
123 | var index = this.currentFrame();
124 | var locX = x - (this.frameWidth/2) * scaleBy;
125 | var locY = y - (this.frameHeight/2) * scaleBy;
126 | ctx.drawImage(this.spriteSheet,
127 | index*this.frameWidth, 0, // source from sheet
128 | this.frameWidth, this.frameHeight,
129 | locX, locY,
130 | this.frameWidth*scaleBy,
131 | this.frameHeight*scaleBy);
132 | }
133 |
134 | Animation.prototype.currentFrame = function() {
135 | return Math.floor(this.elapsedTime / this.frameDuration);
136 | }
137 |
138 | Animation.prototype.isDone = function() {
139 | return (this.elapsedTime >= this.totalTime);
140 | }
141 |
142 | function Timer() {
143 | this.gameTime = 0;
144 | this.maxStep = 0.05;
145 | this.wallLastTimestamp = 0;
146 | }
147 |
148 | Timer.prototype.tick = function() {
149 | var wallCurrent = Date.now();
150 | var wallDelta = (wallCurrent - this.wallLastTimestamp) / 1000;
151 | this.wallLastTimestamp = wallCurrent;
152 |
153 | var gameDelta = Math.min(wallDelta, this.maxStep);
154 | this.gameTime += gameDelta;
155 | return gameDelta;
156 | }
157 |
158 | function GameEngine() {
159 | this.entities = [];
160 | this.ctx = null;
161 | this.click = null;
162 | this.mouse = null;
163 | this.timer = new Timer();
164 | this.surfaceWidth = null;
165 | this.surfaceHeight = null;
166 | this.halfSurfaceWidth = null;
167 | this.halfSurfaceHeight = null;
168 | }
169 |
170 | GameEngine.prototype.init = function(ctx) {
171 | console.log('game initialized');
172 | this.ctx = ctx;
173 | this.surfaceWidth = this.ctx.canvas.width;
174 | this.surfaceHeight = this.ctx.canvas.height;
175 | this.halfSurfaceWidth = this.surfaceWidth/2;
176 | this.halfSurfaceHeight = this.surfaceHeight/2;
177 | this.startInput();
178 | }
179 |
180 | GameEngine.prototype.start = function() {
181 | console.log("starting game");
182 | var that = this;
183 | (function gameLoop() {
184 | that.loop();
185 | requestAnimFrame(gameLoop, that.ctx.canvas);
186 | })();
187 | }
188 |
189 | GameEngine.prototype.startInput = function() {
190 | var getXandY = function(e) {
191 | var x = e.clientX - that.ctx.canvas.getBoundingClientRect().left - (that.ctx.canvas.width/2);
192 | var y = e.clientY - that.ctx.canvas.getBoundingClientRect().top - (that.ctx.canvas.height/2);
193 | return {x: x, y: y};
194 | }
195 |
196 | var that = this;
197 |
198 | this.ctx.canvas.addEventListener("click", function(e) {
199 | that.click = getXandY(e);
200 | e.stopPropagation();
201 | e.preventDefault();
202 | }, false);
203 |
204 | this.ctx.canvas.addEventListener("mousemove", function(e) {
205 | that.mouse = getXandY(e);
206 | }, false);
207 | }
208 |
209 | GameEngine.prototype.addEntity = function(entity) {
210 | this.entities.push(entity);
211 | }
212 |
213 | GameEngine.prototype.draw = function(callback) {
214 | this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
215 | this.ctx.save();
216 | this.ctx.translate(this.ctx.canvas.width/2, this.ctx.canvas.height/2);
217 | for (var i = 0; i < this.entities.length; i++) {
218 | this.entities[i].draw(this.ctx);
219 | }
220 | if (callback) {
221 | callback(this);
222 | }
223 | this.ctx.restore();
224 | }
225 |
226 | GameEngine.prototype.update = function() {
227 | var entitiesCount = this.entities.length;
228 |
229 | for (var i = 0; i < entitiesCount; i++) {
230 | var entity = this.entities[i];
231 |
232 | if (!entity.removeFromWorld) {
233 | entity.update();
234 | }
235 | }
236 |
237 | for (var i = this.entities.length-1; i >= 0; --i) {
238 | if (this.entities[i].removeFromWorld) {
239 | this.entities.splice(i, 1);
240 | }
241 | }
242 | }
243 |
244 | GameEngine.prototype.loop = function() {
245 | this.clockTick = this.timer.tick();
246 | this.update();
247 | this.draw();
248 | this.click = null;
249 | }
250 |
251 | function Entity(game, x, y) {
252 | this.game = game;
253 | this.x = x;
254 | this.y = y;
255 | this.removeFromWorld = false;
256 | }
257 |
258 | Entity.prototype.update = function() {
259 | }
260 |
261 | Entity.prototype.draw = function(ctx) {
262 | if (this.game.showOutlines && this.radius) {
263 | ctx.beginPath();
264 | ctx.strokeStyle = "green";
265 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
266 | ctx.stroke();
267 | ctx.closePath();
268 | }
269 | }
270 |
271 | Entity.prototype.drawSpriteCentered = function(ctx) {
272 | if (this.sprite && this.x && this.y) {
273 | var x = this.x - this.sprite.width/2;
274 | var y = this.y - this.sprite.height/2;
275 | ctx.drawImage(this.sprite, x, y);
276 | }
277 | }
278 |
279 | Entity.prototype.outsideScreen = function() {
280 | return (this.x > this.game.halfSurfaceWidth || this.x < -(this.game.halfSurfaceWidth) ||
281 | this.y > this.game.halfSurfaceHeight || this.y < -(this.game.halfSurfaceHeight));
282 | }
283 |
284 | Entity.prototype.rotateAndCache = function(image, angle) {
285 | var offscreenCanvas = document.createElement('canvas');
286 | var size = Math.max(image.width, image.height);
287 | offscreenCanvas.width = size;
288 | offscreenCanvas.height = size;
289 | var offscreenCtx = offscreenCanvas.getContext('2d');
290 | offscreenCtx.save();
291 | offscreenCtx.translate(size/2, size/2);
292 | offscreenCtx.rotate(angle + Math.PI/2);
293 | offscreenCtx.drawImage(image, -(image.width/2), -(image.height/2));
294 | offscreenCtx.restore();
295 | //offscreenCtx.strokeStyle = "red";
296 | //offscreenCtx.strokeRect(0,0,size,size);
297 | return offscreenCanvas;
298 | }
299 |
300 | function Alien(game, radial_distance, angle) {
301 | Entity.call(this, game);
302 | this.radial_distance = radial_distance;
303 | this.angle = angle;
304 | this.speed = 100;
305 | this.sprite = this.rotateAndCache(ASSET_MANAGER.getAsset('img/alien.png'), this.angle);
306 | this.radius = this.sprite.height/2;
307 | this.setCoords();
308 | }
309 | Alien.prototype = new Entity();
310 | Alien.prototype.constructor = Alien;
311 |
312 | Alien.prototype.setCoords = function() {
313 | this.x = this.radial_distance * Math.cos(this.angle);
314 | this.y = this.radial_distance * Math.sin(this.angle);
315 | }
316 |
317 | Alien.prototype.update = function() {
318 | this.setCoords();
319 | this.radial_distance -= this.speed * this.game.clockTick;
320 |
321 | if (this.hitPlanet()) {
322 | this.removeFromWorld = true;
323 | this.game.lives -= 1;
324 | }
325 |
326 | Entity.prototype.update.call(this);
327 | }
328 |
329 | Alien.prototype.hitPlanet = function() {
330 | var distance_squared = ((this.x * this.x) + (this.y * this.y));
331 | var radii_squared = (this.radius + Earth.RADIUS) * (this.radius + Earth.RADIUS);
332 | return distance_squared < radii_squared;
333 | }
334 |
335 | Alien.prototype.draw = function(ctx) {
336 | this.drawSpriteCentered(ctx);
337 |
338 | Entity.prototype.draw.call(this, ctx);
339 | }
340 |
341 | Alien.prototype.explode = function() {
342 | this.removeFromWorld = true;
343 | this.game.addEntity(new AlienExplosion(this.game, this.x, this.y));
344 | ASSET_MANAGER.getSound('audio/alien_boom.mp3').play();
345 | }
346 |
347 | function AlienExplosion(game, x, y) {
348 | Entity.call(this, game, x, y);
349 | this.animation = new Animation(ASSET_MANAGER.getAsset('img/alien-explosion.png'), 69, 0.05);
350 | this.radius = this.animation.frameWidth / 2;
351 | }
352 | AlienExplosion.prototype = new Entity();
353 | AlienExplosion.prototype.constructor = AlienExplosion;
354 |
355 | AlienExplosion.prototype.update = function() {
356 | Entity.prototype.update.call(this);
357 | if (this.animation.isDone()) {
358 | this.removeFromWorld = true;
359 | }
360 | }
361 |
362 | AlienExplosion.prototype.draw = function(ctx) {
363 | Entity.prototype.draw.call(this, ctx);
364 | this.animation.drawFrame(this.game.clockTick, ctx, this.x, this.y);
365 | }
366 |
367 | function Sentry(game) {
368 | this.distanceFromEarthCenter = 85;
369 | Entity.call(this, game, 0, this.distanceFromEarthCenter);
370 | this.sprite = ASSET_MANAGER.getAsset('img/sentry.png');
371 | this.radius = this.sprite.width / 2;
372 | this.angle = 0;
373 | }
374 | Sentry.prototype = new Entity();
375 | Sentry.prototype.constructor = Sentry;
376 |
377 | Sentry.prototype.update = function() {
378 | if (this.game.mouse) {
379 | this.angle = Math.atan2(this.game.mouse.y, this.game.mouse.x);
380 | if (this.angle < 0) {
381 | this.angle += Math.PI * 2;
382 | }
383 | this.x = (Math.cos(this.angle) * this.distanceFromEarthCenter);
384 | this.y = (Math.sin(this.angle) * this.distanceFromEarthCenter);
385 | }
386 | if (this.game.click) {
387 | this.shoot();
388 | }
389 | Entity.prototype.update.call(this);
390 | }
391 |
392 | Sentry.prototype.draw = function(ctx) {
393 | ctx.save();
394 | ctx.translate(this.x, this.y);
395 | ctx.rotate(this.angle + Math.PI/2);
396 | ctx.drawImage(this.sprite, -this.sprite.width/2, -this.sprite.height/2);
397 | ctx.restore();
398 |
399 | Entity.prototype.draw.call(this, ctx);
400 | }
401 |
402 | Sentry.prototype.shoot = function() {
403 | var bullet = new Bullet(this.game, this.x, this.y, this.angle, this.game.click);
404 | this.game.addEntity(bullet);
405 | ASSET_MANAGER.getSound('audio/bullet.mp3').play();
406 | }
407 |
408 | function Bullet(game, x, y, angle, explodesAt) {
409 | Entity.call(this, game, x, y);
410 | this.angle = angle;
411 | this.explodesAt = explodesAt;
412 | this.speed = 250;
413 | this.radial_distance = 95;
414 | this.sprite = ASSET_MANAGER.getAsset('img/bullet.png');
415 | this.animation = new Animation(this.sprite, 7, 0.05, true);
416 | }
417 | Bullet.prototype = new Entity();
418 | Bullet.prototype.constructor = Bullet;
419 |
420 | Bullet.prototype.update = function() {
421 | if (this.outsideScreen()) {
422 | this.removeFromWorld = true;
423 | } else if (Math.abs(this.x) >= Math.abs(this.explodesAt.x) || Math.abs(this.y) >= Math.abs(this.explodesAt.y)) {
424 | ASSET_MANAGER.getSound('audio/bullet_boom.mp3').play();
425 | this.game.addEntity(new BulletExplosion(this.game, this.explodesAt.x, this.explodesAt.y));
426 | this.removeFromWorld = true;
427 | } else {
428 | this.x = this.radial_distance * Math.cos(this.angle);
429 | this.y = this.radial_distance * Math.sin(this.angle);
430 | this.radial_distance += this.speed * this.game.clockTick;
431 | }
432 | }
433 |
434 | Bullet.prototype.draw = function(ctx) {
435 | ctx.save();
436 | ctx.translate(this.x, this.y);
437 | ctx.rotate(this.angle + Math.PI/2);
438 | ctx.translate(-this.x, -this.y);
439 | this.animation.drawFrame(this.game.clockTick, ctx, this.x, this.y);
440 | ctx.restore();
441 |
442 | Entity.prototype.draw.call(this, ctx);
443 | }
444 |
445 | function BulletExplosion(game, x, y) {
446 | Entity.call(this, game, x, y);
447 | this.sprite = ASSET_MANAGER.getAsset('img/explosion.png');
448 | this.animation = new Animation(this.sprite, 34, 0.05);
449 | this.radius = this.animation.frameWidth / 2;
450 | }
451 | BulletExplosion.prototype = new Entity();
452 | BulletExplosion.prototype.constructor = BulletExplosion;
453 |
454 | BulletExplosion.prototype.update = function() {
455 | Entity.prototype.update.call(this);
456 |
457 | if (this.animation.isDone()) {
458 | this.removeFromWorld = true;
459 | return;
460 | }
461 |
462 | this.radius = (this.animation.frameWidth/2) * this.scaleFactor();
463 |
464 | for (var i = 0; i < this.game.entities.length; i++) {
465 | var alien = this.game.entities[i];
466 | if (alien instanceof Alien && this.isCaughtInExplosion(alien)) {
467 | console.log("hit!");
468 | this.game.score += 10;
469 | alien.explode();
470 | }
471 | }
472 | }
473 |
474 | BulletExplosion.prototype.isCaughtInExplosion = function(alien) {
475 | var distance_squared = (((this.x - alien.x) * (this.x - alien.x)) + ((this.y - alien.y) * (this.y - alien.y)));
476 | var radii_squared = (this.radius + alien.radius) * (this.radius + alien.radius);
477 | return distance_squared < radii_squared;
478 | }
479 |
480 | BulletExplosion.prototype.scaleFactor = function() {
481 | return 1 + (this.animation.currentFrame() / 3);
482 | }
483 |
484 | BulletExplosion.prototype.draw = function(ctx) {
485 | this.animation.drawFrame(this.game.clockTick, ctx, this.x, this.y, this.scaleFactor());
486 |
487 | Entity.prototype.draw.call(this, ctx);
488 | }
489 |
490 | function Earth(game) {
491 | Entity.call(this, game, 0, 0);
492 | this.sprite = ASSET_MANAGER.getAsset('img/earth.png');
493 | }
494 | Earth.prototype = new Entity();
495 | Earth.prototype.constructor = Earth;
496 |
497 | Earth.RADIUS = 67;
498 |
499 | Earth.prototype.draw = function(ctx) {
500 | ctx.drawImage(this.sprite, this.x - this.sprite.width/2, this.y - this.sprite.height/2);
501 | }
502 |
503 | function EvilAliens() {
504 | GameEngine.call(this);
505 | this.showOutlines = true;
506 | }
507 | EvilAliens.prototype = new GameEngine();
508 | EvilAliens.prototype.constructor = EvilAliens;
509 |
510 | EvilAliens.prototype.start = function() {
511 | this.sentry = new Sentry(this);
512 | this.earth = new Earth(this);
513 | this.addEntity(this.earth);
514 | this.addEntity(this.sentry);
515 | GameEngine.prototype.start.call(this);
516 | }
517 |
518 | EvilAliens.prototype.update = function() {
519 | if (this.lastAlienAddedAt == null || (this.timer.gameTime - this.lastAlienAddedAt) > 1) {
520 | this.addEntity(new Alien(this, this.ctx.canvas.width, Math.floor(Math.random() * Math.PI * 2)));
521 | this.lastAlienAddedAt = this.timer.gameTime;
522 | }
523 |
524 | GameEngine.prototype.update.call(this);
525 | }
526 |
527 | EvilAliens.prototype.draw = function() {
528 | GameEngine.prototype.draw.call(this);
529 | }
530 |
531 | var canvas = document.getElementById('surface');
532 | var ctx = canvas.getContext('2d');
533 | var game = new EvilAliens();
534 | var ASSET_MANAGER = new AssetManager();
535 |
536 | ASSET_MANAGER.queueDownload('img/alien-explosion.png');
537 | ASSET_MANAGER.queueDownload('img/alien.png');
538 | ASSET_MANAGER.queueDownload('img/bullet.png');
539 | ASSET_MANAGER.queueDownload('img/earth.png');
540 | ASSET_MANAGER.queueDownload('img/sentry.png');
541 | ASSET_MANAGER.queueDownload('img/explosion.png');
542 | ASSET_MANAGER.queueSound('alien-boom', 'audio/alien_boom.mp3');
543 | ASSET_MANAGER.queueSound('bullet-boom', 'audio/bullet_boom.mp3');
544 | ASSET_MANAGER.queueSound('bullet', 'audio/bullet.mp3');
545 |
546 | ASSET_MANAGER.downloadAll(function() {
547 | game.init(ctx);
548 | game.start();
549 | });
--------------------------------------------------------------------------------
/static/phase12/scripts/app.js:
--------------------------------------------------------------------------------
1 | soundManager.url = 'swf/';
2 | soundManager.flashVersion = 9;
3 | soundManager.debugFlash = false;
4 | soundManager.debugMode = false;
5 |
6 | window.requestAnimFrame = (function(){
7 | return window.requestAnimationFrame ||
8 | window.webkitRequestAnimationFrame ||
9 | window.mozRequestAnimationFrame ||
10 | window.oRequestAnimationFrame ||
11 | window.msRequestAnimationFrame ||
12 | function(/* function */ callback, /* DOMElement */ element){
13 | window.setTimeout(callback, 1000 / 60);
14 | };
15 | })();
16 |
17 | function AssetManager() {
18 | this.successCount = 0;
19 | this.errorCount = 0;
20 | this.cache = {};
21 | this.downloadQueue = [];
22 | this.soundsQueue = [];
23 | }
24 |
25 | AssetManager.prototype.queueDownload = function(path) {
26 | this.downloadQueue.push(path);
27 | }
28 |
29 | AssetManager.prototype.queueSound = function(id, path) {
30 | this.soundsQueue.push({id: id, path: path});
31 | }
32 |
33 | AssetManager.prototype.downloadAll = function(callback) {
34 | if (this.downloadQueue.length === 0 && this.soundsQueue.length === 0) {
35 | callback();
36 | }
37 |
38 | this.downloadSounds(callback);
39 |
40 | for (var i = 0; i < this.downloadQueue.length; i++) {
41 | var path = this.downloadQueue[i];
42 | var img = new Image();
43 | var that = this;
44 | img.addEventListener("load", function() {
45 | console.log(this.src + ' is loaded');
46 | that.successCount += 1;
47 | if (that.isDone()) {
48 | callback();
49 | }
50 | }, false);
51 | img.addEventListener("error", function() {
52 | that.errorCount += 1;
53 | if (that.isDone()) {
54 | callback();
55 | }
56 | }, false);
57 | img.src = path;
58 | this.cache[path] = img;
59 | }
60 | }
61 |
62 | AssetManager.prototype.downloadSounds = function(callback) {
63 | var that = this;
64 | soundManager.onready(function() {
65 | console.log('soundManager ready');
66 | for (var i = 0; i < that.soundsQueue.length; i++) {
67 | that.downloadSound(that.soundsQueue[i].id, that.soundsQueue[i].path, callback);
68 | }
69 | });
70 | soundManager.ontimeout(function() {
71 | console.log('SM2 did not start');
72 | });
73 | }
74 |
75 | AssetManager.prototype.downloadSound = function(id, path, callback) {
76 | var that = this;
77 | this.cache[path] = soundManager.createSound({
78 | id: id,
79 | autoLoad: true,
80 | url: path,
81 | onload: function() {
82 | console.log(this.url + ' is loaded');
83 | that.successCount += 1;
84 | if (that.isDone()) {
85 | callback();
86 | }
87 | }
88 | });
89 | }
90 |
91 | AssetManager.prototype.getSound = function(path) {
92 | return this.cache[path];
93 | }
94 |
95 | AssetManager.prototype.getAsset = function(path) {
96 | return this.cache[path];
97 | }
98 |
99 | AssetManager.prototype.isDone = function() {
100 | return ((this.downloadQueue.length + this.soundsQueue.length) == this.successCount + this.errorCount);
101 | }
102 |
103 | function Animation(spriteSheet, frameWidth, frameDuration, loop) {
104 | this.spriteSheet = spriteSheet;
105 | this.frameWidth = frameWidth;
106 | this.frameDuration = frameDuration;
107 | this.frameHeight= this.spriteSheet.height;
108 | this.totalTime = (this.spriteSheet.width / this.frameWidth) * this.frameDuration;
109 | this.elapsedTime = 0;
110 | this.loop = loop;
111 | }
112 |
113 | Animation.prototype.drawFrame = function(tick, ctx, x, y, scaleBy) {
114 | var scaleBy = scaleBy || 1;
115 | this.elapsedTime += tick;
116 | if (this.loop) {
117 | if (this.isDone()) {
118 | this.elapsedTime = 0;
119 | }
120 | } else if (this.isDone()) {
121 | return;
122 | }
123 | var index = this.currentFrame();
124 | var locX = x - (this.frameWidth/2) * scaleBy;
125 | var locY = y - (this.frameHeight/2) * scaleBy;
126 | ctx.drawImage(this.spriteSheet,
127 | index*this.frameWidth, 0, // source from sheet
128 | this.frameWidth, this.frameHeight,
129 | locX, locY,
130 | this.frameWidth*scaleBy,
131 | this.frameHeight*scaleBy);
132 | }
133 |
134 | Animation.prototype.currentFrame = function() {
135 | return Math.floor(this.elapsedTime / this.frameDuration);
136 | }
137 |
138 | Animation.prototype.isDone = function() {
139 | return (this.elapsedTime >= this.totalTime);
140 | }
141 |
142 | function Timer() {
143 | this.gameTime = 0;
144 | this.maxStep = 0.05;
145 | this.wallLastTimestamp = 0;
146 | }
147 |
148 | Timer.prototype.tick = function() {
149 | var wallCurrent = Date.now();
150 | var wallDelta = (wallCurrent - this.wallLastTimestamp) / 1000;
151 | this.wallLastTimestamp = wallCurrent;
152 |
153 | var gameDelta = Math.min(wallDelta, this.maxStep);
154 | this.gameTime += gameDelta;
155 | return gameDelta;
156 | }
157 |
158 | function GameEngine() {
159 | this.entities = [];
160 | this.ctx = null;
161 | this.click = null;
162 | this.mouse = null;
163 | this.timer = new Timer();
164 | this.surfaceWidth = null;
165 | this.surfaceHeight = null;
166 | this.halfSurfaceWidth = null;
167 | this.halfSurfaceHeight = null;
168 | }
169 |
170 | GameEngine.prototype.init = function(ctx) {
171 | console.log('game initialized');
172 | this.ctx = ctx;
173 | this.surfaceWidth = this.ctx.canvas.width;
174 | this.surfaceHeight = this.ctx.canvas.height;
175 | this.halfSurfaceWidth = this.surfaceWidth/2;
176 | this.halfSurfaceHeight = this.surfaceHeight/2;
177 | this.startInput();
178 | }
179 |
180 | GameEngine.prototype.start = function() {
181 | console.log("starting game");
182 | var that = this;
183 | (function gameLoop() {
184 | that.loop();
185 | requestAnimFrame(gameLoop, that.ctx.canvas);
186 | })();
187 | }
188 |
189 | GameEngine.prototype.startInput = function() {
190 | var getXandY = function(e) {
191 | var x = e.clientX - that.ctx.canvas.getBoundingClientRect().left - (that.ctx.canvas.width/2);
192 | var y = e.clientY - that.ctx.canvas.getBoundingClientRect().top - (that.ctx.canvas.height/2);
193 | return {x: x, y: y};
194 | }
195 |
196 | var that = this;
197 |
198 | this.ctx.canvas.addEventListener("click", function(e) {
199 | that.click = getXandY(e);
200 | e.stopPropagation();
201 | e.preventDefault();
202 | }, false);
203 |
204 | this.ctx.canvas.addEventListener("mousemove", function(e) {
205 | that.mouse = getXandY(e);
206 | }, false);
207 | }
208 |
209 | GameEngine.prototype.addEntity = function(entity) {
210 | this.entities.push(entity);
211 | }
212 |
213 | GameEngine.prototype.draw = function(callback) {
214 | this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
215 | this.ctx.save();
216 | this.ctx.translate(this.ctx.canvas.width/2, this.ctx.canvas.height/2);
217 | for (var i = 0; i < this.entities.length; i++) {
218 | this.entities[i].draw(this.ctx);
219 | }
220 | if (callback) {
221 | callback(this);
222 | }
223 | this.ctx.restore();
224 | }
225 |
226 | GameEngine.prototype.update = function() {
227 | var entitiesCount = this.entities.length;
228 |
229 | for (var i = 0; i < entitiesCount; i++) {
230 | var entity = this.entities[i];
231 |
232 | if (!entity.removeFromWorld) {
233 | entity.update();
234 | }
235 | }
236 |
237 | for (var i = this.entities.length-1; i >= 0; --i) {
238 | if (this.entities[i].removeFromWorld) {
239 | this.entities.splice(i, 1);
240 | }
241 | }
242 | }
243 |
244 | GameEngine.prototype.loop = function() {
245 | this.clockTick = this.timer.tick();
246 | this.update();
247 | this.draw();
248 | this.click = null;
249 | }
250 |
251 | function Entity(game, x, y) {
252 | this.game = game;
253 | this.x = x;
254 | this.y = y;
255 | this.removeFromWorld = false;
256 | }
257 |
258 | Entity.prototype.update = function() {
259 | }
260 |
261 | Entity.prototype.draw = function(ctx) {
262 | if (this.game.showOutlines && this.radius) {
263 | ctx.beginPath();
264 | ctx.strokeStyle = "green";
265 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
266 | ctx.stroke();
267 | ctx.closePath();
268 | }
269 | }
270 |
271 | Entity.prototype.drawSpriteCentered = function(ctx) {
272 | if (this.sprite && this.x && this.y) {
273 | var x = this.x - this.sprite.width/2;
274 | var y = this.y - this.sprite.height/2;
275 | ctx.drawImage(this.sprite, x, y);
276 | }
277 | }
278 |
279 | Entity.prototype.outsideScreen = function() {
280 | return (this.x > this.game.halfSurfaceWidth || this.x < -(this.game.halfSurfaceWidth) ||
281 | this.y > this.game.halfSurfaceHeight || this.y < -(this.game.halfSurfaceHeight));
282 | }
283 |
284 | Entity.prototype.rotateAndCache = function(image, angle) {
285 | var offscreenCanvas = document.createElement('canvas');
286 | var size = Math.max(image.width, image.height);
287 | offscreenCanvas.width = size;
288 | offscreenCanvas.height = size;
289 | var offscreenCtx = offscreenCanvas.getContext('2d');
290 | offscreenCtx.save();
291 | offscreenCtx.translate(size/2, size/2);
292 | offscreenCtx.rotate(angle + Math.PI/2);
293 | offscreenCtx.drawImage(image, -(image.width/2), -(image.height/2));
294 | offscreenCtx.restore();
295 | //offscreenCtx.strokeStyle = "red";
296 | //offscreenCtx.strokeRect(0,0,size,size);
297 | return offscreenCanvas;
298 | }
299 |
300 | function Alien(game, radial_distance, angle) {
301 | Entity.call(this, game);
302 | this.radial_distance = radial_distance;
303 | this.angle = angle;
304 | this.speed = 100;
305 | this.sprite = this.rotateAndCache(ASSET_MANAGER.getAsset('img/alien.png'), this.angle);
306 | this.radius = this.sprite.height/2;
307 | this.setCoords();
308 | }
309 | Alien.prototype = new Entity();
310 | Alien.prototype.constructor = Alien;
311 |
312 | Alien.prototype.setCoords = function() {
313 | this.x = this.radial_distance * Math.cos(this.angle);
314 | this.y = this.radial_distance * Math.sin(this.angle);
315 | }
316 |
317 | Alien.prototype.update = function() {
318 | this.setCoords();
319 | this.radial_distance -= this.speed * this.game.clockTick;
320 |
321 | if (this.hitPlanet()) {
322 | this.removeFromWorld = true;
323 | this.game.lives -= 1;
324 | }
325 |
326 | Entity.prototype.update.call(this);
327 | }
328 |
329 | Alien.prototype.hitPlanet = function() {
330 | var distance_squared = ((this.x * this.x) + (this.y * this.y));
331 | var radii_squared = (this.radius + Earth.RADIUS) * (this.radius + Earth.RADIUS);
332 | return distance_squared < radii_squared;
333 | }
334 |
335 | Alien.prototype.draw = function(ctx) {
336 | this.drawSpriteCentered(ctx);
337 |
338 | Entity.prototype.draw.call(this, ctx);
339 | }
340 |
341 | Alien.prototype.explode = function() {
342 | this.removeFromWorld = true;
343 | this.game.addEntity(new AlienExplosion(this.game, this.x, this.y));
344 | ASSET_MANAGER.getSound('audio/alien_boom.mp3').play();
345 | }
346 |
347 | function AlienExplosion(game, x, y) {
348 | Entity.call(this, game, x, y);
349 | this.animation = new Animation(ASSET_MANAGER.getAsset('img/alien-explosion.png'), 69, 0.05);
350 | this.radius = this.animation.frameWidth / 2;
351 | }
352 | AlienExplosion.prototype = new Entity();
353 | AlienExplosion.prototype.constructor = AlienExplosion;
354 |
355 | AlienExplosion.prototype.update = function() {
356 | Entity.prototype.update.call(this);
357 | if (this.animation.isDone()) {
358 | this.removeFromWorld = true;
359 | }
360 | }
361 |
362 | AlienExplosion.prototype.draw = function(ctx) {
363 | Entity.prototype.draw.call(this, ctx);
364 | this.animation.drawFrame(this.game.clockTick, ctx, this.x, this.y);
365 | }
366 |
367 | function Sentry(game) {
368 | this.distanceFromEarthCenter = 85;
369 | Entity.call(this, game, 0, this.distanceFromEarthCenter);
370 | this.sprite = ASSET_MANAGER.getAsset('img/sentry.png');
371 | this.radius = this.sprite.width / 2;
372 | this.angle = 0;
373 | }
374 | Sentry.prototype = new Entity();
375 | Sentry.prototype.constructor = Sentry;
376 |
377 | Sentry.prototype.update = function() {
378 | if (this.game.mouse) {
379 | this.angle = Math.atan2(this.game.mouse.y, this.game.mouse.x);
380 | if (this.angle < 0) {
381 | this.angle += Math.PI * 2;
382 | }
383 | this.x = (Math.cos(this.angle) * this.distanceFromEarthCenter);
384 | this.y = (Math.sin(this.angle) * this.distanceFromEarthCenter);
385 | }
386 | if (this.game.click) {
387 | this.shoot();
388 | }
389 | Entity.prototype.update.call(this);
390 | }
391 |
392 | Sentry.prototype.draw = function(ctx) {
393 | ctx.save();
394 | ctx.translate(this.x, this.y);
395 | ctx.rotate(this.angle + Math.PI/2);
396 | ctx.drawImage(this.sprite, -this.sprite.width/2, -this.sprite.height/2);
397 | ctx.restore();
398 |
399 | Entity.prototype.draw.call(this, ctx);
400 | }
401 |
402 | Sentry.prototype.shoot = function() {
403 | var bullet = new Bullet(this.game, this.x, this.y, this.angle, this.game.click);
404 | this.game.addEntity(bullet);
405 | ASSET_MANAGER.getSound('audio/bullet.mp3').play();
406 | }
407 |
408 | function Bullet(game, x, y, angle, explodesAt) {
409 | Entity.call(this, game, x, y);
410 | this.angle = angle;
411 | this.explodesAt = explodesAt;
412 | this.speed = 250;
413 | this.radial_distance = 95;
414 | this.sprite = ASSET_MANAGER.getAsset('img/bullet.png');
415 | this.animation = new Animation(this.sprite, 7, 0.05, true);
416 | }
417 | Bullet.prototype = new Entity();
418 | Bullet.prototype.constructor = Bullet;
419 |
420 | Bullet.prototype.update = function() {
421 | if (this.outsideScreen()) {
422 | this.removeFromWorld = true;
423 | } else if (Math.abs(this.x) >= Math.abs(this.explodesAt.x) || Math.abs(this.y) >= Math.abs(this.explodesAt.y)) {
424 | ASSET_MANAGER.getSound('audio/bullet_boom.mp3').play();
425 | this.game.addEntity(new BulletExplosion(this.game, this.explodesAt.x, this.explodesAt.y));
426 | this.removeFromWorld = true;
427 | } else {
428 | this.x = this.radial_distance * Math.cos(this.angle);
429 | this.y = this.radial_distance * Math.sin(this.angle);
430 | this.radial_distance += this.speed * this.game.clockTick;
431 | }
432 | }
433 |
434 | Bullet.prototype.draw = function(ctx) {
435 | ctx.save();
436 | ctx.translate(this.x, this.y);
437 | ctx.rotate(this.angle + Math.PI/2);
438 | ctx.translate(-this.x, -this.y);
439 | this.animation.drawFrame(this.game.clockTick, ctx, this.x, this.y);
440 | ctx.restore();
441 |
442 | Entity.prototype.draw.call(this, ctx);
443 | }
444 |
445 | function BulletExplosion(game, x, y) {
446 | Entity.call(this, game, x, y);
447 | this.sprite = ASSET_MANAGER.getAsset('img/explosion.png');
448 | this.animation = new Animation(this.sprite, 34, 0.05);
449 | this.radius = this.animation.frameWidth / 2;
450 | }
451 | BulletExplosion.prototype = new Entity();
452 | BulletExplosion.prototype.constructor = BulletExplosion;
453 |
454 | BulletExplosion.prototype.update = function() {
455 | Entity.prototype.update.call(this);
456 |
457 | if (this.animation.isDone()) {
458 | this.removeFromWorld = true;
459 | return;
460 | }
461 |
462 | this.radius = (this.animation.frameWidth/2) * this.scaleFactor();
463 |
464 | for (var i = 0; i < this.game.entities.length; i++) {
465 | var alien = this.game.entities[i];
466 | if (alien instanceof Alien && this.isCaughtInExplosion(alien)) {
467 | console.log("hit!");
468 | this.game.score += 10;
469 | alien.explode();
470 | }
471 | }
472 | }
473 |
474 | BulletExplosion.prototype.isCaughtInExplosion = function(alien) {
475 | var distance_squared = (((this.x - alien.x) * (this.x - alien.x)) + ((this.y - alien.y) * (this.y - alien.y)));
476 | var radii_squared = (this.radius + alien.radius) * (this.radius + alien.radius);
477 | return distance_squared < radii_squared;
478 | }
479 |
480 | BulletExplosion.prototype.scaleFactor = function() {
481 | return 1 + (this.animation.currentFrame() / 3);
482 | }
483 |
484 | BulletExplosion.prototype.draw = function(ctx) {
485 | this.animation.drawFrame(this.game.clockTick, ctx, this.x, this.y, this.scaleFactor());
486 |
487 | Entity.prototype.draw.call(this, ctx);
488 | }
489 |
490 | function Earth(game) {
491 | Entity.call(this, game, 0, 0);
492 | this.sprite = ASSET_MANAGER.getAsset('img/earth.png');
493 | }
494 | Earth.prototype = new Entity();
495 | Earth.prototype.constructor = Earth;
496 |
497 | Earth.RADIUS = 67;
498 |
499 | Earth.prototype.draw = function(ctx) {
500 | ctx.drawImage(this.sprite, this.x - this.sprite.width/2, this.y - this.sprite.height/2);
501 | }
502 |
503 | function EvilAliens() {
504 | GameEngine.call(this);
505 | //this.showOutlines = true;
506 | this.lives = 10;
507 | this.score = 0;
508 | }
509 | EvilAliens.prototype = new GameEngine();
510 | EvilAliens.prototype.constructor = EvilAliens;
511 |
512 | EvilAliens.prototype.start = function() {
513 | this.sentry = new Sentry(this);
514 | this.earth = new Earth(this);
515 | this.addEntity(this.earth);
516 | this.addEntity(this.sentry);
517 | GameEngine.prototype.start.call(this);
518 | }
519 |
520 | EvilAliens.prototype.update = function() {
521 | if (this.lastAlienAddedAt == null || (this.timer.gameTime - this.lastAlienAddedAt) > 1) {
522 | this.addEntity(new Alien(this, this.ctx.canvas.width, Math.floor(Math.random() * Math.PI * 2)));
523 | this.lastAlienAddedAt = this.timer.gameTime;
524 | }
525 |
526 | if (this.score <= 0) {
527 | // show game over screen
528 | }
529 |
530 | GameEngine.prototype.update.call(this);
531 | }
532 |
533 | EvilAliens.prototype.draw = function() {
534 | GameEngine.prototype.draw.call(this, function(game) {
535 | game.drawScore();
536 | game.drawLives();
537 | });
538 | }
539 |
540 | EvilAliens.prototype.drawLives = function() {
541 | this.ctx.fillStyle = "red";
542 | this.ctx.font = "bold 2em Arial";
543 | this.ctx.fillText("Lives: " + this.lives, -this.ctx.canvas.width/2 + 50, this.ctx.canvas.height/2 - 80);
544 | }
545 |
546 | EvilAliens.prototype.drawScore = function() {
547 | this.ctx.fillStyle = "red";
548 | this.ctx.font = "bold 2em Arial";
549 | this.ctx.fillText("Score: " + this.score, -this.ctx.canvas.width/2 + 50, this.ctx.canvas.height/2 - 50);
550 | }
551 |
552 | var canvas = document.getElementById('surface');
553 | var ctx = canvas.getContext('2d');
554 | var game = new EvilAliens();
555 | var ASSET_MANAGER = new AssetManager();
556 |
557 | ASSET_MANAGER.queueDownload('img/alien-explosion.png');
558 | ASSET_MANAGER.queueDownload('img/alien.png');
559 | ASSET_MANAGER.queueDownload('img/bullet.png');
560 | ASSET_MANAGER.queueDownload('img/earth.png');
561 | ASSET_MANAGER.queueDownload('img/sentry.png');
562 | ASSET_MANAGER.queueDownload('img/explosion.png');
563 | ASSET_MANAGER.queueSound('alien-boom', 'audio/alien_boom.mp3');
564 | ASSET_MANAGER.queueSound('bullet-boom', 'audio/bullet_boom.mp3');
565 | ASSET_MANAGER.queueSound('bullet', 'audio/bullet.mp3');
566 |
567 | ASSET_MANAGER.downloadAll(function() {
568 | game.init(ctx);
569 | game.start();
570 | });
--------------------------------------------------------------------------------
/static/phase13/scripts/app.js:
--------------------------------------------------------------------------------
1 | soundManager.url = 'swf/';
2 | soundManager.flashVersion = 9;
3 | soundManager.debugFlash = false;
4 | soundManager.debugMode = false;
5 |
6 | window.requestAnimFrame = (function(){
7 | return window.requestAnimationFrame ||
8 | window.webkitRequestAnimationFrame ||
9 | window.mozRequestAnimationFrame ||
10 | window.oRequestAnimationFrame ||
11 | window.msRequestAnimationFrame ||
12 | function(/* function */ callback, /* DOMElement */ element){
13 | window.setTimeout(callback, 1000 / 60);
14 | };
15 | })();
16 |
17 | function AssetManager() {
18 | this.successCount = 0;
19 | this.errorCount = 0;
20 | this.cache = {};
21 | this.downloadQueue = [];
22 | this.soundsQueue = [];
23 | }
24 |
25 | AssetManager.prototype.queueDownload = function(path) {
26 | this.downloadQueue.push(path);
27 | }
28 |
29 | AssetManager.prototype.queueSound = function(id, path) {
30 | this.soundsQueue.push({id: id, path: path});
31 | }
32 |
33 | AssetManager.prototype.downloadAll = function(callback) {
34 | if (this.downloadQueue.length === 0 && this.soundsQueue.length === 0) {
35 | callback();
36 | }
37 |
38 | this.downloadSounds(callback);
39 |
40 | for (var i = 0; i < this.downloadQueue.length; i++) {
41 | var path = this.downloadQueue[i];
42 | var img = new Image();
43 | var that = this;
44 | img.addEventListener("load", function() {
45 | console.log(this.src + ' is loaded');
46 | that.successCount += 1;
47 | if (that.isDone()) {
48 | callback();
49 | }
50 | }, false);
51 | img.addEventListener("error", function() {
52 | that.errorCount += 1;
53 | if (that.isDone()) {
54 | callback();
55 | }
56 | }, false);
57 | img.src = path;
58 | this.cache[path] = img;
59 | }
60 | }
61 |
62 | AssetManager.prototype.downloadSounds = function(callback) {
63 | var that = this;
64 | soundManager.onready(function() {
65 | console.log('soundManager ready');
66 | for (var i = 0; i < that.soundsQueue.length; i++) {
67 | that.downloadSound(that.soundsQueue[i].id, that.soundsQueue[i].path, callback);
68 | }
69 | });
70 | soundManager.ontimeout(function() {
71 | console.log('SM2 did not start');
72 | });
73 | }
74 |
75 | AssetManager.prototype.downloadSound = function(id, path, callback) {
76 | var that = this;
77 | this.cache[path] = soundManager.createSound({
78 | id: id,
79 | autoLoad: true,
80 | url: path,
81 | onload: function() {
82 | console.log(this.url + ' is loaded');
83 | that.successCount += 1;
84 | if (that.isDone()) {
85 | callback();
86 | }
87 | }
88 | });
89 | }
90 |
91 | AssetManager.prototype.getSound = function(path) {
92 | return this.cache[path];
93 | }
94 |
95 | AssetManager.prototype.getAsset = function(path) {
96 | return this.cache[path];
97 | }
98 |
99 | AssetManager.prototype.isDone = function() {
100 | return ((this.downloadQueue.length + this.soundsQueue.length) == this.successCount + this.errorCount);
101 | }
102 |
103 | function Animation(spriteSheet, frameWidth, frameDuration, loop) {
104 | this.spriteSheet = spriteSheet;
105 | this.frameWidth = frameWidth;
106 | this.frameDuration = frameDuration;
107 | this.frameHeight= this.spriteSheet.height;
108 | this.totalTime = (this.spriteSheet.width / this.frameWidth) * this.frameDuration;
109 | this.elapsedTime = 0;
110 | this.loop = loop;
111 | }
112 |
113 | Animation.prototype.drawFrame = function(tick, ctx, x, y, scaleBy) {
114 | var scaleBy = scaleBy || 1;
115 | this.elapsedTime += tick;
116 | if (this.loop) {
117 | if (this.isDone()) {
118 | this.elapsedTime = 0;
119 | }
120 | } else if (this.isDone()) {
121 | return;
122 | }
123 | var index = this.currentFrame();
124 | var locX = x - (this.frameWidth/2) * scaleBy;
125 | var locY = y - (this.frameHeight/2) * scaleBy;
126 | ctx.drawImage(this.spriteSheet,
127 | index*this.frameWidth, 0, // source from sheet
128 | this.frameWidth, this.frameHeight,
129 | locX, locY,
130 | this.frameWidth*scaleBy,
131 | this.frameHeight*scaleBy);
132 | }
133 |
134 | Animation.prototype.currentFrame = function() {
135 | return Math.floor(this.elapsedTime / this.frameDuration);
136 | }
137 |
138 | Animation.prototype.isDone = function() {
139 | return (this.elapsedTime >= this.totalTime);
140 | }
141 |
142 | function Timer() {
143 | this.gameTime = 0;
144 | this.maxStep = 0.05;
145 | this.wallLastTimestamp = 0;
146 | }
147 |
148 | Timer.prototype.tick = function() {
149 | var wallCurrent = Date.now();
150 | var wallDelta = (wallCurrent - this.wallLastTimestamp) / 1000;
151 | this.wallLastTimestamp = wallCurrent;
152 |
153 | var gameDelta = Math.min(wallDelta, this.maxStep);
154 | this.gameTime += gameDelta;
155 | return gameDelta;
156 | }
157 |
158 | function GameEngine() {
159 | this.entities = [];
160 | this.ctx = null;
161 | this.click = null;
162 | this.mouse = null;
163 | this.timer = new Timer();
164 | this.stats = new Stats();
165 | this.surfaceWidth = null;
166 | this.surfaceHeight = null;
167 | this.halfSurfaceWidth = null;
168 | this.halfSurfaceHeight = null;
169 | }
170 |
171 | GameEngine.prototype.init = function(ctx) {
172 | console.log('game initialized');
173 | this.ctx = ctx;
174 | this.surfaceWidth = this.ctx.canvas.width;
175 | this.surfaceHeight = this.ctx.canvas.height;
176 | this.halfSurfaceWidth = this.surfaceWidth/2;
177 | this.halfSurfaceHeight = this.surfaceHeight/2;
178 | this.startInput();
179 | document.body.appendChild(this.stats.domElement);
180 | }
181 |
182 | GameEngine.prototype.start = function() {
183 | console.log("starting game");
184 | var that = this;
185 | (function gameLoop() {
186 | that.loop();
187 | requestAnimFrame(gameLoop, that.ctx.canvas);
188 | })();
189 | }
190 |
191 | GameEngine.prototype.startInput = function() {
192 | var getXandY = function(e) {
193 | var x = e.clientX - that.ctx.canvas.getBoundingClientRect().left - (that.ctx.canvas.width/2);
194 | var y = e.clientY - that.ctx.canvas.getBoundingClientRect().top - (that.ctx.canvas.height/2);
195 | return {x: x, y: y};
196 | }
197 |
198 | var that = this;
199 |
200 | this.ctx.canvas.addEventListener("click", function(e) {
201 | that.click = getXandY(e);
202 | e.stopPropagation();
203 | e.preventDefault();
204 | }, false);
205 |
206 | this.ctx.canvas.addEventListener("mousemove", function(e) {
207 | that.mouse = getXandY(e);
208 | }, false);
209 | }
210 |
211 | GameEngine.prototype.addEntity = function(entity) {
212 | this.entities.push(entity);
213 | }
214 |
215 | GameEngine.prototype.draw = function(callback) {
216 | this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
217 | this.ctx.save();
218 | this.ctx.translate(this.ctx.canvas.width/2, this.ctx.canvas.height/2);
219 | for (var i = 0; i < this.entities.length; i++) {
220 | this.entities[i].draw(this.ctx);
221 | }
222 | if (callback) {
223 | callback(this);
224 | }
225 | this.ctx.restore();
226 | }
227 |
228 | GameEngine.prototype.update = function() {
229 | var entitiesCount = this.entities.length;
230 |
231 | for (var i = 0; i < entitiesCount; i++) {
232 | var entity = this.entities[i];
233 |
234 | if (!entity.removeFromWorld) {
235 | entity.update();
236 | }
237 | }
238 |
239 | for (var i = this.entities.length-1; i >= 0; --i) {
240 | if (this.entities[i].removeFromWorld) {
241 | this.entities.splice(i, 1);
242 | }
243 | }
244 | }
245 |
246 | GameEngine.prototype.loop = function() {
247 | this.clockTick = this.timer.tick();
248 | this.update();
249 | this.draw();
250 | this.click = null;
251 | this.stats.update();
252 | }
253 |
254 | function Entity(game, x, y) {
255 | this.game = game;
256 | this.x = x;
257 | this.y = y;
258 | this.removeFromWorld = false;
259 | }
260 |
261 | Entity.prototype.update = function() {
262 | }
263 |
264 | Entity.prototype.draw = function(ctx) {
265 | if (this.game.showOutlines && this.radius) {
266 | ctx.beginPath();
267 | ctx.strokeStyle = "green";
268 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
269 | ctx.stroke();
270 | ctx.closePath();
271 | }
272 | }
273 |
274 | Entity.prototype.drawSpriteCentered = function(ctx) {
275 | if (this.sprite && this.x && this.y) {
276 | var x = this.x - this.sprite.width/2;
277 | var y = this.y - this.sprite.height/2;
278 | ctx.drawImage(this.sprite, x, y);
279 | }
280 | }
281 |
282 | Entity.prototype.outsideScreen = function() {
283 | return (this.x > this.game.halfSurfaceWidth || this.x < -(this.game.halfSurfaceWidth) ||
284 | this.y > this.game.halfSurfaceHeight || this.y < -(this.game.halfSurfaceHeight));
285 | }
286 |
287 | Entity.prototype.rotateAndCache = function(image, angle) {
288 | var offscreenCanvas = document.createElement('canvas');
289 | var size = Math.max(image.width, image.height);
290 | offscreenCanvas.width = size;
291 | offscreenCanvas.height = size;
292 | var offscreenCtx = offscreenCanvas.getContext('2d');
293 | offscreenCtx.save();
294 | offscreenCtx.translate(size/2, size/2);
295 | offscreenCtx.rotate(angle + Math.PI/2);
296 | offscreenCtx.drawImage(image, -(image.width/2), -(image.height/2));
297 | offscreenCtx.restore();
298 | //offscreenCtx.strokeStyle = "red";
299 | //offscreenCtx.strokeRect(0,0,size,size);
300 | return offscreenCanvas;
301 | }
302 |
303 | function Alien(game, radial_distance, angle) {
304 | Entity.call(this, game);
305 | this.radial_distance = radial_distance;
306 | this.angle = angle;
307 | this.speed = 100;
308 | this.sprite = this.rotateAndCache(ASSET_MANAGER.getAsset('img/alien.png'), this.angle);
309 | this.radius = this.sprite.height/2;
310 | this.setCoords();
311 | }
312 | Alien.prototype = new Entity();
313 | Alien.prototype.constructor = Alien;
314 |
315 | Alien.prototype.setCoords = function() {
316 | this.x = this.radial_distance * Math.cos(this.angle);
317 | this.y = this.radial_distance * Math.sin(this.angle);
318 | }
319 |
320 | Alien.prototype.update = function() {
321 | this.setCoords();
322 | this.radial_distance -= this.speed * this.game.clockTick;
323 |
324 | if (this.hitPlanet()) {
325 | this.removeFromWorld = true;
326 | this.game.lives -= 1;
327 | }
328 |
329 | Entity.prototype.update.call(this);
330 | }
331 |
332 | Alien.prototype.hitPlanet = function() {
333 | var distance_squared = ((this.x * this.x) + (this.y * this.y));
334 | var radii_squared = (this.radius + Earth.RADIUS) * (this.radius + Earth.RADIUS);
335 | return distance_squared < radii_squared;
336 | }
337 |
338 | Alien.prototype.draw = function(ctx) {
339 | this.drawSpriteCentered(ctx);
340 |
341 | Entity.prototype.draw.call(this, ctx);
342 | }
343 |
344 | Alien.prototype.explode = function() {
345 | this.removeFromWorld = true;
346 | this.game.addEntity(new AlienExplosion(this.game, this.x, this.y));
347 | ASSET_MANAGER.getSound('audio/alien_boom.mp3').play();
348 | }
349 |
350 | function AlienExplosion(game, x, y) {
351 | Entity.call(this, game, x, y);
352 | this.animation = new Animation(ASSET_MANAGER.getAsset('img/alien-explosion.png'), 69, 0.05);
353 | this.radius = this.animation.frameWidth / 2;
354 | }
355 | AlienExplosion.prototype = new Entity();
356 | AlienExplosion.prototype.constructor = AlienExplosion;
357 |
358 | AlienExplosion.prototype.update = function() {
359 | Entity.prototype.update.call(this);
360 | if (this.animation.isDone()) {
361 | this.removeFromWorld = true;
362 | }
363 | }
364 |
365 | AlienExplosion.prototype.draw = function(ctx) {
366 | Entity.prototype.draw.call(this, ctx);
367 | this.animation.drawFrame(this.game.clockTick, ctx, this.x, this.y);
368 | }
369 |
370 | function Sentry(game) {
371 | this.distanceFromEarthCenter = 85;
372 | Entity.call(this, game, 0, this.distanceFromEarthCenter);
373 | this.sprite = ASSET_MANAGER.getAsset('img/sentry.png');
374 | this.radius = this.sprite.width / 2;
375 | this.angle = 0;
376 | }
377 | Sentry.prototype = new Entity();
378 | Sentry.prototype.constructor = Sentry;
379 |
380 | Sentry.prototype.update = function() {
381 | if (this.game.mouse) {
382 | this.angle = Math.atan2(this.game.mouse.y, this.game.mouse.x);
383 | if (this.angle < 0) {
384 | this.angle += Math.PI * 2;
385 | }
386 | this.x = (Math.cos(this.angle) * this.distanceFromEarthCenter);
387 | this.y = (Math.sin(this.angle) * this.distanceFromEarthCenter);
388 | }
389 | if (this.game.click) {
390 | this.shoot();
391 | }
392 | Entity.prototype.update.call(this);
393 | }
394 |
395 | Sentry.prototype.draw = function(ctx) {
396 | ctx.save();
397 | ctx.translate(this.x, this.y);
398 | ctx.rotate(this.angle + Math.PI/2);
399 | ctx.drawImage(this.sprite, -this.sprite.width/2, -this.sprite.height/2);
400 | ctx.restore();
401 |
402 | Entity.prototype.draw.call(this, ctx);
403 | }
404 |
405 | Sentry.prototype.shoot = function() {
406 | var bullet = new Bullet(this.game, this.x, this.y, this.angle, this.game.click);
407 | this.game.addEntity(bullet);
408 | ASSET_MANAGER.getSound('audio/bullet.mp3').play();
409 | }
410 |
411 | function Bullet(game, x, y, angle, explodesAt) {
412 | Entity.call(this, game, x, y);
413 | this.angle = angle;
414 | this.explodesAt = explodesAt;
415 | this.speed = 250;
416 | this.radial_distance = 95;
417 | this.sprite = ASSET_MANAGER.getAsset('img/bullet.png');
418 | this.animation = new Animation(this.sprite, 7, 0.05, true);
419 | }
420 | Bullet.prototype = new Entity();
421 | Bullet.prototype.constructor = Bullet;
422 |
423 | Bullet.prototype.update = function() {
424 | if (this.outsideScreen()) {
425 | this.removeFromWorld = true;
426 | } else if (Math.abs(this.x) >= Math.abs(this.explodesAt.x) || Math.abs(this.y) >= Math.abs(this.explodesAt.y)) {
427 | ASSET_MANAGER.getSound('audio/bullet_boom.mp3').play();
428 | this.game.addEntity(new BulletExplosion(this.game, this.explodesAt.x, this.explodesAt.y));
429 | this.removeFromWorld = true;
430 | } else {
431 | this.x = this.radial_distance * Math.cos(this.angle);
432 | this.y = this.radial_distance * Math.sin(this.angle);
433 | this.radial_distance += this.speed * this.game.clockTick;
434 | }
435 | }
436 |
437 | Bullet.prototype.draw = function(ctx) {
438 | ctx.save();
439 | ctx.translate(this.x, this.y);
440 | ctx.rotate(this.angle + Math.PI/2);
441 | ctx.translate(-this.x, -this.y);
442 | this.animation.drawFrame(this.game.clockTick, ctx, this.x, this.y);
443 | ctx.restore();
444 |
445 | Entity.prototype.draw.call(this, ctx);
446 | }
447 |
448 | function BulletExplosion(game, x, y) {
449 | Entity.call(this, game, x, y);
450 | this.sprite = ASSET_MANAGER.getAsset('img/explosion.png');
451 | this.animation = new Animation(this.sprite, 34, 0.05);
452 | this.radius = this.animation.frameWidth / 2;
453 | }
454 | BulletExplosion.prototype = new Entity();
455 | BulletExplosion.prototype.constructor = BulletExplosion;
456 |
457 | BulletExplosion.prototype.update = function() {
458 | Entity.prototype.update.call(this);
459 |
460 | if (this.animation.isDone()) {
461 | this.removeFromWorld = true;
462 | return;
463 | }
464 |
465 | this.radius = (this.animation.frameWidth/2) * this.scaleFactor();
466 |
467 | for (var i = 0; i < this.game.entities.length; i++) {
468 | var alien = this.game.entities[i];
469 | if (alien instanceof Alien && this.isCaughtInExplosion(alien)) {
470 | console.log("hit!");
471 | this.game.score += 10;
472 | alien.explode();
473 | }
474 | }
475 | }
476 |
477 | BulletExplosion.prototype.isCaughtInExplosion = function(alien) {
478 | var distance_squared = (((this.x - alien.x) * (this.x - alien.x)) + ((this.y - alien.y) * (this.y - alien.y)));
479 | var radii_squared = (this.radius + alien.radius) * (this.radius + alien.radius);
480 | return distance_squared < radii_squared;
481 | }
482 |
483 | BulletExplosion.prototype.scaleFactor = function() {
484 | return 1 + (this.animation.currentFrame() / 3);
485 | }
486 |
487 | BulletExplosion.prototype.draw = function(ctx) {
488 | this.animation.drawFrame(this.game.clockTick, ctx, this.x, this.y, this.scaleFactor());
489 |
490 | Entity.prototype.draw.call(this, ctx);
491 | }
492 |
493 | function Earth(game) {
494 | Entity.call(this, game, 0, 0);
495 | this.sprite = ASSET_MANAGER.getAsset('img/earth.png');
496 | }
497 | Earth.prototype = new Entity();
498 | Earth.prototype.constructor = Earth;
499 |
500 | Earth.RADIUS = 67;
501 |
502 | Earth.prototype.draw = function(ctx) {
503 | ctx.drawImage(this.sprite, this.x - this.sprite.width/2, this.y - this.sprite.height/2);
504 | }
505 |
506 | function EvilAliens() {
507 | GameEngine.call(this);
508 | //this.showOutlines = true;
509 | this.lives = 10;
510 | this.score = 0;
511 | }
512 | EvilAliens.prototype = new GameEngine();
513 | EvilAliens.prototype.constructor = EvilAliens;
514 |
515 | EvilAliens.prototype.start = function() {
516 | this.sentry = new Sentry(this);
517 | this.earth = new Earth(this);
518 | this.addEntity(this.earth);
519 | this.addEntity(this.sentry);
520 | GameEngine.prototype.start.call(this);
521 | }
522 |
523 | EvilAliens.prototype.update = function() {
524 | if (this.lastAlienAddedAt == null || (this.timer.gameTime - this.lastAlienAddedAt) > 1) {
525 | this.addEntity(new Alien(this, this.ctx.canvas.width, Math.floor(Math.random() * Math.PI * 2)));
526 | this.lastAlienAddedAt = this.timer.gameTime;
527 | }
528 |
529 | if (this.score <= 0) {
530 | // show game over screen
531 | }
532 |
533 | GameEngine.prototype.update.call(this);
534 | }
535 |
536 | EvilAliens.prototype.draw = function() {
537 | GameEngine.prototype.draw.call(this, function(game) {
538 | game.drawScore();
539 | game.drawLives();
540 | });
541 | }
542 |
543 | EvilAliens.prototype.drawLives = function() {
544 | this.ctx.fillStyle = "red";
545 | this.ctx.font = "bold 2em Arial";
546 | this.ctx.fillText("Lives: " + this.lives, -this.ctx.canvas.width/2 + 50, this.ctx.canvas.height/2 - 80);
547 | }
548 |
549 | EvilAliens.prototype.drawScore = function() {
550 | this.ctx.fillStyle = "red";
551 | this.ctx.font = "bold 2em Arial";
552 | this.ctx.fillText("Score: " + this.score, -this.ctx.canvas.width/2 + 50, this.ctx.canvas.height/2 - 50);
553 | }
554 |
555 | var canvas = document.getElementById('surface');
556 | var ctx = canvas.getContext('2d');
557 | var game = new EvilAliens();
558 | var ASSET_MANAGER = new AssetManager();
559 |
560 | ASSET_MANAGER.queueDownload('img/alien-explosion.png');
561 | ASSET_MANAGER.queueDownload('img/alien.png');
562 | ASSET_MANAGER.queueDownload('img/bullet.png');
563 | ASSET_MANAGER.queueDownload('img/earth.png');
564 | ASSET_MANAGER.queueDownload('img/sentry.png');
565 | ASSET_MANAGER.queueDownload('img/explosion.png');
566 | ASSET_MANAGER.queueSound('alien-boom', 'audio/alien_boom.mp3');
567 | ASSET_MANAGER.queueSound('bullet-boom', 'audio/bullet_boom.mp3');
568 | ASSET_MANAGER.queueSound('bullet', 'audio/bullet.mp3');
569 |
570 | ASSET_MANAGER.downloadAll(function() {
571 | game.init(ctx);
572 | game.start();
573 | });
--------------------------------------------------------------------------------