Comment créer une barre de progression dans un kit sprite?

Je veux créer ma propre barre de progression dans Sprite Kit.
J'ai pensé que j'aurais besoin d'images – une barre de progression entièrement vide et une barre de progression remplie.
J'ai ces images, je les ai remplies au-dessus de celles vides, elles sont des SKSPriteNodes maintenant je n'arrive pas à comprendre comment couper mon image remplie là où j'en ai besoin?

Comment est-ce que je coupe l'image de SKSpriteNode à un certain point? Peut-être la texture?

Je recommand de regarder dans SKCropNode . Pour une aide visuelle sur le fonctionnement de SKCropNode , searchz-le dans le Guide de programmation Apple . J'ai lu le document entier plusieurs fois et c'est une lecture particulièrement bonne.

SKCropNode est essentiellement un SKNode que vous ajoutez à votre scène, mais ses enfants peuvent être recadrés par un masque. Ce masque est défini dans la propriété maskNode du SKCropNode. De cette manière, vous n'avez besoin que d'une image de texture. Je voudrais sous-class SKCropNode pour implémenter des fonctionnalités pour déplacer ou resize le masque, de sorte que vous pouvez facilement mettre à jour son apparence.

 @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 

Dans votre scène:

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

Note: ce code ne déplace pas le masque (donc le sprite sera coupé de chaque côté) mais je suis sûr que vous avez l'idée.

Tout simplement: vous avez besoin d'une image de cadre (facultatif) et une image de «barre». L'image de barre dehors pour être une couleur simple et solide et aussi haut que vous en avez besoin et 1 ou 2 pixels de large. Un SKShapeNode en barre fera aussi bien.

Juste faire la barre et animer consiste simplement à changer la propriété size de SKSpriteNode. Par exemple, pour que la barre représente la progression entre 0 et 100, faites simplement:

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

Mettez à jour la taille chaque fois que progressValue change.

Vous remarquerez que l'image augmentera en largeur à la fois vers la gauche et vers la droite, pour l'étirer uniquement vers la droite, changez le point d'ancrage pour aligner l'image à gauche:

 sprite.anchorPoint = CGPointMake(0.0, 0.5); 

C'est tout. Dessinez un sprite de cadre autour de lui pour le rendre plus agréable.

En supposant que HealthBarNode est une sous-class de SKSpriteNode avec une propriété publique qui varie entre 0.0 et 1.0 et dont la texture propriété parentale est générée à partir de l'image entière de largeur _textureWidth (une propriété privée), vous pouvez faire quelque chose comme ceci:

 - (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; } 

Si vous définissez l' health de health sur une nouvelle valeur, la barre d'intégrité (ajoutée en tant qu'enfant à la scène principale, par exemple) sera recadrée correctement.

J'ai construit une petite bibliothèque pour faire face à ce scénario précis! Voici SpriteBar: https://github.com/henryeverett/SpriteBar

Il n'y a pas de "couper" une image / texture.

Une alternative à ce que Cocos propose est de faire quelques textures et de les échanger dans votre noeud en fonction de votre santé. J'ai fait un jeu où la barre de santé a changé de texture tous les 10 points (plage de 0 à 100). Après quelques essais et erreurs, j'ai fini par faire ce que Cocos avait déjà suggéré.

entrez la description de l'image ici

Je l'ai fait comme ça, et ça fonctionne parfaitement.

Donc d'abord, j'ai déclaré 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]; 

J'ai ensuite ajouté un 'Frame' pour la barre, avec un SKShapeNode, sans couleur de remplissage (clearcolour), et une couleur de trait:

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

Quand je voulais réduire la santé, j'ai fait ce qui suit:

  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, propre et pas compliqué du tout.

c'est mon ProgressBar dans swift:

 import Foundation import SpriteKit class IMProgressBar : SKNode{ var emptySprite : SKSpriteNode? = nil var progressBar : SKCropNode init(emptyImageName: Ssortingng!,filledImageName : Ssortingng) { 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") } 

}

//Comment utiliser :

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

ou

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

et ajoutez cette SKNode progression à n'importe quel SKNode :

 self.addChild(progressBar) 

//C'est tout.