如何在sprite工具包中创build进度条?

我想在Sprite Kit中创build我自己的进度条。
我想我会需要图像 – 一个完全空的进度条和填充进度条。
我有这些图像,我把一个放在空的顶部,他们是正规的SKSPriteNodes现在我无法弄清楚如何我需要削减我的填充图像?

我如何在某一点切割SKSpriteNode图像? 也许纹理?

我会build议看看SKCropNode 。 有关SKCropNode如何工作的视觉帮助,请参阅Apple编程指南 。 我已经通读了整个文件多次,这是一个特别好的阅读。

SKCropNode基本上是一个你添加到你的场景的SKNode,但是它的孩子可以被一个面具裁剪。 该掩码在maskNode属性中设置。 这样,你只需要一个纹理图像。 我会inheritanceSKCropNode的实现function,以移动或调整面具的大小,所以你可以很容易地更新其外观。

 @interface CustomProgressBar : SKCropNode /// Set to a value between 0.0 and 1.0. - (void) setProgress:(CGFloat) progress; @end @implementation CustomProgressBar - (id)init { if (self = [super init]) { self.maskNode = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(300,20)]; SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@"progressBarImage"]; [self addChild:sprite]; } return self; } - (void) setProgress:(CGFloat) progress { self.maskNode.xScale = progress; } @end 

在你的场景中:

 #import "CustomProgressBar.h" // ... CustomProgressBar * progressBar = [CustomProgressBar new]; [self addChild:progressBar]; // ... [progressBar setProgress:0.3]; // ... [progressBar setProgress:0.7]; 

注意:这段代码不会移动mask(所以sprite会在两边被裁剪掉),但是我相信你明白了。

很简单:你需要一个帧图像(可选)和一个“酒吧”图像。 条形图像是一个单一的,纯色和高达你需要它,1或2像素宽。 一个SKShapeNode作为酒吧也会做。

只需制作条形图和animation即可,只需更改SKSpriteNode的大小属性即可。 例如,要使条形图代表0到100之间的进度,请执行以下操作:

 sprite.size = CGSizeMake(progressValue, sprite.size.height); 

每当progressValue更改时更新大小。

您会注意到图像的宽度将增加到左右两侧,以使其仅向右伸展,将anchorPoint更改为左alignment图像:

 sprite.anchorPoint = CGPointMake(0.0, 0.5); 

就这些。 画一个框架精灵,使其看起来更好。

假设HealthBarNodeHealthBarNode的一个子类,其公共属性的health在0.0到1.0之间变化, SKSpriteNode属性texture是从宽度_textureWidth (一个私有属性)的整个颜色条图像中生成的,你可以这样做:

 - (void)setHealth:(CGFloat)fraction { self.health = MIN(MAX(0.0, fraction), 1.0); // clamp health between 0.0 and 1.0 SKTexture *textureFrac = [SKTexture textureWithRect:CGRectMake(0, 0, fraction, 1.0) inTexture:self.texture]; // check docs to understand why you can pass in self.texture as the last parameter every time self.size = CGSizeMake(fraction * _textureWidth, self.size.height); self.texture = textureFrac; } 

health值设置为新的值会导致健康状况栏(例如添加为主要场景的孩子)正确裁剪。

我build立了一个小型图书馆来处理这个确切的情况! 这里是SpriteBar: https : //github.com/henryeverett/SpriteBar

没有“剪切”图像/纹理。

Cocos提供的另一种方法是制作一些纹理,并根据健康状况将它们交换到节点中。 我做了一个游戏,健康栏每10分钟改变一次纹理(范围是0-100)。 经过一些尝试和错误,但我只是最终做了科科斯已经build议。

在这里输入图像说明

我这样做,它完美的作品。

所以首先,我宣布了一个SKSpriteNode:

 baseBar = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:CGSizeMake(CGRectGetMidX(self.frame)-40, self.frame.size.height/10)]; //The following will make the health bar to reduce from right to left //Change it to (1,0.5) if you want to have it the other way //But you'd have to play with the positioning as well [baseBar setAnchorPoint:CGPointMake(0, 0.5)]; CGFloat goodWidth, goodHeight; goodHeight =self.frame.size.height-(baseBar.frame.size.height*2/3); goodWidth =self.frame.size.width-(10 +baseBar.frame.size.width); [baseBar setPosition:CGPointMake(goodWidth, goodHeight)]; [self addChild:baseBar]; 

然后,我为该栏添加了一个“框架”,一个SKShapeNode,没有填充颜色(clearcolour)和一个笔触颜色:

 //The following was so useful SKShapeNode *edges = [SKShapeNode shapeNodeWithRect:baseBar.frame]; edges.fillColor = [UIColor clearColor]; edges.strokeColor = [UIColor blackColor]; [self addChild:edges]; 

当我想减less健康,我做了以下几点:

  if (playerHealthRatio>0) { playerHealthRatio -= 1; CGFloat ratio = playerHealthRatio / OriginalPlayerHealth; CGFloat newWidth =baseBar.frame.size.width*ratio; NSLog(@"Ratio: %f newwidth: %f",ratio,newWidth); [baseBar runAction:[SKAction resizeToWidth:newWidth duration:0.5]]; }else{ // NSLog(@"Game over"); } 

简单,干净,并不复杂。

那是我的ProgressBar在swift中:

 import Foundation import SpriteKit class IMProgressBar : SKNode{ var emptySprite : SKSpriteNode? = nil var progressBar : SKCropNode init(emptyImageName: String!,filledImageName : String) { progressBar = SKCropNode() super.init() let filledImage = SKSpriteNode(imageNamed: filledImageName) progressBar.addChild(filledImage) progressBar.maskNode = SKSpriteNode(color: UIColor.whiteColor(), size: CGSize(width: filledImage.size.width * 2, height: filledImage.size.height * 2)) progressBar.maskNode?.position = CGPoint(x: -filledImage.size.width / 2,y: -filledImage.size.height / 2) progressBar.zPosition = 0.1 self.addChild(progressBar) if emptyImageName != nil{ emptySprite = SKSpriteNode.init(imageNamed: emptyImageName) self.addChild(emptySprite!) } } func setXProgress(xProgress : CGFloat){ var value = xProgress if xProgress < 0{ value = 0 } if xProgress > 1 { value = 1 } progressBar.maskNode?.xScale = value } func setYProgress(yProgress : CGFloat){ var value = yProgress if yProgress < 0{ value = 0 } if yProgress > 1 { value = 1 } progressBar.maskNode?.yScale = value } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } 

}

//如何使用 :

 let progressBar = IMProgressBar(emptyImageName: "emptyImage",filledImageName: "filledImage") 

要么

 let progressBar = IMProgressBar(emptyImageName: nil,filledImageName: "filledImage") 

并将此progressBar添加到任何SKNode

 self.addChild(progressBar) 

//就这样。