2011-07-09 95 views
2

我想要一个可旋转的线,由箭头键控制。当你点击鼠标时,一个球从光标上落下,当它碰到线时停下来。AS3碰撞检测问题?

但是,球总是停在线的最高点,穿过平行于x轴的线。

我的文档类如下:

package 
{ 
    import flash.display.MovieClip; 
    import flash.events.* 
    import flash.display.Stage 
    import ball 

    public class Engine extends MovieClip 
    { 
     public static var stageRef:Stage 

     private static var leftKey:Boolean = false 
     private static var rightKey:Boolean = false 

     public static var pi = Math.PI 
     public static var lineRotate:Number = 0 
     public static var spinRate:Number = 60 

     public static var ground:line = new line() 

     public function Engine() 
     { 
      // constructor code 
      stage.addEventListener(Event.ENTER_FRAME, loop) 
      stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler) 
      stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler) 
      stage.addEventListener(MouseEvent.CLICK, addBall) 

      stageRef = stage 

      ground.x = 300 
      ground.y = 200 

      stage.addChild(ground) 
     } 

     private static function keyDownHandler(e:KeyboardEvent) 
     { 
      if (e.keyCode == 37) //left 
      { 
       leftKey = true 
      } 

      if (e.keyCode == 39) 
      { 
       rightKey = true 
      } 
     } 

     private static function keyUpHandler(e:KeyboardEvent) 
     { 
      if (e.keyCode == 37) //left 
      { 
       leftKey = false 
      } 

      if (e.keyCode == 39) //right 
      { 
       rightKey = false 
      } 
     } 

     public function loop(e:Event) 
     { 
      spin() 
     } 

     public static function addBall(e:MouseEvent) //adds ball 
     { 
      var tempBall:ball = new ball() 

      tempBall.x = e.stageX 
      tempBall.y = e.stageY 

      stageRef.addChild(tempBall) 
     } 

     private static function spin() //spins the "ground" line 
     { 
      if (leftKey) // minus 
      { 
       lineRotate -= spinRate 
      } 

      if (rightKey) // plus 
      { 
       lineRotate += spinRate 
      } 

      ground.rotation = lineRotate * (pi/180) //convert to radians 
     } 
    } 
} 

对球的类如下:

package 
{ 
    import flash.display.MovieClip; 
    import flash.events.* 

    public class ball extends MovieClip 
    { 
     public var vX:Number = 0 
     public var vY:Number = 2 

     private var gravity:Number = 0 
     public function ball() 
     { 
      // constructor code 
      addEventListener(Event.ENTER_FRAME, loop) 
     } 

     public function loop(e:Event) 
     { 
      this.x += vX 
      this.y += vY 

      this.vY += gravity 

      if (this.x > stage.stageWidth || this.x < 0 || this.y < 0 || this.y > stage.stageHeight) 
      { 
       removeSelf() 
      } 

      if (Engine.ground.hitTestObject(this)) 
      { 
       trace('yep') 
       stopBall() 

      } 
      else 
      { 
       trace('nope') 
      } 
     } 

     public function removeSelf() 
     { 
      removeEventListener(Event.ENTER_FRAME, loop) 
      this.parent.removeChild(this) 
     } 

     public function stopBall() 
     { 
      gravity = 0 
      vY = 0 
      vX = 0 
     } 
    } 
} 

我已经上传到瑞士法郎here.

回答

2

你可以做的最简单的事情,对于球是一个hitTestPoint与第三个参数为真,打开形状检测。

ground.hitTestPoint(x,y,true);

http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/DisplayObject.html#hitTestPoint()

好了,所以,嗯,你可以在球上签了单点,像它的底点,或者你可以检查点沿着球底部的阵列,方便精确。如果你没有制定更复杂的计划,这是最快捷的方法。但是,如果您想创建一个完整的有形的游戏,请将其留给像http://www.box2dflash.org/这样的二维物理库。

忘记一个更大的游戏skinner碰撞检测(像这样的小东西可以生存下来,虽然),因为它是位图的基础上,会杀死性能更box2D,这是一个很好的面具的例子,但它不是一个好主意用于性能方面的原因。

我已经改变了你的代码。我已经在球的底部击出了一堆点,记住球在动画片中的0,0是以球中心为中心。

package 
{ 
    import flash.display.MovieClip; 
    import flash.events.*; 
    import flash.geom.Point; 

    public class ball extends MovieClip 
    { 
     public var vX:Number = 0; 
     public var vY:Number = 2; 

     private var gravity:Number = 0; 
     public function ball() 
     { 
      // constructor code 
      addEventListener(Event.ENTER_FRAME, loop); 
     } 

     public function loop(e:Event) 
     { 
      this.x += vX; 
      this.y += vY; 

      this.vY += gravity; 

      if (this.x > stage.stageWidth || this.x < 0 || this.y < 0 || this.y > stage.stageHeight) 
      { 
       removeSelf(); 
      } 

      /*we will now check something like 18 points on the bottom side of the ball for colision 
      instead of just the bottom, you can probably guess why... if you cant, replace i on line 
      43 (var angleInRadians...) with 270 to test and then drop balls on a slopped ground surface... of course 
      you should definitely juse a physics engine like http://www.box2dflash.org/ for anything more complex. 
      */ 
      for (var i:int = 180; i<=360; i+=10) 
      { 
       /*keep in mind that ball.rotation property has 0 at the top of the ball, while here for these we are using the standard 
       Cartesian coordinate system. The effect of this on rotation would be that it is +90 and for X(yes, X) it would be Math.SIN(), 
       not Math.COS()!!!, and for Y it would be Math.sin() with a minus in front because of the flash coordinate system y axis rotation. 
       It's not really related to this, but it's a point that has anoyed me to no end in trig related stuff in flash when I was starting. 
       */ 
       var angleInRadians:Number = i/180 * Math.PI; 
       var posX:Number = this.x + Math.round(Math.cos(angleInRadians) * width/2); 
       var posY:Number = this.y - Math.round(Math.sin(angleInRadians) * height/2);//minus because y in flash is upside down 
       Engine.ground.hitTestPoint(posX,posY, true); 

       if (Engine.ground.hitTestPoint(posX,posY, true)) 
       { 
        stopBall(); 
       } 
       else 
       { 
       } 
      } 
      /*if (Engine.ground.hitTestObject(this)) 
         { 
          trace('yep') 
          stopBall() 

         } 
         else 
         { 
          trace('nope') 
         }*/ 
     } 

     public function removeSelf() 
     { 
      removeEventListener(Event.ENTER_FRAME, loop); 
      this.parent.removeChild(this); 
     } 

     public function stopBall() 
     { 
      gravity = 0; 
      vY = 0; 
      vX = 0; 
     } 
    } 
} 

与上述无关,您需要重新考虑一下您的面向对象,您做的事情有点错误:)。这个小的项目可以应付,但更大的项目会让你头疼。不要把它当作攻击,我想试着引导你走向“正确”的道路,并向你展示你的代码中的逻辑谬误,我不会提到这个“闯入”你会导致你的代码错误:)。

例如,重力,班级内的球?哎呀......如果你想忍受忍者,怪兽,布娃娃等的重力呢?你打算把Ninjas从球类中分出来吗?

忍者延伸球?这应该很有趣。

你认为那可能是一个更好的地方引力的东西? “引力”根本就是球的一种属性(也许,事实上,它不过是这样,但不是你把这种均匀的引力放在这里,它更像是一个渗透的,所有现在的东西,因为有一个巨大的身体,我们离得太近了)?它应该是在发动机...

此外,您也Engine.ground的事情......现在,这是一个静态变量...这又是一个坏事情,很糟糕的事情:)

的原因与前面的例子类似,但稍微转了一下。如果你想在内部重复使用球,那么说Engine2?还是Crytek引擎?或UDK?我认为这可能是有问题的,你不觉得吗?你将不得不去和改变球类......试想一下,如果所有的代码,你用过强迫你这样做...

基本上,你大概可以做这样的事情:

VAR喇嘛:球=新球(地面);

这是更好的,更muuuch ......现在我们可以在Crytek的,UDK使用它,引擎2轻松...

从技术上讲,你想避免在你的代码的东西像这样的静态变量,想法被称为封装。这个想法是,你隐藏了与其它类无关的类的内部工作,或者不应该知道它。你需要知道的越少,你的课程越便携,可重复使用(yada yada)。 Engine.ground是一个巨大的封装断路器,因为球绝对不需要知道类引擎,它应该只涉及到地面本身的参考...

你会学习所有这些,模式编程,特别是哪些模式可以节省时间,哪些是令人震惊的,以及为什么(静态变量有它们的用途,但只用于超简单的东西,如果你知道它们是什么,就避免使用单例)。

http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming

对不起,我已经给您造成的头痛...

记住,使用物理引擎的更复杂的代码,不推倒重来(重用一切为了您的预测,对他们来说是好的/足够的)......测试这类东西很有趣,但其他人在你面前做得更好,除非你特别需要深入研究他们的领域,否则你不需要关心自己每一个细节。你可能正在尝试构建游戏/某些东西,而不是打扰牛顿动态...

HitTest对于简单的东西虽然很好,但是它接近于简单的......:)我们已经稍微进入了物理学,你可能会发现你很快需要一个更强大的解决方案...

所以一般来说,试着通过考虑你的类之间的封装和依赖关系来使你的代码“健壮”。如果依赖感觉不自然(即球取决于引擎),那么某些东西可能是错误的,并且会在稍后中断,将打破另一个游戏或引擎或...我会在此结束它...

保重玩的开心。

+0

雅,我明白你的意思与整个classng的东西。这最终会逐渐渗透到一个更大的游戏中,并且这样更有条理。我知道我只有一条线和球,所以我觉得把它们分类是一个不错的主意,因为所有的东西都是分开的。 谢谢反正!当我有第二个时,我会尝试你的建议... – Electriczap4

+0

当你意识到后果并且你不关心他们时,在事情发生的时候就可以破解它。从一开始,从正确的角度思考它仍然是一个好主意:)。你不需要单独的类,引擎可以接管你需要的东西。注意我没有关于发送一个引用到底的问题......这是否是一个好主意也是有争议的,但是对于这个代码来说它确实不重要,因为它的大小......按照逻辑来分组的东西是好的if它是为了达到目的,并不总是有一个“正确”的方式来做到这一点,虽然有快速和缓慢。玩的开心! – Neoraptor

+0

你的代码很好。它有一个小的不需要的依赖。我对此感到困扰,因为我知道当人们开始编程时,他们不知道这样的事情。我以为你是新人,所以我搞砸了你,因为我必须以艰难的方式学习它...... 2000-3000行的代码游戏让我头痛,因为我的依赖主要是愚蠢的。我大约在喊OOP。再加上所有的书籍和内容都没有提出这些简单的东西,我窃听你。事实上,我自己在那场比赛中学会了自己。成为程序员的10倍。这就是为什么我关注这个:) – Neoraptor

2

按照文章Collision detection methods: hit-test and hit-testobject alternatives,即由设计:

正如您所看到的,Flash使用边框 对象框 - 它需要 可能的最高点和最低点, 最左边和最右边的点以及 围绕它们绘制矩形。

作者提到了解决此限制的几种替代方法,例如使用hitTestPoint或Grant Skinner的基于形状的碰撞检测。

+1

链接到gSkinner的博客的源代码和示例:http://gskinner.com/blog/archives/2005/10/source_code_sha.html –