【发布时间】:2012-11-07 19:46:02
【问题描述】:
总结
我正在为 iOS 开发一款相当简单的 2D 塔防游戏。
到目前为止,我一直专门使用 Core Graphics 来处理渲染。应用程序中根本没有图像文件(还)。我在进行相对简单的绘图时遇到了一些严重的性能问题,我正在寻找有关如何解决这个问题的想法,而不是转向 OpenGL。
游戏设置
在高层次上,我有一个 Board 类,它是 UIView 的子类,用于表示游戏板。游戏中的所有其他对象(塔、小兵、武器、爆炸等)也是 UIView 的子类,并在创建时作为子视图添加到 Board。
我将游戏状态与对象中的视图属性完全分开,并且每个对象的状态都会在主游戏循环中更新(由NSTimer 以 60-240 Hz 的频率触发,具体取决于游戏速度设置)。该游戏完全可以玩,无需绘制、更新或动画视图。
我使用CADisplayLink 计时器以原生刷新率 (60 Hz) 处理视图更新,该计时器在需要根据游戏状态变化更新其视图属性的棋盘对象上调用 setNeedsDisplay。板上的所有对象都会覆盖drawRect:,以在其框架内绘制一些非常简单的二维形状。因此,例如,当一个武器被激活时,它会根据武器的新状态重新绘制自己。
性能问题
在 iPhone 5 上进行测试,板上总共有大约 2 打游戏对象,帧速率明显低于 60 FPS(目标帧速率),通常在 10-20 FPS 范围内。随着屏幕上的更多动作,它从这里开始走下坡路。而在 iPhone 4 上,情况更糟。
使用仪器我确定只有大约 5% 的 CPU 时间用于实际更新游戏状态——其中绝大多数用于渲染。具体来说,CGContextDrawPath 函数(据我了解,它是矢量路径的光栅化完成的地方)占用了大量的 CPU 时间。有关详细信息,请参阅底部的 Instruments 屏幕截图。
根据对 StackOverflow 和其他网站的一些研究,Core Graphics 似乎无法满足我的需求。显然,描边矢量路径非常昂贵(尤其是在绘制不透明且 alpha 值
问题
我应该考虑哪些优化来尝试从 Core Graphics 中获得流畅的 60 FPS?
一些想法...
有人建议我考虑将我的所有对象都绘制到一个 CALayer 上,而不是让每个对象都单独使用 CALayer,但根据 Instruments 显示的内容,我不相信这会有所帮助。
就我个人而言,我有一个理论,即使用CGAffineTransforms 来制作我的动画(即在drawRect: 中绘制对象的形状一次,然后在后续帧中进行变换以移动/旋转/调整其图层大小)将解决我的问题,因为它们直接基于OpenGL。但我认为这样做不会比直接使用 OpenGL 更容易。
示例代码
为了让您了解我正在做的绘图水平,这里是我的一个武器对象(从塔发射的“光束”)的drawRect: 实现示例。
注意:此光束可以“重新定位”并且它穿过整个电路板,因此为简单起见,它的框架与电路板尺寸相同。然而,板上的大多数其他对象都将其框架设置为可能的最小外接矩形。
- (void)drawRect:(CGRect)rect
{
CGContextRef c = UIGraphicsGetCurrentContext();
// Draw beam
CGContextSetStrokeColorWithColor(c, [UIColor greenColor].CGColor);
CGContextSetLineWidth(c, self.width);
CGContextMoveToPoint(c, self.origin.x, self.origin.y);
CGPoint vector = [TDBoard vectorFromPoint:self.origin toPoint:self.destination];
double magnitude = sqrt(pow(self.board.frame.size.width, 2) + pow(self.board.frame.size.height, 2));
CGContextAddLineToPoint(c, self.origin.x+magnitude*vector.x, self.origin.y+magnitude*vector.y);
CGContextStrokePath(c);
}
仪器运行
让游戏运行一段时间后看看 Instruments:
TDGreenBeam 类具有上面示例代码部分中显示的确切 drawRect: 实现。
【问题讨论】:
-
+1 表示问题的格式。容易理解。
标签: iphone ios performance core-graphics quartz-2d