实验2 台球
简介
台球源于英国,它是一项在国际上广泛流行的高雅的室内体育运动,是一种用球杆在台上击球,依靠计算得分确定比赛胜负的室内娱乐体育项目。台球也称为桌球(中国港、澳地区的称法)、撞球(中国台湾地区的称法)。在没有开球之前,每个球的摆放位置如图1-8所示。
图1-8 桌球
这次,要绘制的就是类似图1-8的效果。在绘制之前,先来绘制实心圆。
实心圆
CanvasRenderingContext2D提供了fill函数,为一个封闭的区域内填充颜色,如圆形、矩形等。实心圆和空心圆的区别在于:
● 设置实心圆颜色:CanvasRenderingContext2D.fillStyle;
● 设置空心圆路径颜色:CanvasRenderingContext2D.strokeStyle;
● 填充实心圆:CanvasRenderingContext2D.fill;
● 连接空心圆路径:CanvasRenderingContext2D.stroke。
掌握了这些,可以轻松地在Canvas中画一个实心圆:
<canvasid="myCanvas"width="200"height="100"style="border:1px solid #c3c3c3;"> Your browser does not support the canvas element. </canvas> <scripttype="text/javascript"> var c=document.getElementById("myCanvas"); var cxt=c.getContext("2d"); cxt.fillStyle="#FF7F00"; cxt.beginPath(); cxt.arc(70, 18, 15, 0, Math.PI * 2, true); cxt.closePath(); cxt.fill(); </script>
效果如图1-9所示。
图1-9画圆
实心圆
掌握了画实心圆,就可以开始绘制台球桌面上的16个小球(包括母球)了。在绘制之前,先复习一下初等几何知识,一个直角三角形,如果有一个角为30°,那么三角形的三个边的比例如图1-10所示。
图1-10 三角形各边比例
再回到要绘制的台球,如图1-11所示。最外层的圆心连成的三角形是等边三角形,然后被分成两个直角三角形,等边三角形的3个角都是60°,所以被分成的直角三角形的三个边的比例是。
图1-11 桌球布局分析
假设母球和离母球最近的顶部的球的位置分别如下:
var parentBall={ position: { x: 200, y: 200 }, r: r, color: "#fff" }; var firstBall={ position: { x: 550, y: 200 }, r: r, color: "#fff" };
这里用了面向对象的思想分别定义了小球的位置、半径和颜色。知道了顶部小球的位置,加上上面的分析,可以生成后面一系列小球的坐标:
for (var j=1; j < 5; j++) { for (var k=0; k < j+1; k++) { var ball={ position: { x: firstBall.position.x+j * Math.sqrt(3) * r, y: firstBall.position.y - j * r+2 * k * r }, r: r, color: "#fff" }; balls.push(ball); } }
把所有生成的球放入一个balls的数组当中,然后调用CanvasRenderingContext2DAPI,根据小球的坐标、颜色和半径,把所有小球绘制出来:
cxt.fillStyle="#fff"; for (i in balls) { cxt.beginPath(); cxt.arc(balls[i].position.x, balls[i].position.y, balls[i].r, 0, Math.PI * 2, true); cxt.closePath(); cxt.fill(); }
完整的代码如下:
<canvasid="myCanvas"width="847"height="440"style="background-color:#000000"> Your browser does not support the canvas element. </canvas> <script> var canvas=document.getElementById("myCanvas"); var cxt=canvas.getContext("2d"); var r=10; var balls=[]; function initBall() { \注:initBall方法生成所有的小球\ var parentBall={ position: { x: 200, y: 200 }, r: r, color: "#fff" }; var firstBall={ position: { x: 550, y: 200 }, r: r, color: "#fff" }; for (var j=1; j < 5; j++) { for (var k=0; k < j+1; k++) { \注:根据 firstBall的坐标,通过两个嵌套的for循环生成所有小球坐标\ var ball={ position: { x: firstBall.position.x+j * Math.sqrt(3) * r, y: firstBall.position.y - j * r+2 * k * r }, r: r, color: "#fff" }; balls.push(ball); } } balls.push(firstBall); balls.push(parentBall); } function draw() { cxt.fillStyle="#fff"; for (i in balls) { cxt.beginPath(); cxt.arc(balls[i].position.x, balls[i].position.y, balls[i].r, 0, Math.PI * 2, true); cxt.closePath(); cxt.fill(); } } initBall(); draw(); </script>
运行效果如图1-12所示。
图1-12 在Canvas上模拟绘制
当然,也可以在初始化小球时让每个小球产生一个随机颜色,利用下面这种方法产生随机颜色。
function randomColor() { var arrHex=["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"]; var strHex="#"; var index; for (var i=0; i < 6; i++) { index=Math.round(Math.random() * 15); strHex +=arrHex[index]; } return strHex; }
在初始化小球时调用该方法。
var firstBall={ position: { x: 550, y: 200 }, r: r, color: randomColor() \注:产生随机颜色\ }; for (var j=1; j < 5; j++) { for (var k=0; k < j+1; k++) { var ball={ position: { x: firstBall.position.x+j * Math.sqrt(3) * r, y: firstBall.position.y - j * r+2 * k * r }, r: r, color: randomColor() \注:产生随机颜色\ }; balls.push(ball); } }
在画球时直接使用小球的color属性即可。
function draw() {
for (i in balls) {
cxt.fillStyle=balls[i].color; \注:在这里使用\
cxt.beginPath();
cxt.arc(balls[i].position.x, balls[i].position.y, balls[i].r, 0, Math.PI * 2, true);
cxt.closePath();
cxt.fill();
}
}
效果如图1-13所示。
图1-13 彩色桌球
通过这个实验,学习了基本的绘制实心圆的方法,并通过不同颜色的小球模拟出桌球的初始摆放。在真实的游戏开发当中,会让美工画好具有反光和立体感的小球,然后把对应的位置填上相应的小球图片,就可以达到最终想要的效果。