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