渲染数百个“块”图像 -vs- 部分渲染“地图”块数
似乎这些解决方案都没有消除与将图像渲染到屏幕上相关的延迟(无论是来自 .png 还是使用 CG)。
有一个 28x16 的块网格,每个块都有 16x16 像素,在游戏中的某些时刻,大约一半的块需要因为状态更改而更改其图像。当其中一半需要单独更改其图像(无论是来自 .png 或使用 CG)时,将每个块作为主视图的子视图会导致延迟。
我尝试使用一个“地图”视图,其 drawRect: 方法为:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);
// width and height are defined as the width and height of the grid (28x16 for iPhone)
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
// states[] is an enum instance variable that holds the states of each block in the map (state determines image)
if (states[(x * height) + y] == PXBlockStateEmpty) {
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:153.0/255.0 green:153.0/255.0 blue:153.0/255.0 alpha:0.5].CGColor);
CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5].CGColor);
CGContextAddRect(context, CGRectMake(x * 16, y * 16, 16, 16));
CGContextDrawPath(context, kCGPathFillStroke);
} else if (states[(x * height) + y] == PXBlockStateSolid || states[(x * height) + y] == PXBlockStateSolidEdge) {
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:0.0 green:0.0 blue:102.0/255.0 alpha:0.9].CGColor);
CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5].CGColor);
CGContextAddRect(context, CGRectMake(x * 16, y * 16, 16, 16));
CGContextDrawPath(context, kCGPathFillStroke);
} else if (states[(x * height) + y] == PXBlockStateBuilding) {
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:51.0/255.0 green:51.0/255.0 blue:51.0/255.0 alpha:0.5].CGColor);
CGContextFillRect(context, CGRectMake(x * 16, y * 16, 16, 16));
}
}
}
所以我的解决方案是在地图上调用 setNeedsDisplayInRect: ,传递状态发生变化的块的框架(16x16 矩形)。我是否错误地使用了 setNeedsDisplayInRect: ,或者这只是一种低效的方法?
当棋盘上的很多地方都充满了不同的图像时,这两种选项(一个子视图与数百个子视图)都会使游戏滞后一点,并且每当任何块的图像需要更新时,第二个解决方案都会特别滞后。
有什么想法吗?感谢您的帮助!
It seems that none of these solutions eliminate the lag associated with rendering images onto the screen (whether from .png's or using CG).
There is a 28x16 grid of blocks that are each 16x16 pixels, and at some points in the game, about half of them need to change their image because of a state change. Having each block as a subview of the main view causes a lag when half of them need to individually change their image (either from .png's or using CG).
I tried having one "map" view with whose drawRect: method is:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);
// width and height are defined as the width and height of the grid (28x16 for iPhone)
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
// states[] is an enum instance variable that holds the states of each block in the map (state determines image)
if (states[(x * height) + y] == PXBlockStateEmpty) {
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:153.0/255.0 green:153.0/255.0 blue:153.0/255.0 alpha:0.5].CGColor);
CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5].CGColor);
CGContextAddRect(context, CGRectMake(x * 16, y * 16, 16, 16));
CGContextDrawPath(context, kCGPathFillStroke);
} else if (states[(x * height) + y] == PXBlockStateSolid || states[(x * height) + y] == PXBlockStateSolidEdge) {
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:0.0 green:0.0 blue:102.0/255.0 alpha:0.9].CGColor);
CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5].CGColor);
CGContextAddRect(context, CGRectMake(x * 16, y * 16, 16, 16));
CGContextDrawPath(context, kCGPathFillStroke);
} else if (states[(x * height) + y] == PXBlockStateBuilding) {
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:51.0/255.0 green:51.0/255.0 blue:51.0/255.0 alpha:0.5].CGColor);
CGContextFillRect(context, CGRectMake(x * 16, y * 16, 16, 16));
}
}
}
So my solution was to call setNeedsDisplayInRect: on the map, passing the frame (a 16x16 rect) of the block whose state changed. Am I using setNeedsDisplayInRect: incorrectly, or is this just an inefficient way to do it?
Both options (one subview vs hundreds of subviews) lag the game for a bit when a lot of the board is filled with a different image, and the second solution in particular lags whenever ANY block's image needs to be updated.
Any ideas? Thank you for your help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
调用 setNeedsDisplayInRect: 会影响 drawRect: 的参数,但在其他方面与 setneedsDisplay 相同。绘制矩形:接收的矩形是所有脏矩形的并集。如果您只绘制与该矩形相交的内容,而保持其他内容不变,您可能会看到速度的提高。从上面的代码片段来看,您每次都会绘制每个图块。由于它是一个联合体,您也可以单独跟踪脏瓷砖并只绘制脏瓷砖。在这种情况下,请为各个图块调用 CGContextClearRect,而不是清除整个上下文,除非它们都脏了。
CGContextAddRect 将一个矩形添加到将要绘制的路径中。由于您在每次循环时绘制路径而无需开始新路径,因此您可以在循环进行时重新绘制区域。使用 CGContextFillRect 和 CGContextStrokeRect 而不是路径可能会更快。
使每个图块成为单独的 UIView 比绘制整个图块会产生更多的开销。一旦解决了问题,您应该能够通过此方法获得更好的速度。
Calling setNeedsDisplayInRect: affects the argument to drawRect: but is otherwise the same as setneedsDisplay. The rectangle drawRect: receives is the union of all dirty rectangles. If you only draw content that intersects that rectangle, leaving other content untouched, you may see a speed improvement. Judging from the code snippet above you draw every tile every time. Since it is a union, you might also track dirty tiles separately and only draw dirty tiles. In that case, call CGContextClearRect for individual tiles instead of clearing the whole context, unless they are all dirty.
CGContextAddRect adds a rectangle to a path that will be drawn. Since you draw the path at every loop without beginning a new path, you redraw areas as the loop progresses. It would probably be faster to use CGContextFillRect and CGContextStrokeRect instead of a path.
Making each tile a separate UIView incurs more overhead than drawing as a whole. You should be able to get better speed from this method once the kinks are worked out.