android游戏物理引擎开发——粒子系统(三)
生病了,医院躺了几天,动了个小手术,动手术之后的几天在医院看了几本《大众软件》,又想到自己必须得买台台式机了,这破笔记本实在用不下去了,然后开始喜欢看些硬件的东西,等我熟悉了以后,写几个硬件DIY的教程~~啦啦啦,德玛~first Boold~ 等毕业就买,现在买了寝室也没地方放~先前期研究研究吧~
进入正题吧~!
碰撞检测也是游戏开发中必须有的一环
碰撞检测什么游戏都会用到,FPS游戏里的子弹和角色的碰撞,角色扮演里角色之间的碰撞,角色和环境之间的碰撞~太多了~我先给大家做一个碰撞基础知识的介绍,然后给大家细讲一下碰撞中的矩形碰撞!介绍这个的原因是我之后想做一个类似雷电的游戏,此游戏中用到的检测就是矩形检测。
一般按照一下流程来应用碰撞检测:
(1)更新实体对象的位置
(2)进行碰撞检测
(3)如果碰到了,进行相应的处理
上面的流程针对于单个实体对象来说,还有一种是在一类实体的位置全部更新完毕以后,再逐个碰撞检测。
碰撞检测又涉及到3个内容:
(1)确定检测对象
一个游戏中会有很多对象,但是碰撞检测的时候不是所有的对象都需要进行检测,比如说,我的飞机发出的子弹,就没有必要再和我的飞机检测,再比如,我的视野里面有两个静止宝箱,这两个宝箱之间也不需要进行碰撞检测,他们怎么都不会碰撞的。所以,开始进行碰撞检测之前,需要确定需要检测的对象
(2)检测是否碰撞
这地方是碰撞的核心环节,有很多种碰撞算法,需要合理选择,下面的这个几个算法的介绍引用于android巴士论坛的按剑殇人
一、地图格子划分检测
最简单的一种检测,就是把地图(或者称为场景,总之是指碰撞发生的范围)划成一个个格子,类似仙剑奇侠传这样。假设地图有800*600px,20*20个像素为一格。那么可以划为40*30个格子。地图中参与检测的对象都存储着自身所在的格子坐标,判断碰撞就显而易见了,例如可以认为两个物体在相邻格判为碰撞,或者两个物体在同一格。采用这种方式有个要求,就是地图中所有可能参与碰撞的物体都要是20*20像素左右大小或者是其整数倍,例如房子占了3*3个格子,诸如此类。如果不遵守这个规则,有的物体只占了格子的一半,那么在玩家眼里这种检测就显得非常的粗糙。这种检测就像是把地图的像素点放大几十倍一样,与逐像素检测相比,效率提高了几十倍甚至上百倍。这种方式可运用于对检测要求不严格的游戏,例如踩地雷的RPG、推箱子之类的智力游戏。
二、矩形检测
当地图中的物体不能严格按照某个块大小的整数倍来绘制时,那么就需要另想其他的方法。这种方法适用于地图中的物体近似为矩形或者虽然不是矩形,但是碰撞精度要求不高的情况下。每个物体记录一个能够将自己框住的最小矩形的左上角坐标和矩形长宽。碰撞退化为判断矩形与矩形之间是否重叠,而这仅需要4次比较即可得出,速度很快。但为了判断整个场景中的物体,必须取第一个物体,迭代其他所有物体进行判断,再取第二个物体,迭代除第一第二个物体外的所有物体进行判断,以此类推。总计要进行(n-1)!次矩形判断才能准确得出场景中所有的碰撞可能。
三、圆形检测
与上一种方法类似,区别在于用一个能够包含物体的最小圆代替了矩形。主要是考虑到游戏中的物体外形以平滑为主,例如人物角色。而判断两个圆是否碰撞的计算也很简单,就是判断两个圆心之间的距离是否小于两个圆的半径之和。虽然球形检测在某些情况下提高了精度,但却损失了速度,因为点距离的计算需要用到平方和开方。具体相比慢多少我就不太清楚了。另外,为了计算整个地图的所有碰撞可能,也要进行(n-1)!次比较。
四、像素检测
精确到像素级,已经不能比这更精确了,相对的,效率也是最低的。怎样判断两个物体是否碰撞呢?在过去png格式图片还不盛行的时候,游戏中用到的图片中的透明部分是指定用某种颜色来表示的,例如洋红色。就像电影中的绿幕蓝幕,通过处理把这些颜色的像素点当做透明点处理,而为了判断检测,需要准备一张原图像的黑白图,黑色区域表示透明,这张图片中的每个像素值为0或者1,判断检测的时候取两张图片的黑白图,进行与运算,结果为1(有白点重叠),则判为碰撞。但是现在有了PNG和XNA,逐像素检测就相对简单一些。首先仍然需要有一个矩形框包围物体,通过矩形检测得到重叠的矩形区域可以大大减少检测的像素点数量。然后在这个区域内,取两个图片的点逐行逐列迭代,如果遇到某个点两张图片均有颜色存在,即判为碰撞。同理,进行(n-1)!次比较后得到全地图的碰撞可能。
五、四叉树检测
准确的说这事在第三四五种方法的基础上的优化策略,或者说是第一种方法同后三种方法的组合应用。主要是针对那最后的(n-1)!次比较。方法是,像第一种方法一样将地图分为格子,格子的大小应该能够容纳10个左右的地图中最大物体,例如一个800*600的地图可能就划为9个区。同样的,每个物体要记录自己所在的区坐标以及矩形包围盒。如果该物体完全位于该区内,则只要将其与该区内的其他物体判断碰撞。如果该物体虽然位于某个区,但是小部分位于隔壁区,则额外的需要迭代隔壁区的物体,这点效率损失是可以容忍的,相比于迭代全地图的物体。
有个问题,我怎么知道哪些物体是跟该物体位于同一个区呢?那不是还是要迭代一遍所有物体?这时候就是题目发挥的地方的,之所以称为四叉树检测(当然,这名字是我自己取的),就是因为那些区块是以四叉树的方式链接的,即得到一个区块的对象,就可以直接得到其上下左右相邻的区块的对象,而物体可以是存储在所在区的一个列表中。这样就不用遍历所有物体也可以直接取出隔壁区的物体了。当地图很大的时候,四叉树的优势体现得很好。
六、3D中的碰撞检测
以上是我所掌握碰撞方法,可能还有更多吧。那么3D中的检测其实是2D的延伸,例如矩形检测变为立方体检测,圆形检测引申为球形检测,四叉树检测进化为八叉树检测。
(3)处理碰撞
这个地方就因游戏而异了,比如雷电中子弹和敌机碰撞,敌机爆炸之类~
下面上代码吧,关于矩形检测的,圆形检测液类似~
public class MySurfaceView extends SurfaceView implements Callback, Runnable { private int x1 = 30, y1 = 100, w1 = 40, h1 = 40;
private int x2 = 80, y2 = 100, w2 = 40, h2 = 40; //定义两个矩形的左上角坐标和他们的宽高
private SurfaceHolder holder; //holder用于控制surfaceView
private Canvas canvas;
private Paint paint; //画笔的实例,还用说么?
private Thread th; //定义一个新的线程,用来不断的执行ondraw
private boolean flag = false; //线程是否执行的标志位
private boolean isCollsion; //检测碰撞的标志位 public MySurfaceView(Context context) {
super(context);
//在构造函数里初始化一些实例
holder = this.getHolder();
holder.addCallback(this); //为holder添加监听器,监听surfaceView的改变
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.WHITE); //设置画笔的抗锯齿和颜色
setFocusable(true); //设置焦点,有了焦点,点击屏幕才会生效
// TODO Auto-generated constructor stub
} public void onDraw(){
try{
canvas = holder.lockCanvas(); //给surfaceView锁定一块画布
if(canvas != null){
canvas.drawColor(Color.BLACK); //如果画布不等于空,就刷屏成黑色
if(isCollsion){ //如果发生碰撞
paint.setTextSize(20);
canvas.drawText("IsCollsion", 10, 50, paint); //在屏幕左上角协商iscollsion
}else{
paint.setColor(Color.WHITE);
}
}
canvas.drawRect(x1, y1, x1 + w1, y1 + h1, paint); //把矩形1和矩形2给画上
canvas.drawRect(x2, y2, x2 + w2, y2 + h2, paint);
}catch(Exception e){
e.printStackTrace();
}finally{
if(canvas != null){
holder.unlockCanvasAndPost(canvas);
}
}
} @Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
//碰撞检测流程(一):更新实体对象的位置
x1 = (int)event.getX() - w2/2; //取得点击处的坐标,进而求得矩形2的左上角坐标
y1 = (int)event.getY() - h2/2; //碰撞检测流程(三):碰到之后,进行相应处理
if(IsCollsion(x1, x2, y1, y2, w1, w2, h1, h2)){
isCollsion = true; //如果碰撞上了就把isCollsion改为true
}else{
isCollsion = false;
} return true;
} /*
* x1,y1是矩形1左上角的坐标,w1,h1是矩形1的宽高,x2,y2,w2,h2同理,是h2的左上角坐标
* 和宽高
*/
//碰撞检测流程(二):进行碰撞检测
public boolean IsCollsion(int x1, int x2, int y1, int y2, int w1,
int w2, int h1, int h2){
//满足以下四种情况之一,则不会发送碰撞,除此之外都会发送碰撞
if(x1 < x2 && x1 + w1 <= x2){
return false;
}else if(x1 > x2 && x1 >= x2 + w2){
return false;
}else if(y1 < y2 && y1 + h1 <= y2){
return false;
}else if(y1 > y2 && y1 >= y2 + h2){
return false;
}
return true; //不满足以上四种情况的全是发生碰撞
} @Override
public void run() {
// TODO Auto-generated method stub
while(flag){
long start = System.currentTimeMillis();
onDraw();
long end = System.currentTimeMillis();
try{
if (end - start < 50) {
Thread.sleep(50 - (end - start));
}
}catch(Exception e){
e.printStackTrace();
}
}
} public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
return super.onKeyDown(keyCode, event); } @Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub } @Override
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub
flag = true;
th = new Thread(this); //实例化线程
th.start(); //执行线程
} @Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub } }
activity类
public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new MySurfaceView(this));
} }
今天就这么多~我继续学习去了~~游戏引擎的内容就这么多~!
android游戏物理引擎开发——粒子系统(三)的更多相关文章
- Android游戏与应用开发最佳学习路线图
Android 游戏与应用开发最佳学习路线图 为了帮助大家更好的学习 Android,并快速入门特此我们为大家制定了以下学习路线图,希望能够帮助大家. 一.路线图概括: 二.具体需要掌握知识点: 三. ...
- 将 Android* Bullet 物理引擎移植至英特尔® 架构
简单介绍 因为眼下的移动设备上可以使用更高的计算性能.移动游戏如今也可以提供震撼的画面和真实物理(realistic physics). 枪战游戏中的手雷爆炸效果和赛车模拟器中的汽车漂移效果等便是由物 ...
- go语言游戏服务端开发(三)——服务机制
五邑隐侠,本名关健昌,12年游戏生涯. 本教程以Go语言为例. P2P网络为服务进程间.服务进程与客户端间通信提供了便利,在这个基础上可以搭建服务. 在服务层,通信包可以通过定义协议号来确定该包怎 ...
- 用Box2d物理引擎设计类似愤怒小鸟投篮游戏 物理引擎的引入和基本框架搭建
- Python游戏引擎开发(七):绘制矢量图
今天来完毕绘制矢量图形. 没有读过前几章的同学,请先阅读前几章: Python游戏引擎开发(一):序 Python游戏引擎开发(二):创建窗体以及重绘界面 Python游戏引擎开发(三):显示图片 P ...
- Python游戏引擎开发(五):Sprite精灵类和鼠标事件
本次来实现Sprite类和鼠标事件. 说起这个Sprite啊,涉及过2D游戏研究领域的看官应该都听说过它. 它中文原意是"精灵",只是在不同人的眼中,它所表示的意义不同. 比方说在 ...
- [原创]cocos2d-x研习录-第三阶 特性之物理引擎
游戏物理引擎是指在游戏中涉及物理现象的逻辑处理,它用于模拟现实世界的各种物理规律(如赛车碰撞.子弹飞行.物体掉落等),让玩家能够在游戏中有真实的体验. Cocos2D-x中支持Box2D和Chipmu ...
- Bullet物理引擎的安装与使用
图形赋予游戏一种视觉的吸引力,但是能够让游戏的世界鲜活起来的还应该是内部的物理引擎.物理引擎是游戏引擎中的子模块,是一种软件组件,可仿真物理系统.它根据牛顿力学定律,计算游戏中物体的合理的物理位置,并 ...
- Unity3D游戏开发初探—3.初步了解U3D物理引擎
一.什么是物理引擎? 四个世纪前,物理学家牛顿发现了万有引力,并延伸出三大牛顿定理,为之后的物理学界的发展奠定了强大的理论基础.牛顿有句话是这么说的:“如果说我看得比较远的话,那是因为我站在巨人的肩膀 ...
随机推荐
- android下拉选择框spinner
spinner是什么东西呢?有点像下拉菜单,其实是一个弹出窗口,但是是可以进行进一步操作的弹出窗口.你点击那个三角形的符号,弹出一个窗口,通常是列表,然后进行操作. 它在xml文件中的定义和其它控件没 ...
- python re.sub
python re.sub python re.sub属于python正则的标准库,主要是的功能是用正则匹配要替换的字符串然后把它替换成自己想要的字符串的方法下面给个例子:import relin ...
- 1182-IP地址转换
描述 给定一个点分十进制的IP地址,把这个IP地址转换为二进制形式. 输入 输入只有一行,一个点分十进制的IP地址 包括四个正整数,用三个.分开,形式为a.b.c.d 其中0<=a,b,c,d& ...
- POJ 3007 Organize Your Train part II(哈希链地址法)
http://poj.org/problem?id=3007 题意 :给你一个字符串,让你无论从什么地方分割,把这个字符串分成两部分s1和s2,然后再求出s3和s4,让你进行组合,看能出来多少种不同的 ...
- memcached远程 telnet 无法连接,解决方案
因为默认的Memcached配置,使用了本机ip:127.0.0.1 ,此时利用VI修改下配置 vi /etc/memcached.conf 文件打开后,修改下,把-l前面加入#号注释掉,重启服务器就 ...
- 使用NSURLSession实现断点续传
在sb中创建按钮,并且连线到.m文件中
- jni.h头文件详解二
作者:左少华 博客:http://blog.csdn.net/shaohuazuo/article/details/42932813 转载请注明出处:http://blog.csdn.net/shao ...
- Linq中的常用方法
System.Linq System.Linq.Enumerable 类 Range Repeat Reverse Select Where Sum Zip Aggregate Count Firs ...
- mapreduce实现"浏览该商品的人大多数还浏览了"经典应用
输入: 日期 ...cookie id. ...商品id.. xx xx xx 输出: 商品id ...
- EasyUI中datagrid的行编辑模式中,找到特定的Editor,并为其添加事件
有时候在行编辑的时候,一个编辑框的值要根据其它编辑框的值进行变化,那么可以通过在开启编辑时,找到特定的Editor,为其添加事件 // 绑定事件, index为当前编辑行 var editors = ...