Flash/Flex学习笔记(41):碰撞检测
2010-11-22 17:23
302 查看
碰撞检测基本上可能分为二类:对象与对象的碰撞检测、对象与点的碰撞检测
为了方便测试,先写一个box类(生成一个小矩形)
show sourceview source
print?
最基本的对象碰撞检测:hitTestObject
show sourceview source
print?
如果把Box换成前面例子中的Ball,就是下面这个样子:
很明显:矩形换成球后,碰撞检测变得不精确了,有一些球似乎并没有真正撞到其它球也停下来了,这是为什么腻?
答案就在于:Flash对象碰撞检测默认采用“对象的矩形边界”做为检测依据。上面二张图演示了这一细节:第一张图虽然肉眼看上去只有二个矩形相交了,但是在Flash看来,其实每对图形都碰到了(第二张图),所以大家应该也能明白为啥换成球后,有些球会浮在空中了。
对象与点的碰撞检测:hitTestPoint
show sourceview source
print?
用鼠标在二个物体上划过,会看到鼠标所在点与矩形及小球的碰撞检测结果,同样这里也存在一个问题:对于小球而言,默认也是采用矩形边界检测的,所以鼠标移到小球的边角时,虽然还没碰到球,也提示"碰到了",还好Flash提供了一个可选参数,以改进检测的精确度,只要把hitTestPoint第三个可选参数设置为true即可
if (ball.hitTestPoint(mouseX,mouseY) || box.hitTestPoint(mouseX,mouseY,true)) {
基于距离的检测:即检测二个物体的中心点距离是否低于最小距离
show sourceview source
print?
很明显,这种方法对于圆形物体是十分精确的,但对于非规则形状,只能近似检测.
如果结合上二篇提到的弹性运动,可以做出更复杂的动画:
show sourceview source
print?
原理图:
多物体基于距离的碰撞检测:
show sourceview source
print?
为了方便测试,先写一个box类(生成一个小矩形)
show sourceview source
print?
01
package
{
02
03
import
flash.display.Sprite;
04
05
public
class
Box
extends
Sprite {
06
07
private
var
w:
Number
;
08
private
var
h:
Number
;
09
private
var
color:
uint
;
10
public
var
vx:
Number
=
0
;
11
public
var
vy:
Number
=
0
;
12
13
public
function
Box(width:
Number
=
50
, height:
Number
=
50
, color:
uint
=
0xff0000
) {
14
w=width;
15
h=height;
16
this
.color=color;
17
init();
18
}
19
20
public
function
init():
void
{
21
graphics.beginFill(color);
22
graphics.drawRect(-w /
2
, -h /
2
, w, h);
23
graphics.endFill();
24
}
25
}
26
}
最基本的对象碰撞检测:hitTestObject
show sourceview source
print?
01
package
{
02
03
import
flash.display.Sprite;
04
import
flash.events.Event;
05
06
public
class
Boxes
extends
Sprite {
07
08
private
var
box:Box;
09
private
var
boxes:
Array
;
10
private
var
gravity:
Number
=
0.1
;
11
12
public
function
Boxes() {
13
init();
14
}
15
16
private
function
init():
void
{
17
boxes =
new
Array
();
18
createBox();
19
addEventListener(Event.ENTER_FRAME, onEnterFrame);
20
}
21
22
private
function
onEnterFrame(event:Event):
void
{
23
box.vy+=gravity;
24
box.y+=box.vy;
25
26
//如果物体下落到了舞台(最下)边界,则再造一个出来往下掉
27
if
(box.y+box.height/
2
>stage.stageHeight) {
28
box.y=stage.stageHeight-box.height/
2
;
29
createBox();
30
}
else
{
31
for
(
var
i:
uint
=
0
;i <boxes.length;i++) {
32
//每个正在下掉的物体与其它物体做(矩形)碰撞检测
33
if
(box!=boxes[i]&&box.hitTestObject(boxes[i])) {
34
box.y=boxes[i].y-boxes[i].height/
2
-box.height/
2
;
35
//堆到顶了,则停止
36
if
(box.y<=box.height/
2
){
37
removeEventListener(Event.ENTER_FRAME,onEnterFrame);
38
}
39
else
{
40
createBox();
41
}
42
}
43
}
44
}
45
46
}
47
48
private
function
createBox():
void
{
49
box=
new
Box(Math.random()*
40
+
10
,Math.random()*
40
+
10
,Math.random()*
0xffffff
);
50
box.x=Math.random()*stage.stageWidth;
51
addChild(box);
52
boxes.push(box);
53
}
54
}
55
}
如果把Box换成前面例子中的Ball,就是下面这个样子:
很明显:矩形换成球后,碰撞检测变得不精确了,有一些球似乎并没有真正撞到其它球也停下来了,这是为什么腻?
答案就在于:Flash对象碰撞检测默认采用“对象的矩形边界”做为检测依据。上面二张图演示了这一细节:第一张图虽然肉眼看上去只有二个矩形相交了,但是在Flash看来,其实每对图形都碰到了(第二张图),所以大家应该也能明白为啥换成球后,有些球会浮在空中了。
对象与点的碰撞检测:hitTestPoint
show sourceview source
print?
01
package
{
02
import
flash.display.Sprite;
03
import
flash.events.Event;
04
import
flash.text.TextField;
05
06
public
class
PointHitTest
extends
Sprite {
07
private
var
ball:Ball;
08
private
var
box:Box;
09
private
var
txt:TextField =
new
TextField();
10
11
public
function
PointHitTest() {
12
init();
13
}
14
15
private
function
init():
void
{
16
ball=
new
Ball;
17
addChild(ball);
18
ball.x=stage.stageWidth/
2
;
19
ball.y=stage.stageHeight/
2
;
20
21
box =
new
Box(
90
,
90
);
22
addChild(box);
23
box.x =
100
;
24
box.y =ball.y;
25
26
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
27
28
addChild(txt);
29
txt.selectable =
false
;
30
}
31
32
private
function
EnterFrameHandler(event:Event):
void
{
33
if
(ball.hitTestPoint(mouseX,mouseY) || box.hitTestPoint(mouseX,mouseY)) {
34
txt.text =
"碰到了!"
;
35
}
36
else
{
37
txt.text =
""
;
38
}
39
txt.x =mouseX +
15
;
40
txt.y =mouseY;
41
}
42
}
43
}
用鼠标在二个物体上划过,会看到鼠标所在点与矩形及小球的碰撞检测结果,同样这里也存在一个问题:对于小球而言,默认也是采用矩形边界检测的,所以鼠标移到小球的边角时,虽然还没碰到球,也提示"碰到了",还好Flash提供了一个可选参数,以改进检测的精确度,只要把hitTestPoint第三个可选参数设置为true即可
if (ball.hitTestPoint(mouseX,mouseY) || box.hitTestPoint(mouseX,mouseY,true)) {
基于距离的检测:即检测二个物体的中心点距离是否低于最小距离
show sourceview source
print?
01
var
ball_1:Ball=
new
Ball(
70
,
0xff0000
);
02
var
ball_2:Ball=
new
Ball(
70
,
0x0000ff
);
03
04
ball_1.x=stage.stageWidth/
2
;
05
ball_1.y=stage.stageHeight/
2
;
06
07
ball_2.x=stage.stageWidth/
2
;
08
ball_2.y=stage.stageHeight/
2
;
09
10
ball_1.vx =Math.random()*
20
-
20
;
11
ball_1.vy =Math.random()*
20
-
20
;
12
ball_2.vx =Math.random()*
20
-
20
;
13
ball_2.vy =Math.random()*
20
-
20
;
14
15
addChild(ball_1);
16
addChild(ball_2);
17
18
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
19
20
function
EnterFrameHandler(e:Event):
void
{
21
ball_1.x+=ball_1.vx;
22
ball_1.y+=ball_1.vy;
23
ball_2.x+=ball_2.vx;
24
ball_2.y+=ball_2.vy;
25
CheckBoundary(ball_1);
26
CheckBoundary(ball_2);
27
28
var
dx:
Number
=ball_1.x-ball_2.x;
29
var
dy:
Number
=ball_1.y-ball_2.y;
30
var
dist:
Number
=Math.sqrt(dx*dx+dy*dy);
31
if
(dist<(ball_1.radius + ball_2.radius)) {
32
33
var
angle:
Number
=Math.atan2(dy,dx);
34
ball_1.vx=dist*Math.cos(angle)*
0.1
;
35
ball_1.vy=dist*Math.sin(angle)*
0.1
;
36
ball_2.vx=dist*Math.cos(angle)*-
0.1
;
37
ball_2.vy=dist*Math.sin(angle)*-
0.1
;
38
}
39
}
40
41
function
CheckBoundary(b:Ball) {
42
if
(b.x>stage.stageWidth-b.width/
2
||b.x<=b.width/
2
) {
43
b.x-=b.vx;
44
b.vx*=-
1
;
45
}
46
47
if
(b.y>stage.stageHeight-b.height/
2
||b.y<=b.height/
2
) {
48
b.y-=b.vy;
49
b.vy*=-
1
;
50
}
51
}
很明显,这种方法对于圆形物体是十分精确的,但对于非规则形状,只能近似检测.
如果结合上二篇提到的弹性运动,可以做出更复杂的动画:
show sourceview source
print?
01
package
{
02
import
flash.display.Sprite;
03
import
flash.events.Event;
04
public
class
Bubbles
extends
Sprite {
05
private
var
balls:
Array
;
06
private
var
numBalls:
Number
=
10
;
07
private
var
centerBall:Ball;
08
private
var
bounce:
Number
=-
1
;
09
private
var
spring:
Number
=
0.2
;
10
public
function
Bubbles() {
11
init();
12
}
13
private
function
init():
void
{
14
balls=
new
Array
;
15
centerBall=
new
Ball(
100
,
0xcccccc
);
16
addChild(centerBall);
17
centerBall.x=stage.stageWidth/
2
;
18
centerBall.y=stage.stageHeight/
2
;
19
for
(
var
i:
uint
=
0
;i<numBalls;i++) {
20
var
ball:Ball=
new
Ball(Math.random()*
40
+
5
,Math.random()*
0xffffff
);
21
ball.x=Math.random()*stage.stageWidth;
22
ball.y=Math.random()*stage.stageHeight;
23
ball.vx=(Math.random()*
2
-
1
)*
10
;
24
ball.vy=(Math.random()*
2
-
1
)*
10
;
25
addChild(ball);
26
balls.push(ball);
27
}
28
addEventListener(Event.ENTER_FRAME,onEnterFrame);
29
}
30
private
function
onEnterFrame(event:Event):
void
{
31
for
(
var
i:
uint
=
0
;i<numBalls;i++) {
32
var
ball:Ball=balls[i];
33
move(ball);
34
var
dx:
Number
=ball.x-centerBall.x;
35
var
dy:
Number
=ball.y-centerBall.y;
36
var
dist:
Number
=Math.sqrt(dx*dx+dy*dy);
37
var
minDist:
Number
=ball.radius+centerBall.radius;
38
if
(dist<minDist) {
39
var
angle:
Number
=Math.atan2(dy,dx);
40
var
tx:
Number
=centerBall.x+Math.cos(angle)*minDist;
//弹性运动的目标点x坐标
41
var
ty:
Number
=centerBall.y+Math.sin(angle)*minDist;
//弹性运动的目标点y坐标
42
ball.vx+=(tx-ball.x)*spring;
43
ball.vy+=(ty-ball.y)*spring;
44
}
45
}
46
}
47
private
function
move(ball:Ball):
void
{
48
ball.x+=ball.vx;
49
ball.y+=ball.vy;
50
if
(ball.x+ball.radius>stage.stageWidth) {
51
ball.x=stage.stageWidth-ball.radius;
52
ball.vx*=bounce;
53
}
else
if
(ball.x-ball.radius<
0
) {
54
ball.x=ball.radius;
55
ball.vx*=bounce;
56
}
57
if
(ball.y+ball.radius>stage.stageHeight) {
58
ball.y=stage.stageHeight-ball.radius;
59
ball.vy*=bounce;
60
}
else
if
(ball.y-ball.radius<
0
) {
61
ball.y=ball.radius;
62
ball.vy*=bounce;
63
}
64
}
65
}
66
}
原理图:
多物体基于距离的碰撞检测:
show sourceview source
print?
01
package
{
02
import
flash.display.Sprite;
03
import
flash.events.Event;
04
public
class
Bubbles2
extends
Sprite {
05
private
var
balls:
Array
;
06
private
var
numBalls:
Number
=
20
;
07
private
var
bounce:
Number
=-
0.9
;
08
private
var
spring:
Number
=
0.2
;
09
private
var
gravity:
Number
=
1
;
10
public
function
Bubbles2() {
11
init();
12
}
13
private
function
init():
void
{
14
balls =
new
Array
();
15
for
(
var
i:
uint
=
0
;i <numBalls;i++) {
16
var
ball:Ball=
new
Ball(Math.random()*
30
+
20
,Math.random()*
0xffffff
);
17
ball.x=Math.random()*stage.stageWidth;
18
ball.y=Math.random()*stage.stageHeight;
19
ball.vx=Math.random()*
6
-
3
;
20
ball.vy=Math.random()*
6
-
3
;
21
addChild(ball);
22
balls.push(ball);
23
}
24
addEventListener(Event.ENTER_FRAME, onEnterFrame);
25
}
26
private
function
onEnterFrame(event:Event):
void
{
27
for
(
var
i:
uint
=
0
;i <numBalls -
1
;i++) {
28
var
ball0:Ball=balls[i];
29
for
(
var
j:
uint
=i +
1
;j <numBalls;j++) {
30
var
ball1:Ball=balls[j];
31
var
dx:
Number
=ball1.x-ball0.x;
32
var
dy:
Number
=ball1.y-ball0.y;
33
var
dist:
Number
=Math.sqrt(dx*dx+dy*dy);
34
var
minDist:
Number
=ball0.radius+ball1.radius;
35
if
(dist<minDist) {
36
/*
37
var angle:Number=Math.atan2(dy,dx);
38
var tx:Number=ball0.x+Math.cos(angle)*minDist;
39
var ty:Number=ball0.y+Math.sin(angle)*minDist;
40
*/
41
var
tx:
Number
=ball0.x + (dx/dist)*minDist;
42
var
ty:
Number
=ball0.y + (dy/dist)*minDist;
43
var
ax:
Number
=(tx -ball1.x) * spring;
44
var
ay:
Number
=(ty -ball1.y) * spring;
45
ball0.vx-=ax;
46
ball0.vy-=ay;
47
ball1.vx+=ax;
48
ball1.vy+=ay;
49
}
50
}
51
}
52
for
(i =
0
;i <numBalls;i++) {
53
var
ball:Ball=balls[i];
54
move(ball);
55
}
56
}
57
private
function
move(ball:Ball):
void
{
58
ball.vy+=gravity;
59
ball.x+=ball.vx;
60
ball.y+=ball.vy;
61
if
(ball.x+ball.radius>stage.stageWidth) {
62
ball.x=stage.stageWidth-ball.radius;
63
ball.vx*=bounce;
64
}
else
if
(ball.x -ball.radius <
0
) {
65
ball.x=ball.radius;
66
ball.vx*=bounce;
67
}
68
if
(ball.y+ball.radius>stage.stageHeight) {
69
ball.y=stage.stageHeight-ball.radius;
70
ball.vy*=bounce;
71
}
else
if
(ball.y -ball.radius <
0
) {
72
ball.y=ball.radius;
73
ball.vy*=bounce;
74
}
75
}
76
}
77
}
相关文章推荐
- Flash/Flex学习笔记(41):碰撞检测
- QT按键判断和碰撞检测的问题,紧急求助啊!!!3Q
- IOS_加速计_碰撞检测_小球位置修复_dispatch_once单例
- 成功研究出多边形的碰撞检测算法
- cocos2d-html5 碰撞检测的几种方法
- 2D游戏中常见的碰撞检测处理(仅碰撞体)【持续更新】
- Android 游戏检测碰撞方法:多种检测碰撞的定义及说明
- [教程] Unity3d中的碰撞检测(一) [复制链接]
- 如何用cocos2d-x来开发简单的Uphone游戏:(三) 射击子弹 & 碰撞检测
- 游戏中的碰撞检测
- 《MFC游戏开发》笔记十 游戏中的碰撞检测进阶:地图类型&障碍物判定
- html5 乒乓球(碰撞检测)实例二
- COCOS2D-X 像素级碰撞检测
- HGE像素碰撞,像素检测,多边形碰撞检测
- cocos creator学习11——碰撞检测系统
- 单一世界架构初探之碰撞检测
- android 游戏 碰撞检测
- cocos2dx中精灵的实时碰撞检测
- 圆、矩形、线段碰撞检测
- <cocos2d-x for wp7>使用cocos2d-x制作基于Tile地图的游戏:碰撞检测和收集物品(二)