zoukankan      html  css  js  c++  java
  • [翻译]XNA外文博客文章精选之nine


    PS:自己翻译的,转载请著明出处

                                                                            与Platforms一起玩
                                      我恨碰撞检测教程。他们全都是相同的。他们解释的错综复杂,详细介绍两个对象如何发生了碰撞,但总是留给你来做些什么。我真的不关心马利奥的边框合是否改变了颜色,这不会去保持它站在地面上而是不下落。
                                      这不是一个碰撞检测的文章。它是一个碰撞响应的文章。这里我使马利奥站在地面上,当它撞到墙了就停止,在它向天花版跳跃时,让它碰撞到头。
                                      尽管这种文章很缺乏,它实际上非常简单去区分两个边框盒子,一旦你发现它们已经碰撞了。我将创建一个小的-platformer去证明它。如果你没有创建一个sideScroller,请不要烦恼,从代码中删除重力的部分,并且碰撞检测和响应只是对其他类型有关。
                                      获取样本在我们开始之前,因为我不会粘贴功能代码的巨大部分。WASD移动的玩家(非常不现实)。

    Getting Started
                                      一个bounding盒正是听起来那个样子。这个盒子它包围一个对象去定义它的边界。这里定义了Min点(左上角)和Max点(右下角)。

    1 (0,0- Min
    2  #########
    3  #########
    4  #########
    5  #########
    6  ######### (3232- Max

                                     现在你知道什么是bouding盒子了吧,是时候去谈下某些缺点了:Bounding盒子不是很完美的对象表示。它们通常太大或者太小去完美的封装一个对象。
                你有两个操作:
                1.接受这个对象将会被标记为碰撞,这一点都不清楚。
                2.减少bounding盒子的大小并且让你的精灵的一些象素被认为是"player leeway".
                                     第二是个不错的方法,因为它总是很好的裁减一些松懈的玩家,然后当一个透明的象素碰到另一个透明的象素时它们就会死。

    Collision Detection and Response(碰撞检测和响应)
                                     那么到底如何,我们如何区分两个bounding盒呢?第一步是找出他们实际上是否碰撞(我说谎,它不考虑碰撞检测)。第二部分是计算最少的数量,为了解决这个碰撞我们需要去取代一个对象。这是被称为minimum translation检测或者简称MTD。
                                     这看起来很难去理解,但是它摆在这里:

     1 // Thank you Microsoft for intellisense with a name like that. ;)
     2 public static Vector2 CalculateMinimumTranslationDistance(BoundingBox left, BoundingBox right)
     3 {
     4     // Our displacement result vector containing the translation (movement) information
     5     // that resolves our intersection.
     6     Vector2 result = Vector2.Zero;
     7     // This is re-used to calculate the difference in distance between sides.
     8     float difference = 0.0f;
     9     // This stores the absolute minimum distance we'll need to separate our colliding object.
    10     float minimumTranslationDistance = 0.0f;
    11     // Axis stores the value of X or Y.  X = 0, Y = 1.
    12     // Side stores the value of left (-1) or right (+1).
    13     // They're used later in calculating the result vector.
    14     int axis = 0, side = 0;
    15     // Left
    16     difference = left.Max.X - right.Min.X;
    17     if (difference < 0.0f)
    18     {
    19         return Vector2.Zero;
    20     }
    21     { 
    22         // These braces are superfluous but should make it more 
    23         //clear that they're similiar to the if statements below.
    24         minimumTranslationDistance = difference;
    25         axis = 0;
    26         side = -1;
    27     }
    28     // Right
    29     difference = right.Max.X - left.Min.X;
    30     if (difference < 0.0f)
    31     {
    32         return Vector2.Zero;
    33     }
    34     if (difference < minimumTranslationDistance)
    35     {
    36         minimumTranslationDistance = difference;
    37         axis = 0;
    38         side = 1;
    39     }
    40     // Down
    41     difference = left.Max.Y - right.Min.Y;
    42     if (difference < 0.0f)
    43     {
    44         return Vector2.Zero;
    45     }
    46     if (difference < minimumTranslationDistance)
    47     {
    48         minimumTranslationDistance = difference;
    49         axis = 1;
    50         side = -1;
    51     }
    52     // Up
    53     difference = right.Max.Y - left.Min.Y;
    54     if (difference < 0.0f)
    55     {
    56         return Vector2.Zero;
    57     }
    58     if (difference < minimumTranslationDistance)
    59     {
    60         minimumTranslationDistance = difference;
    61         axis = 1;
    62         side = 1;
    63     }
    64     // Intersection occurred:
    65     if (axis == 1// Y Axis
    66         result.Y = (float)side * minimumTranslationDistance;
    67     else // X Axis
    68         result.X = (float)side * minimumTranslationDistance;
    69     return result;
    70 }

                                     我们计算在一个bounding盒子的边靠着的另外bounding盒子的对边的距离。如果这个距离比0小,我们知道,这里决不会有盒子的互相接触。如果它是大于等于0,我们继续我们的测试。我们同样保存很小的距离作为我们的最终的MTD来使用。

                                     为了帮助准确的理解继续会发生什么,仔细看下两个盒子的图象。数字是它们的Min和Max位置。让我们从我们方法的If声明中用A的位置取代"左",用B的位置取代"右"。
    Check #1: difference = 64 - 32 = 32
    - Result: difference > 0, 有一个碰撞的可能,让我继续检查
    Check #2: difference = 96 - 0 = 96
    - Result: difference > 0, 有一个碰撞的可能,让我继续检查
    Check #3: difference = 64 - 32 = 32
    - Result: difference > 0, 有一个碰撞的可能,让我继续检查
    Check #4: difference = 96 - 0 = 96
    - Result: difference > 0, 如果我们仍在这里,那么有个明确的碰撞。
    现在我们知道了他们碰撞了,我们计算我们的MTD向量:

    1 Result = (0-1 * 32) or (0-32) [The -1 is taken from our "side" variable]

                                     简单的转换(移动)A的bounding盒子通过(0,-32)并且你会看见,碰撞已经被解决了。
                                     一点都不难,对吗?

    Wrapping Up(打包)
                                    现在我们知道如何去检查碰撞和(更重要的)解决它们,你已经生成了一个platformer。
                                    这个样例添加两个类,Entity和World。Entity接收一个bounding盒子和添加物理信息到它里面。World是造成这些实体的物理控制的原因。唯一的不平凡的代码是World.Update方法:

     1 public void Update(float deltaTime, float totalTime)
     2 {
     3     for (int i = 0; i < entities.Count; ++i)
     4     {
     5         // Add some gravity to their velocity.
     6         entities[i].Velocity += gravity * entities[i].Weight;
     7         // Move 'em.
     8         entities[i].Move(entities[i].Velocity * deltaTime);
     9         // Check for collisions.
    10         for (int j = 0; j < entities.Count; ++j)
    11         {
    12             if (entities[i] == entities[j])
    13                 continue;
    14             Vector2 displacement = BoundingBox.CalculateMinimumTranslationDistance(entities[i].BoundingBox, entities[j].BoundingBox);
    15             // Tell the entity that it's colliding with an object.
    16             if (displacement != Vector2.Zero)
    17             {
    18                 entities[i].OnCollision(entities[j], displacement);
    19             }
    20         }
    21     }
    22 }
                                   通过每一个实体简单的循环,添加重力,为碰撞移动并检查他们。这里你可以看见我们使用(非常详细)CalculateMinimumTranslationDistance()方法为这个第一次。我们支持向量,它计算这个Entity的OnCollision()方法,这个方法决定如何处理它。
                                   希望本文可以帮你解决你的碰撞响应痛苦,使你感觉容易点。请随时反馈,让我不断的更新,你可以对代码进行任何的更新。
    源代码:http://www.ziggyware.com/readarticle.php?article_id=134
    (完)
  • 相关阅读:
    java中eclipse控制台接受输入的方法
    java中Timer类的详细介绍(详解)
    java中Timer类的详细介绍(详解)
    java中Timer类的详细介绍(详解)
    java中Timer类的详细介绍(详解)
    java中ReentrantLock类的详细介绍(详解)
    java中ReentrantLock类的详细介绍(详解)
    java中ReentrantLock类的详细介绍(详解)
    java中ReentrantLock类的详细介绍(详解)
    Spring中WebApplicationInitializer的理解
  • 原文地址:https://www.cnblogs.com/315358525/p/1562601.html
Copyright © 2011-2022 走看看