1 /**
  2  * PNG Sprite generator
  3  * @constructor
  4  */
  5 function BB_Sprite() {
  6 	this.scale = 1;
  7 	this.image = new Image();
  8 };
  9 
 10 /**
 11  * Draw sprites
 12  * @param ctx
 13  * @param {Number} x
 14  * @param {Number} y
 15  * @param {Number} w
 16  * @param {Number} h
 17  * @param {Number} sx
 18  * @param {Number} sy
 19  */
 20 BB_Sprite.prototype.paint = function(ctx, x, y, w, h, sx, sy) {
 21 	var sw = Math.round(w * this.scale),
 22 		sh = Math.round(h * this.scale);
 23 	sx = Math.round(sx * this.scale);
 24 	sy = Math.round(sy * this.scale);
 25 	ctx.drawImage(this.image, sx, sy, sw, sh, x, y, w, h);
 26 };
 27 
 28 /**
 29  * Render circles
 30  * @param ctx
 31  * @param {Number} x
 32  * @param {Number} y
 33  * @param {Number} r
 34  * @param {Number} fill
 35  * @param {Number} stroke
 36  * @param {Number} width
 37  * @param {Number} shadow
 38  */
 39 BB_Sprite.prototype.renderCircle = function(ctx, x, y, r, fill, stroke, width, shadow) {
 40 	ctx.save();
 41 	ctx.beginPath();
 42 	ctx.arc(x, y, r, 0, 2 * Math.PI, false);
 43 	if (shadow) {
 44 		shadow *= this.scale;
 45 		ctx.shadowBlur = shadow;
 46 		ctx.shadowColor = "rgba(0,0,0,.5)";
 47 		ctx.shadowOffsetX = shadow;
 48 		ctx.shadowOffsetY = shadow;
 49 	}
 50 	if (fill) {
 51 		ctx.fillStyle = fill;
 52 		ctx.fill();
 53 	}
 54 	if (stroke) {
 55 		ctx.lineWidth = width || 1;
 56 		ctx.strokeStyle = stroke;
 57 		ctx.stroke();
 58 	}
 59 	ctx.restore();	
 60 };
 61 
 62 /**
 63  * Render the red button
 64  * @param ctx
 65  * @param {Number} x
 66  * @param {Number} y
 67  * @param {Number} angle
 68  * @param {Number} rubber
 69  * @param {Number} scale
 70  */
 71 BB_Sprite.prototype.renderBall = function(ctx, x, y, angle, rubber, scale) {
 72 	var g = ctx.createRadialGradient(-10, -10, 80, -10, -10, 0),
 73 		s = scale || 1;
 74     g.addColorStop(0, "#c00");
 75     g.addColorStop(1, "#900");
 76 	ctx.save();
 77 	ctx.translate(x, y);
 78 	ctx.scale(s, s);
 79 	this.renderCircle(ctx, 0, 0, 17.5, g, '#009', 3, .5);
 80 	ctx.rotate(Math.PI / 180 * angle);
 81 	this.renderCircle(ctx, -5, -5, 3, '#200', '#600');
 82 	this.renderCircle(ctx, -5, 5, 3, '#200', '#600');
 83 //	this.renderCircle(ctx, 5, -5, 3, '#200', '#600');
 84 	this.renderCircle(ctx, 5, 0, 3, '#200', '#600');
 85 	if (rubber) {
 86 		ctx.lineWidth = 2.5;
 87 		ctx.lineCap = 'round';
 88 		ctx.strokeStyle = '#ddd';
 89 		ctx.beginPath();
 90 		ctx.moveTo(-5, -5);
 91 		ctx.lineTo(5, 5);
 92 		ctx.stroke();
 93 		ctx.beginPath();
 94 		ctx.moveTo(-5, 5);
 95 		ctx.lineTo(5, -5);
 96 		ctx.stroke();
 97 	}
 98 	ctx.restore();
 99 };
100 
101 /**
102  * Render the golden buttons
103  * @param ctx
104  * @param {Number} x
105  * @param {Number} y
106  * @param {Number} angle
107  * @param {Number} scale
108  */
109 BB_Sprite.prototype.renderCoin = function(ctx, x, y, angle, scale) {
110 	var g = ctx.createRadialGradient(-5, -5, 40, -5, -5, 0),
111 		s = scale || 1;
112     g.addColorStop(0, "#fc0");
113     g.addColorStop(1, "#f60");
114 	ctx.save();
115 	ctx.translate(x, y);
116 	ctx.scale(s, s);
117 	this.renderCircle(ctx, 0, 0, 8, g, '#c60', 2, .5);
118 	ctx.rotate(Math.PI / 180 * angle);
119 	this.renderCircle(ctx, -3, 0, 2, '#420', '#c60');
120 	this.renderCircle(ctx, 3, 0, 2, '#420', '#c60');
121 	ctx.restore();
122 };
123 
124 /**
125  * Render UI buttons 
126  * @param ctx
127  * @param {Number} x
128  * @param {Number} y
129  * @param {Number} w
130  * @param {Number} h
131  * @param {Number} r
132  * @param {String} text
133  * @param {Number} status
134  */
135 BB_Sprite.prototype.renderButton = function(ctx, x, y, w, h, r, text, status) {
136 	var g = ctx.createLinearGradient(0,0,0,h);
137 	g.addColorStop(0,"#fec");
138 	g.addColorStop(1, "#cb9");
139 	ctx.save();
140 	ctx.translate(x, y);
141 	ctx.beginPath();
142 	ctx.moveTo(0, r);
143 	ctx.arcTo(0, 0, r, 0, r);
144 	ctx.lineTo(w-r, 0);
145 	ctx.arcTo(w, 0, w, r, r);
146 	ctx.lineTo(w, h-r);
147 	ctx.arcTo(w, h, w-h, h, r);
148 	ctx.lineTo(r, h);
149 	ctx.arcTo(0, h, 0, h-r, r);
150 	ctx.closePath();
151 	ctx.fillStyle = g;
152 	ctx.fill();
153 	ctx.strokeStyle = status > 1 ? "#fff" : "#cb9";
154 	ctx.lineWidth = 2;
155 	ctx.stroke();
156 	
157 	ctx.font = "bold 20px Arial";
158 	ctx.textAlign = "center";
159 	//ctx.textBaseline = "middle";
160 	ctx.fillStyle = "#ccc";
161 	ctx.fillText(text, w/2, 22);
162 	ctx.fillStyle = status > 0 ? "#320" : "#986";
163 	ctx.fillText(text, w/2, 21);
164 	ctx.restore();
165 };
166 
167 /**
168  * Render the whole sprite
169  * @param ctx
170  * @param {Number} scale
171  * @returns {BB_Sprite}
172  */
173 BB_Sprite.prototype.render = function(ctx, scale) {
174 	this.scale = scale;
175 	ctx.save();
176 	var i;
177 	for (i=0; i<24; i++) {
178 		var a = i*7.5;
179 		if (i<12) {
180 			this.renderBall(ctx, i*40+20, 20, a, false);
181 			this.renderBall(ctx, i*40+20, 60, a, true);
182 		}
183 		if (i<3) {
184 			this.renderBall(ctx, i*20+10, 108, 0, false, .35);
185 			this.renderCoin(ctx, i*16+8, 124, 0, .8);
186 		}
187 		this.renderCoin(ctx, i*20+10, 90, a);
188 	}
189 	for (i=0; i<3; i++) {
190 		this.renderButton(ctx, 67, i*32+102, 86, 28, 13, "BACK", i);
191 		this.renderButton(ctx, 167, i*32+102, 86, 28, 13, "START", i);
192 		this.renderButton(ctx, 267, i*32+102, 86, 28, 13, "NEXT", i);
193 		this.renderButton(ctx, 367, i*32+102, 86, 28, 13, "SOUND", i);
194 	}
195 	this.image.src = ctx.canvas.toDataURL('image/png');
196 	ctx.restore();
197 	ctx.clearRect(0, 0, 480, 320);
198 	return this;
199 };
200