1 /** 2 * Game scene 3 * @param {BB_App} app 4 * @param {number} level 5 * @returns {BB_Game} 6 * @constructor 7 */ 8 function BB_Game(app, level) { 9 var self = this, 10 sprite = app.sprite, 11 drawer = app.drawer, 12 map = BB_Game.maps[level]; 13 this.app = app; 14 this.level = level; 15 this.sound = 0; 16 this.border = 20; 17 this.score = new BB_Score(sprite); 18 this.overlay = new BB_Overlay(sprite, this.score, level); 19 this.overlay.back.disabled = level <= 0; 20 this.overlay.next.disabled = level >= BB_Game.maps.length-1; 21 this.ball = new BB_Ball(sprite, map.b[0], map.b[1]); 22 this.coins = []; 23 this.walls = []; 24 this.holes = []; 25 drawer.wood(0, 0, this.w, this.h, 10); 26 drawer.wood(0, 0, this.w, this.border, 2, 2); 27 drawer.wood(0, this.border, this.border, this.h, 2, 2); 28 map.w.forEach(function(w) { 29 var wall = new BB_Wall(w[0], w[1], w[2], w[3]); 30 drawer.wood(wall.x, wall.y, wall.w, wall.h, 2, 2); 31 self.walls.push(wall); 32 }); 33 drawer.wood(this.w-this.border, this.border, this.border, this.h, 2, 2); 34 drawer.wood(0, this.h-this.border, this.w, this.border, 2, 2); 35 sprite.paint(drawer.ctx, 2, 2, 16, 16, 0, 116); 36 map.h.forEach(function(h) { 37 var hole = new BB_Hole(h[0], h[1]); 38 drawer.hole(hole.ox(), hole.oy(), hole.r, 2); 39 self.holes.push(hole); 40 }); 41 map.c.forEach(function(c) { 42 self.coins.push(new BB_Coin(sprite, c[0], c[1])); 43 }); 44 this.goal = this.coins.length; 45 this.repaint = true; 46 } 47 48 /** 49 * Extends CP_Item 50 */ 51 BB_Game.prototype = new CP_Item(480, 320); 52 53 /** 54 * Paint game canvas 55 * @param ctx 56 */ 57 BB_Game.prototype.paint = function(ctx) { 58 if (this.repaint) { 59 this.clear(ctx); 60 this.score.paint(ctx); 61 this.coins.forEach(function(coin) { 62 coin.paint(ctx); 63 }); 64 this.ball.paint(ctx); 65 if (this.end()) { 66 this.overlay.paint(ctx); 67 } 68 this.repaint = false; 69 } 70 }; 71 72 /** 73 * Check game status 74 * @returns {Boolean} 75 */ 76 BB_Game.prototype.end = function() { 77 return !this.ball.v && (!this.score.shot || !this.goal); 78 }; 79 80 /** 81 * Game thread 82 */ 83 BB_Game.prototype.run = function() { 84 var goal = 0; 85 app = this.app, 86 ball = this.ball, 87 score = this.score, 88 coins = this.coins, 89 repaint = this.score.run(), 90 sound = false; 91 i = 0; 92 this.coins.forEach(function(coin) { 93 if (coin.run()) repaint = true; 94 }); 95 if (ball.run()) { 96 if (this.check(ball)) { 97 score.on('wall'); 98 sound = 0; 99 } 100 this.walls.forEach(function(wall) { 101 if (wall.check(ball)) { 102 score.on('wall'); 103 sound = 0; 104 } 105 }); 106 this.holes.forEach(function(hole) { 107 if (hole.check(ball)) { 108 ball.reset(); 109 score.on('reset'); 110 } 111 }); 112 this.coins.forEach(function(coin) { 113 if (!coin.has) { 114 if (coin.check(ball)) { 115 sound = 2; 116 score.on('coin'); 117 } 118 goal++; 119 } 120 }); 121 this.goal = goal; 122 if (this.end()) { 123 score.on('end'); 124 app.storage.setScore(this.level, score, !goal); 125 this.overlay.next.disabled = !score.next; 126 } 127 if (sound !== false) { 128 app.sound.play(sound + this.sound); 129 this.sound = ++this.sound % 2; 130 } 131 repaint = true; 132 } 133 this.repaint = repaint; 134 }; 135 136 /** 137 * Check ball bounce on drawer 138 * @param {BB_Ball} ball 139 * @returns {Boolean} 140 */ 141 BB_Game.prototype.check = function(ball) { 142 if (ball.x < this.border) { 143 ball.x = this.border; 144 ball.bounce(-1, 1); 145 return true; 146 } else if (ball.x + ball.w > this.w - this.border) { 147 ball.x = this.w - this.border - ball.w; 148 ball.bounce(-1, 1); 149 return true; 150 } 151 if (ball.y < this.border) { 152 ball.y = this.border; 153 ball.bounce(1, -1); 154 return true; 155 } else if (ball.y + ball.h > this.h - this.border) { 156 ball.y = this.h - this.border - ball.h; 157 ball.bounce(1, -1); 158 return true; 159 } 160 return false; 161 }; 162 163 /** 164 * Game event handler 165 * @param {String} e 166 * @param {Number} x 167 * @param {Number} y 168 * @param {Boolean} touch 169 */ 170 BB_Game.prototype.on = function(e, x, y, touch) { 171 if (this.end()) { 172 this.repaint = this.overlay.check(x, y) || this.repaint; 173 if (e == 'end') { 174 if (this.overlay.start.active) { 175 this.app.start(); 176 } else if ( 177 this.overlay.next.active && 178 !this.overlay.next.disabled 179 ) { 180 this.app.start(1); 181 } else if ( 182 this.overlay.back.active && 183 !this.overlay.back.disabled 184 ) { 185 this.app.start(-1); 186 } 187 } 188 } else if (this.score.shot && this.goal) { 189 switch (e) { 190 case 'start': 191 case 'move': 192 if (touch) { 193 this.ball.hold(x, y); 194 } 195 break; 196 case 'end': 197 this.ball.shot(x, y); 198 this.score.on('shot'); 199 break; 200 } 201 this.repaint = true; 202 } else if (e == 'end') { 203 ball.stop(); 204 } 205 }; 206 207 /* 208 { //creator 209 b:[], 210 c:[[50, 50],[140,50],[230,50],[320,50],[410,50], 211 [50, 100],[140,100],[230,100],[320,100],[410,100], 212 [50, 150],[140,150],[230,150],[320,150],[410,150], 213 [50, 200],[140,200],[230,200],[320,200],[410,200], 214 [50, 250],[140,250],[230,250],[320,250],[410,250]], 215 w:[[20,280,95,20],[20,280,185,20],[20,280,275,20],[20,280,365,20], 216 [440,20,20,100],[440,20,20,150],[440,20,20,200]], 217 h:[] 218 }, 219 */ 220 221 /** 222 * Game maps data 223 * b: ball position 224 * c: coins position 225 * w: walls position and size 226 * h: holes position 227 */ 228 BB_Game.maps = [{ //X 229 b:[220, 140], 230 c:[[50, 50],[410,50], 231 [140,100],[320,100], 232 [140,200],[320,200], 233 [50, 250],[410,250]], 234 w:[], 235 h:[] 236 },{ //diamond 237 b:[220, 140], 238 c:[[230,50], 239 [140,100],[320,100], 240 [50, 150],[410,150], 241 [140,200],[320,200], 242 [230,250]], 243 w:[], 244 h:[] 245 },{ //square 246 b:[220, 140], 247 c:[[50, 50],[230,50],[410,50], 248 [50,150],[410,150], 249 [50,250],[230,250],[410,250]], 250 w:[], 251 h:[] 252 },{ //diamond hole 253 b:[130, 140], 254 c:[[230,50], 255 [140,100],[320,100], 256 [50, 150],[410,150], 257 [140,200],[320,200], 258 [230,250]], 259 w:[], 260 h:[[305,135]] 261 },{ //one wall 262 b:[130, 140], 263 c:[[140,50],[230,50],[320,50], 264 [50, 100],[410,100], 265 [50, 150],[410,150], 266 [50, 200],[410,200], 267 [140,250],[230,250],[320,250]], 268 w:[[20,120,275,100]], 269 h:[] 270 },{ //lines 271 b:[220, 140], 272 c:[[50, 50],[230,50],[410,50], 273 [50, 100],[230,100],[410,100], 274 [50, 150],[410,150], 275 [50, 200],[230,200],[410,200], 276 [50, 250],[230,250],[410,250]], 277 w:[[20,200,95,20],[20,200,365,100]], 278 h:[] 279 },{ //diamond plus 280 b:[40,40], 281 c:[[230,50], 282 [140,100],[320,100], 283 [50, 150],[410,150], 284 [140,200],[320,200], 285 [230,250]], 286 w:[[40,20,190,150],[20,100,230,110],[40,20,250,150]], 287 h:[] 288 },{ //two levels 289 b:[220, 140], 290 c:[[50, 50],[140,50],[230,50],[320,50],[410,50], 291 [50, 150],[140,150],[320,150],[410,150], 292 [50, 250],[140,250],[230,250],[320,250],[410,250]], 293 w:[[175,20,20,100],[175,20,285,200]], 294 h:[] 295 },{ //treasure 296 b:[40,140], 297 c:[[50,50],[140,50],[230,50],[320,50],[410,50], 298 [50, 100],[140,100],[230,100],[320,100],[410,100], 299 [50, 200],[140,200],[230,200],[320,200],[410,200], 300 [50, 250],[140,250],[230,250],[320,250],[410,250]], 301 w:[[280,20,100,150]], 302 h:[] 303 },{ //cross 304 b:[220, 140], 305 c:[[230,50], 306 [230,100], 307 [50, 150],[140,150],[320,150],[410,150], 308 [230,200], 309 [230,250],], 310 w:[[20,80,185,20],[20,80,275,20],[20,80,185,220],[20,80,275,220]], 311 h:[] 312 },{ //boxes 313 b:[220, 140], 314 c:[[140,50],[230,50],[320,50], 315 [140,100],[320,100], 316 [140,150],[320,150], 317 [140,200],[320,200], 318 [140,250],[230,250],[320,250]], 319 w:[[40,40,85,140],[40,40,355,140]], 320 h:[] 321 },{ //corners 322 b:[220, 140], 323 c:[[140,50],[230,50],[320,50], 324 [50, 100],[410,100], 325 [50, 150],[410,150], 326 [50, 200],[410,200], 327 [140,250],[230,250],[320,250]], 328 w:[[20,20,50,50],[20,20,410,50],[20,20,50,250],[20,20,410,250]], 329 h:[] 330 },{ //two holes 331 b:[220, 140], 332 c:[[50, 50],[140,50],[320,50],[410,50], 333 [50, 100],[140,100],[320,100],[410,100], 334 [50, 200],[140,200],[320,200],[410,200], 335 [50, 250],[140,250],[320,250],[410,250]], 336 w:[], 337 h:[[35,135],[395,135]] 338 },{ //full house 339 b:[220, 140], 340 c:[[50, 50],[140,50],[230,50],[320,50],[410,50], 341 [50, 100],[140,100],[230,100],[320,100],[410,100], 342 [50, 150],[140,150],[320,150],[410,150], 343 [50, 200],[140,200],[230,200],[320,200],[410,200], 344 [50, 250],[140,250],[230,250],[320,250],[410,250]], 345 w:[], 346 h:[] 347 },{ //random 348 b:[310,190], 349 c:[[50, 50],[230,50],[320,50],[410,50], 350 [50, 100],[410,100], 351 [230,150], 352 [50, 200], 353 [230,250],[320,250],[410,250]], 354 w:[[160,20,20,150]], 355 h:[] 356 },{ //3+2 357 b:[220, 40], 358 c:[[50, 50],[410,50], 359 [50, 100],[230,100],[410,100], 360 [50, 150],[230,150],[410,150], 361 [50, 200],[230,200],[410,200], 362 [50, 250],[410,250]], 363 w:[[20,100,185,110],[20,100,275,110]], 364 h:[] 365 },{ //one on one 366 b:[40,40], 367 c:[[140,50],[230,50],[320,50], 368 [140,150],[230,150],[320,150], 369 [140,250],[230,250],[320,250]], 370 w:[[200,20,20,200]], 371 h:[[395,35]] 372 },{ //shield 373 b:[220, 140], 374 c:[[50, 50],[140,50],[230,50],[320,50],[410,50], 375 [50, 250],[140,250],[230,250],[320,250],[410,250]], 376 w:[[140,20,20,150],[140,20,320,150]], 377 h:[] 378 },{ //Labirinty 379 b:[220, 140], 380 c:[[50, 50],[140,50],[410,50], 381 [410,100], 382 [50, 200], 383 [50, 250],[320,250],[410,250]], 384 w:[[20,80,95,220],[20,80,365,20], 385 [80,20,20,100],[80,20,380,200]], 386 h:[] 387 },{ //sraf 388 b:[40,40], 389 c:[[230,50],[320,50],[410,50], 390 [140,150],[230,150],[320,150], 391 [50, 250],[140,250],[230,250]], 392 w:[[20,100,95,100], 393 [100,20,115,100],[100,20,265,200],[20,100,365,120]], 394 h:[] 395 }]; 396