【翻译】AS3中如何修改注册点

这是我认为每个人都希望知道如何在ActionScript中实现的:在运行时动态改变一个影片剪辑或精灵的注册点。我想知道这个很长时间了,也在网上看到了一些不太满意的解决方案。然而,它们为我开发自己的解决方案提供了有价值的线索,所以,我并不是在这里打击任何人。你能找到的最主流的解决方案之一是链接库符号到一个类,然后,你获取诸如rotation2、x2、y2、scaleX2、scaleY2等属性,你知道的。

然而,这不是我想要的……

我不想使用以2结尾的新属性,因为这看起来不自然。相反,我需要一个函数,我可以调用它改变注册点,然后只需要使用正常的影片剪辑属性:rotation、x、y、scaleX和scaleY。如果影片剪辑注册点可以在第一个地方永久的移动,后续的转换就可以从新的注册点开始了。我需要一些东西可以直接应用到已有的影片剪辑实例而无需先链接该影片剪辑到一个自定义的类。

如果不是必须的,我也不想非使用Matrix类来处理。并不是说使用它不好,但是如果有更简单的解决方案,显然我会更喜欢它。

当我在线查阅时,经常被很多人的断言所打击——影片剪辑的注册点不能移动(从技术上讲,确实如此)!然而,我也看到许多在线的示例,人们已经设法完成了它。那么,你是如何移动一个注册点的?我必须知道!我看了许多论坛上的许多贴子,沮丧者即使死了都想知道答案。事实上,改变注册点是如此基本的东西,你可能想ActionScript语言内建了解决方案,但没有。

这是一个技术性问题

像我刚才说的,你确实不能移动一个注册点。对任何精灵或影片剪辑来说,注册点的位置永远是(0,0)。这是一个技术性问题,证明我们都在问一个错误的问题。如果你不能移动一个注册点,问如何实现它就没有任何意义了。然而当你不能从技术上移动注册点的时候,你却可以参照它来移动其他所有的东西。这就是答案的关键!你不能移动注册点,但你可以从效果上移动它!通过移动其他的一切!

这类似于你如何用Flash创作工具改变注册点。你永远不会移动注册点自身,因为那是不可能的。相反,你相对该点移动所有的图形内容。假设你在舞台上有一个影片剪辑实例,其注册点在左上角,你想让注册点在中间。你将编辑这个剪辑:进入剪辑内部,选择所有的图形并让他们在注册点上居中。然后回到场景1,你会发现舞台上的对象从先前的位置移动了,因为你改变了它的内部,你会调整它的x和y位置来补偿刚才产生的变化。或许你已经这样做过。步骤就像这样:

1. 在剪辑内部,编辑模式下,向左向上移动剪辑内每一个图形内容

2. 回到场景,向右向下移动影片剪辑相同的数量

注意你并没有移动注册点本身,但你向左上方移动了影片剪辑的所有显示子对象,并且最后回到场景1,你向右下方移动了影片剪辑进行补偿。

所以如果我们想在程序中动态改变注册点,我们基本上要进行同样的处理,只使用代码。我不再让你有任何悬念。为此我花了一整天的大部分,完成后,我的函数只有11行(如果你不将注释计算在内)!但它起作用了,并且工作很棒!我很高兴与您共享!

噢,我差点忘了。我也想要一个解决方案,它不管注册点最初设定在哪里,我也做到了!这个函数很容易使用。第一个参数是你要影响的对象,该对象必须是一个显示对象容器(DisplayObjectContainer),所以它可以是Sprite、MovieClip,甚至Loader实例。第二个和第三个参数就是你想要的新注册点的x和y值——相对于剪辑图形内容的左上角。而且,就像我所说的,代码工作时忽略注册点现在在哪里。下页是这个函数(未做处理,保留作者原汁原味):

  1. function setRegPoint(obj:DisplayObjectContainer, newX:Number, newY:Number):void {
  2.         //get the bounds of the object and the location
  3.         //of the current registration point in relation
  4.         //to the upper left corner of the graphical content
  5.         //note: this is a PSEUDO currentRegX and currentRegY, as the
  6.         //registration point of a display object is ALWAYS (0, 0):
  7.         var bounds:Rectangle = obj.getBounds(obj.parent);
  8.         var currentRegX:Number = obj.x - bounds.left;
  9.         var currentRegY:Number = obj.y - bounds.top;
  10.        
  11.         var xOffset:Number = newX - currentRegX;
  12.         var yOffset:Number = newY - currentRegY;
  13.         //shift the object to its new location--
  14.         //this will put it back in the same position
  15.         //where it started (that is, VISUALLY anyway):
  16.         obj.x += xOffset;
  17.         obj.y += yOffset;
  18.        
  19.         //shift all the children the same amount,
  20.         //but in the opposite direction
  21.         for(var i:int = 0; i < obj.numChildren; i++) {
  22.                 obj.getChildAt(i).x -= xOffset;
  23.                 obj.getChildAt(i).y -= yOffset;
  24.         }
  25. }
复制代码

注释很好的解释了大部分是怎么回事,这是一个更充分的解释:

getBounds()函数用来获取剪辑的边界框。剪辑的x和y属性给出了当前注册点的位置。暂时让我们只考虑x方向:bounds.left值是图形内容的最左边的位置,剪辑的x属性给出了注册点的x位置。这两个值都来自父视图(坐标空间),这两个数之间的差异给出了注册点相对图形内容最左边的当前位置,然后从我们要使用的新x值中扣除该(差)值,存储在变量xOffset中。剩下的部分是将所有的子对象向左移动这个数值,最后再讲剪辑自身向右移动这个数值。在y方向上保持同样的处理。

在示例文件中,舞台上有一个称为 book 的影片剪辑实例。初始时特意使 book 影片剪辑的注册点不在左上角,也不在中心。然后 setRegPoint() 函数将注册点设定到中心,这仅需要一次简单的函数调用。当 book 被点击时,其 scaleX 属性被乘以 -1 ,这是众所周知的进行水平翻转技术。因为函数调用已经设置注册点到中心,缩放使用了新的注册点来进行。 book 影片剪辑内部还有一对 shape ,用来演示所有的内容进行了移动。下页是完成任务的辅助代码(联合上面的函数代码):
  1. book.addEventListener(MouseEvent.CLICK, bookClicked);
  2. function bookClicked(event:MouseEvent):void {
  3.         book.scaleX *= -1;
  4. }
  5. //set the registration point for the book object in the middle instead:
  6. setRegPoint(book, book.width / 2, book.height / 2);
复制代码

下页是在线演示

http://theflashconnection.com/sites/default/files/Jody%20Hall/dynamic_registration_point.fla

注意:附件文件是CS4格式的。它演示了使用这面的函数是如何的容易。舞台上的影片剪辑动态修改了它的注册点。之后的所有变换都将使用新的点替代原来的那个。如果你在使用CS3,不能打开这个文件,但不用做太多,我在上面已经给出了全部的代码,只要复制、粘贴到你自己的文件,应用到你自己的影片剪辑实例。享用!





原地址:http://bbs.9ria.com/thread-163401-1-1.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C++,虽然没有直接对应Python的`import`语句,但你可以使用`#include`来引入相应的库文件。`numpy`和`matplotlib`在C++没有直接对应的库,因为它们是Python的数据科学库。然而,如果你在使用C++的环境(如C++11或更高版本),可能需要通过Python接口来调用这些库的功能,比如使用`pybind11`库来创建Python-C++绑定。 对于`numpy`,你会导入`<Eigen/Dense>`(如果使用Eigen库)或类似`<opencv2/core.hpp>`(如果是OpenCV)来处理矩阵操作。 对于`matplotlib`,在C++通常不会直接使用,因为它是一个图形库,而C++有自己的绘图库如`GLFW`、`SDL2`,或使用第三方库如`VTK`、`Qt`等。如果要在C++使用类似功能,可能会结合C++和Python交互的工具(如Boost.Python或Pybind11)来间接调用Python的`matplotlib`。 所以,如果你真的想在C++实现类似功能,代码可能看起来像这样(使用pybind11为例): ```cpp #include <pybind11/pybind11.h> #include <pybind11/eigen.h> // 对于Eigen void importEigen() { pybind11::module_ eigen = pybind11::module::import("numpy"); eigen.def("array", [](std::vector<double> data) { return Eigen::Map<Eigen::VectorXd>(data.data(), data.size()); }); } // 对于其他依赖库的导入(这里假设已经包含头文件) void importMatplotlib() { // 这里仅示例,实际使用可能需要更复杂的导入和调用机制 pybind11::module_ matplotlib = pybind11::module::import("matplotlib.pyplot"); // 如果有绘图函数,你可以这样注册: matplotlib.def("plot", &plt::plot, "A placeholder for matplotlib plot function"); } int main() { importEigen(); importMatplotlib(); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值