2011-12-23 52 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

相關問題