如何改善我的2D碰撞检测系统? [英] how to improve my 2D collision detection system?

查看:97
本文介绍了如何改善我的2D碰撞检测系统?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,我是2006年开始在VB .NET上编写程序的,读过Jim Buyens的书《更快,更聪明的入门编程》,那是我编程的唯一技能,所以我可以这么说我是写程序的新手.我的梦想是制作自己的游戏,我在网上搜索了一个简单的碰撞检测系统,但发现的全部是检测2到3个或最多10个对象之间的碰撞",这非常简单,因为其中很少对象,我们确切地知道它们有多少.没有什么比在多个对象之间进行冲突检测"更重要的了,因此我使用以下逻辑使自己成为一个:我创建了一个字符串数组,该数组的大小等于组成游乐场的像素数-如果我的游乐场是9000 x 9000,则该数组就是这样的:strWorldArr(81000000)-数组中的每个元素表示运动场的单个像素,并且在运动场上移动的所有对象均使用其坐标来定位数组元素(表示其下方的像素),从而在数组的元素中填充其名称.这是我的碰撞检测系统主要部分的代码:

< REM> REM:如果移动的对象存在的数组元素的值是干净的,则在移动对象之前检查像素:
     函数CleanChecker(ByVal panHero作为HeroBody,ByVal szeSize作为大小,_
         ; . ;     ByVal intCycle As Integer)
            Dim intCount As Integer = 0
        对于i = 0要进行intCycle
              对于e = intStartPos至intEndPos
                    如果strWorldArr(e)<> panHero.Name和strWorldArr(e)<> †"然后
                           intCount + = 1
                    如果结束
              下一步
                  intStartPos + = szeSize.Width
                 intEndPos + = szeSize.Width
          下一步
           返回intCount
  结束功能

      REM:此子例程在对象后面清洁或填充它的新位置:
      Sub CleanOrFill(ByVal panHero作为HeroBody,ByVal strChar作为字符串,_n
;             &b ;                      对于i = 0要进行intCycle
              对于e = intStartPos至intEndPos
                     strWorldArr(e)= strChar
                下一步
                  intStartPos + = szeSize.Width
                 intEndPos + = szeSize.Width
          下一步
     结束子

      REM:此子例程是调用CleanChecker和CleanOrFill来检测碰撞的4个子例程之一:   私人Sub mUP(ByVal panHero作为HeroBody,ByVal szeSize作为大小,_
                      Dim intChkStart As Integer = panHero.Left + intStartNum(panHero.Top-intObjSpeed)
         Dim intChkEnd As Integer = intChkStart + panHero.Width
         Dim intCleanStart As Integer = panHero.Left + intStartNum(panHero.Bottom-intObjSpeed)
         Dim intCleanEnd As Integer = intCleanStart + panHero.Width

        如果CleanChecker(panHero,szeSize,intChkStart,intChkEnd,intObjSpeed)> = intTolerance然后
            REM:路径被阻止
        其他
               REM:路径可以通过
               panHero.Top-= intObjSpeed
               CleanOrFill(panHero,panHero.Name,szeSize,intChkStart,intChkEnd,intObjSpeed)
                                                                    CleanOrFill(panHero,†",szeSize,intCleanStart,intCleanEnd,intObjSpeed)
                                                           如果结束
      End Sub</pre>

要将此代码传递给我使用的所有对象,每个对象都使用For Each ... Next语句.
在core2 duo CPU 2GHz 4mb l2高速缓存和2GB RAM上,该系统可以平滑地支持多达100个对象,在intel Pentium4 1800 MHz 512 kb l2高速缓存和1GB RAM上,该系统运行非常差,以至于
甚至不能正常移动一个物体.
我认为这段代码非常简单,为什么要花这么多功率才能运行?这种缓慢的计算与编程语言-Visual Basic 2008-.NET Framework 3.5有关系吗?反正有什么办法可以改善该系统的碰撞检测性能,或者该项目注定要失败?
对不起,我的英语不好,谢谢您.

< div class ="ForumMod">于2009年3月18日星期三,10:39 AM</div>

Hi everyone,
I started writing programs on VB .NET in the year of 2006, reading Jim Buyens book "Faster Smarter Beginning Programming" and that''s only skill I got in programming, so I could say that I''m new in writing programs. My dream was to make my own game, I searched the net to find a simple collision detect system, but all I found was "detecting collisions between 2 or three, or maximum 10 objects" which is pretty simple because there is very small count of objects and we know exactly how much they are. There was nothing like "collision detect between various number of objects", so I''ve made myself one using the following logic:
   I''ve created a string array which size is equal to the count of the pixels that the playground is made of - if my playground is 9000 x 9000 then the array is something like this: strWorldArr(81000000) - each element in the array represents a single pixel of the playground and all objects that move on the playground fill their name in the elements of the array using their coordinates to locate the elements of the array which represents the pixels beneath them. Here is the code of the main part of my collision detect system:

<pre>REM: checking the pixels before moving the object if the values of the array elements which they present are clean then its good to go:
      Function CleanChecker(ByVal panHero As HeroBody, ByVal szeSize As Size, _
                              ByVal intStartPos As Integer, ByVal intEndPos As Integer, _
                              ByVal intCycle As Integer)
            Dim intCount As Integer = 0
            For i = 0 To intCycle
                  For e = intStartPos To intEndPos
                        If strWorldArr(e) <> panHero.Name And strWorldArr(e) <> "†" Then
                              intCount += 1
                        End If
                  Next
                  intStartPos += szeSize.Width
                  intEndPos += szeSize.Width
            Next
            Return intCount
      End Function

      REM: this subroutine cleans behind the object, or fills it''s new positions:
      Sub CleanOrFill(ByVal panHero As HeroBody, ByVal strChar As String, _
                              ByVal szeSize As Size, ByVal intStartPos As Integer, _
                              ByVal intEndPos As Integer, ByVal intCycle As Integer)
            For i = 0 To intCycle
                  For e = intStartPos To intEndPos
                        strWorldArr(e) = strChar
                  Next
                  intStartPos += szeSize.Width
                  intEndPos += szeSize.Width
            Next
      End Sub

      REM: this subroutine is one of 4 which call the CleanChecker and CleanOrFill to detect a collision:
      Private Sub mUP(ByVal panHero As HeroBody, ByVal szeSize As Size, _
                              ByVal intObjSpeed As Integer, ByVal intTolerance As Integer)

            Dim intChkStart As Integer = panHero.Left + intStartNum(panHero.Top - intObjSpeed)
            Dim intChkEnd As Integer = intChkStart + panHero.Width
            Dim intCleanStart As Integer = panHero.Left + intStartNum(panHero.Bottom - intObjSpeed)
            Dim intCleanEnd As Integer = intCleanStart + panHero.Width

            If CleanChecker(panHero, szeSize, intChkStart, intChkEnd, intObjSpeed) >= intTolerance Then
               REM: the path is blocked
            Else
               REM: the path is passable
                  panHero.Top -= intObjSpeed
                  CleanOrFill(panHero, panHero.Name, szeSize, intChkStart, intChkEnd, intObjSpeed)
                  CleanOrFill(panHero, "†", szeSize, intCleanStart, intCleanEnd, intObjSpeed)
            End If
      End Sub</pre>

To pass this code through all of the objects I use For Each... Next statement.
On core2 duo CPU 2GHz 4mb l2 cache and 2GB RAM this system can support smoothly up to 100
objects, on intel Pentium4 1800 MHz 512 kb l2 cache and 1GB RAM this system works so badly that it
can''t move even one object normally.
I think that this code is pretty simple, why it takes so much power to run? Is this slow calculation have
anything to do with the programming language - Visual Basic 2008 - .NET Framework 3.5? Is there anyway to
improve the collision detect performance of this system or this project is doomed?
Sorry for my bad english, and thank you in advance.

<div class="ForumMod">modified on Wednesday, March 18, 2009 10:39 AM</div>

推荐答案

成员3734843写道:
Member 3734843 wrote:

我认为这段代码非常简单,为什么要花这么多功率才能运行?

I think that this code is pretty simple, why it takes so much power to run?



好吧,由于.NET CLR下的String是不可变的(无法更改它们),因此,每次更改字符串时,您都在创建一个新的81 MEGABYTE字符串! [WTF]丢弃每个旧字符串,而不是在创建新字符串之前.将其乘以您更改字符串的次数,就很有可能创建了有史以来最糟糕的碰撞检测算法.




Well, since String''s under the .NET CLR are immutable (cannot change them), every time you make a change to a string you''re creating a new 81 MEGABYTE string! [WTF] Each old string is dropped, by not before the new one is created. Multiply that by the number of times you''re making a change to the string and you''ve quite possibly created the worst collision detection algorithm ever.


成员3734843写道:
Member 3734843 wrote:

这种缓慢的计算是否与编程语言-Visual Basic 2008-.NET Framework 3.5有关系?

Is this slow calculation have
anything to do with the programming language - Visual Basic 2008 - .NET Framework 3.5?



没有.我可以向您保证,性能问题完全在算法的设计中.




Nope. I can assure you, the performance problem is entirely in the design of your algorithm.


成员3734843写道:
Member 3734843 wrote:

无论如何,有没有要改善该系统的碰撞检测性能或该项目注定要失败?

Is there anyway to
improve the collision detect performance of this system or this project is doomed?



直到您完全重写检测算法以更有效地使用处理器,您就是项目

使用整数数组应可显着提高性能.完全刮取数组并比较对象与对象的边界会好得多,因为您不必每次增加1像素就可以与81000000像素进行比较.

这归结为代表您的对象更高效,更适合于更好的碰撞检测.的确,拿一本书或两本有关游戏编程的书.我真的无法在论坛帖子中解释如何做得更好.



Until you completely rewrite the detection algo to use the processor more efficiently, you''re project is doomed.

Using an array of integers should improve performance dramatically. Completely scraping the array and comparing the bounds of object to object would be far better since you don''t have to compare against 81000000 pixels every time you more something by 1 pixel.

It comes down to representing your objects more effificently and in a manner that lends itself to better collision detection. Really, pickup a book or two on game programming. I really can''t explain how to do something better in a forum post.


这篇关于如何改善我的2D碰撞检测系统?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆