1

如何跟踪和使用初始化时旋转的对象的坐标?

假设我有一把剑放在 Main init() 的舞台上;并旋转(调整),使其与角色视角一起看起来不错。然而,在另一堂课中,我正在让剑在按键计时器事件上旋转更多,以创建“摆动”动画。

所有这些都是通过 flashdevelop 完成的。我只使用 CS6 来创建符号。随着这种“摆动”的发生,我想在剑尖上添加另一个符号,它是一个碰撞点对象。它在摆动开始时被添加到舞台上,并在每次摆动后被移除。我希望这个对象跟随剑的尖端,但似乎我只能实现它跟随原始剑对象的坐标,好像我最初没有修改所述剑的旋转。我尝试实现 GlobalToLocal() 和 LocalToGlobal() 方法,但我认为我不完全理解发生了什么。

我希望我对我正在尝试做的事情足够清楚。谢谢你。这是有问题的相关代码。代码与我尝试上述两种方法之前一样,目前的问题与之前描述的完全一样。我想要这些方法中的任何一种还是我只是做错了什么?

主要初始化:

sword = new Sword();

sword.x = 53;
sword.y = 90;
addChild(sword);
sword.rotationZ = -150;
sword.rotationY = 25;
sword.rotationX = -15;

Coll_Point = new coll_point();

处理摆动的类有这样一个方法:

private function SwingTime(event:Event):void
{
    Main.Coll_Point.x = Main.sword.x + Main.sword.width;
    Main.Coll_Point.y = Main.sword.y + Main.sword.height;
    Main.MazeNr1.addChild(Main.Coll_Point);

    if (Main.sword.rotationZ > -330)
    Main.sword.rotationZ -= 20;

    if (Main.sword.rotationX < 15)
    Main.sword.rotationX += 10;

    if ((Main.sword.rotationZ == -330) && (Main.sword.rotationX == 15))
    {
        SwingTimer.stop();
        SwingBckTimer.start();
    }
}

编辑: 更全面的代码版本:

public class Main extends MovieClip 
{
    public static var from_point:Point = null;
    public static var to_point:Point = new Point();
    public function Main():void
    {
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);
    }

    // Puts everything on the stage here.
    private function init(e:Event = null):void
    {
    removeEventListener(Event.ADDED_TO_STAGE, init);
        PlayerInst = new Dorf();
        PlayerInst.x = 45;
        PlayerInst.y = 51;
        addChild(PlayerInst);

        sword = new Sword();
        sword.x = 53;
        sword.y = 90;
        sword.rotationZ = -150;
        sword.rotationY = 25;
        sword.rotationX = -15;
        from_point = new Point (Main.sword.width, Main.sword.height);
        to_point = sword.localToGlobal(from_point);
        addChild(sword);
        swordBD = new BitmapData(32, 32, true, 0x0000000000);
        swordBD.draw(sword);

        Coll_Point = new coll_point();
        Coll_PointBD = new BitmapData(2, 2, true, 0x0000000000);
        Coll_PointBD.draw(Coll_Point);
    }
}

这就是 Main 的样子,实际上每个对象实例都以这种方式添加到舞台上。包括碰撞点、背景、字符、视线半径的渐变填充等。相关的符号类大概是这样的:

public class Creature extends MovieClip 
{
    protected var Swing:Boolean;
    private var SwingTimer:Timer = new Timer (5, 0);
    private var SwingBckTimer:Timer = new Timer (150, 1);
// Constructor.
    public function Creature()
    {
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);
    }

    // Initializer.
    private function init(event:Event = null):void
    {
        removeEventListener(Event.ADDED_TO_STAGE, init);

        SwingTimer.addEventListener(TimerEvent.TIMER, SwingTime);
        SwingBckTimer.addEventListener(TimerEvent.TIMER, SwingBack);
    }
private function SwingAction():void
    {
        if (Swing == true)
        {
            SwingTimer.start();
        }
    }

    private function SwingTime(event:Event):void
    {
        Main.Coll_Point.x = Main.sword.localToGlobal(Main.from_point).x;
        Main.Coll_Point.y = Main.sword.localToGlobal(Main.from_point).y;
        Main.sword.addChild(Main.Coll_Point);
        trace(Main.Coll_Point.x);
        trace(Main.Coll_Point.y);

        if (Main.sword.rotationZ > -330)
        Main.sword.rotationZ -= 20;

        if (Main.sword.rotationX < 15)
        Main.sword.rotationX += 10;

        if ((Main.sword.rotationZ == -330) && (Main.sword.rotationX == 15))
        {
            SwingTimer.stop();
            SwingBckTimer.start();
        }
    }

    private function SwingBack(event:Event):void
    {
        Main.sword.rotationZ = -150;
        Main.sword.rotationX = -15;
        //Main.MazeNr1.removeChild(Main.Coll_Point);
    }

还有一个相当长的 update(); 动画和移动每个需要移动的对象的函数。

4

2 回答 2

1

我想你的问题可能出在

    Main.Coll_Point.x = Main.sword.x + Main.sword.width;
    Main.Coll_Point.y = Main.sword.y + Main.sword.height;

Coll_Point 需要全局坐标。

仅当剑没有旋转以使高度与 y 轴对齐且宽度与 x 轴对齐时,这些部件才能按预期+ Main.sword.width工作。+ Main.sword.height

您应该在 ( )的本地位置上使用localToGlobal(Main.sword ) Main.sword.width, Main.sword.height来获取代表剑旋转尖端的全局位置,然后再将其添加为子级。



有两种方法可以解决这个问题(您似乎将两者结合起来)。你可以


  • 将 Coll_Point 作为子级添加到层次结构中剑之上的东西(Stage,MazeNr1,...),并在每次计时器回调时手动更新位置。您每次都必须重新计算位置,因此将localToGlobal()from init 带到您的计时器功能。如果没有被调用,它将不会更新。

为此,您应该在计时器回调中有这种代码:

var local:Point = new Point(Main.sword.width, Main.sword.height);
var global:Point = Main.sword.localToGlobal(local);
Main.Coll_Point.x = global.x;
Main.Coll_Point.y = global.y;



  • 将点作为孩子添加到剑上。这可能是一种更好的方法,因为位置会自动更新。我之前不记得的是,你然后以“本地”形式给出坐标,所以不要使用localToGlobal()

在您创建的地方运行一次Collision_Point

Coll_Point.x = <your x offset>;
Coll_Point.y = <your y offset>;
Main.sword.attachChild(Coll_Point);

而不是剑heightwidth你可能想尝试类似的东西-heightwidth/2



这是一个快速(而不是最漂亮)的图片来演示这个问题。局部空间随对象旋转:

在此处输入图像描述

于 2014-06-04T20:31:20.840 回答
1

我能想到的唯一能帮助您解决此问题的方法是让您的碰撞对象与剑具有相同的注册点。我的意思是方向点应该匹配,并且碰撞图形应该在精灵内部移动,以便它与剑顶部的位置匹配。

这样,您可以将碰撞对象放在剑的相同位置并应用相同的旋转。这样,它会随着剑的顶部移动,并且仍然让 hitTest 正常工作。

我无法想象任何其他方式来解决这个问题,因为任何代码都会获得界限和位置。但真正重要的是注册点和剑的顶端,这是一个图形的东西,不能用编码来处理。

我希望你能想象我的意思——如果现在,只要说出来,我会为你提供一张图片:)

于 2014-06-04T20:41:03.313 回答