我想在Sprite Kit中創建我自己的進度條。
我想我會需要圖像 - 一個完全空的進度條和填充進度條。
我有這些圖像,我把一個放在空的頂部,他們經常SKSPriteNodes
現在我不知道我如何削減我的需要填充的圖像?如何在sprite工具包中創建進度條?
我該如何在特定點處切割SKSpriteNode圖像?也許紋理?
我想在Sprite Kit中創建我自己的進度條。
我想我會需要圖像 - 一個完全空的進度條和填充進度條。
我有這些圖像,我把一個放在空的頂部,他們經常SKSPriteNodes
現在我不知道我如何削減我的需要填充的圖像?如何在sprite工具包中創建進度條?
我該如何在特定點處切割SKSpriteNode圖像?也許紋理?
我會建議您調查SKCropNode。對於SKCropNode
工作的視覺輔助,請在Apple Programming Guide中查找。我已經多次閱讀整個文檔,這是一個特別好的閱讀。
SKCropNode
基本上是一個SKNode,你添加到你的場景,但它的孩子可以通過面具裁剪。該掩碼設置在SKCropNode的maskNode
屬性中。這樣,你只需要一個紋理圖像。我將繼承SKCropNode以實現移動或調整遮罩大小的功能,以便您輕鬆更新其外觀。
@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];
注:此代碼不動的面具(所以精靈將在兩側裁剪),但我敢肯定你的想法。
SKCropNode沒有mask屬性,所以我假設這應該是maskNode? – Mike
現貨!我編輯了答案以反映你的改進。 – CloakedEddy
嗨,不好意思問這個問題,但是這段代碼確實顯示了帶'progressBarImage'圖像的精靈,但是'spriteNodeWithColor:[SKColor whiteColor]'什麼也沒做,爲什麼?我正在開發ios9。 –
很簡單:你需要一個幀圖像(可選)和一個「酒吧」圖像。條形圖像是一個單一的,純色和高達你需要它,1或2像素寬。 SKShapeNode as bar也可以。
只需製作條形圖和動畫即可改變SKSpriteNode的大小屬性。例如,使巴表示介於0和100只是做的進展:
sprite.size = CGSizeMake(progressValue, sprite.size.height);
更新大小,只要progressValue變化。
你會發現圖像將在寬度增加至左,右,使其伸展僅向右變更anchorPoint左對齊的圖像:
sprite.anchorPoint = CGPointMake(0.0, 0.5);
這是所有。在它周圍繪製一個框架精靈,使其看起來更好。
這個好,如果我有純色和正方形,就可以得到節點紋理的子集(假設是整個顏色條)酒吧,但如果我有複雜的酒吧呢?只是想削減它?有什麼方法可以在Sprite Kit中剪切或操作紋理? – Dvole
沒有「剪切」圖像/紋理。
Cocos提供的另一種方法是製作幾個紋理,並根據健康狀況將它們交換到節點中。我做了一個遊戲,健康欄每10分鐘改變一次紋理(範圍是0-100)。儘管經歷了一些嘗試和錯誤,但我最終只是做了科科斯已經提出的建議。
有一種方法可以剪切圖像,請參閱我的回答,參考'SKCropNode'。 – CloakedEddy
假設HealthBarNode
是SKSpriteNode
與0.0和1.0,並且其父母財產texture
從寬度_textureWidth
(私有屬性)的全部彩條圖像生成之間變化的公共屬性health
一個子類,則可以做這樣的事情:
- (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
到一個新的值將導致健康酒吧(作爲子項添加到主場景,說),以得到適當的裁剪。
另一種方法是使用'SKCropNode' – Aky
我會添加'SKCropNode'作爲這個選項的另一個選項併發送它。 :) – prototypical
我使用這種方法獲取垃圾來代替紋理。我嘗試改變不同的值,但同樣,原始紋理是黃色的,我得到了一些灰色廢話的藍色。 – Dvole
我建立了一個小庫來處理這個確切的場景!這裏是SpriteBar:https://github.com/henryeverett/SpriteBar
我這樣做,它完美的作品。
因此,首先,我宣佈一個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];
當我想以減少健康,我做了以下內容:
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");
}
簡單,乾淨,不是C完全沒有問題。
那是我在迅速ProgressBar
:
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")
和這個進度添加到任何SKNode
:
self.addChild(progressBar)
//就是這樣。
非常感謝@Bikee! – Tritmm
你應該可以通過調用'+(SKTexture *)textureWithRect:inTexture:' – Aky