├── README.md ├── res ├── g.png ├── bg.png ├── atlas.png ├── birdy.png ├── blood.png ├── board.png ├── icon.png ├── over.png ├── reset.png ├── start.png ├── tube.png ├── tube2.png ├── birddie.png ├── sfx_die.mp3 ├── sfx_hit.mp3 ├── sfx_wing.mp3 ├── iconweixin.png ├── sfx_point.mp3 └── sfx_swooshing.mp3 ├── bower_components └── phaser │ ├── bower.json │ ├── README.md │ └── .bower.json ├── .gitignore ├── gulpfile.coffee ├── bower.json ├── package.json ├── gulpfile.js ├── LICENSE ├── index.html ├── index.coffee └── index.js /README.md: -------------------------------------------------------------------------------- 1 | FlappyTube 2 | ========== 3 | -------------------------------------------------------------------------------- /res/g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/g.png -------------------------------------------------------------------------------- /res/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/bg.png -------------------------------------------------------------------------------- /res/atlas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/atlas.png -------------------------------------------------------------------------------- /res/birdy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/birdy.png -------------------------------------------------------------------------------- /res/blood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/blood.png -------------------------------------------------------------------------------- /res/board.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/board.png -------------------------------------------------------------------------------- /res/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/icon.png -------------------------------------------------------------------------------- /res/over.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/over.png -------------------------------------------------------------------------------- /res/reset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/reset.png -------------------------------------------------------------------------------- /res/start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/start.png -------------------------------------------------------------------------------- /res/tube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/tube.png -------------------------------------------------------------------------------- /res/tube2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/tube2.png -------------------------------------------------------------------------------- /res/birddie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/birddie.png -------------------------------------------------------------------------------- /res/sfx_die.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/sfx_die.mp3 -------------------------------------------------------------------------------- /res/sfx_hit.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/sfx_hit.mp3 -------------------------------------------------------------------------------- /res/sfx_wing.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/sfx_wing.mp3 -------------------------------------------------------------------------------- /res/iconweixin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/iconweixin.png -------------------------------------------------------------------------------- /res/sfx_point.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/sfx_point.mp3 -------------------------------------------------------------------------------- /res/sfx_swooshing.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flynngao/FlappyTube/HEAD/res/sfx_swooshing.mp3 -------------------------------------------------------------------------------- /bower_components/phaser/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phaser", 3 | "version": "1.1.4", 4 | "main": "./phaser.js" 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | node_modules 16 | res -------------------------------------------------------------------------------- /bower_components/phaser/README.md: -------------------------------------------------------------------------------- 1 | # bower-phaser 2 | 3 | The source for this package is in the [main Phaser repo](https://github.com/photonstorm/phaser). 4 | 5 | ## Install 6 | 7 | Install with `bower`: 8 | 9 | ```shell 10 | bower install phaser 11 | ``` 12 | 13 | Add a ` 17 | ``` 18 | -------------------------------------------------------------------------------- /bower_components/phaser/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phaser", 3 | "version": "1.1.4", 4 | "main": "./phaser.js", 5 | "homepage": "https://github.com/nDmitry/bower-phaser", 6 | "_release": "1.1.4", 7 | "_resolution": { 8 | "type": "version", 9 | "tag": "1.1.4", 10 | "commit": "22afbebdaa47f373cf5f99fe4403052a0b887fff" 11 | }, 12 | "_source": "git://github.com/nDmitry/bower-phaser.git", 13 | "_target": "~1.1.4", 14 | "_originalSource": "phaser" 15 | } -------------------------------------------------------------------------------- /gulpfile.coffee: -------------------------------------------------------------------------------- 1 | gulp = require 'gulp' 2 | coffee = require 'gulp-coffee' 3 | gutil = require 'gulp-util' 4 | connect = require 'gulp-connect' 5 | 6 | gulp.task 'coffee', -> 7 | gulp.src ['index.coffee','!gulpfile.coffee'] 8 | .pipe coffee( bare: true ).on('error', gutil.log) 9 | 10 | gulp.task 'watch', -> 11 | gulp.watch ['index.html','index.coffee', '!gulpfile.coffee'], ['coffee'] 12 | 13 | gulp.task "connect", connect.server( 14 | root: __dirname 15 | port: 3000 16 | livereload: true 17 | ) 18 | 19 | gulp.task 'default', ['coffee','connect','watch'] -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flappytube", 3 | "version": "0.0.1", 4 | "homepage": "https://github.com/flynngao/FlappyTube", 5 | "authors": [ 6 | "Flynn Gao " 7 | ], 8 | "description": "Flappy Tube", 9 | "main": "index.html", 10 | "keywords": [ 11 | "H5", 12 | "games", 13 | "flappy" 14 | ], 15 | "license": "MIT", 16 | "private": true, 17 | "ignore": [ 18 | "**/.*", 19 | "node_modules", 20 | "bower_components", 21 | "test", 22 | "tests" 23 | ], 24 | "dependencies":{ 25 | "phaser": "~1.1.4" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flappytube", 3 | "version": "0.0.1", 4 | "description": "Flppay Tube", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "game", 11 | "flappy", 12 | "tube" 13 | ], 14 | "repository": { 15 | "type": "git", 16 | "url": "git@github.com:flynngao/FlappyTube.git" 17 | }, 18 | "devDependencies": { 19 | "gulp": "~3.5.2", 20 | "coffee-script": "*", 21 | "gulp-coffee": "*", 22 | "gulp-util": "~2.2.14", 23 | "gulp-connect": "*" 24 | }, 25 | "author": "Flynn Gao", 26 | "license": "MIT" 27 | } 28 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.7.1 2 | var coffee, connect, gulp, gutil; 3 | 4 | gulp = require('gulp'); 5 | 6 | coffee = require('gulp-coffee'); 7 | 8 | gutil = require('gulp-util'); 9 | 10 | connect = require('gulp-connect'); 11 | 12 | gulp.task('coffee', function() { 13 | return gulp.src(['index.coffee', '!gulpfile.coffee']).pipe(coffee({ 14 | bare: true 15 | }).on('error', gutil.log)); 16 | }); 17 | 18 | gulp.task('watch', function() { 19 | return gulp.watch(['index.html', 'index.coffee', '!gulpfile.coffee'], ['coffee']); 20 | }); 21 | 22 | gulp.task("connect", connect.server({ 23 | root: __dirname, 24 | port: 3000, 25 | livereload: true 26 | })); 27 | 28 | gulp.task('default', ['coffee', 'connect', 'watch']); 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Flynngao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flappy Tube 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 45 | 46 | 47 |
48 | Code and Design by FlynnGao 49 | 50 | 51 | 52 | 53 | 63 | 71 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /index.coffee: -------------------------------------------------------------------------------- 1 | DEBUG = false 2 | SPEED = 160 3 | GRAVITY = 600 4 | SPAWN_RATE = 1 / 1200 5 | 6 | HEIGHT = 480 7 | WIDTH = 320 8 | GAME_HEIGHT = 336 9 | GROUND_HEIGHT = 64 10 | GROUND_Y = HEIGHT - GROUND_HEIGHT 11 | HARD = 250 12 | 13 | # Object 14 | tube = null 15 | birds = null 16 | birddie = null 17 | ground = null 18 | bg = null 19 | blood = null 20 | bloods = null 21 | # Game Flow 22 | gameStart = false 23 | gameOver = false 24 | birdsTimer = null 25 | dieRate = null 26 | # Game Texts 27 | score = null 28 | bestScore = 0 29 | bestText = null 30 | comingsoon = null 31 | scoreText = null 32 | instText = null 33 | gameOverText = null 34 | resetText = null 35 | gameStartText = null 36 | avoidText = null 37 | board = null 38 | # Sounds 39 | flapSnd = null 40 | scoreSnd = null 41 | hurtSnd = null 42 | fallSnd = null 43 | swooshSnd = null 44 | 45 | floor = Math.floor 46 | 47 | main = -> 48 | 49 | hitBirds = (tube,bird)-> 50 | 51 | bird.kill() 52 | 53 | score += 1 54 | bestScore = if score > bestScore then score else bestScore 55 | scoreText.setText score 56 | 57 | b = bloods.getFirstDead() 58 | b.reset(bird.body.x,bird.body.y) 59 | b.play('blood',20,false,true) 60 | hurtSnd.play() 61 | return 62 | 63 | createBirds = -> 64 | 65 | dieRate = score / HARD 66 | birds.forEachAlive (bird) -> 67 | if bird.x + bird.width < game.world.bounds.left 68 | bird.kill() 69 | return 70 | birddie.forEachAlive (bird) -> 71 | if bird.x + bird.width < game.world.bounds.left 72 | bird.kill() 73 | return 74 | 75 | for i in [(parseInt(Math.random()*10)%4+8)...0] 76 | raceName = if Math.random() > dieRate then 'birdy' else 'birddie' 77 | race = if raceName == 'birdy' then birds else birddie 78 | bird = race.create(game.world.width-(Math.random()-0.5)*120, i * (35-(Math.random()-0.5)*5), raceName) 79 | bird.anchor.setTo 0.5, 0.5 80 | bird.body.velocity.x = -SPEED * 1.5 81 | 82 | 83 | return 84 | 85 | flap = -> 86 | 87 | start() unless gameStart 88 | 89 | unless gameOver 90 | tube.body.velocity.y = -200; 91 | tube.body.gravity.y = 0; 92 | 93 | tween = game.add.tween(tube.body.velocity).to(y:-280, 25, Phaser.Easing.Bounce.In,true); 94 | tween.onComplete.add -> 95 | tube.body.gravity.y = GRAVITY 96 | 97 | flapSnd.play() 98 | 99 | 100 | return 101 | 102 | start = -> 103 | gameStart = true 104 | gameStartText.renderable = false 105 | comingsoon.renderable = false 106 | # SPAWN birds! 107 | birdsTimer = game.time.events.loop 1 / SPAWN_RATE, createBirds 108 | scoreText.setText score 109 | avoidText.renderable = false 110 | return 111 | 112 | over = -> 113 | gameOver = true 114 | 115 | gameOverText.renderable = true 116 | resetText.renderable = true 117 | board.renderable = true 118 | bestText.renderable = true 119 | bestText.setText bestScore 120 | bestText.x = 210 121 | bestText.y = 240 122 | scoreText.x = 210 123 | scoreText.y = 195 124 | 125 | document.getElementById('star').style.display = 'block'; 126 | # Stop spawning tubes 127 | game.time.events.remove(birdsTimer) 128 | 129 | 130 | game.time.events.add 1000, -> 131 | game.input.onTap.addOnce -> 132 | reset() 133 | fallSnd.play() 134 | return 135 | 136 | preload = -> 137 | assets = 138 | image: 139 | "bg" : 'res/bg.png' 140 | "birdy" : 'res/birdy.png' 141 | "birddie": 'res/birddie.png' 142 | "g" : 'res/g.png' 143 | "tube" : 'res/tube.png' 144 | "start" : 'res/start.png' 145 | "reset" : 'res/reset.png' 146 | "over" : 'res/over.png' 147 | "board" : 'res/board.png' 148 | audio: 149 | "die" : 'res/sfx_die.mp3' 150 | "hit" : 'res/sfx_hit.mp3' 151 | "point" : 'res/sfx_point.mp3' 152 | "flap" : 'res/sfx_wing.mp3' 153 | spritesheet: 154 | "blood" : ['res/blood.png',64, 64] 155 | 156 | 157 | 158 | Object.keys(assets).forEach (type) -> 159 | Object.keys(assets[type]).forEach (id) -> 160 | game.load[type].apply game.load, [id].concat(assets[type][id]) 161 | return 162 | return 163 | return 164 | 165 | create = -> 166 | 167 | Phaser.Canvas.setSmoothingEnabled(game.context, false) 168 | game.stage.scaleMode = Phaser.StageScaleMode.SHOW_ALL 169 | game.stage.scale.setScreenSize(true) 170 | game.world.width = WIDTH 171 | game.world.height = HEIGHT 172 | 173 | 174 | # bg 175 | bg = game.add.tileSprite(0, 0,WIDTH,HEIGHT,'bg'); 176 | 177 | # ground 178 | ground = game.add.tileSprite(0,GROUND_Y,WIDTH,GROUND_HEIGHT,'g'); 179 | 180 | # Add Birds 181 | birds = game.add.group() 182 | birddie = game.add.group() 183 | 184 | tube = game.add.sprite(0,0,"tube") 185 | tube.anchor.setTo(0.5 , 0.5) 186 | 187 | # Add sounds 188 | flapSnd = game.add.audio("flap") 189 | scoreSnd = game.add.audio("point") 190 | hurtSnd = game.add.audio("hit") 191 | fallSnd = game.add.audio("die") 192 | 193 | #bloods 194 | bloods = game.add.group() 195 | bloods.createMultiple(20,'blood') 196 | bloods.forEach((x)-> 197 | x.anchor.x = 0.5 198 | x.anchor.y = 0.5 199 | x.animations.add('blood') 200 | return 201 | this) 202 | 203 | board = game.add.sprite(game.world.width / 2 ,game.world.height / 2.3,'board') 204 | board.anchor.setTo 0.5, 0.5 205 | board.scale.setTo 1, 1 206 | board.renderable = false 207 | 208 | #score 209 | scoreText = game.add.text(game.world.width / 2, game.world.height / 6, "", 210 | font: "20px \"sans\"" 211 | fill: "#fff" 212 | stroke:"#111" 213 | strokeThickness:4 214 | align:"center") 215 | scoreText.anchor.setTo 0.5 , 0.5 216 | 217 | bestText = game.add.text(game.world.width / 2, game.world.height / 6, "", 218 | font: "20px \"sans\"" 219 | fill: "#fff" 220 | stroke:"#111" 221 | strokeThickness:4 222 | align:"center") 223 | bestText.anchor.setTo 0.5 , 0.5 224 | bestText.renderable = false 225 | 226 | avoidText = game.add.text(game.world.width / 2, game.world.height / 2.7, "", 227 | font: "14px \"sans\"" 228 | fill: "#fff" 229 | stroke:"#111" 230 | strokeThickness:4 231 | align:"center") 232 | avoidText.anchor.setTo 0.5 , 0.5 233 | avoidText.setText("Avoid this") 234 | 235 | gameStartText = game.add.sprite(game.world.width / 2, game.world.height / 2,'start') 236 | gameStartText.anchor.setTo 0.5, 0.5 237 | gameStartText.scale.setTo 1, 1 238 | # Add game over text 239 | gameOverText = game.add.sprite(game.world.width / 2, game.world.height / 4,'over') 240 | gameOverText.anchor.setTo 0.5, 0.5 241 | gameOverText.scale.setTo 1, 1 242 | gameOverText.renderable = false 243 | 244 | comingsoon = game.add.text(game.world.width / 1.5, game.world.height / 4.5,'', 245 | font: "12px \"sans\"" 246 | fill: "#d9d12b" 247 | stroke:"#111" 248 | strokeThickness:3 249 | align:"center") 250 | comingsoon.anchor.setTo 0.5, 0.5 251 | comingsoon.scale.setTo 1, 1 252 | comingsoon.setText(' ^\nComing soon!') 253 | 254 | 255 | 256 | 257 | resetText = game.add.sprite(game.world.width/ 2, game.world.height / 1.5,'reset') 258 | resetText.anchor.setTo 0.5, 0.5 259 | resetText.scale.setTo 1, 1 260 | resetText.renderable = false 261 | 262 | # control 263 | game.input.onDown.add flap 264 | 265 | 266 | reset() 267 | 268 | return 269 | 270 | update = -> 271 | if gameStart 272 | 273 | unless gameOver 274 | # Check game over 275 | game.physics.overlap tube, birddie, -> 276 | over() 277 | fallSnd.play() 278 | over() if not gameOver and tube.body.bottom >= GROUND_Y 279 | 280 | game.physics.overlap tube, birds, hitBirds, null ,this 281 | 282 | # Scroll ground 283 | ground.tilePosition.x -= game.time.physicsElapsed * SPEED / 2 unless gameOver 284 | bg.tilePosition.x -= game.time.physicsElapsed * SPEED unless gameOver 285 | 286 | 287 | else 288 | 289 | if tube.body.bottom >= GROUND_Y + 3 290 | tube.y = GROUND_Y - 13 291 | tube.body.velocity.y = 0 292 | tube.body.allowGravity = false 293 | tube.body.gravity.y = 0 294 | 295 | return 296 | 297 | render = -> 298 | return 299 | 300 | reset = -> 301 | 302 | gameStart = false 303 | gameOver = false 304 | gameOverText.renderable = false 305 | resetText.renderable = false 306 | gameStartText.renderable = true 307 | board.renderable = false 308 | bestText.renderable = false 309 | avoidText.renderable = true 310 | comingsoon.renderable = true 311 | document.getElementById('star').style.display = 'none'; 312 | score = 0 313 | scoreText.setText('Flappy Tube 2') 314 | scoreText.x = game.world.width / 2 315 | scoreText.y = game.world.height / 6 316 | birds.removeAll() 317 | tube.reset game.world.width * 0.25, game.world.height /2.3 318 | 319 | 320 | return 321 | 322 | 323 | state = 324 | preload : preload 325 | create : create 326 | update : update 327 | render : render 328 | 329 | game = new Phaser.Game(WIDTH, HEIGHT, Phaser.CANVAS, 'screem', state, false) 330 | 331 | 332 | main() -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.7.1 2 | var DEBUG, GAME_HEIGHT, GRAVITY, GROUND_HEIGHT, GROUND_Y, HARD, HEIGHT, SPAWN_RATE, SPEED, WIDTH, avoidText, bestScore, bestText, bg, birddie, birds, birdsTimer, blood, bloods, board, comingsoon, dieRate, fallSnd, flapSnd, floor, gameOver, gameOverText, gameStart, gameStartText, ground, hurtSnd, instText, main, resetText, score, scoreSnd, scoreText, swooshSnd, tube; 3 | 4 | DEBUG = false; 5 | 6 | SPEED = 160; 7 | 8 | GRAVITY = 600; 9 | 10 | SPAWN_RATE = 1 / 1200; 11 | 12 | HEIGHT = 480; 13 | 14 | WIDTH = 320; 15 | 16 | GAME_HEIGHT = 336; 17 | 18 | GROUND_HEIGHT = 64; 19 | 20 | GROUND_Y = HEIGHT - GROUND_HEIGHT; 21 | 22 | HARD = 250; 23 | 24 | tube = null; 25 | 26 | birds = null; 27 | 28 | birddie = null; 29 | 30 | ground = null; 31 | 32 | bg = null; 33 | 34 | blood = null; 35 | 36 | bloods = null; 37 | 38 | gameStart = false; 39 | 40 | gameOver = false; 41 | 42 | birdsTimer = null; 43 | 44 | dieRate = null; 45 | 46 | score = null; 47 | 48 | bestScore = 0; 49 | 50 | bestText = null; 51 | 52 | comingsoon = null; 53 | 54 | scoreText = null; 55 | 56 | instText = null; 57 | 58 | gameOverText = null; 59 | 60 | resetText = null; 61 | 62 | gameStartText = null; 63 | 64 | avoidText = null; 65 | 66 | board = null; 67 | 68 | flapSnd = null; 69 | 70 | scoreSnd = null; 71 | 72 | hurtSnd = null; 73 | 74 | fallSnd = null; 75 | 76 | swooshSnd = null; 77 | 78 | floor = Math.floor; 79 | 80 | main = function() { 81 | var create, createBirds, flap, game, hitBirds, over, preload, render, reset, start, state, update; 82 | hitBirds = function(tube, bird) { 83 | var b; 84 | bird.kill(); 85 | score += 1; 86 | bestScore = score > bestScore ? score : bestScore; 87 | scoreText.setText(score); 88 | b = bloods.getFirstDead(); 89 | b.reset(bird.body.x, bird.body.y); 90 | b.play('blood', 20, false, true); 91 | hurtSnd.play(); 92 | }; 93 | createBirds = function() { 94 | var bird, i, race, raceName, _i, _ref; 95 | dieRate = score / HARD; 96 | birds.forEachAlive(function(bird) { 97 | if (bird.x + bird.width < game.world.bounds.left) { 98 | bird.kill(); 99 | } 100 | }); 101 | birddie.forEachAlive(function(bird) { 102 | if (bird.x + bird.width < game.world.bounds.left) { 103 | bird.kill(); 104 | } 105 | }); 106 | for (i = _i = _ref = parseInt(Math.random() * 10) % 4 + 8; _ref <= 0 ? _i < 0 : _i > 0; i = _ref <= 0 ? ++_i : --_i) { 107 | raceName = Math.random() > dieRate ? 'birdy' : 'birddie'; 108 | race = raceName === 'birdy' ? birds : birddie; 109 | bird = race.create(game.world.width - (Math.random() - 0.5) * 120, i * (35 - (Math.random() - 0.5) * 5), raceName); 110 | bird.anchor.setTo(0.5, 0.5); 111 | bird.body.velocity.x = -SPEED * 1.5; 112 | } 113 | }; 114 | flap = function() { 115 | var tween; 116 | if (!gameStart) { 117 | start(); 118 | } 119 | if (!gameOver) { 120 | tube.body.velocity.y = -200; 121 | tube.body.gravity.y = 0; 122 | tween = game.add.tween(tube.body.velocity).to({ 123 | y: -280 124 | }, 25, Phaser.Easing.Bounce.In, true); 125 | tween.onComplete.add(function() { 126 | return tube.body.gravity.y = GRAVITY; 127 | }); 128 | flapSnd.play(); 129 | } 130 | }; 131 | start = function() { 132 | gameStart = true; 133 | gameStartText.renderable = false; 134 | comingsoon.renderable = false; 135 | birdsTimer = game.time.events.loop(1 / SPAWN_RATE, createBirds); 136 | scoreText.setText(score); 137 | avoidText.renderable = false; 138 | }; 139 | over = function() { 140 | gameOver = true; 141 | gameOverText.renderable = true; 142 | resetText.renderable = true; 143 | board.renderable = true; 144 | bestText.renderable = true; 145 | bestText.setText(bestScore); 146 | bestText.x = 210; 147 | bestText.y = 240; 148 | scoreText.x = 210; 149 | scoreText.y = 195; 150 | document.getElementById('star').style.display = 'block'; 151 | game.time.events.remove(birdsTimer); 152 | game.time.events.add(1000, function() { 153 | return game.input.onTap.addOnce(function() { 154 | return reset(); 155 | }); 156 | }); 157 | fallSnd.play(); 158 | }; 159 | preload = function() { 160 | var assets; 161 | assets = { 162 | image: { 163 | "bg": 'res/bg.png', 164 | "birdy": 'res/birdy.png', 165 | "birddie": 'res/birddie.png', 166 | "g": 'res/g.png', 167 | "tube": 'res/tube.png', 168 | "start": 'res/start.png', 169 | "reset": 'res/reset.png', 170 | "over": 'res/over.png', 171 | "board": 'res/board.png' 172 | }, 173 | audio: { 174 | "die": 'res/sfx_die.mp3', 175 | "hit": 'res/sfx_hit.mp3', 176 | "point": 'res/sfx_point.mp3', 177 | "flap": 'res/sfx_wing.mp3' 178 | }, 179 | spritesheet: { 180 | "blood": ['res/blood.png', 64, 64] 181 | } 182 | }; 183 | Object.keys(assets).forEach(function(type) { 184 | Object.keys(assets[type]).forEach(function(id) { 185 | game.load[type].apply(game.load, [id].concat(assets[type][id])); 186 | }); 187 | }); 188 | }; 189 | create = function() { 190 | Phaser.Canvas.setSmoothingEnabled(game.context, false); 191 | game.stage.scaleMode = Phaser.StageScaleMode.SHOW_ALL; 192 | game.stage.scale.setScreenSize(true); 193 | game.world.width = WIDTH; 194 | game.world.height = HEIGHT; 195 | bg = game.add.tileSprite(0, 0, WIDTH, HEIGHT, 'bg'); 196 | ground = game.add.tileSprite(0, GROUND_Y, WIDTH, GROUND_HEIGHT, 'g'); 197 | birds = game.add.group(); 198 | birddie = game.add.group(); 199 | tube = game.add.sprite(0, 0, "tube"); 200 | tube.anchor.setTo(0.5, 0.5); 201 | flapSnd = game.add.audio("flap"); 202 | scoreSnd = game.add.audio("point"); 203 | hurtSnd = game.add.audio("hit"); 204 | fallSnd = game.add.audio("die"); 205 | bloods = game.add.group(); 206 | bloods.createMultiple(20, 'blood'); 207 | bloods.forEach(function(x) { 208 | x.anchor.x = 0.5; 209 | x.anchor.y = 0.5; 210 | x.animations.add('blood'); 211 | return; 212 | return this; 213 | }); 214 | board = game.add.sprite(game.world.width / 2, game.world.height / 2.3, 'board'); 215 | board.anchor.setTo(0.5, 0.5); 216 | board.scale.setTo(1, 1); 217 | board.renderable = false; 218 | scoreText = game.add.text(game.world.width / 2, game.world.height / 6, "", { 219 | font: "20px \"sans\"", 220 | fill: "#fff", 221 | stroke: "#111", 222 | strokeThickness: 4, 223 | align: "center" 224 | }); 225 | scoreText.anchor.setTo(0.5, 0.5); 226 | bestText = game.add.text(game.world.width / 2, game.world.height / 6, "", { 227 | font: "20px \"sans\"", 228 | fill: "#fff", 229 | stroke: "#111", 230 | strokeThickness: 4, 231 | align: "center" 232 | }); 233 | bestText.anchor.setTo(0.5, 0.5); 234 | bestText.renderable = false; 235 | avoidText = game.add.text(game.world.width / 2, game.world.height / 2.7, "", { 236 | font: "14px \"sans\"", 237 | fill: "#fff", 238 | stroke: "#111", 239 | strokeThickness: 4, 240 | align: "center" 241 | }); 242 | avoidText.anchor.setTo(0.5, 0.5); 243 | avoidText.setText("Avoid this"); 244 | gameStartText = game.add.sprite(game.world.width / 2, game.world.height / 2, 'start'); 245 | gameStartText.anchor.setTo(0.5, 0.5); 246 | gameStartText.scale.setTo(1, 1); 247 | gameOverText = game.add.sprite(game.world.width / 2, game.world.height / 4, 'over'); 248 | gameOverText.anchor.setTo(0.5, 0.5); 249 | gameOverText.scale.setTo(1, 1); 250 | gameOverText.renderable = false; 251 | comingsoon = game.add.text(game.world.width / 1.5, game.world.height / 4.5, '', { 252 | font: "12px \"sans\"", 253 | fill: "#d9d12b", 254 | stroke: "#111", 255 | strokeThickness: 3, 256 | align: "center" 257 | }); 258 | comingsoon.anchor.setTo(0.5, 0.5); 259 | comingsoon.scale.setTo(1, 1); 260 | comingsoon.setText(' ^\nComing soon!'); 261 | resetText = game.add.sprite(game.world.width / 2, game.world.height / 1.5, 'reset'); 262 | resetText.anchor.setTo(0.5, 0.5); 263 | resetText.scale.setTo(1, 1); 264 | resetText.renderable = false; 265 | game.input.onDown.add(flap); 266 | reset(); 267 | }; 268 | update = function() { 269 | if (gameStart) { 270 | if (!gameOver) { 271 | game.physics.overlap(tube, birddie, function() { 272 | over(); 273 | return fallSnd.play(); 274 | }); 275 | if (!gameOver && tube.body.bottom >= GROUND_Y) { 276 | over(); 277 | } 278 | game.physics.overlap(tube, birds, hitBirds, null, this); 279 | if (!gameOver) { 280 | ground.tilePosition.x -= game.time.physicsElapsed * SPEED / 2; 281 | } 282 | if (!gameOver) { 283 | bg.tilePosition.x -= game.time.physicsElapsed * SPEED; 284 | } 285 | } else { 286 | if (tube.body.bottom >= GROUND_Y + 3) { 287 | tube.y = GROUND_Y - 13; 288 | tube.body.velocity.y = 0; 289 | tube.body.allowGravity = false; 290 | tube.body.gravity.y = 0; 291 | } 292 | } 293 | } 294 | }; 295 | render = function() {}; 296 | reset = function() { 297 | gameStart = false; 298 | gameOver = false; 299 | gameOverText.renderable = false; 300 | resetText.renderable = false; 301 | gameStartText.renderable = true; 302 | board.renderable = false; 303 | bestText.renderable = false; 304 | avoidText.renderable = true; 305 | comingsoon.renderable = true; 306 | document.getElementById('star').style.display = 'none'; 307 | score = 0; 308 | scoreText.setText('Flappy Tube 2'); 309 | scoreText.x = game.world.width / 2; 310 | scoreText.y = game.world.height / 6; 311 | birds.removeAll(); 312 | tube.reset(game.world.width * 0.25, game.world.height / 2.3); 313 | }; 314 | state = { 315 | preload: preload, 316 | create: create, 317 | update: update, 318 | render: render 319 | }; 320 | return game = new Phaser.Game(WIDTH, HEIGHT, Phaser.CANVAS, 'screem', state, false); 321 | }; 322 | 323 | main(); 324 | --------------------------------------------------------------------------------