Html5如何实现Canvas动画基础碰撞检测


这篇文章主要介绍了Html5如何实现Canvas动画基础碰撞检测,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

Html5 Canvas动画基础碰撞检测的实现

在Canvas中进行碰撞检测,大家往往直接采用游戏引擎(Cocos2d-JS、Egret)或物理引擎(Box2D)内置的碰撞检测功能,好奇的你有思考过它们的内部运行机制吗?下面将针对基本的碰撞检测技术进行讲解:

1、基于矩形的碰撞检测

所谓碰撞检测就是判断物体间是否发生重叠,这里我们假设讨论的碰撞体都是矩形物体。下面示例中我们将创建两个rect对象A和B(以下简称A,B),其中A位置固定,B跟随鼠标移动,当A,B重叠时控制台将提示intercect!!

1、创建Rect对象

这里我们新建Rect.js,建立Rect对象并为其添加原型方法draw,该方法将根据当前对象的属性(位置、大小)绘制到传入的画布对象(context)中。

代码如下 :

functionRect(x,y,width,height){this.x=x;this.y=y;this.width=width;this.height=height;}Rect.prototype.draw=function(context){context.save();context.translate(this.x,this.y);context.fillRect(0,0,this.width,this.height);context.restore();}

2、获取鼠标位置

因为B需要跟随鼠标移动所以我们需要检测鼠标在画布的当前位置。创建Capturemouse函数检测鼠标在传入的文档节点(element)上的移动并返回一个mouse对象(其中包含了鼠标的x,y坐标)。

代码如下:

functionCapturemouse(element){varmouse={x:null,y:null};element.addEventListener('mousemove',function(event){varx,y;if(event.pageX||event.pageY){x=event.pageX;y=event.pageY;}else{x=event.clientX+document.body.scrollLeft+document.documentElement.scrollLeft;y=event.clientY+document.body.scrollTop+document.documentElement.scrollTop;}x-=element.offsetLeft;y-=element.offsetTop;mouse.x=x;mouse.y=y;},false);returnmouse;}

3、碰撞检测

检测A,B是否发生重叠,在讨论是否发生重叠时我们可以先看看没有重叠的四种情况,如下图:

以下是对这四种状态的判断:

1、rectB.y+rectB.height < rectA.y
2、rectB.y > rectA.x +rectA.width
3、rectB.y > rectA.y + rectA.height
4、rectB.x+rectB.width < rectA.x

知道如何判断没有重叠的状态,那发生重叠的状态该如何判断呢?没错“取反”!,我们创建函数Interaect并添加到Init.js中,该函数传入两个Rect对象参数,当两Rect对象发生重叠将返回true。

代码如下:

functionIntersect(rectA,rectB){return!(rectB.y+rectB.height<rectA.y||rectB.y>rectA.x+rectA.width||rectB.y>rectA.y+rectA.height||rectB.x+rectB.width<rectA.x)}

4、动画循环

新建animationjs,设置requestAnimationFrame()动画函数。

在循环体中将做以下两件事:

“清空”当前canvas中内容,为绘制下一帧做准备。
检测A,B是否发生重叠,若重叠则在控制台输出interact!!!
检测当前鼠标在canvas上的移动并将鼠标位置更新到B的位置属性中。
根据新的位置属性重新绘制A,B(当然,A的位置不会更新但因为每次循环将清空canvas所以需要重新绘制)
代码如下:

functiondrawAnimation(){window.requestAnimationFrame(drawAnimation);context.clearRect(0,0,canvas.width,canvas.height);if(Intersect(rectA,rectB)){console.log('interact!!!!');}if(mouse.x){rectB.x=mouse.x;rectB.y=mouse.y;}rectA.draw(context);rectB.draw(context);}

3、初始化

新建Init.js ,获取canvas元素并绑定鼠标移动检测,初始化Rect对象A和B,最后开启动画循环。

代码如下:

window.onload=function(){canvas=document.getElementById('collCanvas');context=canvas.getContext('2d');Capturemouse(canvas);rectA=newRect(canvas.width/2,canvas.height/2,100,100);rectB=newRect(100,100,100,100);drawAnimation();}

2、基于圆形的碰撞检测

说完矩形碰撞,我们再来聊聊圆形碰撞,同样我们将创建两个Circle对象A和B(以下简称A,B),其中A位置固定,B跟随鼠标移动,当A,B重叠时控制台将提示intercect!!

1、创建circle对象

functionCircle(x,y,radius){this.x=x;this.y=y;this.radius=radius;}Circle.prototype.draw=function(context){context.save();context.translate(this.x,this.y);context.beginPath();context.arc(0,0,this.radius,0,Math.PI*2,false);context.fill();context.restore();}

2、检测圆形碰撞

圆形间碰撞检测可以简单地通过两圆心间距离与两圆半径之和的比较做判断,当两圆心距离小于两圆半径之和时则发生碰撞。

如下图:

所以我们首先需要做的是计算出两圆心间的距离,这里我们将用到两点间的距离公式,如下:

当取得两圆心间的距离之后将与两圆半径之和比较,如果距离小于半径之和则返回true。

现在我们更新Interaect函数。

代码如下:

functionIntersect(circleA,circleB){vardx=circleA.x-circleB.x;vardy=circleA.y-circleB.y;vardistance=Math.sqrt(dx*dx+dy*dy);returndistance<(circleA.radius+circleB.radius);}

3、动画循环

更新animation.js,这里我们替换Rect对象为Circle对象。

代码如下:

functiondrawAnimation(){window.requestAnimationFrame(drawAnimation);context.clearRect(0,0,canvas.width,canvas.height);if(Intersect(circleA,circleB)){console.log('interact!!!!');}if(mouse.x){circleB.x=mouse.x;circleB.y=mouse.y;}circleA.draw(context);circleB.draw(context);}

4、初始化

更新Init.js ,初始化Circle对象A和B,最后开启动画循环。

代码如下:

window.onload=function(){canvas=document.getElementById('collCanvas');context=canvas.getContext('2d');Capturemouse(canvas);circleA=newCircle(canvas.width/2,canvas.height/2,100);circleB=newCircle(100,100,100);drawAnimation();}

3、基于矩形与圆形间的碰撞检测

前面讲解都是单一形状间的碰撞检测,下面我们将检测矩形和圆形间的碰撞。

1、检测碰撞

和矩形检测一样,我们先看看没有发生碰撞的四种情况。

如下图:

以下是对这四种状态的判断:

Circle.y+Circle.radius<Rect.yCircle.x-Circle.radius>Rect.x+Rect.widthCircle.y-Circle.radius>Rect.y+Rect.heightCircle.x+Circle.radius<Rect.x更新Interaect函数,将没有重叠的状态“取反”,向该函数传入Rect对象和Circle对象,当Rect对象与Circle对象发生重叠将返回true。

代码如下:

function Intersect(Rect,Circle) {
return !(Circle.y + Circle.radius < Rect.y ||
Circle.x - Circle.radius > Rect.x + Rect.width ||
Circle.y - Circle.radius > Rect.y + Rect.height ||
Circle.x + Circle.radius < Rect.x)
}
2、动画循环

更新animation.js,这里我们将circle对象跟随鼠标运动,并检测与固定位置的rect对象的碰撞。

代码如下:

functiondrawAnimation(){window.requestAnimationFrame(drawAnimation);context.clearRect(0,0,canvas.width,canvas.height);if(Intersect(rect,circle)){console.log('interact!!!!');}if(mouse.x){circle.x=mouse.x;circle.y=mouse.y;}circle.draw(context);rect.draw(context);}

3、初始化

更新Init.js ,初始化Circle对象和Rect对象,最后开启动画循环。

代码如下:

window.onload=function(){canvas=document.getElementById('collCanvas');context=canvas.getContext('2d');Capturemouse(canvas);circle=newCircle(100,100,100);rect=newRect(canvas.width/2,canvas.height/2,100,100);drawAnimation();}

感谢你能够认真阅读完这篇文章,希望小编分享的“Html5如何实现Canvas动画基础碰撞检测”这篇文章对大家有帮助,同时也希望大家多多支持主机评测网,关注主机评测网行业资讯频道,更多相关知识等着你来学习!


上一篇:Entity?Framework如何使用LINQ操作实体

下一篇:开发医药小程序需设计什么功能


Copyright © 2002-2019 测速网 www.inhv.cn 皖ICP备2023010105号
测速城市 测速地区 测速街道 网速测试城市 网速测试地区 网速测试街道
温馨提示:部分文章图片数据来源与网络,仅供参考!版权归原作者所有,如有侵权请联系删除!

热门搜索 城市网站建设 地区网站制作 街道网页设计 大写数字 热点城市 热点地区 热点街道 热点时间 房贷计算器