oyv*_*uge 11 frame-rate sprite-kit skshapenode
我正在使用Sprite Kit 制作一个" Achtung die kurve ".对于不断移动的线/玩家,我正在使用A CGMutablePathRef和SKShapeNode.在更新方法中,我正在这样做
// _lineNode is an instance of SKShapeNode and path is CGMutablePathRef
CGPathAddLineToPoint(path, NULL, _xPos, _yPos);
_lineNode.path = path;
Run Code Online (Sandbox Code Playgroud)
添加到该行.更新方法还在不断更新_xPos和_yPos以使其增长.
我想我真正要问的是有另一种更有效的绘制线条的方法,因为我现在这样做的方式现在会在一段时间后(大约15-20秒)将帧速率降低太多.此时FPS不断下降,直到游戏无法播放.时间分析器告诉我这一行:_lineNode.path = path是FPS丢弃的原因.
谢谢你的帮助!非常感谢.
PS.我试图不使用SKShapeNode,因为他们似乎无法画得太好(曲线中的小孔/文物等)
截图:

pro*_*cal 19
不幸的是,SKShapeNode并不适合你想做的事情.然而,有一种方法可以优化这一点,尽管有一些警告.
fps最大的问题之一是绘图计数非常高,因为你添加的每个线段都是另一个绘图.如果您showsDrawCount在SKView实例上设置,您将看到我的意思.
在这个答案中,一个平局中有多个skshapenode?,如果您正在绘制一次,您可以获得有关如何使用a的shouldRasterize属性SKEffectNode来解决问题的更多信息.如果不这样做,每帧将在多次绘制上花费处理器时间.
所以你可以看到抽奖是主要问题,你没有得到你想要的表现.但是,您似乎希望随着时间的推移不断绘制,所以我建议的可能是一个可行的解决方案.
我建议的解决方案的逻辑是这样的:
1 - 创建一个SKSpriteNode我们可以用作画布的东西.
2 - 创建一个SKShapeNode仅用于绘制当前线段的一个.
3 - 让它SKShapeNode成为画布的孩子.
4 - 通过绘制新的线段 SKShapeNode
5 - 使用SKView`textureFromNode方法保存当前在画布上绘制的内容.
6 - 将画布的纹理设置为该纹理.
循环回到#4并SKShapeNode为下一个线段创建一条新路径.
根据需要重复.
结果应该是你的抽奖计数永远不会高于2抽奖,这将解决高抽奖计数的问题.
基本上,你保留了之前在纹理中绘制的内容,因此只需要一次SKShapeNode绘制最新的线段和一次绘制SKTexture.
同样,我还没有尝试过这个过程,如果有任何延迟,那么textureFromNode每个帧都会进行调用.如果有什么东西会成为你的瓶颈,那就是它!
我可能会在今天的某个时候尝试这个理论,因为我需要textureFromNode解决另一个问题,所以我肯定会发现这个方法有多快/慢!哈哈
UPDATE
这不是完整的代码,但是实现所需绘图性能(60fps)的重要部分:
基本节点元素是:
container - >包含需要缓存的所有元素的SKNode
canvas - > SKSpriteNode将显示绘制段的缓存版本
段数池 - >用于初始绘制段,并根据需要重新使用
首先创建一个SKShapeNodes池:
pool = [[NSMutableArray alloc]init];
//populate the SKShapeNode pool
// the amount of segments in pool, dictates how many segments
// will be drawn before caching occurs.
for (int index = 0; index < 5; index++)
{
SKShapeNode *segment = [[SKShapeNode alloc]init];
segment.strokeColor = [SKColor whiteColor];
segment.glowWidth = 1;
[pool addObject:segment];
}
Run Code Online (Sandbox Code Playgroud)
接下来创建从池中获取SKShapeNode的方法:
-(SKShapeNode *)getShapeNode
{
if (pool.count == 0)
{
// if pool is empty,
// cache the current segment draws and return segments to pool
[self cacheSegments];
}
SKShapeNode *segment = pool[0];
[pool removeObjectAtIndex:0];
return segment;
}
Run Code Online (Sandbox Code Playgroud)
接下来,创建一个从池中获取段并绘制线的方法:
-(void)drawSegmentFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint
{
SKShapeNode *curSegment = [self getShapeNode];
CGMutablePathRef path = CGPathCreateMutable();
curSegment.lineWidth = 3;
curSegment.strokeColor = [SKColor whiteColor];
curSegment.glowWidth = 1;
curSegment.name = @"segment";
CGPathMoveToPoint(path, NULL, fromPoint.x, fromPoint.y);
CGPathAddLineToPoint(path, NULL, toPoint.x, toPoint.y);
curSegment.path = path;
lastPoint = toPoint;
[canvas addChild:curSegment];
}
Run Code Online (Sandbox Code Playgroud)
接下来是一种创建纹理并将现有段返回池的方法:
-(void)cacheSegments
{
SKTexture *cacheTexture =[ self.view textureFromNode:container];
canvas.texture = cacheTexture;
[canvas setSize:CGSizeMake(canvas.texture.size.width, canvas.texture.size.height)];
canvas.anchorPoint = CGPointMake(0, 0);
[canvas enumerateChildNodesWithName:@"segment" usingBlock:^(SKNode *node, BOOL *stop)
{
[node removeFromParent];
[pool addObject:node];
}];
}
Run Code Online (Sandbox Code Playgroud)
最后是触摸处理程序:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self cacheSegments];
for (UITouch *touch in touches)
{
CGPoint location = [touch locationInNode:self];
lastPoint = location;
[self drawSegmentFromPoint:lastPoint toPoint:location];
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches)
{
CGPoint location = [touch locationInNode:self];
[self drawSegmentFromPoint:lastPoint toPoint:location];
}
}
Run Code Online (Sandbox Code Playgroud)
正如我所说的,这不是全包代码,我假设您对可以在应用程序中实现的概念有足够的了解.这些只是我的准系统实现的例子.
| 归档时间: |
|
| 查看次数: |
4736 次 |
| 最近记录: |