【整理】HTML5游戏开发学习笔记(2)- 弹跳球

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)引入加速度

原文地址:https://www.cnblogs.com/Benoly/p/4028448.html