2011-12-23 53 views
2

我已经在这里看到了很多类似的问题,但不幸的是他们中没有一个人似乎给出了我以后的确切答案,或者他们可能只是数学超出了我!如何用AS3将弹丸移动到鼠标x,y?

我正在创建一个游戏,在屏幕左边缘有一个大炮。我希望能够从大炮中弹出一个炮弹,以便它与鼠标指针在屏幕上相交。

我已经看过几个例子,它们将弧线从a点移动到b点,但是我需要的是让炮弹首先沿炮的轴线移动,如果球没有弹出以大炮指向的不同角度离开加农炮的末端。

作用在球上的唯一力将是重力,它是起始速度。另外,为了使事情复杂化,我需要根据鼠标指针离开加农炮的末端有多远来改变加农炮的角度,因此,如果指针远离加农炮指向上方的角度45度,但如果指针非常靠近大炮的末端,那么大炮会直接指向指针,这个我已经或多或少已经通过获得它们之间的距离,然后将它除以数字并从大炮的旋转值中减去它,但这是一个粗略的做法。

编辑 使用下面的代码我设法在下面的屏幕截图中的行。但你可以看到它不是我需要的轨迹,我需要的东西更像是红线,我插嘴说。

line

,这里是我是如何实现的代码(可能是错误地)

public class GameTurretLine2 
    { 
     var rt:Object = null; 
     var lineMc:MovieClip = new MovieClip(); 

     var myTurret:GameMainGun = null; 

     var pta:Point = new Point(0,0); 
     var ptb:Point = new Point(0,0); 
     var ptc:Point = new Point(0,0); 
     var ptd:Point = new Point(0,0); 

     public function GameTurretLine2(rt2,turret) 
     { 
      rt = rt2; 
      myTurret = turret; 

      lineMc.graphics.lineStyle(2, 0x55aa00); 

      mainLoop(); 

      rt.rt.GameLayers.turretLineMc.addChild(lineMc); 

     } 
     function mainLoop() 
     { 

      lineMc.graphics.clear(); 

      //get points 
      var turretEnd:Object = myTurret.rt.Useful.localToGlobalXY(myTurret.mC.turret.firePoint); 
      var turretStart:Object = myTurret.rt.Useful.localToGlobalXY(myTurret.mC.turret); 
      var mousePos:Point = new Point(myTurret.rt.rt.mouseX,myTurret.rt.rt.mouseY); 
      var inbetween:Point = new Point(0,0); 

      //start 
      pta.x = turretStart.newX; 
      pta.y = turretStart.newY; 

      //mouse end 
      ptd.x = mousePos.x; 
      ptd.y = mousePos.y; 

      // The cannon's angle: 
      // make the cannon's angle some inverse factor 
      // of the distance between the mouse and cannon tip 

      var dist:Number = myTurret.rt.Useful.getDistance(turretEnd.newX, turretEnd.newY, mousePos.x, mousePos.y); 
      var cAng:Number = dist * (180/Math.PI); 

      var ptbc:Point = new Point((ptd.x - pta.x) *.5,0); 
      ptbc.y = Math.tan(cAng) * ptbc.x; 

      //ptb = new Point(ptbc.x - ptbc.x * .15, ptbc.y); 
      ptb = new Point(turretEnd.newX, turretEnd.newY); 
      ptc = new Point(ptbc.x + ptbc.x * .5, ptbc.y); 

      // create the Bezier: 
      var bz:BezierSegment = new BezierSegment(pta,ptb,ptc,ptd); 
      trace(bz); 

      // define the distance between points that you want to draw 
      // has to be between 0 and 1. 
      var stepVal:Number = .1; 
      var curPt:Point = pta; 

      //draw circles 

      lineMc.graphics.drawCircle(pta.x, pta.y, 4); 
      lineMc.graphics.drawCircle(ptb.x, ptb.y, 4); 
      lineMc.graphics.drawCircle(ptc.x, ptc.y, 4); 
      lineMc.graphics.drawCircle(ptd.x, ptd.y, 4); 

      lineMc.graphics.lineStyle(2, 0x0000ff); 

      //step along the curve to draw it 
      for(var t:Number = 0;t < 1;t+=stepVal){ 
       lineMc.graphics.moveTo(curPt.x, curPt.y); 
       curPt = bz.getValue(t); 
       trace("curPt = " + curPt.x + "," + curPt.y); 
       lineMc.graphics.lineTo(curPt.x, curPt.y); 
      } 

      trace("pta = " + pta.x + "," + pta.y); 
      trace("ptb = " + ptb.x + "," + ptb.y); 
      trace("ptc = " + ptc.x + "," + ptc.y); 
      trace("ptd = " + ptd.x + "," + ptd.y); 


     } 
    } 

也出于一些奇怪的原因,由代​​码创建的行从屏幕截图中的图像翻转到缩进代码(y翻转),只需轻轻移动鼠标即可,以便移动鼠标线路无处不在。

回答

2

一种方法是创建贝塞尔曲线。

这听起来像是一种可行的解决方案,因为您基本上希望曲线始终适合某个三角形。如果这个三角形定义了贝塞尔曲线的控制点,那么可以使得该炮弹在重力作用下非常接近炮弹的弧线(这不是重力的完美表示)。这种方法的一个副作用是(倒置的)高度可以定义炮弹的力量。

您可以使用fl.motion.BezierSegment创建一条曲线并沿着它前进。这段代码粘贴到一个FLA:

import fl.motion.BezierSegment; 

var mySprite:Sprite = new Sprite(); 
addChild(mySprite); 
mySprite.graphics.lineStyle(2, 0x55aa00); 

// End point of the cannon: 
var pta:Point = new Point(0, 100); 
mySprite.graphics.drawCircle(pta.x, pta.y, 4); 
trace("pta = " + pta.x + "," + pta.y); 

// mouse point 
// var ptd:Point = new Point(mouseX, mouseY); 
// for testing: 
var ptd:Point = new Point(200,100); 
mySprite.graphics.drawCircle(ptd.x, ptd.y, 4); 
trace("ptd = " + ptd.x + "," + ptd.y); 

// The cannon's angle: 
// make the cannon's angle some inverse factor 
// of the distance between the mouse and cannon tip 
// var dx:Number = ptd.x-pta.x; 
// var dy:Number = ptd.y-pta.y; 
// var dist:Number = Math.sqrt(dx * dx + dy * dy); 
var cAng:Number = 30 * /(180/Math.PI); 

// point the cannon in the correct direction here, however you are intending to do that. 

// triangulate the cannon pt and mouse pt assuming the cannon's angle for both: 
// *** NOTE: for simplicity, this assumes a straight line on the x-plane. *** 
var ptbc:Point = new Point((ptd.x - pta.x) *.5,0); 
ptbc.y = Math.tan(cAng) * ptbc.x; 
trace("ptbc = " + ptbc.x + "," + ptbc.y); 

// to adjust the curve: 
var ptb:Point = new Point(ptbc.x - ptbc.x * .15, ptbc.y); 
var ptc:Point = new Point(ptbc.x + ptbc.x * .5, ptbc.y); 
mySprite.graphics.drawCircle(ptb.x, ptb.y, 4); 
mySprite.graphics.drawCircle(ptc.x, ptc.y, 4); 

// create the Bezier: 
var bz:BezierSegment = new BezierSegment(pta,ptb,ptc,ptd); 
trace(bz); 

// define the distance between points that you want to draw 
// has to be between 0 and 1. 
var stepVal:Number = .1; 
var curPt:Point = pta; 

mySprite.graphics.lineStyle(2, 0x0000ff); 

//step along the curve to draw it 
for(var t:Number = 0;t < 1;t+=stepVal){ 
    mySprite.graphics.moveTo(curPt.x, curPt.y); 
    curPt = bz.getValue(t); 
    trace("curPt = " + curPt.x + "," + curPt.y); 
    mySprite.graphics.lineTo(curPt.x, curPt.y); 
} 

mySprite.x = stage.stageWidth/2-mySprite.width/2; 
mySprite.y = stage.stageHeight/2-mySprite.height/2; 

原样,这个代码不直接连接鼠标,所以你将不得不使用自己的MouseEvent和AdjustCannonEvent运行这段代码。 (另外,请确保在代码中看到注释。)

+0

感谢您的帮助。我不太明白这一点 var ptbc:Point = new Point((ptd.x - pta.x)* .5,0); ptbc.y = Math.tan(cAng)* ptbc.x 你说的是假设一条直线,但鼠标指针可以在屏幕上的任何位置,因此,在终点炮点和鼠标指针x之间不存在角度,Y? – Phil 2011-12-23 19:03:32

+0

是的。但我的回答是阐述了曲线放置和曲线高度调整的基本思路。定义非x线性角度要复杂得多,尽管我认为这里有一些通用的解决方案。 – iND 2011-12-23 21:28:29

+0

另外请注意,炮弹应该从大炮尖端开始,而不是大炮的旋转点。您可以简单地旋转加农炮,在结尾选择一些点,然后使用localToGlobal()将其转换为对鼠标可用的位置。 – iND 2011-12-23 21:31:07

相关问题