`
madfroghe
  • 浏览: 122148 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Flash/Flex学习笔记(36):碰撞检测

阅读更多

碰撞检测基本上可能分为二类:对象与对象的碰撞检测、对象与点的碰撞检测

为了方便测试,先写一个box类(生成一个小矩形)


package {


import flash.display.Sprite;

public class Box extends Sprite {

 
private var w:Number;

 
private var h:Number;

 
private var color:uint;

 
public var vx:Number=0;

 
public var vy:Number=0;

 
public function Box(width:Number=50, height:Number=50, color:uint=0xff0000) {

 
w=width;

h=height;

 
this.color=color;

 
init();

 
}

 
public function init():void {

 
graphics.beginFill(color);


graphics.drawRect(-w / 2, -h / 2, w, h);

 
graphics.endFill();


}

 
}

 
}

最基本的对象碰撞检测:hitTestObject

package {

 
import flash.display.Sprite;

 
import flash.events.Event;

 
public class Boxes extends Sprite {


private var box:Box;


private var boxes:Array;

 
private var gravity:Number=0.1;

 
public function Boxes() {


init();

 
}

 
private function init():void {

 
boxes = new Array();

 
createBox();

 
addEventListener(Event.ENTER_FRAME, onEnterFrame);

 
}


private function onEnterFrame(event:Event):void {

 
box.vy+=gravity;

 
box.y+=box.vy;

 
//如果物体下落到了舞台(最下)边界,则再造一个出来往下掉

 
if (box.y+box.height/2>stage.stageHeight) {

 
box.y=stage.stageHeight-box.height/2;

 
createBox();

 
} else{

 
for (var i:uint = 0; i < boxes.length; i++) {

 
//每个正在下掉的物体与其它物体做(矩形)碰撞检测

 
if (box!=boxes[i]&&box.hitTestObject(boxes[i])) {

 
box.y=boxes[i].y-boxes[i].height/2-box.height/2;

 
//堆到顶了,则停止


if (box.y<=box.height/2){

 
removeEventListener(Event.ENTER_FRAME,onEnterFrame);

 
} else{

 
createBox();


}

 
}

 
}

 
}

 
}

 

private function createBox():void {

 
box=new Box(Math.random()*40+10,Math.random()*40+10,Math.random()*0xffffff);

 
box.x=Math.random()*stage.stageWidth;


addChild(box);


boxes.push(box);

 
}

}

 
}

如果把Box换成前面例子中的Ball,就是下面这个样子:

很明显:矩形换成球后,碰撞检测变得不精确了,有一些球似乎并没有真正撞到其它球也停下来了,这是为什么腻?

答案就在于:Flash对象碰撞检测默认采用“对象的矩形边界”做为检测依据。上面二张图演示了这一细节:第一张图虽然肉眼看上去只有二个矩形相交了,但是在Flash看来,其实每对图形都碰到了(第二张图),所以大家应该也能明白为啥换成球后,有些球会浮在空中了。

对象与点的碰撞检测:hitTestPoint

package {

 
import flash.display.Sprite;

 
import flash.events.Event;

 
import flash.text.TextField;

 
public class PointHitTest extends Sprite {

 
private var ball:Ball;

 
private var box:Box;

 
private var txt:TextField = new TextField();


public function PointHitTest() {

 
init();

 
}

 
private function init():void {


ball=new Ball;

 
addChild(ball);

 
ball.x=stage.stageWidth/2;

 
ball.y=stage.stageHeight/2;

 
box = new Box(90,90);

 
addChild(box);

 
box.x = 100;

 
box.y = ball.y;

 
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

 
addChild(txt);

 
txt.selectable = false;

 
}

 
private function EnterFrameHandler(event:Event):void {

 
if (ball.hitTestPoint(mouseX,mouseY) || box.hitTestPoint(mouseX,mouseY)) {

 
txt.text = "碰到了!";

 
} else{

 
txt.text = "";


}

 
txt.x = mouseX + 15;

 
txt.y = mouseY;

 
}

 
}

 
}

用鼠标在二个物体上划过,会看到鼠标所在点与矩形及小球的碰撞检测结果,同样这里也存在一个问题:对于小球而言,默认也是采用矩形边界检测的,所以鼠标移到小球的边角时,虽然还没碰到球,也提示"碰到了",还好Flash提供了一个可选参数,以改进检测的精确度,只要把hitTestPoint第三个可选参数设置为true即可

if (ball.hitTestPoint(mouseX,mouseY) || box.hitTestPoint(mouseX,mouseY,true)) {

基于距离的检测:即检测二个物体的中心点距离是否低于最小距离

var ball_1:Ball=new Ball(70,0xff0000);


var ball_2:Ball=new Ball(70,0x0000ff);

 
ball_1.x=stage.stageWidth/2;

 
ball_1.y=stage.stageHeight/2;

 
ball_2.x=stage.stageWidth/2;

 
ball_2.y=stage.stageHeight/2;

 
ball_1.vx = Math.random()*20 - 20;


ball_1.vy = Math.random()*20 - 20;

 
ball_2.vx = Math.random()*20 - 20;

 
ball_2.vy = Math.random()*20 - 20;

 
addChild(ball_1);


addChild(ball_2);


addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

 
function EnterFrameHandler(e:Event):void {

 
ball_1.x+=ball_1.vx;

 
ball_1.y+=ball_1.vy;


ball_2.x+=ball_2.vx;

 
ball_2.y+=ball_2.vy;


CheckBoundary(ball_1);

 
CheckBoundary(ball_2);

 
var dx:Number=ball_1.x-ball_2.x;


var dy:Number=ball_1.y-ball_2.y;

 
var dist:Number=Math.sqrt(dx*dx+dy*dy);

 
if (dist<(ball_1.radius + ball_2.radius)) {

 
var angle:Number=Math.atan2(dy,dx);

 
ball_1.vx=dist*Math.cos(angle)*0.1;

 
ball_1.vy=dist*Math.sin(angle)*0.1;

 
ball_2.vx=dist*Math.cos(angle)*-0.1;

 
ball_2.vy=dist*Math.sin(angle)*-0.1;

 
}

 
}

 
function CheckBoundary(b:Ball) {

 
if (b.x>stage.stageWidth-b.width/2||b.x<=b.width/2) {


b.x-=b.vx;


b.vx*=-1;

 
}

 
if (b.y>stage.stageHeight-b.height/2||b.y<=b.height/2) {

 
b.y-=b.vy;

 
b.vy*=-1;

 
}

 
}

很明显,这种方法对于圆形物体是十分精确的,但对于非规则形状,只能近似检测.

如果结合上二篇提到的弹性运动,可以做出更复杂的动画:

 
package {

 
import flash.display.Sprite;


import flash.events.Event;

public class Bubbles extends Sprite {

private var balls:Array;


private var numBalls:Number=10;

 
private var centerBall:Ball;

 
private var bounce:Number=-1;


private var spring:Number=0.2;

 
public function Bubbles() {


init();

 
}

 
private function init():void {

 
balls=new Array ;

 
centerBall=new Ball(100,0xcccccc);

 
addChild(centerBall);

 
centerBall.x=stage.stageWidth/2;


centerBall.y=stage.stageHeight/2;

 
for (var i:uint=0; i<numBalls; i++) {


var ball:Ball=new Ball(Math.random()*40+5,Math.random()*0xffffff);


ball.x=Math.random()*stage.stageWidth;

 
ball.y=Math.random()*stage.stageHeight;


ball.vx=(Math.random()*2-1)*10;

 
ball.vy=(Math.random()*2-1)*10;

 
addChild(ball);

 
balls.push(ball);

 
}

 
addEventListener(Event.ENTER_FRAME,onEnterFrame);

 
}

 
private function onEnterFrame(event:Event):void {

 
for (var i:uint=0; i<numBalls; i++) {


var ball:Ball=balls[i];

 
move(ball);

 
var dx:Number=ball.x-centerBall.x;

 
var dy:Number=ball.y-centerBall.y;

 
var dist:Number=Math.sqrt(dx*dx+dy*dy);

 
var minDist:Number=ball.radius+centerBall.radius;

 
if (dist<minDist) {

 
var angle:Number=Math.atan2(dy,dx);

 
var tx:Number=centerBall.x+Math.cos(angle)*minDist;//弹性运动的目标点x坐标

 
var ty:Number=centerBall.y+Math.sin(angle)*minDist;//弹性运动的目标点y坐标

 
ball.vx+=(tx-ball.x)*spring;

 
ball.vy+=(ty-ball.y)*spring;

 
}

 
}

 
}

 
private function move(ball:Ball):void {

 
ball.x+=ball.vx;

 
ball.y+=ball.vy;

 
if (ball.x+ball.radius>stage.stageWidth) {

 
ball.x=stage.stageWidth-ball.radius;

 
ball.vx*=bounce;


} else if (ball.x-ball.radius<0) {

 
ball.x=ball.radius;

 
ball.vx*=bounce;


}


if (ball.y+ball.radius>stage.stageHeight) {

 
ball.y=stage.stageHeight-ball.radius;

 
ball.vy*=bounce;

 
} else if (ball.y-ball.radius<0) {

 
ball.y=ball.radius;

 
ball.vy*=bounce;


}

 
}


}

 
}

原理图:

多物体基于距离的碰撞检测:

package {


import flash.display.Sprite;

 
import flash.events.Event;

 
public class Bubbles2 extends Sprite {

 
private var balls:Array;

 
private var numBalls:Number=20;

 
private var bounce:Number=-0.9;

 
private var spring:Number=0.2;

 
private var gravity:Number=1;

 
public function Bubbles2() {

 
init();

 
}


private function init():void {

 
balls = new Array();

 
for (var i:uint = 0; i < numBalls; i++) {

 
var ball:Ball=new Ball(Math.random()*30+20,Math.random()*0xffffff);

 
ball.x=Math.random()*stage.stageWidth;

 
ball.y=Math.random()*stage.stageHeight;

 
ball.vx=Math.random()*6-3;

 
ball.vy=Math.random()*6-3;

 
addChild(ball);


balls.push(ball);

 
}


addEventListener(Event.ENTER_FRAME, onEnterFrame);


}


private function onEnterFrame(event:Event):void {

 
for (var i:uint = 0; i < numBalls - 1; i++) {

 
var ball0:Ball=balls[i];

 
for (var j:uint = i + 1; j < numBalls; j++) {

 
var ball1:Ball=balls[j];                    


var dx:Number=ball1.x-ball0.x;

 
var dy:Number=ball1.y-ball0.y;


var dist:Number=Math.sqrt(dx*dx+dy*dy);

 
var minDist:Number=ball0.radius+ball1.radius;

 
if (dist<minDist) {

 
/*

 
var angle:Number=Math.atan2(dy,dx);

 
var tx:Number=ball0.x+Math.cos(angle)*minDist;

 
var ty:Number=ball0.y+Math.sin(angle)*minDist;

 
*/

 
var tx:Number=ball0.x + (dx/dist)*minDist;


var ty:Number=ball0.y + (dy/dist)*minDist;


var ax:Number = (tx - ball1.x) * spring;

 
var ay:Number = (ty - ball1.y) * spring;

 
ball0.vx-=ax;


ball0.vy-=ay;

 
ball1.vx+=ax;

 
ball1.vy+=ay;


}

 
}

 
}

 
for (i = 0; i < numBalls; i++) {

 
var ball:Ball=balls[i];

 
move(ball);

 
}

 
}

 
private function move(ball:Ball):void {

 
ball.vy+=gravity;

 
ball.x+=ball.vx;


ball.y+=ball.vy;

 
if (ball.x+ball.radius>stage.stageWidth) {

 
ball.x=stage.stageWidth-ball.radius;

 
ball.vx*=bounce;

 
} else if (ball.x - ball.radius < 0) {

 
ball.x=ball.radius;

 
ball.vx*=bounce;

 
}

 
if (ball.y+ball.radius>stage.stageHeight) {

 
ball.y=stage.stageHeight-ball.radius;


ball.vy*=bounce;

 
} else if (ball.y - ball.radius < 0) {

 
ball.y=ball.radius;

 
ball.vy*=bounce;


}

 
}

 
}


}

 

分享到:
评论

相关推荐

    Flash/Flex 框架应用 Cairngorm、Mate、PureMVC以及Swiz 的典型例子

    附件是关于 Flash/Flex 几个重要框架 Cairngorm、Mate、PureMVC以及Swiz 的典型例子,由 Tony Hillerson 提供 Homepage: http://insideria.com

    flex/Flash开发系列书籍:WEB3D应用研究

    flex/Flash开发系列书籍:基于FLASH的WEB3D应用研究

    flash/flex画曲线,绘图板

    在IT行业中,Flash/Flex是一种基于ActionScript编程语言和Adobe Flex框架的开发工具,用于创建交互式的、富媒体的Web应用程序。"Flash/Flex画曲线,绘图板"这个主题涉及的是如何使用这些技术来创建一个允许用户自由...

    RE/flex lexical analyzer generator:以正则表达式为中心的快速词法分析器生成器,用于C ++-开源

    语言:C ++许可证:BSD-3代码质量:A + https://lgtm.com/projects/g/Genivia/RE-flex/context:cpp文档:https://www.genivia.com/doc/reflex/html /index.html存储库:https://github.com/Genivia/RE-flex更改日志...

    [Flash/Flex] 使用css定义文本样式

    xmlns:s="library://ns.adobe.com/flex/spark" applicationStyleSheet="@Embed('path/to/your/styles.css')"&gt; ... &lt;/s:Application&gt; ``` 然后在`styles.css`中定义样式,如: ```css .myTextStyle { color: #FF...

    FDT-flash/flex devtoolkit for eclipse.

    **FDT - 一款强大的Flash/Flex开发工具集** FDT(Flash Development Tool)是一款专为Adobe Flash和Flex开发者设计的集成开发环境(IDE),它基于Eclipse平台,提供了高效、专业的开发工具和服务。FDT的出现极大地...

    flash/flex 的aqua皮肤

    在IT行业中,Flash/Flex是一种广泛使用的开发工具,主要用于创建交互式、富媒体的Web应用程序。Flex是基于ActionScript和MXML的开放源代码框架,它允许开发者构建可自定义的用户界面,而Flash则是其背后的动画和...

    FLEX安装方法 集成到eclipse中

    FLEX 安装方法 集成到 eclipse 中 ...* 汉化 FLEX 尤其是 FLEX/AIR 方面的中文资料 * 原创的关于 FLEX 的博客:http://liguoliang.com/ * Adobe 公司 FLEX 主页:http://www.adobe.com/cn/products/flex/

    Flex:登录

    标题“Flex:登录”指的是使用Adobe Flex技术实现用户登录功能的一种方法。Flex是Adobe公司推出的一款基于ActionScript的开源框架,主要用于...压缩包中的"Flex Login"可能包含示例代码或项目结构,供读者学习和参考。

    flex学习笔记 flex学习总结 flex学习教程

    Flex Builder(现已被Adobe Flash Builder取代)是一个集成开发环境,提供了代码提示、调试和项目管理等功能,使得开发更加高效。 3. **Flex组件库**:Flex提供了丰富的预定义组件,如Button、Label、Canvas等,可...

    RTMP直播例子--基于FLASH/FLEX(含源代码) 下载

    在这个“RTMP直播例子--基于FLASH/FLEX(含源代码) 下载”中,我们可以深入探讨RTMP直播的基本原理、FLEX编程以及如何在实际项目中应用这些技术。 首先,RTMP协议的工作原理是通过建立一个持久性的TCP连接,允许...

    解决flash/flex/as3 访问中文域名时的流错误示例

    在《潮汕IT男》网站的文章《解决flash/flex/as3 访问中文域名时的流错误》中,作者陈林生提供了详细的步骤和代码示例,帮助开发者理解和解决这个问题。文章地址是:[http://chenlinsheng.com/?p=990]...

    FLEX学习笔记

    《FLEX学习笔记》 FLEX,全称为Flex Builder,是由Adobe公司开发的一款基于MXML和ActionScript的开源框架,用于构建富互联网应用程序(RIA)。它允许开发者创建具有交互性、响应性和丰富用户体验的Web应用。FLEX的...

    Flex学习笔记.rar

    本压缩包“Flex学习笔记.rar”显然是一份针对初学者的教程资料,旨在帮助新接触Flex的开发者快速上手。 在“FlexBeginner.pdf”这份文档中,你可以期待找到以下关键知识点: 1. **Flex概述**:介绍Flex技术的基本...

    flex开源项目介绍.doc

    Flex开源项目介绍 Flex是一种用于构建富互联网应用程序(RIA)的开源框架,它基于ActionScript 3(AS3)编程语言和MXML标记语言。这些开源项目为开发者提供了丰富的组件库、工具和框架,帮助他们扩展Flex的功能,...

    4个简单的Flex例子(包含custom-class-mapping)共享

    总共有4个例子: 1.http://127.0.0.1:8080/flexDemo/HelloWorld/HelloWorld.html ...如果你的数据库配置和我的不一样,请修改flexDemo\WEB-INF\classes\下的DBSetting.properties文件,数据库建表的sql语句是user.sql

    [转] [Flash/Flex] 使用Flare3D来实现Flash 3D的推箱子游戏原型---纹理

    这篇教程主要介绍如何使用Flare3D在Flash/Flex环境中创建一个3D推箱子游戏的原型,重点关注3D纹理的应用。Flare3D是一个强大的工具,它为Flash开发者提供了将2D内容转换为3D场景的能力,使得在Flash平台上开发复杂的...

    flex4cookbook

    xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="app_creationCompleteHandler(event)"&gt; &lt;fx:Script&gt; &lt;![CDATA[ import mx.events.FlexEvent; ...

    flex actionscript学习笔记

    Flex ActionScript 学习笔记是关于使用Adobe Flex技术并结合ActionScript 3.0进行开发的知识总结。ActionScript 3.0是随着Flash CS3一起推出的一种强大的编程语言,相较于之前的ActionScript版本,它有着显著的提升...

    flex学习笔记,技巧学习

    根据提供的信息,我们可以总结出以下关于Flex学习笔记中的关键技术知识点: ### 1. Flex 基础设置 在Flex开发中,通常会涉及到基础样式的设置。例如,在给定的部分内容中提到了字体大小、颜色及背景色的设置。虽然...

Global site tag (gtag.js) - Google Analytics