首页 > 解决方案 > Flash Actionscript 2.0 localToGlobal 坐标问题

问题描述

我不知道这里是否有人足够大,可以记住 ActionScript 2.0,但不幸的是,我发现自己坚持使用它,因为我正在为(天际)编写 mod 的游戏仍然使用 AS2 作为 UI。

我正在为我的动画/补间使用 Greensock TweenLite/TimeLineLite,但我在一些简单的坐标计算方面遇到了困难。

我试图从它的起始位置为图标 A 设置动画,将其放大并在 x 和 y 中移动,并以与图标 B 完全相同的位置和大小完成。

图标 A 和图标 B 在不同的影片剪辑中,从一个共同的父剪辑向上两级,所以我尝试使用 localToGlobal 来获取每个图标的阶段 x/y,然后通过两组之间的差异移动 x/y舞台坐标。

例如:

Icon A Global x = 95
Icon B Global x = 150
Difference = 55

Icon A Local x + 55 应该放在与 Icon B 相同的 x 位置对吗?好吧,这与我在屏幕上的结果相去甚远,甚至没有接近。

为了帮助更好地可视化,这是小部件在游戏中的外观:

示例截图

这就是它在 CS6 中的样子:

Flash 工作区

因此,例如,我试图将 leftPreselectIcon(示例屏幕截图中的龙骨战斧)移动/缩放到 leftIcon(Firebolts 法杖)的确切位置。

以下是相关功能:

public function prepareForPreselectAnimation(): Void
{
    //This function checks if the preselect icons are to the left or right of their main icon and sets the animate out direction to the opposite side. It also stores current main icon x/y as the target values for the preselect icons to animate to. Finally it gets and stores all necessary current scale and alpha values to ensure everything returns to the exact state it was in prior to starting the animation
    
    var leftIconLTG:Object = {x:(leftIcon._height * 0.5), y:(leftIcon._width * 0.5)};
    var leftPreselectIconLTG:Object = {x:(leftPreselectIcon._height * 0.5), y:(leftPreselectIcon._width * 0.5)};
    var rightIconLTG:Object = {x:(rightIcon._height * 0.5), y:(rightIcon._width * 0.5)};
    var rightPreselectIconLTG:Object = {x:(rightPreselectIcon._height * 0.5), y:(rightPreselectIcon._width * 0.5)};
    var shoutIconLTG:Object = {x:(shoutIcon._height * 0.5), y:(shoutIcon._width * 0.5)};
    var shoutPreselectIconLTG:Object = {x:(shoutPreselectIcon._height * 0.5), y:(shoutPreselectIcon._width * 0.5)};

    leftIcon.localToGlobal(leftIconLTG);
    leftPreselectIcon.localToGlobal(leftPreselectIconLTG);
    rightIcon.localToGlobal(rightIconLTG);
    rightPreselectIcon.localToGlobal(rightPreselectIconLTG);
    shoutIcon.localToGlobal(shoutIconLTG);
    shoutPreselectIcon.localToGlobal(shoutPreselectIconLTG);

    skyui.util.Debug.log("leftIconLTG - x: " + leftIconLTG.x + ", y: " + leftIconLTG.y)
    skyui.util.Debug.log("leftPreselectIconLTG - x: " + leftPreselectIconLTG.x + ", y: " + leftPreselectIconLTG.y)

    if (leftIconLTG.x > leftPreselectIconLTG.x){
        leftTargetX = (leftIcon_mc._width) //If preselect icon is to the left of the main widget animate main widget out to right
        //leftPTargetX = (leftIconLTG.x - leftPreselectIconLTG.x) + (leftIcon._width / 2)
    } else {
        leftTargetX = -(leftIcon_mc._width) //If preselect icon is to the right of the main widget animate main widget out to left
        //leftPTargetX = (leftIconLTG.x - leftPreselectIconLTG.x) - (leftIcon._width)
    }
    leftPTargetX = (leftIconLTG.x - leftPreselectIconLTG.x)
    skyui.util.Debug.log("leftTargetX: " + leftTargetX + ", leftPTargetX: " + leftPTargetX)
    if (rightIconLTG.x > rightPreselectIconLTG.x){
        rightTargetX = (rightIcon_mc._width)
        //rightPTargetX = (rightIconLTG.x - rightPreselectIconLTG.x) + (rightIcon._width / 2)
    } else {
        rightTargetX = -(rightIcon_mc._width)
        //rightPTargetX = (rightIconLTG.x - rightPreselectIconLTG.x) - (rightIcon._width)
    }
    rightPTargetX = (rightIconLTG.x - rightPreselectIconLTG.x)
    if (shoutIconLTG.x > shoutPreselectIconLTG.x){
        shoutTargetX = (shoutIcon_mc._width)
        //shoutPTargetX = (shoutIconLTG.x - shoutPreselectIconLTG.x) + (shoutIcon._width / 2)
    } else {
        shoutTargetX = -(shoutIcon_mc._width)
        //shoutPTargetX = (shoutIconLTG.x - shoutPreselectIconLTG.x) - (shoutIcon._width)
    }
    shoutPTargetX = (shoutIconLTG.x - shoutPreselectIconLTG.x)
    
    leftPTargetY = leftIconLTG.y - leftPreselectIconLTG.y;
    skyui.util.Debug.log("leftPTargetY: " + leftPTargetY)
    rightPTargetY = rightIconLTG.y - rightPreselectIconLTG.y;
    shoutPTargetY = shoutIconLTG.y - shoutPreselectIconLTG.y;

    //Store current alpha and scale values ready to reapply
    leftIconAlpha = leftIcon_mc._alpha;
    leftTargetScale = ((leftIcon_mc._xscale / leftPreselectIcon_mc._xscale) * 100);
    //leftPTargetX = ((leftIconLTG.x - leftPreselectIconLTG.x) * (leftIcon_mc._xscale / leftPreselectIcon_mc._xscale));
    leftPIconAlpha = leftPreselectIcon_mc._alpha;
    leftPIconScale = leftPreselectIcon._xscale;
    rightIconAlpha = rightIcon_mc._alpha;
    rightTargetScale = ((rightIcon_mc._xscale / rightPreselectIcon_mc._xscale) * 100);
    rightPIconAlpha = rightPreselectIcon_mc._alpha;
    rightPIconScale = rightPreselectIcon._xscale;
    shoutIconAlpha = shoutIcon_mc._alpha;
    shoutTargetScale = ((shoutIcon_mc._xscale / shoutPreselectIcon_mc._xscale) * 100);
    shoutPIconAlpha = shoutPreselectIcon_mc._alpha;
    shoutPIconScale = shoutPreselectIcon._xscale;
    leftNameAlpha = leftName_mc._alpha;
    leftPNameAlpha = leftPreselectName_mc._alpha;
    rightNameAlpha = rightName_mc._alpha;
    rightPNameAlpha = rightPreselectName_mc._alpha;
    shoutNameAlpha = shoutName_mc._alpha;
    shoutPNameAlpha = shoutPreselectName_mc._alpha;

    skse.SendModEvent("iEquip_ReadyForPreselectAnimation", null);

}

public function equipPreselectedItem(iSlot: Number, currIcon: String, newIcon: String, newName: String, currPIcon: String, newPIcon: String, newPName: String): Void
{
    
    var iconClip: MovieClip;
    var iconClip_mc: MovieClip;
    var currIcon: String;
    var pIconClip: MovieClip;
    var pIconClip_mc: MovieClip;
    var currPIcon: String;
    var itemName_mc: MovieClip;
    var preselectName_mc: MovieClip;
    var targetX: Number;
    var pTargetX: Number;
    var pTargetY: Number;
    var pIconAlpha: Number;
    var pIconScale: Number;
    var pIconTargetScale: Number
    var iconAlpha: Number;
    var itemNameAlpha: Number;
    var preselectNameAlpha: Number;
    
    switch(iSlot) {
        case 0:
            iconClip = leftIcon;
            iconClip_mc = leftIcon_mc;
            pIconClip = leftPreselectIcon;
            pIconClip_mc = leftPreselectIcon_mc;
            itemName_mc = leftName_mc;
            preselectName_mc = leftPreselectName_mc;
            targetX = leftTargetX;
            pTargetX = leftPTargetX;
            pTargetY = leftPTargetY;
            pIconAlpha = leftPIconAlpha;
            pIconScale = leftPIconScale;
            iconAlpha = leftIconAlpha;
            pIconTargetScale = leftTargetScale;
            itemNameAlpha = leftNameAlpha;
            preselectNameAlpha = leftPNameAlpha;
            break
        case 1:
            iconClip = rightIcon;
            iconClip_mc = rightIcon_mc;
            pIconClip = rightPreselectIcon;
            pIconClip_mc = rightPreselectIcon_mc;
            itemName_mc = rightName_mc;
            preselectName_mc = rightPreselectName_mc;
            targetX = rightTargetX;
            pTargetX = rightPTargetX;
            pTargetY = rightPTargetY;
            pIconAlpha = rightPIconAlpha;
            pIconScale = rightPIconScale;
            iconAlpha = rightIconAlpha;
            pIconTargetScale = rightTargetScale;
            itemNameAlpha = rightNameAlpha;
            preselectNameAlpha = rightPNameAlpha;
            break
        case 2:
            iconClip = shoutIcon;
            iconClip_mc = shoutIcon_mc;
            pIconClip = shoutPreselectIcon;
            pIconClip_mc = shoutPreselectIcon_mc;
            itemName_mc = shoutName_mc;
            preselectName_mc = shoutPreselectName_mc;
            targetX = shoutTargetX;
            pTargetX = shoutPTargetX;
            pTargetY = shoutPTargetY;
            pIconAlpha = shoutPIconAlpha;
            pIconScale = shoutPIconScale;
            iconAlpha = shoutIconAlpha;
            pIconTargetScale = shoutTargetScale;
            itemNameAlpha = shoutNameAlpha;
            preselectNameAlpha = shoutPNameAlpha;
            break
        }
        
    var tempIcon: MovieClip = iconClip.duplicateMovieClip("tempIcon", this.getNextHighestDepth());
    tempIcon.gotoAndStop(currIcon);
    iconClip._alpha = 0;
    iconClip.gotoAndStop(newIcon);
    var tempPIcon: MovieClip = pIconClip.duplicateMovieClip("tempPIcon", this.getNextHighestDepth());
    //var iconLTG: Object = {x:(iconClip._width * 0.5), y:(iconClip._height * 0.5)}
    //iconClip.localToGlobal(iconLTG);
    //var tempPIconLTG: Object = {x:(tempPIcon._width * 0.5), y:(tempPIcon._height * 0.5)}
    //tempPIcon.localToGlobal(tempPIconLTG);
    //pTargetX = ((iconLTG.x - tempPIconLTG.x) * (iconClip_mc._xscale / pIconClip_mc._xscale));
    
    //skyui.util.Debug.log("iconLTG.x: " + iconLTG.x + ", iconLTG.y: " + iconLTG.y + "tempPIconLTG.x: " + tempPIconLTG.x + ", tempPIconLTG.y: " + tempPIconLTG.y + ", pTargetX: " + pTargetX)

    tempPIcon._xscale = pIconClip_mc._xscale;
    tempPIcon._yscale = pIconClip_mc._yscale;
    tempPIcon.gotoAndStop(currPIcon);
    pIconClip._alpha = 0;
    pIconClip._xscale = 25;
    pIconClip._yscale = 25;
    pIconClip.gotoAndStop(newPIcon);
    var tl = new TimelineLite({paused:true, autoRemoveChildren:true, onComplete:equipPreselectedItemComplete});
    tl.to(itemName_mc, 0.3, {_alpha:0, ease:Quad.easeOut}, 0)
    .to(preselectName_mc, 0.3, {_alpha:0, ease:Quad.easeOut}, 0)
    .call(updateNamesForEquipPreselect, [iSlot, newName, newPName, this])
    .to(tempIcon, 0.6, {_x:targetX, _y:((tempIcon._height) / 2), _rotation:"+=90", _alpha:0, _xscale:25, _yscale:25, ease:Quad.easeOut}, 0);
    .to(tempPIcon, 0.6, {_x:pTargetX, _y:pTargetY, _alpha:iconAlpha, _xscale:pIconTargetScale, _yscale:pIconTargetScale, ease:Quad.easeOut}, 0)
    .to(iconClip, 0, {_alpha:iconAlpha, ease:Linear.easeNone})
    .to(tempPIcon, 0, {_alpha:0, ease:Linear.easeNone})
    .to(pIconClip, 0.4, {_alpha:pIconAlpha, _xscale:pIconScale, _yscale:pIconScale, ease:Elastic.easeOut}, 0.5)
    .to(itemName_mc, 0.3, {_alpha:itemNameAlpha, ease:Quad.easeOut}, 0.6)
    .to(preselectName_mc, 0.3, {_alpha:preselectNameAlpha, ease:Quad.easeOut}, 0.6)

    tl.play();
}

我也把它上传到了Pastebin 这里

应该起作用的简单的 Icon AX 值 + 全局 X 值差异会导致:

截图 2

开始时两个图标之间的距离越大,问题就越严重。如果我将图标 A 的起始位置编辑得更远,结果如下:

截图 3

从这两个示例中,记录的值和计算为:

[20:12:47.970] leftIconLTG - x: 149.49916992187, y: 581.28598632812
[20:12:47.970] leftPreselectIconLTG - x: 94.587438964844, y: 577.68461914063
[20:12:47.970] leftTargetX: 39.15, leftPTargetX: 54.911730957031
[20:12:47.970] leftPTargetY: 3.6013671874999

[20:13:18.510] leftIconLTG - x: 149.49916992187, y: 581.28598632812
[20:13:18.510] leftPreselectIconLTG - x: 594.56030273438, y: 577.68461914063
[20:13:18.510] leftTargetX: -58.55, leftPTargetX: -445.0611328125
[20:13:18.510] leftPTargetY: 3.6013671874999

如您所见,目标 leftIcon 全局 (LTG) x 为 149.5,在第一个屏幕截图中,leftPreselectIcon 从全局 x 94.6 开始。leftPTargetX 包含在 54.9 处正确计算的差异。因此,将 leftPreselectIcon 从它的本地起始 x 0 移动到 54.9 理论上应该将其移动到正确的位置。

那么我在这里做错了什么?正如您从注释掉的代码中看到的那样,我做了其他一些尝试,包括在计算中添加半/全图标宽度,甚至通过将全局 x 差异值乘以比例来测试比例差异是否与它有关使用屏幕上的高度进行计算,从图标 A 缩放到图标 B 缩放的因子。但他们都没有让我靠近。


解决了

解决方案是为每组图标创建“存储”对象,然后在目标图标上调用 localToGlobal,然后在要移动的图标上调用 globalToLocal,两者都调用同一个对象:

var leftPIconTarget:Object = {x:0, y:0};

    leftIcon.localToGlobal(leftPIconTarget);

    leftPreselectIcon.globalToLocal(leftPIconTarget);

leftPIconTarget 现在包含 leftPreselectIcon 上补间的目标 x 和 y 坐标,并且无论我将起始位置移动到屏幕上的哪个位置,它都会继续工作。唯一奇怪的是我必须将右 x 设为负数,否则它会朝错误的方向移动,这根本没有意义,因为如果我将左侧图标移到右侧,那么它必须从右到左设置动画我不不必让它消极。去搞清楚!无论如何,它有效,这就是我所关心的!

标签: actionscriptflash-cs6

解决方案


推荐阅读