Как переместить снаряд по дуге на мышь X, Y с AS3? - PullRequest
2 голосов
/ 23 декабря 2011

Я читал здесь несколько подобных вопросов, но, к сожалению, ни один из них, похоже, не дает точного ответа, который я ищу, или они могли бы, но математика за мной!

Я создаю игру, в которой у вас есть пушка по левому краю экрана. Я хочу иметь возможность стрелять из пушечного ядра по дуге так, чтобы оно пересекалось с указателем мыши на экране.

Я видел несколько примеров, которые перемещают снаряд по дуге из точки a в точку b, но мне нужно, чтобы пушечное ядро ​​сначала двигалось вдоль оси самой пушки, не будет хорошо, если мяч покинет конец пушки под другим углом, на который указывает пушка.

Единственной силой, действующей на шар, будет сила тяжести и начальная скорость.

Также, чтобы усложнить ситуацию, мне нужно изменить угол пушек в зависимости от того, насколько далеко указатель мыши находится от конца пушки, поэтому, если указатель находится далеко, чем пушка будет указывать вверх, скажем, под углом 45 градусов, но если указатель находится очень близко к концу пушки, то пушка будет указывать прямо на указатель, это я более или менее уже получил, просто получив расстояние между ними, а затем разделив его на число и вычесть это из значения вращения пушки, но это немного грубый способ сделать это.

EDIT Используя приведенный ниже код, я справился со строкой на скриншоте ниже. Но, как вы видите, мне нужна не та траектория, мне нужно нечто большее, чем красная линия, которую я вставил.

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 Ответ

2 голосов
/ 23 декабря 2011

Один из способов - создать кривую Безье.

Это звучит как работоспособное решение, потому что вы, по сути, хотите, чтобы кривая всегда помещалась под каким-то треугольником.Если этот треугольник определяет контрольные точки для кривой Безье, вы можете сделать так, чтобы они очень близко соответствовали дуге пушечного ядра под действием силы тяжести (это не идеальное представление о гравитации).Одним из побочных эффектов этого метода является то, что (перевернутая) высота может определять силу пушечного ядра.

Вы можете использовать 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 для запуска этого кода.(Также обязательно обратите внимание на примечание в коде.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...