Swift SpriteKit Health Bar - ios

I want to add a Health Bar (a progressing Bar) in my Scene.
It's a rectangle bar filled with a color, on the upper left in the Scene, and every second the bar decreases (the filled color). After 2 Objects (SKSpriteNode's) hit each other, it gives you + 5 seconds time.
Thanks to LearnCocos2D and CloakedEddy, I know that I can make the Bar by using simply SKSpriteNode with Color or SKCropNode instead of SKShapeNode.
How should I implement it now at best to decrease itself every second smoothly?
My Code:
....
var progressValue = 200
....
HealthBar = SKSpriteNode(color:SKColor .yellowColor(), size: CGSize(width: progressValue, height: 30))
HealthBar.position = CGPointMake(self.frame.size.width / 3, self.frame.size.height / 1.05)
HealthBar.anchorPoint = CGPointMake(0.0, 0.5)
HealthBar.zPosition = 4
self.addChild(HealthBar)

What you could do is have a SKSpriteNode be the health bar. Then you have a SKSpriteNode as a frame over the first node. You have an action SKAction.repeatForever(SKAction.sequence([SKAction.moveByX(moveAmount, y: 0, duration: 0.5), SKAction.waitForDuration(0.5)])) and make the health bar (not the frame) run that action. What that will do is move the health bar off the screen, making it look like its going down.
About the collision problem, look at this tutorial. If that doesn't help, maybe you could find others. I want to help with this one, but collision detection is fairly in-depth even with SpriteKit. I hope this helped. Good Luck!

Related

SKSpriteNode not responding to set color & blendModeFactor (SpriteKit & Swift)

I know there are several other posts about this, but my case is kinda specific, i haven't seen this one yet.
I have in my game a ball-shaped sprite, that whenever I tap on it, I would like to add a colorised version of the very same sprite but with an effect of fadeIn and fadeOut.
Going to give you an example code:
self.ball = SKSpriteNode(imageNamed: "ball")
self.ball.position = CGPoint(x: midX, y: midY)
self.ball.zPosition = 1
self.ball.size = CGSize(width: 100, height: 100)
self.touchEffect = SKSpriteNode(imageNamed: "ball")
self.touchEffect.position = CGPoint(x: 0, y: 0)
self.touchEffect.zPosition = 2
self.touchEffect.size = CGSize(width: 100, height: 100)
self.touchEffect.color = UIColor.whiteColor()
self.touchEffect.blendColorFactor = 1
self.touchEffect.alpha = 0
self.ball.addChild(self.touchEffect)
self.addChild(self.ball)
Now, up to this point... I can't even see the touchEffect sprite colorised (if I put alpha to 1), but the same color of the original sprite. Why is this?
At the touchesBegan I do something like this:
func showTapEffect() {
let fadeIn = SKAction.fadeInWithDuration(0.3)
let fadeOut = SKAction.fadeOutWithDuration(0.3)
let sequence = SKAction.sequence([fadeIn,fadeOut])
self.touchEffect.runAction(sequence)
}
I also used it in different scenarios within my very same game, and it worked. Don't know why this unique case doesn't. Any hint? If you need more example code, let me know, is not a copy paste of my current code tho, I just typed it from my memory so you might see a typo error in there. But the code is very alike.
(And my sprite isn't dark or black)
Thanks in advance.
I am posting this an an answer because it is too large for comments, and I can post code in here if need be.
I just reread your thing like 3 times over, You are blending with White, what color are you expecting to get? if you blend Blue and White, you get Blue, if you blend Purple and Blue, You would get Blue. If you blend Blue and Gray, you get a darker Blue. It is all percentage multiplication. I do not believe you get a blend mode to pick from with colors. How it works is it takes the color of each pixel, and on the pixel, breaks it up into R,G,B, then it takes your color, and breaks that up into R G B (lets call it CR CG CB). The math becomes (R * CR,G * CG,B * CB) on a per pixel level.
You are doing (R * 1,G * 1,B * 1) which is (R,G,B)
If you want to colorize your sprite, then you need your sprite to be a gray scale image, and use colors only when you want them to stay that color (To a degree, because blending will still apply to them, you need to figure out the math on how you want it to blend)

infinite scrolling background - how to make objects move with ground

I have an infinitely scrolling background and a character 'walking' on the ground plane.
I want to drop objects from above and have them land on the ground - so far so good. But the objects don't move with the ground.
Can't find any examples where this is taken care of.
my 'ground' is just an edge at the correct height with regard to my graphics background.
let Edge = SKNode()
Edge.physicsBody = SKPhysicsBody(edgeFromPoint: CGPointZero, toPoint: CGPointMake(self.frame.width + 1, 0))
Edge.position = CGPointMake(0, bottomShelf_ItemStartPosition.y)
self.addChild(Edge)
I've tried giving my ground SKSriteNode physical properties, but this didn't make any difference.
What would be the best approach for this? Must be a simple way to make the moving ground effect objects.
adding scroll routine:
func backgroudScrollUpdate1(){
back.position = CGPoint(x: back.position.x - scrollPerFrameAmount, y: back.position.y)
back2.position = CGPoint(x: back2.position.x - scrollPerFrameAmount, y: back2.position.y)
if (back.position.x < -(back.size.width / 2)) {
back.position = CGPointMake(back2.position.x + back.size.width, back.position.y)
}
if (back2.position.x < -(back.size.width / 2)) {
back2.position = CGPointMake(back.position.x + back2.size.width, back2.position.y)
}
}
update - some progress
i have set up a physics world, where my ground is infinitely scrolling. I've got some items that fall out of the 'sky' and land on the ground. I can move the things around by applying impulse directly or one thing hitting another.
But, what i expected is that the scrolling ground would 'pull' things along with it if they are on the ground?
I have played around with different friction levels of both the ground at the items touching the ground, but it doesn't seem to matter.
one thing that did sort of work is if i set the phsyics body of an item to a circle, then the ground does influence the item, turning it around in the opposite direction of the scrolling - but when it hits an edge it just stops, rather than spinning at the edge.
If that part is working, then why wouldn't a rectangle be dragged along by the ground ?
would love to see example code of a phsyics world that does have the ground effecting other nodes..

Moving SCNLight with SCNAction

I have a spotlight, created with the code beneath, casting shadows on all of my nodes:
spotLight.type = SCNLightTypeSpot
spotLight.spotInnerAngle = 50.0
spotLight.spotOuterAngle = 150.0
spotLight.castsShadow = true
spotLight.shadowMode = SCNShadowMode.Deferred
spotlightNode.light = spotLight
spotlightNode.eulerAngles = SCNVector3(x: GLKMathDegreesToRadians(-90), y: 0, z: 0)
spotlightNode.position = levelData.coordinatesForGridPosition(column: 0, row: playerGridRow)
spotlightNode.position.y = 1.5
rootNode.addChildNode(spotlightNode)
The scene is moving along the z axis, and the camera has an infinite animation that makes it move:
let moveAction = SCNAction.moveByX(0.0, y: 0.0, z: CGFloat(-GameVariables.segmentSize / 2), duration: 2.0)
cameraContainerNode.runAction(SCNAction.repeatActionForever(moveAction))
As the camera moves though, the light doesn't, so after a while, the whole scene is dark. I want to move the light with the camera, however if I apply to the light node the same moving animation, all the shadows start to flicker. I tried to change the SCNShadowMode to Forward and the light type to Directional, but the flickering is still there. With directional, I actually loose most of my shadows. If I create a new light node later on, it will seem that I have two "suns", which of course is impossible. The final aim is simply to have an infinite light that shines parallel to the scene from the left, casting all the shadows to the right. Any ideas?
Build a node tree to hold both spotlight and camera.
Create, say, cameraRigNode as an SCNNode with no geometry. Create cameraContainerNode and spotlightNode the same way you are now. But make them children of cameraRigNode, not the scene's root node.
Apply moveAction to cameraRigNode. Both the camera and the light will now move together.

SpriteKit - Basic Positioning of a label in a background

Very new to Sprite Kit and i'm doing some reading now, but wanted to ask about something that I haven't found the best answer to yet.
I'm doing a tutorial with some code that creates a background, and then adds a label to show a score. I started changing the label code to position it on the top-left corner of the screen.
Here is the code (with my edits to the label, gameLabel):
let screenSize = UIScreen.mainScreen().bounds
let screenWidth = screenSize.width
let screenHeight = screenSize.height
let background = SKSpriteNode(imageNamed: "background")
background.position = CGPoint(x: screenWidth / 10, y: (screenHeight / 15) - 100)
background.blendMode = .Replace
background.zPosition = -1
addChild(background)
gameScore = SKLabelNode(fontNamed: "Chalkduster")
gameScore.text = "Score: 0"
gameScore.position = CGPoint(x: screenWidth / 10, y: (screenHeight / 15) - 100)
gameScore.horizontalAlignmentMode = .Left
gameScore.verticalAlignmentMode = .Top
gameScore.fontSize = 48
addChild(gameScore)
So the label is not displaying in any case, and my assumption is this:
Because i'm adding the background first, the label is getting added within the confines of the background, therefore it needs to be positioned differently, perhaps using the label size instead of the screen size?
My questions:
How can I get the label to always appear in the top left?
The author chose a hard-coded CGPoint for this background image and then said it has to be on an iPad, but i'd like to do it for iPhone 6/plus in landscape as well as iPad. Is there a way I can just make it work on both devices without having to specify a CGPoint like that? Can't it just scale and work regardless?
Thanks and apologies if these are basic questions - i'm going to do my best to continue reading on the subject..
Your question has a simple answer to it. You have forgotten and missed out somethings in your code, and I can show you these things.
In your code you set the background ZPosition to -1, the smallest number will always appear at the back. So if you set the SKLabelNode to a bigger zPosition it will always appear at the front, as maybe there may be a problem with rendering, as I have also experience like these, I fix it this way:
Before you add the LabelNode set it's property to this:
gamescore.zPosition = 0
0, In this case could just be anything bigger than the backgrounds(or the node that you want to appear at the back). So this just tells the compiler that you want the LabelNode to appear at the front, or in front of the Background.
If you want to make a universal app or game, with SpriteKit you will need to add some extra code to your game or app. Since I think that it is better to give you a good tutorial to show you instead of showing you some basics, I will give you a good link on how to do this:
SpriteKit: how to make a universal app
I hope this helps, and don't worry this took me some time to figure out my self.

SKLIghtNode with Swift

I have a player in the center of the screen, which I'd like to be the "source" of the light, so every other sprite, such as flying enemies, are casting a shadow.
I have this code:
light.categoryBitMask = 1
light.falloff = 1
light.shadowColor = UIColor.blackColor()
light.position = CGPoint(x: size.width / 2, y: size.height / 2)
addChild(light)
I'm totally new to Swift, never had any experience with SpriteKit, so I figured out that I should add this to every Sprite:
enemyOne.shadowCastBitMask = 1
What I get is quite interesting. The screen flickers everytime an enemy sprite is being spawned. But other than that, and a really small light in the center of the screen, where my player is, I'm not getting any shadows.
To make my plan more clear, I'd like to make it look like this:
This is what it looks like, as requested:

Resources