ios - mientras - ¿Cómo crear barra de progreso en el kit de sprites?
crear barra de progreso en vba (7)
Quiero crear mi propia barra de progreso en Sprite Kit.
Pensé que necesitaría imágenes: una barra de progreso completamente vacía y una barra de progreso llena.
Tengo esas imágenes, puse una llena sobre una vacía, son SKSPriteNodes
regulares SKSPriteNodes
Ahora no puedo entender cómo puedo cortar mi imagen completa donde la necesito.
¿Cómo puedo cortar la imagen SKSpriteNode en cierto punto? Tal vez la textura?
¡Construí una pequeña biblioteca para manejar este escenario exacto! Aquí está SpriteBar: https://github.com/henryeverett/SpriteBar
Lo hice así, y funciona perfectamente.
Entonces, primero, declare un 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];
Luego agregué un ''Marco'' para la barra, con un SKShapeNode, sin color de relleno (color claro) y un color de trazo:
//The following was so useful
SKShapeNode *edges = [SKShapeNode shapeNodeWithRect:baseBar.frame];
edges.fillColor = [UIColor clearColor];
edges.strokeColor = [UIColor blackColor];
[self addChild:edges];
Cuando quería reducir la salud, hice lo siguiente:
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");
}
Simple, limpio y nada complicado.
Muy simple: necesita una imagen de marco (opcional) y una imagen de "barra". La imagen de la barra es un solo color sólido y tan alto como lo necesite y de 1 o 2 píxeles de ancho. Un SKShapeNode como barra también lo hará.
Solo hacer la barra y animar es simplemente una cuestión de cambiar la propiedad de tamaño de SKSpriteNode. Por ejemplo, hacer que la barra represente un progreso entre 0 y 100 simplemente lo hace:
sprite.size = CGSizeMake(progressValue, sprite.size.height);
Actualice el tamaño cada vez que progressValue cambie.
Notarás que la imagen aumentará en ancho hacia la izquierda y hacia la derecha, para que se estire solo hacia la derecha, cambia el punto de anclaje para alinear a la izquierda la imagen:
sprite.anchorPoint = CGPointMake(0.0, 0.5);
Eso es todo. Dibuja un sprite de marco alrededor para que se vea mejor.
No hay "cortar" una imagen / textura.
Una alternativa a lo que ofrece Cocos es hacer un par de texturas e intercambiarlas en su nodo dependiendo de la salud. Hice un juego donde la barra de salud cambiaba la textura cada 10 puntos (el rango era 0-100). Después de un poco de prueba y error, terminé haciendo lo que Cocos ya sugirió.
Suponiendo que HealthBarNode
es una subclase de SKSpriteNode
con un health
propiedad público que varía entre 0.0 y 1.0 y cuya texture
propiedad parental se genera a partir de la imagen de barra de color completa de width _textureWidth
(una propiedad privada), podría hacer algo como esto:
- (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;
}
Establecer el health
de health
en un nuevo valor hará que la barra de estado (agregada como un niño a la escena principal, por ejemplo) se recorte apropiadamente.
Yo recomendaría investigar en SKCropNode . Para obtener ayuda visual sobre cómo funciona SKCropNode
, búsquelo en la Guía de programación de Apple . He leído todo el documento varias veces y es una lectura particularmente buena.
SKCropNode
es básicamente un SKNode que agregas a tu escena, pero sus hijos pueden ser recortados por una máscara. Esta máscara se establece en la propiedad maskNode
del SKCropNode. De esta forma, solo necesitas una imagen de textura. Subclase SKCropNode para implementar la funcionalidad para mover o cambiar el tamaño de la máscara, para que pueda actualizar fácilmente su apariencia.
@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
En tu escena:
#import "CustomProgressBar.h"
// ...
CustomProgressBar * progressBar = [CustomProgressBar new];
[self addChild:progressBar];
// ...
[progressBar setProgress:0.3];
// ...
[progressBar setProgress:0.7];
Nota: este código no mueve la máscara (por lo que el sprite se recortará en ambos lados), pero estoy seguro de que entiendes la idea.
esa es mi ProgressBar
en 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")
}
}
//Cómo utilizar :
let progressBar = IMProgressBar(emptyImageName: "emptyImage",filledImageName: "filledImage")
o
let progressBar = IMProgressBar(emptyImageName: nil,filledImageName: "filledImage")
y agregue este progressBar a cualquier SKNode
:
self.addChild(progressBar)
//Eso es todo.