http://bbs.9ria.com/viewthread.php?tid=86124&extra=page%3D1%26amp%3Borderby%3Ddateline%26amp%3Bfilter%3D2592000
从这一篇开始.我们将开始学习物理引擎ape的用法.就我知道的.比较常用的flash引擎有两种,第一种是box2d,第二种是ape.box2d引擎是从c++移植过来的.用了一段时间的box2d.给我的感觉就是很复杂.可是性能确实是很好的.box2d生成对象比ape要繁琐许多.生成对象和销毁对象都是用工厂方法,而ape引擎给我的感觉就是轻巧,简单.原生的版本只有19个类,而谷歌代码托管加强版本的ape也只有23个类,ape对象都是以一种称作"粒子"的方式来组织的.生成对象的方式也比box2d方便许多.这里不是讨论哪个引擎的好坏.项目中选择适合自己的才是正确的一种方法.好了.这里我们就进入入第一篇关于ape的教程吧.
第一篇:模拟最简单的物理世界.
先看例子:
例子
使用ape的第一件事就是:修改掉ape的Vector类.为什么要修改它呢.因为在flash的新版本中.官方加入了Vector类.这个类会和ape里面的Vector类冲突.所以我们第一件事就是把Vector类修改成apeVector.这里读者不必自己修改,在下面的附件中.我已经修改好了.这里只是给大家提个醒而已.好了修改之后.我们要做的第一件事情就是初始化我们的物理引擎了;
首先放出这篇教程的所有源码,后面我们会一行一行的解释(请读者自己导入相关的包)
- package
- {
- import flash.display.Sprite;
- import flash.events.Event;
- import org.cove.ape.APEngine;
- import org.cove.ape.ApeVectorForce;
- import org.cove.ape.CircleParticle;
- import org.cove.ape.Group;
- import org.cove.ape.RectangleParticle;
- /**
- * ...
- * @author 陈伟群
- */
- public class Chapter_1 extends Sprite
- {
- private var groupFall:Group;
- private var ballFall:CircleParticle;
- private var rectFall:RectangleParticle;
- public function Chapter_1()
- {
- //初始化物理引擎
- APEngine.init(0.25);
- APEngine.addForce(new ApeVectorForce(false, 0, 10));
- APEngine.container = this;
- /*---------------------关于制造墙-------------------------------*/
- //制造墙的容器
- var groupWall:Group = new Group(true);
- //制造四面墙
- var rightWall:RectangleParticle = new RectangleParticle(15, 200, 30, 400, 0, true);
- rightWall.setStyle(0, 0, 1, 0xffcc00);
- groupWall.addParticle(rightWall);
-
- var leftWall:RectangleParticle = new RectangleParticle(535, 200, 30, 400, 0, true);
- leftWall.setStyle(0, 0, 1, 0xffcc00);
- groupWall.addParticle(leftWall);
-
- var bottomWall:RectangleParticle = new RectangleParticle(275, 385, 550, 30,0, true);
- bottomWall.setStyle(0, 0, 1, 0xffcc00);
- groupWall.addParticle(bottomWall);
-
- //把墙组加到引擎里面进行渲染
- APEngine.addGroup(groupWall);
- /*----------------------制造掉落的东东----------------------------*/
- groupFall = new Group(true);
- APEngine.addGroup(groupFall);
- //两个组之间的碰撞
- groupWall.addCollidable(groupFall);
- addEventListener(Event.ENTER_FRAME, engineHandler);
- }
-
- private function engineHandler(e:Event):void
- {
- //渲染
-
- if (int(Math.random()*20)==0)
- {
- ballFall = new CircleParticle(Math.random() * 550, Math.random() * 20, Math.random() * -10 + 20);
- groupFall.addParticle(ballFall);
- //rectFall = new RectangleParticle(Math.random() * 550, Math.random() * 20,Math.random() * -10 + 20,Math.random() * -10 + 20,Math.random()*3.14);
- //groupFall.addParticle(rectFall);
- }
- APEngine.step();
- APEngine.paint();
- }
-
-
- }
- }
====================================================================================================
- //初始化物理引擎
- APEngine.init(1 / 4);
- APEngine.addForce(new ApeVectorForce(false, 0, 10));
- APEngine.container = this;
上面的代码几乎是固定的
ApeEngine的init()方法必须的.一般的默认值是0.25,这个值越大.那么模拟的速度就越快.可是会变的很不精确.我试过把它的值调得很大.发现会出现穿透的现象(大家可以在我给的代码中试试.非常的诡异,呵呵);ApeEngine的addForce()方法是说个系统的粒子添加一个无质量的力,为什么要叫做无质量的力呢?其实找我的理解就是额...我想起了那个著名的斜塔实验.这个力传入的参数是一个实现了IFore接口的类(注意这个是使用增强版本的ape,原生版本的可能是我们Vector类,这里我们一律使用实现了IFore接口的类),
ApeEngine的的contain属性.我们就当成ape渲染的容器了吧.
接着就是创建物理世界的边界了,就是说是我们的墙体.首先我们先来看看创建这些的基本步骤
- //制造墙的容器
- var groupWall:Group = new Group(false);
第一步是:给我们将要创建的矩形粒子(这里指的是墙体)一个容器.容器的作用是什么?这里我们先卖个关子.等你看完这篇教程
也许你会有更好的理解.这里的Group的构造函数是说在这个容器里面的粒子是不是能互相碰撞.这种情况就是说如果你有一罐糖果.你摇晃这这个
罐子的时候,里面的糖果会不会互相碰撞.如果你选择了否.那么你将看到你的糖果互相穿透了.神奇吧.因为我们这里是墙体,墙当然是静态的.所以
我们不需要他们互相碰撞.当然,在这里你设置能true.也是可以的.
- //制造墙体(矩形粒子)
- var rightWall:RectangleParticle = new RectangleParticle(15, 200, 30, 400, 0, true);
- rightWall.setStyle(0, 0, 1, 0xffcc00);
- groupWall.addParticle(rightWall);
- APEngine.addGroup(groupWall);
第二步:这一步是创建一个墙体.这个矩形粒子类有四个必须参数.五个可选参数.这篇重点要讲前六个,后面的一般保持默认就好.后面我们会讲.第一二个参数是粒子的xy坐标.这里要说一下的就是这里的坐标是指从矩形的中心点开始算的.这个概念和我们的注册点是九宫格中间那点有点像所以这样就导致了一个现象.xy不是从左上角开始算的.是从中心点开始算的.这是要引起注意的地方.这里就知道可以解释为什么第一二个参数是15,200而不是0,0了.第三四个参数就是宽与高了.第五个参数是说粒子的角度.注意这里应该使用弧度制.第六个参数是说这个物体是是不是需要固定的(静止);
然后是setStyle方法.这个方法和我们的graohics.drawRect()差不多,具是设置粒子的样式.后面还会讲到给粒子一个皮肤(用自定义的剪辑);
groupWall.addParticle(rightWall);说的是我们把刚刚创建好的粒子加入到容器中.APEngine.addGroup(groupWall)就是把容器加入到APE引擎了..呵呵.看到上面的代码.也许有人会想了.那三个墙体创建方法是一样的.可以写成函数,ok,在下一篇我们将做得更彻底一点.把三面墙都写到一个叫做,世界边界类中.呵呵.
好了.现在我们的墙体已经差不多OK了.我们还要对引擎进行渲染;
- private function engineHandler(e:Event):void
- {
- //渲染
-
- APEngine.step();
- APEngine.paint();
- }
这里需要注意的是应该放在帧处理事件中的.因为这是个不断渲染的过程.paint函数会使引擎不断的调用粒子的paint()方法.
这里我们的世界边界就完成了.注意.这里使用的世界边界只是指我们自己完成的墙体(和box2d 2.0版本的AABB世界边界不同,ape也不会帮我们
自动把超出世界边界的物体休眠);
好了.这里我们总结一下,创建粒子的基本步骤吧:
1.创个容器组(group)
2.创建粒子
3.把粒子加入容器组(group).
4.把容器组加入到引擎
根据这个原理.我们就可以知道了创建粒子的方法了.上面的创建圆形粒子(CircleParticle)的方法也是一样的.注意我们把他放到了全局变量中因为我们要操作它.关于圆形粒子的创建就不多说了,和矩形粒子不同的地方就是宽高变成了半截而已.剩下的.几乎是一模一样的.聪明的你一定能很快就领悟的.这里我想说的是这一句
- groupWall.addCollidable(groupFall);
每个group都有这个方面.是接受另一个group的引用,这里的意思是说.着两个组需要互相碰撞.在这个例子的意思就是说圆形粒子要和墙体碰撞好了.说到这里.这一篇教程就大概算好了.关于组的作用.就我的理解就是.更方便的组织.特别是单我们下次把他整个放到一个类的时候.然后细心的你.一定看到了那个注释了.
- //rectFall = new RectangleParticle(Math.random() * 550, Math.random() * 20,Math.random() * -10 + 20,Math.random() * -10 + 20,Math.random()*3.14);
- //groupFall.addParticle(rectFall);
把那个注释打开.你会看到不可思议的事情发生...我试过调高他的模拟的精确值.还是解决不了.这里我不确定是我的方法错了.还是ape自身的不完善.希望有高手来指正一下.
下一篇我们将讨论更多类型的粒子.