`
izuoyan
  • 浏览: 9222995 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Flash game中关于碰撞检测之Rectangle篇

阅读更多

yasu 发表了一段代码,比较了关于通过Rectangle的intersects,Sprite的hitTestObject以及他自己的Myrect这3种方法的效率。
代码及演示如下:


//-------------------------------------------
// Collision Performance Test
// - [RECTANGLE] Rectangle.intersects
// - [MY RECT] calc orijinal
// - [HITTEST] Sprite.hitTestObject
//
//-----------------------------------------------
package
{
import com.bit101.components.PushButton;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.ColorTransform;
import flash.geom.Rectangle;

import net.hires.debug.Stats;

[SWF(frameRate=60, width=465, height=465)]
/**
* Collision Performance Test
* @author yasu
*/
public class Main extends Sprite
{

private static const MAX:int = 400;
private static const STAGE_W:int = 465;
private static const STAGE_H:int = 465;
private static const RECT_WH:int = 10;
private static const COLOR_TRANS:ColorTransform =
new ColorTransform(0.6, 0.6, 0.6, 1);

public function Main()
{
bmd = new BitmapData(STAGE_W, STAGE_H, false, 0xFF000000);
addChild(new Bitmap(bmd));

btnA = new PushButton(this, 80, STAGE_H - 50,
"RECTANGLE", _onClick);
btnB = new PushButton(this, 200, STAGE_H - 50,
"MY RECT", _onClick);
btnC = new PushButton(this, 320, STAGE_H - 50,
"HITTEST", _onClick);

addChild(new Stats);
}
private var MAX_SPEED:int = 20;
private const RECT_BMD:BitmapData = new BitmapData(
RECT_WH, RECT_WH, false, 0x666666);
private const RECT_HIT_BMD:BitmapData = new BitmapData(
RECT_WH, RECT_WH, false, 0x990000);
private var bmd:BitmapData;
private var btnA:PushButton;
private var btnB:PushButton;
private var btnC:*;
private var myrects:Vector.<ObjMyRect>;
private var objs:Array = [];
private var rectangles:Vector.<ObjRectangle>;
private var sprites:Vector.<ObjSprite>;

private function _initMyRects():void
{
myrects = new Vector.<ObjMyRect>(MAX, true);
for (var i:int = 0; i < MAX; i++)
{
myrects[ i ] = new ObjMyRect();
var size:int = Math.random() * RECT_WH >> 0
myrects[ i ].rect = new MyRect(
Math.random() * STAGE_W >> 0,
Math.random() * STAGE_H >> 0,
size,
size)
myrects[ i ].vx = (Math.random() - 0.5) * MAX_SPEED >> 0;
myrects[ i ].vy = (Math.random() - 0.5) * MAX_SPEED >> 0;
}
}
private function _initRectangle():void
{
rectangles = new Vector.<ObjRectangle>(MAX, true);
for (var i:int = 0; i < MAX; i++)
{
rectangles[ i ] = new ObjRectangle();
var size:int = Math.random() * RECT_WH >> 0
rectangles[ i ].rect = new Rectangle(
Math.random() * STAGE_W >> 0,
Math.random() * STAGE_H >> 0,
size,
size)
rectangles[ i ].vx = (Math.random() - 0.5) * MAX_SPEED >> 0;
rectangles[ i ].vy = (Math.random() - 0.5) * MAX_SPEED >> 0;
}
}
private function _initSprites():void
{
sprites = new Vector.<ObjSprite>(MAX, true);
for (var i:int = 0; i < MAX; i++)
{
sprites[ i ] = new ObjSprite();
addChildAt(sprites[ i ], 1);
var size:int = Math.random() * RECT_WH >> 0
sprites[ i ].width = sprites[ i ].height = size;
sprites[ i ].x = Math.random() * STAGE_W >> 0;
sprites[ i ].y = Math.random() * STAGE_H >> 0;
sprites[ i ].vx = (Math.random() - 0.5) * MAX_SPEED >> 0;
sprites[ i ].vy = (Math.random() - 0.5) * MAX_SPEED >> 0;
}
}

private function _onClick(e:Event):void
{
removeEventListener(Event.ENTER_FRAME, onEnterFrameA);
removeEventListener(Event.ENTER_FRAME, onEnterFrameB);
removeEventListener(Event.ENTER_FRAME, onEnterFrameC);
rectangles = null;
myrects = null;
if (sprites)
{
for (var i:int = 0; i < sprites.length; i++)
{
removeChild(sprites[ i ]);
}
}
sprites = null;
bmd.fillRect(bmd.rect, 0x0);

switch (e.currentTarget)
{
case btnA:
_initRectangle();
addEventListener(Event.ENTER_FRAME, onEnterFrameA);
break;
case btnB:
_initMyRects();
addEventListener(Event.ENTER_FRAME, onEnterFrameB);
break;
case btnC:
_initSprites();
addEventListener(Event.ENTER_FRAME, onEnterFrameC);
break;
}
}

private function onEnterFrameA(event:Event):void
{
var i:int, j:int;

var elementA:ObjRectangle;
var elementB:ObjRectangle;
for (i = 0; i < rectangles.length; i++)
{
elementA = rectangles[ i ] as ObjRectangle;
elementA.rect.x += elementA.vx;
elementA.rect.y += elementA.vy;

if (elementA.rect.x < 0 || elementA.rect.x > STAGE_W)
elementA.vx *= -1;
if (elementA.rect.y < 0 || elementA.rect.y > STAGE_H)
elementA.vy *= -1;

elementA.isHit = false;
}

for (i = 0; i < rectangles.length; i++)
{
elementA = rectangles[ i ] as ObjRectangle;

for (j = 0; j < rectangles.length; j++)
{
if (j <= i)
continue;

elementB = rectangles[ j ] as ObjRectangle;

if (elementA.rect.intersects(elementB.rect))
{
elementA.isHit = elementB.isHit = true;
}
}
}

bmd.lock();
bmd.colorTransform(bmd.rect, COLOR_TRANS);
for (i = 0; i < rectangles.length; i++)
{
elementA = rectangles[ i ] as ObjRectangle;
bmd.fillRect(elementA.rect, elementA.isHit ? 0x990000 : 0x666666);
}
bmd.unlock();
}

private function onEnterFrameB(event:Event):void
{
var i:int, j:int;

var elementA:ObjMyRect;
var elementB:ObjMyRect;
for (i = 0; i < myrects.length; i++)
{
elementA = myrects[ i ] as ObjMyRect;
elementA.rect.x += elementA.vx;
elementA.rect.y += elementA.vy;

if (elementA.rect.x < 0 || elementA.rect.x > STAGE_W)
elementA.vx *= -1;
if (elementA.rect.y < 0 || elementA.rect.y > STAGE_H)
elementA.vy *= -1;

elementA.isHit = false;
}

for (i = 0; i < myrects.length; i++)
{
elementA = myrects[ i ] as ObjMyRect;

for (j = 0; j < myrects.length; j++)
{
if (j <= i)
continue;

elementB = myrects[ j ] as ObjMyRect;

if (elementA.rect.x + elementA.rect.width < elementB.rect.x)
{
}
else if (elementA.rect.x > elementB.rect.x + elementB.rect.width)
{
}
else if (elementA.rect.y + elementA.rect.height < elementB.rect.y)
{
}
else if (elementA.rect.y > elementB.rect.y + elementB.rect.height)
{
}
else
{
elementA.isHit = elementB.isHit = true;
}
}
}

bmd.lock();
bmd.colorTransform(bmd.rect, COLOR_TRANS);
for (i = 0; i < myrects.length; i++)
{
elementA = myrects[ i ] as ObjMyRect;

bmd.fillRect(new Rectangle(elementA.rect.x, elementA.rect.y,
elementA.rect.width, elementA.rect.height),
elementA.isHit ? 0x990000 : 0x666666);
}
bmd.unlock();
}

private function onEnterFrameC(event:Event):void
{
var i:int, j:int;

var elementA:ObjSprite;
var elementB:ObjSprite;
for (i = 0; i < sprites.length; i++)
{
elementA = sprites[ i ] as ObjSprite;
elementA.x += elementA.vx;
elementA.y += elementA.vy;

if (elementA.x < 0 || elementA.x > STAGE_W)
elementA.vx *= -1;
if (elementA.y < 0 || elementA.y > STAGE_H)
elementA.vy *= -1;

elementA.isHit = false;
}

for (i = 0; i < sprites.length; i++)
{
elementA = sprites[ i ] as ObjSprite;

for (j = 0; j < sprites.length; j++)
{
if (j <= i)
continue;

elementB = sprites[ j ] as ObjSprite;

if (elementA.hitTestObject(elementB))
{
elementA.isHit = elementB.isHit = true;
}
}
}
}
}
}

import flash.display.Shape;
import flash.display.Sprite;
import flash.geom.Rectangle;

class ObjRectangle
{
public var isHit:Boolean;
public var rect:Rectangle;
public var vx:Number;
public var vy:Number;
}

class ObjMyRect
{
public var isHit:Boolean;
public var rect:MyRect;
public var vx:Number;
public var vy:Number;
}

class ObjSprite extends Sprite
{

public function ObjSprite()
{
hitGr = new Shape();
hitGr.graphics.beginFill(0x990000);
hitGr.graphics.drawRect(0, 0, 10, 10);
addChild(hitGr);

defGr = new Shape();
defGr.graphics.beginFill(0x666666);
defGr.graphics.drawRect(0, 0, 10, 10);
addChild(defGr);
}

public var defGr:Shape;
public var hitGr:Shape;

//--------------------------------------
// isHit
//--------------------------------------

private var _isHit:Boolean;

public function get isHit():Boolean
{
return _isHit;
}

public function set isHit(value:Boolean):void
{
_isHit = value;

hitGr.visible = _isHit;
defGr.visible = !_isHit;
}
public var vx:Number;
public var vy:Number;
}

class MyRect
{
public function MyRect(x:Number, y:Number, width:Number, height:Number)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}

public var height:Number;
public var width:Number;
public var x:Number;
public var y:Number;
}




通过上面运行,400个高速运动粒子进行碰撞检测,有碰撞的显示为红色,在这同样的需求情况下,Myrect方式实现的结果帧频保持在60帧,而且CPU占用极低。Sprite的hit方式确实惨不忍睹。:{

OK,让我们看看他这个Myrect有啥特殊。看看代码或许你发现没有啥特别,就是按Rectangle方式定义了宽高及XY点而已。

重新定义并不是高效的原因,真正起作用的是这段代码:

if (elementA.rect.x + elementA.rect.width < elementB.rect.x)
{
}
else if (elementA.rect.x > elementB.rect.x + elementB.rect.width)
{
}
else if (elementA.rect.y + elementA.rect.height < elementB.rect.y)
{
}
else if (elementA.rect.y > elementB.rect.y + elementB.rect.height)
{
}
else
{
elementA.isHit = elementB.isHit = true;
}


看来似乎老套传统的坐标判断一点也不输于现成的方法:)

既然如此,我们把方法onEnterFrameA中Rectangle的intersects方法,替换为上面onEnterFrameB中的这段代码,再次比较一下两者的效率及CPU占用呢?基于这个想法,我做了下面的这个测试,请看演示:

ok,通过上述测试,或许我们可以作出这样一个结论:
在采用Rectangle进行碰撞检测时,少量的碰撞判断,使用intersects方法相当的简单,不过在量多的日子里。。。或许采用老式的加减判断,更加高效。这个故事告诉我们,看似又老又笨的方法或许有时候又高效又好用:}
PS:不过很纳闷,intersects方法的核心难道不是坐标及宽高来判断的?


原文链接:http://www.fans8.com/?p=490

分享到:
评论

相关推荐

    flash 碰撞检测hittest

    在Flash开发中,碰撞检测是实现游戏或者交互式应用中不可或缺的一部分。`hitTest`方法在ActionScript 3(AS3)中扮演着至关重要的角色,用于检测两个显示对象是否在视觉上重叠。本篇文章将深入探讨`hitTest`方法的...

    flash AS3.0检测碰撞工具类 超好用

    标题中的"flash AS3.0检测碰撞工具类 超好用"很可能就是一个这样的工具,它提供了静态方法,使得在代码中直接调用就能完成碰撞检测,无需实例化对象,简化了使用过程。 在AS3.0中,像素级碰撞检测是一种常用的技术...

    xna中的碰撞检测

    在XNA这个强大的游戏开发框架中,碰撞检测是游戏编程中的关键部分,它涉及到游戏对象间的交互,确保了游戏逻辑的正确性。本资源重点讲解如何在2D环境中实现碰撞检测,这对于创建像《超级玛丽》这样的平台跳跃游戏...

    as3 flash检验碰撞

    在这个场景中,"as3 flash检验碰撞"指的是使用AS3编程语言在Flash环境中进行碰撞检测的方法。 首先,我们要理解AS3中的基本图形对象,如MovieClip和Shape,它们是实现碰撞检测的基础。MovieClip是可动画的容器,...

    碰撞检测矩形+像素.rar

    在本文中,我们将深入探讨如何使用C#的GDI+绘图库来实现矩形碰撞检测和像素级碰撞检测,以此来创建一个简单的飞机游戏。这个项目的核心是主角飞机与敌机之间的碰撞检测,虽然没有涉及发射子弹等功能,但它为我们提供...

    Rectangle仿flash交互漂亮个人简历模板

    【标题】:“Rectangle仿flash交互漂亮个人简历模板” 在当今数字化时代,个人简历已经不再局限于传统的纸质形式,而是转向了更具交互性和视觉吸引力的在线版本。"Rectangle仿flash交互漂亮个人简历模板"就是一个很...

    XNA物理碰撞检测代码

    本篇将深入探讨XNA中的物理碰撞检测,并结合描述中的代码示例,讲解如何在C#语言环境下进行物体碰撞的检测。 首先,我们要理解XNA中的基本概念。XNA使用向量和矩阵来表示位置和变换,以及几何形状如矩形、圆形等来...

    AndEngine 碰撞检测

    AndEngine提供了多种碰撞检测方法,其中一种是基于矩形的碰撞检测,即Rectangle-to-Rectangle碰撞检测。这种检测方式简单高效,适用于大多数非精确碰撞需求。当两个矩形实体的边界相交时,我们可以认为这两个实体...

    libgdx 碰撞检测

    本篇文章将深入探讨 LibGDX 中的碰撞检测技术及其应用。 LibGDX 提供了多种碰撞检测方法,适用于不同场景和需求。首先,我们可以使用 `Rectangle` 类进行矩形间的碰撞检测。`Rectangle` 类提供了 `overlaps()` 方法...

    J2ME中碰撞检测代码详解!

    本篇文章将深入解析J2ME中的碰撞检测代码实现。 首先,我们需要理解J2ME的基础架构。J2ME是Java的一个子集,主要设计用于资源有限的设备,如移动电话和嵌入式系统。在图形编程中,我们通常使用Java Wireless ...

    pengzhuang.rar_j2me_j2me 手机 游戏 代码_j2me 碰撞检测

    - 在J2ME中,可以使用`javax.microedition.lcdui.game.Sprite`类来表示游戏对象,它具有内置的碰撞检测功能。`Sprite`类的`collidesWith()`方法可以用来检测两个精灵之间的碰撞。 - 如果需要自定义碰撞检测,可以...

    as3开发中的Rectangle类用法

    在Adobe Flash平台的ActionScript 3.0(简称AS3)编程语言中,`Rectangle`类扮演着非常重要的角色,尤其是在处理图形和图像时。乍看之下,`Rectangle`类似乎仅仅是一个用于绘制矩形的工具,但实际上它更多地被用来...

    【纯JAVA语言做RPG游戏】3.地图碰撞检测和角色行走的实现

    在Java中,我们可以用`Rectangle`类来表示角色和地图物体的边界,然后使用`Rectangle.intersects()`方法来判断是否有碰撞。 角色行走的实现涉及到键盘监听和动画处理。我们可以创建一个`Player`类,它包含位置信息...

    Qt Qml 可拖动设置Rectangle大小Demo

    在本文中,我们将深入探讨如何在Qt Qml中创建一个可拖动调整大小的Rectangle示例。Qt是一个跨平台的应用程序开发框架,广泛用于桌面、移动和嵌入式设备。Qml是Qt的一个组成部分,它提供了一种声明式语言来构建用户...

    RectangleCollision

    通过分析这些文件,我们可以了解到这是一个关于XNA的矩形碰撞检测教程项目,提供了源代码和相关文档,适合初学者了解和学习如何在XNA环境中进行基本的2D碰撞检测。学习者可以通过阅读代码和文档,了解碰撞检测算法的...

    C语言复杂碰撞检测算法.docx

    在 `main` 函数中,我们创建了两个 `Rectangle` 对象 `rect1` 和 `rect2`,并调用 `checkCollision` 函数来检测它们之间是否发生碰撞。根据函数的返回值,程序会输出相应的提示信息。 需要注意的是,这个简单的碰撞...

    C# Rectangle基本用法和图片切割源码

    在C#编程语言中,`Rectangle`类是用于表示二维矩形区域的重要工具,它广泛应用于图形绘制、图像处理和游戏开发等领域。本教程将深入探讨`Rectangle`的基本用法,以及如何使用C#进行图片切割操作。我们将通过实例代码...

    初学java之接口的一个小程序 Circle Rectangle

    根据给定的信息,我们可以总结出以下关于Java编程语言中的接口应用和类实现的相关知识点: ### 一、接口(Interface)的基础概念 在Java中,接口是一种完全抽象的类,它只包含方法签名(即方法名、参数列表以及...

Global site tag (gtag.js) - Google Analytics