如何在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);
就这些。 画一个框架精灵,使其看起来更好。
假设HealthBarNode
是HealthBarNode
的一个子类,其公共属性的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)
//就这样。