• 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()的回调~

    效果图:

  • 相关阅读:
    Java线程同步synchronized的理解
    MySQL基础操作(二)
    MySQL基础操作(一)
    MySQL备份--xtrabackup与mysqldump工具使用
    MySQL主从复制以及在本地环境搭建
    生活在长大——第一次冲刺小任务
    现代软件工程之敏捷开发
    入门github
    我的编程人生
    Java线程
  • 原文地址:https://www.cnblogs.com/KevinYuen/p/2944966.html
Copyright © 2020-2023  润新知