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