Torque2D MIT 脚本阅读(3) CollisionToy

物理碰撞演示,主要演示了两种物体类型之间的碰撞交互,关键技术有碰撞体定义和碰撞回调.

代码片段

  碰撞边界划定:

function CollisionToy::createBackground( %this )
{    
    // 精灵创建
    %object = new Sprite();
    
    // 静态物体
    %object.BodyType = static;
       
    // 位置
    %object.Position = "0 0";

    // 尺寸
    %object.Size = "100 75";

    // 设置背景层,最远,最先绘制
    %object.SceneLayer = 31;
    
    // 设置图像资源
    %object.Image = "ToyAssets:highlightBackground";
    
    // 设置融合色
    %object.BlendColor = SlateGray;
    
    // 创建碰撞边界
    %object.createEdgeCollisionShape( -50, -37.5, -50, 37.5 );
    %object.createEdgeCollisionShape( 50, -37.5, 50, 37.5 );
    %object.createEdgeCollisionShape( -50, 37.5, 50, 37.5 );
    %object.createEdgeCollisionShape( -50, -34.5, 50, -34.5 );   
            
    // 加入场景
    SandboxScene.add( %object );        
}

  障碍物创建:

function CollisionToy::createBlockers( %this )
{
    // 批量创建障碍物
    for( %n = 0; %n < CollisionToy.MaxBlockers; %n++ )
    {
        // 随机尺寸
        %sizeX = getRandom(0.5, 10);
        %sizeY = 10 - %sizeX;
        
        // 创建
        %object = new Sprite();
        %object.BodyType = static;
        %object.Position = getRandom( -40, 40 ) SPC getRandom( -30, 30 );
        %object.Layer = 30;
        %object.Size = %sizeX SPC %sizeY;
        // 创建碰撞边界,默认时使用自身的尺寸
        %object.createPolygonBoxCollisionShape();
        %object.Image = "ToyAssets:Blocks";
        %object.Frame = getRandom(0,55);
        SandboxScene.add( %object );
    }
}

 创建动态碰撞体:

function CollisionToy::createBalls( %this )
{    
    // 批量创建碰撞球
    for( %n = 0; %n < CollisionToy.MaxBalls; %n++ )
    {
        // Create the sprite.
        %object = new Sprite()
        {
            // 设置Namespace,碰撞回调时需要确定方法的归属
            class = "CollisionToyBall";
        };
        
        %object.Position = getRandom(-30,30) SPC getRandom(-30,30);
        %object.Size = 3;
        %object.Layer = 20;

        // 设置碰撞回复系数
        %object.setDefaultRestitution( 1 );
        // 设置摩擦力系数
        %object.setDefaultFriction( 0.1 );
        // 创建环形碰撞边界.
        %object.createCircleCollisionShape( 1.5 );
        // 需要碰撞回调
        %object.CollisionCallback = true;
        
        %object.Image = "ToyAssets:Football";
        %object.Frame = 0;

        // 设置速度
        %object.SetLinearVelocity( getRandom(-40,40) SPC getRandom(-30,30) );
        %object.SetAngularVelocity( getRandom(-360,360) );    
            
        // Add the sprite to the scene.
        SandboxScene.add( %object );
    }
}

 碰撞通告:

function CollisionToyBall::onCollision(%this, %object, %collisionDetails)
{
    // 没有碰撞点返回(比如一方是传感器)
    if ( %collisionDetails.count <= 2 )
        return;

    // 获取碰撞点(碰撞点可能是2个,这里忽略)
    %contactPosition = %collisionDetails._4 SPC %collisionDetails._5;
    
    // 创建一个十字动画来标注碰撞点
    %object = new Sprite();
    //%object.BodyType = static;
    %object.Position = %contactPosition;
    %object.Layer = 10;   
    %object.Size = 3;
    %object.Image = "ToyAssets:Crosshair2";
    %object.BlendColor = LimeGreen;
    %object.AngularVelocity = -180;
    %object.Lifetime = 3;
    %object.PickingAllowed = false;
    SandboxScene.add( %object );
}

回调的实现

  在代码中我们没有看到如何设置碰撞回调的,下面需要说明一下:

     onCollision的写法是固定的,引擎会寻找这个方法,如果有就会调用,但是它怎么知道是要调用CollisionToyBall的方法呢?

  在Ball精灵创建的时候,我们设置了一个属性class,这个class在引擎中是simObject的属性变量mNamespace.

   // Namespace Linking.
   addGroup("Namespace Linking");
   addProtectedField("superclass", TypeString, Offset(mSuperClassName, SimObject), &setSuperClass, &defaultProtectedGetFn, &writeSuperclass, "Script SuperClass of object.");
   addProtectedField("class",      TypeString, Offset(mClassName,      SimObject), &setClass,      &defaultProtectedGetFn, &writeClass, "Script Class of object.");
   endGroup("Namespace Linking");

   在碰撞发布的时候:

if ( pSceneObjectA->isMethod("onCollision") )            
 {
     // Yes, so perform the script callback on it.
     Con::executef( pSceneObjectA, 3, "onCollision",
                    pSceneObjectBBuffer,
                    pMiscInfoBuffer );
 }

bool SimObject::isMethod( const char* methodName )
{
   if( !methodName || !methodName[0] )
      return false;

   StringTableEntry stname = StringTable->insert( methodName );

   if( getNamespace() )
      return ( getNamespace()->lookup( stname ) != NULL );

   return false;
}

 因此它能够找到上面CollisionToyBall::onCollision()的回调~

效果图:

原文地址:https://www.cnblogs.com/KevinYuen/p/2944966.html