java动画碰撞,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)中。

代码如下 :

function Rect(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坐标)。

代码如下:

function Capturemouse (element) {

var mouse={x:null,y:null};

element.addEventListener('mousemove',function (event) {

var x, 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);

return mouse;

}

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。

代码如下:

function Intersect(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所以需要重新绘制)

代码如下:

function drawAnimation() {

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 = new Rect(canvas.width/2,canvas.height/2,100,100);

rectB = new Rect(100,100,100,100);

drawAnimation();

}

2、基于圆形的碰撞检测

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

1、创建circle对象

function Circle(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函数。

代码如下:

function Intersect(circleA,circleB) {

var dx = circleA.x-circleB.x;

var dy = circleA.y-circleB.y;

var distance = Math.sqrt(dx*dx+dy*dy);

return distance < (circleA.radius + circleB.radius);

}

3、动画循环

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

代码如下:

function drawAnimation() {

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 = new Circle(canvas.width/2,canvas.height/2,100);

circleB = new Circle(100,100,100);

drawAnimation();

}

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

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

1、检测碰撞

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

如下图:

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

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

更新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对象的碰撞。

代码如下:

function drawAnimation() {

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 = new Circle(100,100,100);

rect = new Rect(canvas.width/2,canvas.height/2,100,100);

drawAnimation();

}

以上就是本文的全部内容,希望对大家的学习有所帮

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值