123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- <!DOCTYPE html>
- <html>
- <head>
- <script src="https://cdn.jsdelivr.net/npm/phaser/dist/phaser.js"></script>
- </head>
- <body>
- <style>
- body {
- overflow: hidden;
- padding: 0px;
- margin: 0px;
- }
- </style>
- <script>
- const _GRAVITY = 800;
- const _MAX_UPWARDS_VELOCITY = -300;
- const _UPWARDS_ACCELERATION = -450;
- const _TERMINAL_VELOCITY = 400;
- const _PIPE_SPACING_Y = 100;
- const _TREADMILL_SPEED = -125;
- const _CONFIG_WIDTH = 960;
- const _CONFIG_HEIGHT = 540;
- const _GROUND_Y = _CONFIG_HEIGHT;
- class FlappyBirdObject {
- constructor(scene) {
- this._sprite = scene.add.sprite(50, 100, 'bird');
- this._velocity = 0;
- }
- Destroy() {
- this._sprite.destroy();
- }
- Update(timeElapsed, keyboard) {
- // Apply gravity and upward impulses
- this._ApplyGravity(timeElapsed)
- this._HandleInput(timeElapsed, keyboard)
- this._velocity = Math.min(Math.max(this._velocity, _MAX_UPWARDS_VELOCITY), _TERMINAL_VELOCITY);
- this._sprite.y += this._velocity * timeElapsed;
- const v = new Phaser.Math.Vector2(-1 * _TREADMILL_SPEED * timeElapsed, 0);
- v.add(new Phaser.Math.Vector2(0, this._velocity));
- v.normalize();
- const rad = Math.atan2(v.y, v.x);
- const deg = (180.0 / Math.PI) * rad;
- this._sprite.angle = deg * 0.75;
- }
- get Bounds() {
- return this._sprite.getBounds();
- }
- _ApplyGravity(timeElapsed) {
- this._velocity += _GRAVITY * timeElapsed;
- }
- _HandleInput(timeElapsed, keys) {
- if (!Phaser.Input.Keyboard.JustDown(keys.up)) {
- return;
- }
- this._velocity += _UPWARDS_ACCELERATION;
- }
- }
- class PipePairObject {
- constructor(scene, x) {
- const height = _CONFIG_HEIGHT * (0.25 + 0.5 * Math.random());
- this._sprite1 = scene.add.sprite(x, height + _PIPE_SPACING_Y * 0.5, 'pipe');
- this._sprite1.displayOriginX = 0;
- this._sprite1.displayOriginY = 0;
- this._sprite2 = scene.add.sprite(x, height - _PIPE_SPACING_Y * 0.5, 'pipe');
- this._sprite2.displayOriginX = 0;
- this._sprite2.displayOriginY = 0;
- this._sprite2.displayHeight = -1 * this._sprite2.height;
- }
- Destroy() {
- this._sprite1.destroy();
- this._sprite2.destroy();
- }
- Update(timeElapsed) {
- this._sprite1.x += timeElapsed * _TREADMILL_SPEED;
- this._sprite2.x += timeElapsed * _TREADMILL_SPEED;
- }
- Intersects(aabb) {
- const b1 = this._sprite1.getBounds();
- const b2 = this._sprite2.getBounds();
- b2.y -= this._sprite2.height;
- return (
- Phaser.Geom.Intersects.RectangleToRectangle(b1, aabb) ||
- Phaser.Geom.Intersects.RectangleToRectangle(b2, aabb));
- }
- Reset(x) {
- const height = _CONFIG_HEIGHT * (0.25 + 0.5 * Math.random());
- this._sprite1.x = x;
- this._sprite1.y = height + _PIPE_SPACING_Y * 0.5;
- this._sprite2.x = x;
- this._sprite2.y = height - _PIPE_SPACING_Y * 0.5;
- }
- get X() {
- return this._sprite1.x;
- }
- get Width() {
- return this._sprite1.width;
- }
- }
- class FlappyBirdGame {
- constructor() {
- this._game = this._CreateGame();
- this._previousFrame = null;
- this._bird = null;
- this._gameOver = false;
- this._score = 0;
- this._scoreText = null;
- this._gameOverText = null;
- this._pipes = [];
- }
- _Destroy() {
- this._bird.Destroy();
- for (let p of this._pipes) {
- p.Destroy();
- }
- this._scoreText.destroy();
- if (this._gameOverText !== null) {
- this._gameOverText.destroy();
- }
- this._bird = null;
- this._pipes = [];
- this._previousFrame = null;
- }
- _Init() {
- for (let i = 0; i < 5; i+=1) {
- this._pipes.push(new PipePairObject(this._scene, 500 + i * 250));
- }
- this._bird = new FlappyBirdObject(this._scene);
- this._gameOver = false;
- this._score = 0;
- }
- _CreateGame() {
- const self = this;
- const config = {
- type: Phaser.AUTO,
- scene: {
- preload: function() { self._OnPreload(this); },
- create: function() { self._OnCreate(this); },
- update: function() { self._OnUpdate(this); },
- },
- scale: {
- mode: Phaser.Scale.FIT,
- autoCenter: Phaser.Scale.CENTER_BOTH,
- width: _CONFIG_WIDTH,
- height: _CONFIG_HEIGHT
- }
- };
- return new Phaser.Game(config);
- }
- _OnPreload(scene) {
- this._scene = scene;
- this._scene.load.image('sky', 'assets/sky.png');
- this._scene.load.image('bird', 'assets/bird.png');
- this._scene.load.image('pipe', 'assets/pipe.png');
- }
- _OnCreate(scene) {
- const s = this._scene.add.image(0, 0, 'sky');
- s.displayOriginX = 0;
- s.displayOriginY = 0;
- s.displayWidth = _CONFIG_WIDTH;
- s.displayHeight = _CONFIG_HEIGHT;
- this._keys = {
- up: this._scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.UP),
- f: this._scene.input.keyboard.addKey('F'),
- r: this._scene.input.keyboard.addKey('R'),
- }
- this._keys.f.on('down', function () {
- if (this._scene.scale.isFullscreen) {
- this._scene.scale.stopFullscreen();
- } else {
- this._scene.scale.startFullscreen();
- }
- }, this);
- this._keys.r.on('down', function () {
- this._Destroy();
- this._Init();
- this._DrawScore();
- }, this);
- this._Init();
- this._DrawScore();
- }
- _OnUpdate(scene) {
- if (this._gameOver) {
- return;
- }
- const currentFrame = scene.time.now;
- if (this._previousFrame == null) {
- this._previousFrame = currentFrame;
- }
- const timeElapsedInS = (currentFrame - this._previousFrame) / 1000.0;
- this._bird.Update(timeElapsedInS, this._keys);
- this._UpdatePipes(timeElapsedInS);
- this._CheckGameOver();
- this._previousFrame = currentFrame;
- }
- _CheckGameOver() {
- // Ground check
- const birdAABB = this._bird.Bounds;
- birdAABB.top += 10;
- birdAABB.bottom -= 10;
- birdAABB.left += 10;
- birdAABB.right -= 10;
- if (birdAABB.top >= _GROUND_Y) {
- this._GameOver();
- return;
- }
- for (const p of this._pipes) {
- if (p.Intersects(birdAABB)) {
- let a = p.Intersects(birdAABB);
- this._GameOver();
- return;
- }
- }
- }
- _UpdatePipes(timeElapsed) {
- const oldPipeX = this._pipes[0].X + this._pipes[0].Width;
- for (const p of this._pipes) {
- p.Update(timeElapsed);
- }
- const newPipeX = this._pipes[0].X + this._pipes[0].Width;
- if (oldPipeX > 50 && newPipeX <= 50) {
- this._score += 1;
- this._scoreText.text = "Score: " + this._score;
- }
- if ((this._pipes[0].X + this._pipes[0].Width) <= 0) {
- const p = this._pipes.shift();
- p.Reset(this._pipes[this._pipes.length - 1].X + 200.0);
- this._pipes.push(p);
- }
- }
- _GameOver() {
- const text = "GAME OVER";
- const style = {
- font: "100px Roboto",
- fill: "#FFFFFF",
- align: "center",
- fixedWidth: _CONFIG_WIDTH,
- shadow: {
- offsetX: 2,
- offsetY: 2,
- color: "#000",
- blur: 2,
- fill: true
- }
- };
- this._gameOverText = this._scene.add.text(0, _CONFIG_HEIGHT * 0.25, text, style);
- this._gameOver = true;
- }
- _DrawScore() {
- const text = "Score: 0";
- const style = {
- font: "40px Roboto",
- fill: "#FFFFFF",
- align: "center",
- shadow: {
- offsetX: 2,
- offsetY: 2,
- color: "#000",
- blur: 2,
- fill: true
- }
- };
- this._scoreText = this._scene.add.text(0, 0, text, style);
- }
- }
- _GAME = new FlappyBirdGame()
- </script>
- </body>
- </html>
|