1.预备知识
(1)在画布上绘制外部图片资源
(2)梯度(gradient):HTML5中的对象类型,包括线性梯度和径向梯度。如createLinearGradient,绘制梯度需要颜色组
http://www.w3school.com.cn/tags/canvas_createlineargradient.asp
function test1(){ //在画布上绘制外部图片资源 var ctx = document.getElementById('ballCanvas').getContext('2d') var image =new Image() image.src = 'football.jpg' ctx.drawImage(image,0,0,360,300) } //test1() function test2(){ /* 梯度(gradient):HTML5中的对象类型,包括线性梯度和径向梯度。如createLinearGradient, 绘制梯度需要颜色组 http://www.w3school.com.cn/tags/canvas_createlineargradient.asp */ var ctx = document.getElementById('ballCanvas').getContext('2d') var gradient = ctx.createLinearGradient(10,10,200,10) var hue = ['#FFF','#F00','#000'] gradient.addColorStop(0,hue[0]) gradient.addColorStop(0.5,hue[1]) gradient.addColorStop(1,hue[2]) ctx.fillStyle = gradient ctx.fillRect(10,10,200,100) } //test2()
2.实现思路
整个游戏中涉及的对象,包括运动的球(Ball),墙壁(Box),速度(Speed)。
同时,球必须在墙壁内部进行运动,碰到墙壁则会反弹。
当到球和墙壁碰撞的时候,运行方向会发生改变,这个改变对速度的绝对值没有变化,而是改变速度的正负。在实现过程中,我把方向的概念合并到
了速度对象中,主要是代码实现上的方便。
3.代码(片段)
// Ball function Ball(){ var opts, ctx, ballX, ballY function drawBall(){ var ballOpts = opts.ballOpts ballX = ballOpts.x ballY = ballOpts.y ctx.lineWidth = ballOpts.lineWidth ctx.strokeStyle = ballOpts.strokeStyle ctx.beginPath() ctx.arc(ballX,ballY,ballOpts.radius,0,2*Math.PI,false) ctx.closePath() ctx.stroke() } return { init : function(options){ opts = $.extend(options,{ canvas : null, ballOpts : { x : 100, y : 100, radius : 50, lineWidth : 1, strokeStyle : '#000' } }) var canvas = opts.canvas if(canvas==null){ alert('canvas is null.') return } ctx = canvas.getContext('2d') drawBall() return this }, /* beginMove @return:void @speed:{offsetX:0,offsetY:0} @box:Box instance */ beginMove : function(speed,box){ box.refresh() var boxSize = box.getSize(), ballOpts = opts.ballOpts, offsetX = speed.offsetX, offsetY = speed.offsetY, directionChanged = false // 判断球ball是在盒子box内边框(上,右,下,左)内 var boxInnerBoundry = { top:boxSize.y+boxSize.lineWidth, right:boxSize.x+boxSize.lineWidth+boxSize.width, bottom:boxSize.y+boxSize.lineWidth+boxSize.height, left:boxSize.x+boxSize.lineWidth } var top = (ballY-ballOpts.radius-ballOpts.lineWidth)+offsetY, right = (ballX+ballOpts.radius+ballOpts.lineWidth)+offsetX, bottom = (ballY+ballOpts.radius+ballOpts.lineWidth)+offsetY, left = (ballX-ballOpts.radius-ballOpts.lineWidth)+offsetX if(top<boxInnerBoundry.top){ ballY += top-boxInnerBoundry.top offsetY = -offsetY directionChanged = true } if(right>boxInnerBoundry.right){ ballX += right-boxInnerBoundry.right offsetX = -offsetX directionChanged = true } if(bottom>boxInnerBoundry.bottom){ ballY += offsetY - (bottom-boxInnerBoundry.bottom) offsetY = -offsetY directionChanged = true } if(left<boxInnerBoundry.left){ ballX += left-boxInnerBoundry.left offsetX = -offsetX directionChanged = true } ballX += offsetX ballY += offsetY /* 必须变更当前速度speed,因为在定时器中传入的速度speed是个常量, 而实际运动中速度(用加号和减号来表示的方向是会改变的) */ if(directionChanged){ speed.changeSpeed(offsetX,offsetY) } //alert(ballOpts.x+offsetX+'-'+ballOpts.y+offsetY) ctx.beginPath() ctx.arc(ballX,ballY,ballOpts.radius,0,2*Math.PI,false) ctx.closePath() ctx.stroke() } } }
4.优化和完善
(1)主要还是在球和墙壁的判断上,通过大量的IF判断,实现得比较恶心
(2)速度实现为了类似的单例方式,不符合重用
(3)风格可以美化,加入外部图片资源等,比如美化成足球和球场
(4)引入加速度