分析算法的思路:

Step1:假设stage(黑色)上有4个显示对象red_mc,green_mc,blue_mc,yellow_mc,层级关系是stage>root>red_mc,stage>root>yellow_mc>blue_mc>green_mc。要检测碰撞的对象是red_mc和green_mc。如图

图1

补充约定:为方便表述,这里约定显示对象的“初始状态”为相对父级容器坐标系未进行旋转,缩放,即对象的transform.matrix对象是[a=1,b=0,c=0,d=1]。

Step2:一开始,图1中的4个mc都处于初始状态。但这样的碰撞检测不考验算法,因此对它们做缩放,旋转,平移处理(我直接在flashIDE里完成的),使得red_mc和green_mc的空间位置足够复杂。如图:

图2
补充知识:draw()方法的一个细节

如下代码(文档类):
   varbmd1:BitmapData = new BitmapData(150,150);
   bmd1.draw(red_mc);
   varbmp1:Bitmap = new Bitmap(bmd1);
   this.addChild(bmp1);

若red_mc处于初始状态(即图1中的red_mc),效果如下:

图3
十分正常。但是,若用同样地代码来draw变形后的red_mc(即图2中的red_mc),会是什么样子呢?图2中red_mc尺寸太大,这块儿150*150的白色像素会不会只能draw入red_mc的一部分呢?效果如下:

图4

看来,仍旧是以初始状态的red_mc为绘制源。

这就是draw(X)方法的一个细节:不管X怎样变形,平移,都选取X的初始状态作为绘制源。此外,当X处于层层容器嵌套之下时(green_mc就是这种情况),不管它n多父级的变形操作对X形状产生怎样影响,draw也一样选取X的初始状态为绘制源。

Step3:前两步作为准备,现在开始碰撞检测的第一步,利用flash自带的hitTestObject()函数做预判断。若这一步判断false肯定没戏了。

补充知识:

1.hitTestObject()是基于AABB包围体的碰撞检测,即检测虚线框的碰撞。(red_mc的虚线框看似并未仅包住red_mc,这是因为red_mc

图5

进行过旋转变换。)

2.hitTestObject()检测碰撞时,并不关心对象是否在显示列表内。这点很重要。

Step4.通过上步的预判断,再进一步检测:获取两个包围体的交叠矩形区域,用rect1存储相关信息(x,y,width,height),判断rect1区域内red_mc和green_mc是否有像素重叠。若true便碰上了。

补充知识:显示对象的matrix属性

matrix本身的a,b,c,d没什么好说,这里记下matrix操作的细节。

1.red_mc.transform.matrix,这个记录矩阵(习惯称它记录矩阵,文档上称“变换矩阵”),是red_mc相对于父级容器坐标系的记录矩阵。就像通常所说red_mc.x也是red_mc相对于父级坐标系的x轴偏移。

2.要想获得red_mc相对于再上一级,即parent.parent的记录矩阵,该如何呢?直接用parent的matrix乘上red_mc的matrix就好了。

3.若想获取red_mc相对于stage的记录矩阵呢?理论上是root.transform.matrix*........(各级父容器的矩阵逐级相乘)......*red_mc.transform.matrix。很累,flash为此提供了concatenatedMatrix属性,就是显示对象相对于stage的记录矩阵。(矩阵乘法是不能用*号的,应该是concat,我是想写快点儿)

4.假若要获取red_mc相对于root的记录矩阵呢?直接逐级相乘没问题。不过,concatenated属性提供了一个简洁思路------varrootM:Matrix=root.transform.matrix.clone();

var rootM1:Matrix=red_mc.transform.concatenatedMatrix;

rootM.invert();//取得root的逆矩阵

rootM1.concatenatedMatrix.concat(rootM);//这样,rootM1就转化为相对于root的

5.matrix的concat()方法似有bug

当a,d任意为0时,计算的结果就不大对,例如下面两个矩阵

var A:Matrix=newMatrix(1,1,2,2,0,0);

var B:Matrix=newMatrix(0,0,1,1,1,0);

A.concat(B);

trace(A);//输出的ty不是2,我用笔算了几遍,ty都是2

当a,d都不为0时,计算结果没有问题,以后还是放心用吧,因为a,d任意为0,显示对象便不存在了,应不会存在这种情况。

自己写了个矩阵运算类,是很无脑的算法:行对列相乘。很慢很稳妥。是不是内置的矩阵乘法运算采用另外算法,才会有这样的bug呢?

6.matrix的concat()方法用起来要小心顺序

A.concat(B),对应的数学式为(矩阵B*矩阵A),矩阵乘法不满足交换律,这个地方跟常规思路又不同(至少跟我想的顺序相反),因此操作时应小心。

7.不要直接修改显示对象matrix的a,b,c,d,tx,ty属性,也不要直接应用scale,rotate等操作。因为任何设置都是无效的。

如:varA:Matrix=red_mc.taransform.matrix;//A引用的是red_mc.taransform.matrix的一份拷贝

A.scale(0.5,0.5);//编译不会报错,但这个操作只修改A,对red_mc.taransform.matrix不造成修改

A.a=2;//同上

正确的操作是这样的:

varA:Matrix=red_mc.transform.matrix.clone();

//varA:Matrix=red_mc.transform.matrix也行

A.scale(0.5,0.5);

A.a=2;

red_mc.tansform.matrix=A;//创建一个合适矩阵,交付给red_mc.transform.matrix引用。

8.想对matrix执行scale操作时,用scale方法:

A.sacle(0.5,0.5);

不要写:A.a/=A.b/=2;当matrix的b,c属性不为0,这个操作完成的并不是scale功能。

补充知识:BlendMode.DIFFERENCE

文档讲的很清楚:

将显示对象的原色与背景颜色进行比较,然后从较亮的原色值中减去较暗的原色值。此设置通常用于得到更明亮的颜色。

例如,如果显示对象的某个像素的 RGB 值为0xFFCC33,背景像素的 RGB 值为 0xDDF800,则显示像素的结果 RGB 值为 0x222C33(因为 0xFF -0xDD = 0x22,0xF8 - 0xCC = 0x2C,且 0x33 - 0x00 = 0x33)。

补充知识:draw()方法的matrix参数有何效果

文档说:用于缩放、旋转位图或转换位图的坐标

下面用代码和效果图说明:

varbmd1:BitmapData = new BitmapData(200,200);
   bmd1.draw(red_mc,newMatrix(1,0,0,1,0,0));//先不对绘制源做处理,看看正常的样子
   varbmp1:Bitmap = new Bitmap(bmd1);
   this.addChild(bmp1);

图6

很正常,跟图4吻合

再看:

varbmd1:BitmapData = new BitmapData(200,200);
   bmd1.draw(red_mc,newMatrix(1,0,0,1,110,110));//让绘制源沿x,y轴正方向平移了(110,110)的向量
   varbmp1:Bitmap = new Bitmap(bmd1);
   this.addChild(bmp1);

图7
果然,绘制源相对注册点偏移了(110,110)

再看:

varbmd1:BitmapData = new BitmapData(200,200);
   bmd1.draw(red_mc,new Matrix(2, 0, 0, 2, 0, 0));
   varbmp1:Bitmap = new Bitmap(bmd1);
   this.addChild(bmp1);


                                            图8
果然缩放了两倍

这便是matrix参数的功能。

问:如何才能draw到图8中舞台下部的red_mc的形貌呢?

答:肉眼看到的red_mc的形貌,是它在stage坐标系中的形貌,因此将draw参数设置为red_mc.transform.concatenatedMatrix,这样绘制源便从初始状态变换到相对舞台的形貌。

试一下:

varbmd1:BitmapData = new BitmapData(200, 200);
   //为了便于区分,施加一个colorTransform让draw到的像素变为蓝色
   bmd1.draw(red_mc,a_mc.transform.concatenatedMatrix,newColorTransform(1,1,1,-255,-255,255));
   varbmp1:Bitmap = new Bitmap(bmd1);
   this.addChild(bmp1);


                                         图9

什么也没有?因为像素块太小了,red_mc经过矩阵变换,已经跑到了它外面去。

将像素块增大,看看:

varbmd1:BitmapData = new BitmapData(300, 300);
   //为了便于区分,施加一个colorTransform让draw到的像素变为蓝色
   bmd1.draw(a_mc,a_mc.transform.concatenatedMatrix,newColorTransform(1,1,1,1,-255,-255,255,255));
   varbmp1:Bitmap = new Bitmap(bmd1);
   this.addChild(bmp1);


                                        图10
这下好啦!很准。

但,假如像素块儿尺寸因为某种原因不能修改,该怎么办?那就再折磨draw()方法的matrix参数,让red_mc平移到舞台原点:

varbmd1:BitmapData = new BitmapData(200, 200);
   //为了便于区分,施加一个colorTransform让draw到的像素变为蓝色
   var m1:Matrix= a_mc.transform.concatenatedMatrix;
   m1.tx += 0 -m1.tx;
   m1.ty += 0 -m1.ty;
   bmd1.draw(a_mc,m1,newColorTransform(1,1,1,1,-255,-255,255,255));
   varbmp1:Bitmap = new Bitmap(bmd1);
   this.addChild(bmp1);

效果:

图11

就是要这个样子。

刚才说到Step4:获取两个包围体的交叠矩形区域,用rect1存储相关信息(x,y,width,height),判断rect1区域内red_mc和green_mc是否有像素重叠。如图:

图12
判断rect1区域内red_mc和green_mc是否有像素重叠的思路:

new出来一块儿跟rect1等大的黑色像素块。用一种colorTransform去drawrect1区域内的red_mc,再用另一种colorTransform去draw rect1区域内的green_mc,同时采用blendMode.DIFFERENCE混合模式,一旦出现特定颜色,则有像素重叠。

至于如何准确的draw到rect1区域内的red_mc/green_mc的像素,在补充里已经给出思路。

现在再看tink的那个类应该很简单了。并且,个人认为他的类存在一些错误,下篇讨论

关于tink的碰撞检测类【2】相关推荐

  1. 关于tink的碰撞检测类【1】

    tink博客上的一个碰撞检测类,思路是:用flash自带的hitTestObject预判断,再基于像素重叠检测碰撞. 原文链接:http://www.tink.ws/blog/as-30-hittes ...

  2. java 像素级碰撞检测,» 像素级碰撞检测类

    //像素级碰撞检测 package { import flash.display.BitmapData; import flash.display.BlendMode; import flash.di ...

  3. HTML5吃豆豆游戏开发实战(三)2d碰撞检测、重构

    今天把小球和墙壁的碰撞检测写了一下,主要就是坐标比较大小. 然后整个项目越来越大,代码越来越多,所以把准备把代码重构一下. 把代码拆分,相同功能的在一起,形成一个类,比如Collide.js,碰撞检测 ...

  4. osg_操作器、碰撞检测、上楼梯篇

    一.  操作器 OSG经常用到的自带操作器为TrackBall, osgEarth经常用到的自带操作器为EarthManipulator 自己要写操作器应继承于osgGA::CameraManipul ...

  5. python打砖块游戏算法设计分析_python实现打砖块游戏

    本文实例为大家分享了Python实现打砖块游戏的具体代码,供大家参考,具体内容如下#导入模块 import pygame from pygame.locals import * import sys, ...

  6. python小游戏代码大全-Python实现打砖块小游戏代码实例

    这次用Python实现的是一个接球打砖块的小游戏,需要导入pygame模块,有以下两条经验总结: 1.多父类的继承2.碰撞检测的数学模型 知识点稍后再说,我们先看看游戏的效果和实现: 一.游戏效果 二 ...

  7. bat小游戏代码大全_Python打砖块小游戏源代码

    这次用Python实现的是一个接球打砖块的小游戏,最核心的就是:碰撞检测的数学模型 程序运行截图: 其实,编程问题到最后就是数学问题,这个游戏涉及到2D圆形与矩形的碰撞检测问题: 碰撞检测原理:通过找 ...

  8. 课程设计小组报告——基于ARM实验箱的捕鱼游戏的设计与实现

    课程设计小组报告--基于ARM实验箱的捕鱼游戏的设计与实现 一.任务简介 1.1 任务内容 捕鱼游戏是一个娱乐性的游戏开发,可以给人们带来娱乐的同时还可以给人感官上的享受,所以很受人们的欢迎.本次游戏 ...

  9. 可扩展java游戏框架实践之java飞机大战

    前言 在Java awt frame下利用画笔工具实现一个游戏框架. 该框架支持: 游戏动画实现 动图实现 移动实现 碰撞检测 游戏流程控制 游戏音乐控制 功能设计实现 ①游戏动画实现 JFrame下 ...

最新文章

  1. 剑指offer系列之三十七:二叉树的深度
  2. finalspeed安装及使用教程
  3. 通过正则寻找符合要求的字符串
  4. mysql可以运行在不同sql mode模式下面,sql mode模式定义了mysql应该支持的sql语法,数据校验等...
  5. 《Office 365开发入门指南》上市说明和读者服务
  6. pythonweb服务器怎么让别人访问_Django配置让其他电脑访问网站
  7. 零基础学习ruby_学习Ruby:从零到英雄
  8. Python入门基础篇(一)列表,详细实用,简单易懂!!!!
  9. IE 加速插件之 Google Chrome Frame
  10. 304.二维区域和检索-矩阵不可变
  11. 最新老韩泰牛PHP基础班+大牛班+大牛班高级课程
  12. 您的CPU支持该TensorFlow二进制文件未编译为使用的指令:AVX AVX2
  13. 网易云桌面歌词好看的配色方案
  14. xcode 免cleanup build
  15. 什么第一台多媒体电子计算机诞生,第一台多媒体电计算机是哪一年诞生的
  16. DAO:去中心化的新兴领导者
  17. 什么是android应用程序未安装,显示“应用程序未安装”是怎么回事?程序未安装的解决图文步骤...
  18. 又是一年冬至,最喜欢吃冬至茧了
  19. Linpack测试环境的搭建
  20. Vue 输入框禁止贴贴

热门文章

  1. 华为汽车BU业务布局及分析框架
  2. 关于cookie的跨域(一级域)
  3. cufflinks 绘图
  4. 常用数据加密及加密格式
  5. QT实现绘制箱须图(盒须图)
  6. Linux 管理联网 nmcli常用命令
  7. HTML5+JavaScript调用摄像头拍照或者摄像
  8. Pgpool-II + Watchdog 设置与测试
  9. CSDN莫名其妙封号
  10. Stay Hungry, Stay Foolish(求知若饥,虚心若愚)