【问题标题】:On iPhone, what is the best way to move a UIImageView with onscreen controls?在 iPhone 上,使用屏幕控件移动 UIImageView 的最佳方式是什么?
【发布时间】:2009-06-18 13:26:44
【问题描述】:

我正在开发这款游戏的 iPhone 版本。 http://www.students.uni-mainz.de/rathb000/Fillit/Game.html

我正在使用 NSTimer 将船的位置更改 1 个像素,计时器的时间间隔为 0.002。

但是,我注意到如果我进一步缩短时间间隔,船不会更快地移动。事实上,0.05 和 0.002 之间没有区别。您必须作为 NSTimeInterval 提供的最短时间是否有限制?

目前这艘船的移动速度太慢,以至于游戏无法令人兴奋。

此外,当我按下任何按钮移动船时,鸟类的移动(也由 NSTimer 实现)变得缓慢。

知道如何解决这个问题吗?

【问题讨论】:

    标签: iphone uiimageview quartz-graphics nstimer


    【解决方案1】:

    NSTimer 不是实时机制;它作为运行循环的一部分触发,不适合创建流畅、流畅的动画。但是,有一个 SDK 是 iPhone OS 的一部分,称为 Core Animation——它提供了一个函数库,用于执行图层和视图的平滑动画。 Here is a reasonably good series of video tutorials 你可能会觉得有用。还有一本名为Core Animation for Mac OS X and iPhone 的好书,您可能会觉得很有用。

    还有core animation documentation from Apple 描述了如何使用 CABasicAnimation 类来为任何层或视图的属性设置动画。以下是文档中的显式图层动画示例:

    CABasicAnimation *theAnimation; 
    
    theAnimation=[CABasicAnimation animationWithKeyPath:@"opacity"];
    theAnimation.duration=3.0;
    theAnimation.repeatCount=1;
    theAnimation.autoreverses=NO;
    theAnimation.fromValue=CATransform3DTranslate(0,0,0);
    theAnimation.toValue=CATransform3DTranslate(20,20,0);
    
    [theLayer addAnimation:theAnimation forKey:@"animateTransform"];
    

    【讨论】:

    • 非常感谢您提供的链接。就可以了。
    • 没问题,如果您觉得我的答案有用,您也可以选择接受我的答案作为已接受的答案,并带有复选标记图标。
    • 这还有待回答。我仍然卡住了.. :(
    • 一定会试试这个。那么,这段代码会让我的船从 0,0 移动到 20,20 并带有动画吗?我的意思不是“眨眼就在那里”,而是通过平稳的运动让你知道它从这里移动到那里。
    • 嗨,试过这个代码。分配给 fromValue 和 toValue 的值似乎是错误的。它需要一个 NSNumber 类型。我正在阅读您提到的那本书,但它对 iPhone 上的动画几乎没有提及。它主要用于 Mac。
    【解决方案2】:

    来自NSTimer docs:

    定时器不是实时机制;它仅在已添加计时器的运行循环模式之一正在运行并且能够检查计时器的触发时间是否已过时触发。由于典型的运行循环管理的各种输入源,计时器的时间间隔的有效分辨率被限制在 50-100 毫秒的数量级。如果在运行循环处于未监视计时器的模式或长时间调用期间发生计时器的触发时间,则计时器不会触发,直到运行循环下次检查计时器。因此,计时器触发的实际时间可能是计划触发时间之后的很长一段时间。

    也许您可以尝试使用UIView 动画而不是计时器来移动UIView

    【讨论】:

      【解决方案3】:

      您可以考虑增加距离大小:每 0.05 秒移动船 3 或 4 像素,而不是每 0.002 秒移动 1 像素。

      【讨论】:

      • 这会使碰撞检测的逻辑出错。我将不得不标记船经过的所有点。也许我可以采用一个数组并标记中间点,但不确定这是否是个好主意。
      【解决方案4】:

      在我看来,您应该在游戏中的所有实体全局使用相同的时间步,而不是专门用于玩家飞船的时间步。如果飞船在您的时间步内移动得太慢,请增加它每帧移动的距离。

      确实,您应该考虑以像素/秒为单位移动玩家的飞船。当 NSTimer 事件触发时,获取自上次更新以来经过的时间。使用此经过的时间来移动您的游戏实体。例如,如果您的更新时间步长为 0.05 秒,并且您希望以每秒 100 像素的速度移动玩家的飞船,那么您应该在此更新中将其移动 100 * 0.05 = 5 像素。此方法将考虑不同大小的时间步长,并且您的游戏实体将始终以一致的速度移动,即使您的计时器机制不是那么一致。

      【讨论】:

      • 是的,这听起来不错,但我必须让船一次只移动 1 个像素。它是游戏逻辑所需要的。否则,鸟可能无法检测到线路并会通过填充区域,或者在路径不完整时可能不会杀死船。所以我想知道石英中是否有这样的“翻译”功能可以加快运动速度。
      • 我假设碰撞检测使用玩家飞船周围的矩形。您可以增加此矩形以包含玩家飞船及其速度。例如,如果您的玩家飞船在 y 轴上移动了 10 个像素,您可以使用一个矩形,该矩形包含玩家飞船的边界,但也可以在 y 轴上延伸超过飞船 10 个像素,以包含距离的数量。船在最后一帧行驶。
      • 不,船和鸟没有碰撞。只有船和鸟儿画的线。所以线上的所有点都需要标记为 3,以便我们知道鸟何时越过线。如果标记为 4,则鸟必须偏转。所以我必须让船只路径上的每一个点都成为一个特定的值,因此船只一次不能移动超过 1 个像素。
      【解决方案5】:

      不仅 NSTimer 不是用于此类动画的正确工具,您的设计也是错误的。

      间隔为 0002 的计时器每秒触发 500 次。这是为这款游戏制作动画的一种疯狂方式。

      我建议您阅读 2D 游戏设计并找到更好的碰撞检测方法 - 就像匿名建议您应该在船周围有一个碰撞矩形,而不是依赖实际像素。

      您还应该查看Cocos-2D for iPhone

      【讨论】:

      • 是的,我知道我错了。但正如我在上面的评论中所说,我不需要船和鸟之间的碰撞检测。是的,我尝试了 cocos2d 大约一个星期,但发现我的游戏很简单,可以用石英制作。此外,我无法像用户经常声称的 cocos2d 那样快速学习它。无论如何,谢谢。
      • 所以你有你的解决方案,你不想要来自 Stack Overflow 的建议。为什么还要费心问这个问题?
      • 我在哪里提到我有解决方案并且我不需要建议?也许你应该在形成意见之前阅读我上面的 cmets。相信我,这将有助于避免一些交流。
      • 也许我误解了你的答案——他们似乎都是“是的,但这不起作用,因为......”即使他们是很好的答案。如果我这样做并且我弄错了,我道歉。
      • 没问题。没关系...我的问题是我必须将步长保持为 1 个像素,并在不改变它的情况下使船的运动尽可能快。这就是问题。单单让它一步移动2或3个像素就会让游戏的逻辑出错。
      【解决方案6】:

      想通了。

      必须使用核心动画来移动船,并通过 NSTimer 让鸟移动。这种方式可以正常工作,但只能达到一定的限制。当船速增加超过一定限度时,鸟类再次减速。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-22
        • 2011-02-10
        • 2020-05-05
        • 1970-01-01
        相关资源
        最近更新 更多