如何使用AS3将弧形弹丸移动到鼠标x,y?

时间:2011-12-23 01:55:18

标签: actionscript-3

我在这里已经阅读了很多类似的问题,但不幸的是,他们似乎没有给出我所追求的确切答案,或者他们可能但数学超出了我的范围!

我正在创建一个游戏,你在屏幕的左边有一门大炮。我希望能够以弧形从大炮发射炮弹,使其与鼠标指针在屏幕上的位置相交。

我已经看过几个例子,它们将一个弧形射弹从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翻转)只需移动鼠标一小部分,所以当你移动鼠标时跳到处都是。

1 个答案:

答案 0 :(得分:2)

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

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

您可以使用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来运行此代码。 (另外,请务必查看代码中的注释。)