2014-05-09 34 views
12

我想在Sprite Kit中創建我自己的進度條。
我想我會需要圖像 - 一個完全空的進度條和填充進度條。
我有這些圖像,我把一個放在空的頂部,他們經常SKSPriteNodes現在我不知道我如何削減我的需要填充的圖像?如何在sprite工具包中創建進度條?

我該如何在特定點處切割SKSpriteNode圖像?也許紋理?

+0

你應該可以通過調用'+(SKTexture *)textureWithRect:inTexture:' – Aky

回答

14

我會建議您調查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]; 

注:此代碼不動的面具(所以精靈將在兩側裁剪),但我敢肯定你的想法。

+0

SKCropNode沒有mask屬性,所以我假設這應該是maskNode? – Mike

+0

現貨!我編輯了答案以反映你的改進。 – CloakedEddy

+0

嗨,不好意思問這個問題,但是這段代碼確實顯示了帶'progressBarImage'圖像的精靈,但是'spriteNodeWithColor:[SKColor whiteColor]'什麼也沒做,爲什麼?我正在開發ios9。 –

7

很簡單:你需要一個幀圖像(可選)和一個「酒吧」圖像。條形圖像是一個單一的,純色和高達你需要它,1或2像素寬。 SKShapeNode as bar也可以。

只需製作條形圖和動畫即可改變SKSpriteNode的大小屬性。例如,使巴表示介於0和100只是做的進展:

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

更新大小,只要progressValue變化。

你會發現圖像將在寬度增加至左,右,使其伸展僅向右變更anchorPoint左對齊的圖像:

sprite.anchorPoint = CGPointMake(0.0, 0.5); 

這是所有。在它周圍繪製一個框架精靈,使其看起來更好。

+0

這個好,如果我有純色和正方形,就可以得到節點紋理的子集(假設是整個顏色條)酒吧,但如果我有複雜的酒吧呢?只是想削減它?有什麼方法可以在Sprite Kit中剪切或操作紋理? – Dvole

1

沒有「剪切」圖像/紋理。

Cocos提供的另一種方法是製作幾個紋理,並根據健康狀況將它們交換到節點中。我做了一個遊戲,健康欄每10分鐘改變一次紋理(範圍是0-100)。儘管經歷了一些嘗試和錯誤,但我最終只是做了科科斯已經提出的建議。

enter image description here

+1

有一種方法可以剪切圖像,請參閱我的回答,參考'SKCropNode'。 – CloakedEddy

3

假設HealthBarNodeSKSpriteNode與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到一個新的值將導致健康酒吧(作爲子項添加到主場景,說),以得到適當的裁剪。

+0

另一種方法是使用'SKCropNode' – Aky

+0

我會添加'SKCropNode'作爲這個選項的另一個選項併發送它。 :) – prototypical

+0

我使用這種方法獲取垃圾來代替紋理。我嘗試改變不同的值,但同樣,原始紋理是黃色的,我得到了一些灰色廢話的藍色。 – Dvole

1

我這樣做,它完美的作品。

因此,首先,我宣佈一個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完全沒有問題。

1

那是我在迅速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) 

//就是這樣。

+0

非常感謝@Bikee! – Tritmm