About

<#TEMPLATE_INCLUDE_NINEPAGE_ABOUTME#>
  • May

    19

    字符串与数字作为键时,优先转换成数字索引优先,数字索引从 0 开始:

    import flash.utils.Dictionary;
    var d:Dictionary = new Dictionary();
    var obj1:Object = new Object();
    var obj2:Object = new Object();
    d["a"] = 1;//a string
    d[0] = "1";//0 number
    d["1"] = 1;//1 number
    d[1] = 1;//1 number
    //特别注意下面这两行
    d[-1] = "2";//-1 string
    d["-1"] = -1;//-1 string
    for(var key:* in d)
     trace(key , typeof key);

    上面看起来好像是加了 6 个键,但实际上因为 Key 会自动转型,所以只有 4 个键。当字符串"1"出现在键时,数字段先的原则,会变成 1;当数字 -1 出现在键时,因为数字索引从 0 开始,所以无法变成数字索引,变成了字符串的键"-1"。

    May

    8

    private function ballToWallInteractionListener(cb:InteractionCallback):void 
    {
          //虽然没有看过 Haxe 的源码,但可以确定 Nape 刚体在清除之前并不需要调用 clear() 方法
          //ball.shapes.clear();

          space.bodies.remove(ball);

          ball.space = space;    

          //如果不添加新的形状,刚体的 ShapeList 实际上并没有保留任何对象,在 remove 时已经清空了 ShapeList
          //但刚体的速率 velocity,位置 position 之类引用的 Vec2 属性值是仍然保留的,并不会被重置
          ball.shapes.add(new Circle(10));
    }

    May

    8

    Nape:碰撞检测时移除刚体

    • 1 Comments
    • Flash Platform

    Rigid body(刚体)在选择从 Nape 中移除时,要选择好“时机”,否则在 step()  将会引发错误。比如在小球撞击墙面使用如下代码:

    //假装很高级的样子,省略了一些代码
    //......
    private var preListener:PreListener = new PreListener(InteractionType.COLLISION, ballType, wallType, ballToWallPreListener);

    //......
    space.listeners.add(preListener);

    //重点来了
    private function ballToWallPreListener(cb:PreCallback):void 
    {
        space.bodies.remove(ball);
    }

    这时就会引发一个类似如下的错误(因为在迭代运算时需要继续用到刚体对象):

    TypeError: Error #1009: 无法访问空对象引用的属性或方法。
        at zpp_nape.space::ZPP_Space/narrowPhase()
        at zpp_nape.space::ZPP_Space/continuousCollisions()
        at zpp_nape.space::ZPP_Space/step()
        at nape.space::Space/step()

     修改成下面这样子就可以了(迭代运算结束了):  

    //假装很高级的样子,省略了一些代码
    //......
    private var interactionListener:InteractionListener = new InteractionListener(CbEvent.BEGIN, InteractionType.COLLISION, ballType, wallType, ballToWallInteractionListener);

    //......
    space.listeners.add(interactionListener);

    //重点来
     private function ballToWallInteractionListener(cb:InteractionCallback):void 
    {
      space.bodies.remove(ball);// OK
    }

    May

    8

    对刚体的弹性系数 elasticity 设为最大值1,所有摩擦力 Friction 设为 0,但仍然发现它在撞击之后有速率的损失(能量损失?)

    样例代码如下,如果没有最后面那一段注释掉的代码,会发现它的速率一直在变小,虽然它变小的比较慢,它确实在变小(按官方的在线帮助手册 API 资料中所介绍的,elasticity 设为 1 的时候应该没有速率损失才对)。

    package
    {
        import flash.display.Sprite;
        import flash.events.Event;

        import nape.callbacks.CbType;
        import nape.geom.Vec2;
        import nape.phys.Body;
        import nape.phys.BodyType;
        import nape.shape.Circle;
        import nape.shape.Polygon;
        import nape.space.Space;
        import nape.util.BitmapDebug;

        [SWF(backgroundColor="#333333", frameRate="60", width="640", height="480")]    
        public class MainDemo extends Sprite 
        {
            private var space:Space = new Space(new Vec2(0,0));//无重力空间

            private var debug:BitmapDebug = new BitmapDebug(640480, 0x000000, true);

            private var wallType:CbType=new CbType();//墙类型
            private var ballType:CbType=new CbType();//球类型

            private var ball:Body;

            public function MainDemo():void 
            {
                addChild(debug.display);

                ball = addCircle();

                addWall(320,0,640,10);
                addWall(320,480,640,10);
                addWall(0,240,10,480);
                addWall(640,240,10,480);

                addEventListener(Event.ENTER_FRAME, enterFrameHandler);
            }

            private function addCircle():Body 
            {
                var circle:Circle = new Circle(10);
                    circle.material.elasticity = 1;//弹性系数设到最大
                    circle.material.staticFriction = 0;//所有摩擦力为0
                    circle.material.dynamicFriction = 0;
                    circle.material.rollingFriction = 0;

                var napeBody:Body = new Body(BodyType.DYNAMIC, new Vec2(300300));
                    napeBody.cbTypes.add(ballType);                    
                    napeBody.shapes.add(circle);
                    napeBody.space = space;                
                    napeBody.velocity = new Vec2(400 , 400);//给它一个初始速度

                return napeBody;
            }

            private function addWall(pX:Number,pY:Number,w:Number,h:Number):void 
            {
                var polygon:Polygon = new Polygon(Polygon.box(w,h));
                    polygon.material.elasticity = 1;//弹性系数设到最大
                    polygon.material.staticFriction = 0;//所有摩擦力为0
                    polygon.material.dynamicFriction = 0;
                    polygon.material.rollingFriction = 0;

                var napeBody:Body = new Body(BodyType.STATIC,new Vec2(pX,pY));
                    napeBody.cbTypes.add(wallType);
                    napeBody.shapes.add(polygon);
                    napeBody.space = space;
            }

            private function enterFrameHandler(e:Event):void 
            {
                space.step(1/60);

                /*
                ///////////////////////
                //如果没有以下 5 行代码,速度就会越变越小
                var circleSpeed:Number = 500;
                var velocity:Vec2 = ball.velocity;
                var speed:Number = velocity.length;
                var ratio:Number = circleSpeed/speed;
                ball.velocity.muleq(ratio);
                ///////////////////////
                */


                trace(ball.velocity.length);//输出速率大小

                debug.clear();
                debug.draw(space);
                debug.flush();
            }

        }

    }

    使用了最后一段注释掉的代码之后,其实也可以设定更小的弹性系数,比如 elasticity 值为 0.5,它仍然可以保持恒定的速率(但从外部动态的修改刚体的速率这会让我觉的很不科学的样子 - -!)。

    May

    5

    认识 Nape 三种刚体的类型

    • 0 Comments
    • Flash Platform

    如果不认识这三种刚体类型的特性,会遇到不少奇葩的问题。

    1、A static body - once assigned to a Space - is fixed; it cannot be moved or rotated, or have Shapes removed from it; a static body has no velocity. We can, however, perform mutations such as changing the shape materials.

    静态刚体:在添加到空间之前,就要确定好它的位置,否则一旦添加之后就不再允许改变位置,也不允许旋转之类的操作。如果对已经添加到空间的静态对象进行位置或旋转之类的操作,那么有可能会影响整个 Nape 空间的物理模似(亲测,碰撞检测真的失效了,不排除其它的物理特性也会失效)。但可以改变静态刚体的 Material 材质属性。所以一般很少用它,它用的最多的情况就是固定不变的对象模似,比如“地面”。

    2、A kinematic body is similar to a static body, except that it is permitted to have a velocity which will strictly define how the kinematic body moves. Such bodies will not be effected by gravity or any constraints including contacts. You can think of kinematic bodies as being animated.

    运动刚体:它和静态刚体类似,但允许设置它的速率,可以让它产生位置之类的变化。它不会受到物理模似的影响,比如重力、浮力或碰撞等。纯粹可以把这种类型的刚体当成动画对象。所以一般也很少用它。

    3、A dynamic body is under control of the physics simulation, it will fall under gravity, be pulled at by constraints and be effected by collisions and buoyancy forces.

    动态刚体:用的最多的就是这种类型,它是刚体的默认参数类型,它会受所有物理模似的影响,比如重力,浮力,弹力,拉力,碰撞等神马神马的一切。因为要参与物理模似,所以这个对象要有质量,如果质量为 0,那么它就不会参与任何物理模似,包括位置和速度的模似。

    May

    2

    Nape 刚体对象的旋转角度单位

    • 0 Comments
    • Flash Platform

    Nape 对象旋转使用“弧度”为单位,传统显示对象使用“度”为单位。

    graphic.rotation =(body.rotation*180/Math.PI)%360;

    而 Starling 中的显示对象又用了“弧度”为单位,不需要经过计算 - -!!

    Apr

    27

    对 Nape 对象受到冲量后限速

    • 0 Comments
    • Flash Platform

    以小球刚体为例,受到一个极大的冲量,向上飞起,可能就需要过个十几二十秒后才掉落下来,回到屏幕,这往往不是我们想要的效果。

    //判断是否向上运动
    if(smallBall.velocity.y < 0)
    {
        //判断它的速率合成后是否大于100
        if(smallBall.velocity.length > 100)
        {
            smallBall.velocity.x /= 1.05;
            smallBall.velocity.y /= 1.05
        }
    }

    Apr

    26

    比如用鼠标拖动一个小球之后,因为惯性等物理属性,小球并不会立刻停止,如果想让它立刻停止可以这么写:

    //一般一个刚体都会深到重力作用,所以在综合力上加一个与重力相反的力
    ball.force.set(space.gravity.mul(- ball.gravMass,true));

    ball.position.setxy(xxxxx, yyyyyy);//设置刚体的坐标
    ball.rotation = 0;//重置角度
    ball.angularVel = 0;//重置旋转
    ball.velocity = new Vec2(0, 0);//将速度设为0

    Apr

    26

    计算机的术语翻译过来后总是会让人觉的很蹩脚,要找个合适的中文词其实还真不容易。 最近看 Nape 的资料,用白话文来解释一下这个 step() 方法的三个参数,因为觉的网上的说明翻译过来好像都有些问题。
     
    首先,Flash 影片和其它的影片没有什么不同,都是连续的帧画面模似运行的(动态的)一个过程,但帧与帧之间会有时间间隔,这个做过 Flash 开发的应该没有什么疑问。
     
    那么先来说说 step() 方法里面的后面两个参数 velocityIterations 与 positionIterations,它们的字面意思分别是“速度迭代次数”与“位置迭代次数”。它表示在同一时间,对于物体与物体相撞时会产生速度与位置的变化的计算,如果仅仅只是两个物体之间的碰撞就很简单,但如果有第三个、第四个物体同时碰撞,那么它们之间都会有相互影响,会影响到前两个物体的速度与位置的变化,所以需要多次计算这个结果(迭代计算),让它的速度与位置变的更加精确。所以这两个参数实际上是会影响整体运行的性能,值设的越大,越精确,但同时也会越占 CPU,所以官方推荐值是10 就可以了,没必要设的很大。
     
    接着再说第一个参数:deltatime,这个参数比较有意思,粗一看字面意思是“时间增量”,但它实际上完全不是这个概念,它正确的意思是“每次被迭代时的增量”,这个值越大,每次迭代计算时的增量越大,值越小,增量就越小,这个参数值的大小实际上不会影响整体运行的性能(它对性能的影响是微乎其微的)。
     
    对于这第一个参数 deltatime 可以用一个很简单的 Demo 验证一下,创建一个重力参数为 new Vec2(0,600) 的 Space ,然后将舞台的 frameRate 设为 1(每秒只播放一个画面),然后创建一个小球将坐标放在舞台的最中间上面,让它做自由落体运动。如果这个参数值分别设为 1/120, 1/90, 1/60, 1/30,1/10,1,会发现这个值越靠近1,值越大,它的每一次跌代计算后的增量会越大,1 的时候增量就是瞬间完成,而值越小的时候它每一步增量越小。所以不要从字面去理解这个参数,它不是时间增量的概念,不是指多少时间或多少毫秒后进行一次跌代计算,而是指每一次进行迭代计算时增量的大小(它更类似于一个增量系数,影响增量的相对大小)。

    Apr

    21

    这些坑集只是本人在使用时遇到的,不代表全部

    1、实例命名时不要包含字符串“instance”,否则就无法通过 getChildByName() 去获取对象。

    2、MC 在导出时时间轴上的声音是不支持的(至少现在的版本不支持)。

    3、如果调用同一个 MC 连续调用两次 gotoAndStop ,第一次如果传入 stopChild 参数都为 true ,那么第二次的参数改为 false 也不会自动播放子影片的,需要调用子影片的 play() 方法。

    4、MC 对象需要先 gotoAndStop(0),否则有可能读不到它的宽、高值(因为默认它的播放头在 -1 的位置)。

    5、MC 对象时间轴上创建的所有可视化元素会在播放头进入下一帧时还原,并不会因为动态的 AS 修改后一直保持修改后的效果。

    6、MC 嵌套 MC 的时候,如果子 MC 对象没有被播放,在 play() 方法第一个参数中传入true,或gotoAndPlay() 方法第二个参数中传入 true。

    More...