`
blessdyb
  • 浏览: 235265 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Canvas做游戏实践分享(四)

阅读更多

3.4 使用quadraticCurveTo绘制二次贝赛尔曲线

       Canvas提供了一系列的方法来绘制曲线,比如quadraticCurveTo(通过起始两个点以及一个控制点来绘制,前两个参数为控制点横纵坐标,后两个参数为终点横纵坐标,使用的是数学上的二次贝赛尔方程)。下面我们来看一下常见的一些使用。

 

固定控制点
       如下程序,我们实现了一个固定起始点,使用鼠标位置做为控制点,来绘制二次贝赛尔曲线的应用:

<!doctype html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Canvas</title>
	</head>
	<body>
		<canvas id="canvas" width="400" height="400">当前浏览器不支持canvas</canvas>
		<script type="text/javascript" src="utils.js"></script>
		<script type="text/javascript" src="arrow.js"></script>
		<script type="text/javascript">
			window.onload=function(){
				var canvas=document.getElementById("canvas");
				var context=canvas.getContext("2d");
				var mouse=utils.captureMousePosition(canvas);
                                //固定两个端点
				var x0=100,y0=200,x2=300,y2=200;

				canvas.addEventListener('mousemove',function(){
					//context.clearRect(0,0,canvas.width,canvas.height);
                                        //指定控制点为鼠标位置
					var x1=mouse.x;
					var y1=mouse.y;
                                        //绘制曲线
					context.beginPath();
					context.moveTo(x0,y0);
					context.quadraticCurveTo(x1,y1,x2,y2);
					context.stroke();
				},false);
			};
		</script>
	</body>
</html>

 如下,即为其效果图:

曲线过定点

 

      之前我们绘制的曲线是控制点确定的曲线,如果我们已知曲线上的一个点(非起始点),则需要通过贝赛尔方程的一些特性来处理。(n次贝赛尔曲线有n+1个控制点,并且贝赛尔曲线位于这些控制点组成的多边形内部。) 

       已知两个端点(x0,y0)与(x2,y2)及曲线上的一个点(x1,y1).则可以得到其控制点的位置为

x = x1 * 2 - (x0 + x2) / 2;
y = y1 * 2 - (y0 + y2) / 2;
 

(参见如下文章:

http://learn.gxtc.edu.cn/NCourse/jxcamcad/cadcam/Mains/main4-2.htm
http://www.leeyou.net/UTutorial/show.php?cid=153
http://hi.baidu.com/ggggwhw/blog/item/ffd23d35f313543c5ab5f5ed.html)。

所以,我们只需要修正上述固定控制点的代码,通过曲线上的点来求新的固定点的坐标即可:

var x1=mouse.x*2-(x0+x2)/2;
var y1=mouse.y*2-(y0+y2)/2;


多点控制的平滑曲线

 

       下面来看一个复杂一点的问题,如果我们随机有N个点,如何来使用这N个点,利用二次贝赛尔曲线来绘制一条平滑的曲线?最简单的想法就是每三个点一组来绘制一个二次贝赛尔曲线,不难得到如下代码:

                      window.onload=function(){
				var canvas=document.getElementById("canvas");
				var context=canvas.getContext("2d");
				var points=[];
				var pointNumber=9;
				//随机生成点
				for(var i=0;i<pointNumber;i++){
					points.push({
						x:Math.random()* canvas.width,
						y:Math.random()* canvas.height
					});
				}				
				//每三点来绘制一条曲线
				context.beginPath();
				context.moveTo(points[0].x,points[0].y);
				for(var i=1;i< pointNumber; i+=2){
					context.quadraticCurveTo(points[i].x,points[i].y,points[i+1].x,points[i+1].y);
				}				
				context.stroke();
				//绘制所有给定的点
				for(var i=0;i<pointNumber;i++){
					context.moveTo(points[i].x,points[i].y);
					context.beginPath();
					context.arc(points[i].x,points[i].y,2,0,Math.PI*2,true);
					context.closePath();
					context.fill();
				}
			};

 查看结果,会发现并不是想要的效果,除了共用起始点外,所有的二次曲线都是独立分隔的,并不是一条平滑的曲线,如下图:


 这是因为使用二次贝赛尔方程来绘制一个多点控制的平滑曲线,不可以每三个已知点为一组依次来绘制曲线,这样绘制出来的每一个二次曲线并不在一个相对坐标系统内。可以从第二个点开始,使用每两个点的中点来做端点,其它点均做为控制点来绘制曲线,如下图:(空心点为已知的给定点,实心点为给定点的中点)


按上面的说明,我们来更新代码:

                      window.onload=function(){
				var canvas=document.getElementById("canvas");
				var context=canvas.getContext("2d");
				var points=[];
				var pointNumber=9;
				var ctrlPoint={x:0,y:0};
				
				for(var i=0;i<pointNumber;i++){
					points.push({
						x:Math.random()* canvas.width,
						y:Math.random()* canvas.height
					});
				}				
				
				context.beginPath();
				context.moveTo(points[0].x,points[0].y);
                               //从第二个点开始,使用之后两点之间的“中点”来做为端点
                                for(var i=1;i< pointNumber-2; i++){
					ctrlPoint.x=(points[i].x+points[i+1].x)/2;
					ctrlPoint.y=(points[i].y+points[i+1].y)/2;
					context.quadraticCurveTo(points[i].x,points[i].y,ctrlPoint.x,ctrlPoint.y);
				}	
                                //最后两个点需要特殊处理,无法使用此两点间的“中点”
				context.quadraticCurveTo(points[i].x,points[i].y,points[i+1].x,points[i+1].y);			
				context.stroke();
				
				
				for(i=0;i<pointNumber;i++){
					context.moveTo(points[i].x,points[i].y);
					context.beginPath();
					context.arc(points[i].x,points[i].y,5,0,Math.PI*2,true);
					context.closePath();
					context.fill();
				}
			};

 其效果如下图:


封闭曲线的实现

        可以看出,上述代码对于第一个点,最后一个点相关的“中点”都没有使用到。如果我们想利用到这两个点相关的“中点”来构成一个封闭的平滑曲线。那把所有的点均做为控制点来处理,使用它们的“中点”来做为每一个二次贝赛尔曲线的端点,如下代码所示:

                     window.onload=function(){
				var canvas=document.getElementById("canvas");
				var context=canvas.getContext("2d");
				var points=[];
				var pointNumber=9;
				var ctrlPoint={x:0,y:0};
				var ctrlPoint1={x:0,y:0};
				
				for(var i=0;i<pointNumber;i++){
					points.push({
						x:Math.random()* canvas.width,
						y:Math.random()* canvas.height
					});
				}				
				
                                //构造控制点,使用给定点的“中点”来做为曲线的端点
				ctrlPoint1.x=(points[0].x+points[pointNumber-1].x)/2;
				ctrlPoint1.y=(points[0].y+points[pointNumber-1].y)/2;
				context.beginPath();
				context.moveTo(ctrlPoint1.x,ctrlPoint1.y);
				for(var i=0;i< pointNumber-1; i++){
					ctrlPoint.x=(points[i].x+points[i+1].x)/2;
					ctrlPoint.y=(points[i].y+points[i+1].y)/2;
					context.quadraticCurveTo(points[i].x,points[i].y,ctrlPoint.x,ctrlPoint.y);
				}
                               //封闭曲线
                                context.quadraticCurveTo(points[i].x,points[i].y,ctrlPoint1.x,ctrlPoint1.y);			
				context.stroke();
				
				
				for(i=0;i<pointNumber;i++){
					context.moveTo(points[i].x,points[i].y);
					context.beginPath();
					context.arc(points[i].x,points[i].y,2,0,Math.PI*2,true);
					context.closePath();
					context.fill();
				}
			}

 其效果图如下:


 

注意上面的代码中的i,我们在第一个循环外也使用了i,这是因为JavaScript的变量作用域不是块级的,而是以函数来区分的,如:

console.log(j);          //undefined
for(var j=0;j<10;j++){
    console.log(j);      //1~9
}
console.log(j);          //10 
 

 

  • 大小: 26.3 KB
  • 大小: 20.7 KB
  • 大小: 21.6 KB
  • 大小: 28.8 KB
  • 大小: 23.8 KB
1
0
分享到:
评论
1 楼 stchou 2012-02-12  
   canvas用得出神入化~

相关推荐

    HTML5 Canvas游戏开发实战

    9. **最佳实践**:分享HTML5 Canvas开发的最佳实践,包括代码组织、调试技巧以及如何确保兼容性。 10. **社区与资源**:可能还会介绍一些HTML5和Canvas的在线社区、工具、库和框架,帮助读者持续学习和提高。 总的...

    HTML5 Canvas核心技术图形、动画与游戏开发 PDF扫描版[71MB].rar

    在这个"HTML5 Canvas核心技术图形、动画与游戏开发"的PDF扫描版中,读者可以深入学习到Canvas的核心概念和实践技巧。 首先,Canvas的基本使用方法是通过JavaScript API来实现的。这个API提供了大量的绘图命令,如`...

    canvas简单实例详解

    HTML5的Canvas是一个强大的绘图API,它允许开发者在网页上进行动态的、基于...随着对Canvas的深入理解和实践,你会发现它的潜力无穷无尽。在实际项目中,可以结合CSS3、WebGL等技术,构建更复杂的交互式Web应用。

    小程序canvasDemo

    在微信小程序中,Canvas是一个非常重要的组件,它允许开发者在...以上就是关于"小程序canvasDemo"项目中涉及的主要技术点,通过学习和实践,你可以掌握微信小程序中canvas的使用技巧,进一步提升你的小程序开发能力。

    html5_canvas_塔防游戏

    HTML5 Canvas是Web开发中的一个强大工具,它允许开发者在网页上进行动态图形绘制,创造出丰富的交互式用户体验。在这个“html5_canvas_...这样的实现不仅方便分享,也为开发者提供了一个学习和实践Canvas API的好平台。

    canvas+js写的绘图小程序

    《canvas+js绘制图形的实践探索》 在Web开发领域,HTML5的canvas元素提供了一种强大的机制,允许开发者在浏览器上进行动态图形绘制。这篇博文将深入探讨如何结合JavaScript,利用canvas API来构建一个简单的绘图小...

    canvas截图.zip

    这个功能在很多场景下都非常有用,比如网页分享、游戏截图、在线编辑器保存草图等。 首先,我们要了解canvas的基本用法。canvas是一个矩形画布,通过JavaScript来控制它的内容。我们可以通过`&lt;canvas&gt;`标签在HTML中...

    html5 canvas核心技术

    HTML5 Canvas是Web开发中的一个关键技术,...通过学习和实践这些HTML5 Canvas的核心技术,开发者可以构建出交互性强、视觉效果丰富的Web应用程序,无论是数据可视化、游戏开发还是艺术创作,Canvas都能提供强大的支持。

    HTML5 Canvas实战pdf下载

    9. **保存和导出**:Canvas上的内容可以导出为图像,或者使用toDataURL方法生成数据URL,方便分享和存储。 10. **实际应用**:书中实例可能涵盖游戏开发、图表绘制、数据可视化、地图应用等多个实际场景,帮助...

    canvas画图测试

    这篇博客"canvas画图测试"可能涉及了使用Canvas进行图形绘制的基础知识和实践技巧。Canvas API的使用通常包括以下几个核心知识点: 1. **Canvas元素**:在HTML中,`&lt;canvas&gt;`标签定义了一个可编程的画布,通过...

    android游戏源码分享

    2. 用户界面(UI):Android游戏通常使用自定义View或SurfaceView来实现游戏画面,结合Canvas进行绘制。UI的设计也包括菜单、暂停、设置等交互元素。 3. 图形渲染:游戏可能使用OpenGL ES进行高性能的2D或3D图形...

    H5游戏源码分享-跑酷游戏熊出没

    四、源码学习与实践 理解并分析“熊出没”跑酷游戏的源码,有助于提升H5游戏开发技能。开发者可以从中学习如何组织项目结构,如何运用JavaScript实现游戏逻辑,以及如何优化性能。此外,通过修改源码,可以创造出...

    HTML5 Canvas学习笔记(6)拼图游戏(数字版)

    在“HTML5 Canvas学习笔记(6)拼图游戏(数字版)”这篇博文中,作者分享了如何利用Canvas构建一个数字拼图游戏。下面我们将详细探讨这个知识点。 1. **HTML5 Canvas基础**: - Canvas是一个基于矢量图形的画布元素...

    html5 canvas 视频网站文字弹幕动画特效

    这个技术的引入极大地扩展了网页的交互性和动态性,尤其在创建复杂的动画效果和游戏场景时表现得尤为出色。在这个特定的场景中,我们讨论的是如何使用HTML5 Canvas实现视频网站的文字弹幕动画特效。 首先,我们要...

    H5游戏源码分享-跳得更高

    H5游戏源码的分享,对于学习者来说是一次宝贵的实践机会,可以了解游戏逻辑、动画效果、用户交互等核心元素的实现方法。 【标签】"游戏":游戏是软件的一种类型,它可以提供娱乐、挑战或教育功能。H5游戏作为游戏的...

    games:使用canvas api开发一堆HTML游戏以使其更好,并且仅使用HTMLCSSJS堆栈构建游戏

    HTML5 Canvas API是Web开发中的一个强大工具,它允许开发者在网页上绘制2D图形,创建动态、交互式的游戏和应用程序。在这个项目中,“games:使用canvas api...在实践中,不断探索和创新,制作出更丰富、更有趣的游戏。

    《HTML5 Canvas 开发详解(第2版)》PDF

    8. **性能优化**:分享关于Canvas性能的技巧,如批处理绘图操作、使用图像数据缓冲区和避免不必要的重绘。 9. **高级应用**:深入探讨更复杂的用例,如粒子系统、游戏开发、图表绘制和数据可视化。 10. **实践案例...

    H5自写的小游戏源码分享

    在“H5自写的小游戏源码分享”这...同时,这也是一个很好的学习实践机会,可以提升你的JavaScript编程水平,理解游戏开发中的逻辑思维和问题解决能力。不断练习和学习,你将能够创造出更多有趣、引人入胜的HTML5游戏。

    jquery html5微信分享游戏围住神经猫游戏源码下载

    【标题】:“jQuery HTML5微信分享游戏:围住神经猫游戏源码下载” 【描述】:这个资源提供了基于jQuery和HTML5技术开发的微信分享...对于希望从事移动互联网游戏开发的初学者来说,这是一个非常有价值的实践案例。

    QMLcanvas画板鼠标画图

    通过理解和实践这个项目,开发者可以掌握QML中的2D绘图技术,以及如何结合鼠标事件来实现动态的用户交互功能。这对于开发桌面应用、游戏或者任何需要在屏幕上绘制图形的场景都具有很高的实用价值。

Global site tag (gtag.js) - Google Analytics