How to add a ripple effect in Swift & SpriteKit - swift

In SpriteKit I have a starting button
startButton = SKSpriteNode(color: UIColor.red, size: CGSize(width: 130, height: 130))
startButton.name = "startButton"
startButton.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
self.addChild(startButton)
and around this node I want to add a ring that will expand and come back in again sort of like a rippling effect, so how would I add this effect?

Because it is in SpriteKit you have a few options, you could create a sprite that is the same shape as your button but only has an outline but no fill. Place this below your button and then when you want to do the ripple effect apply some actions to below image (repeat3times(sequence[scaleUp, fadeOut]))
Or you could take the same stroked image and create an effect in the particle editor, and then apply that particle effect to your button
You can check out my similar solution here How To Create a Pulse Effect On an SKSpriteNode?

Related

Add a popup text view to a SpriteKit game

I am creating a SpriteKit game and want to be able to take advantage of textAlerts - like all the games I grew up playing. I also want them to be flexible so I can subclass them and add them throughout my game - I am not sure how to do this and so would be very grateful of any advice.
There are a number of ways that I have started to look into:
Use another SKScene
The idea here would be to add another scene immediately on top of our current one. This would have a faded out background and would be configured with the text to be displayed. This seems like the wrong approach
Use an SKNode
I could create a custom node and initialise it with my specific text. I would then disable movement and add the node at the bottom of the screen. I would then customise the actions that occur when it is tapped.
Use an SKLabel
SKLabels are designed to show text so these seem like a promising place to look. The issue is that I want to add an image into the popup view (this a headshot of the person you are talking to) and so it doesn't feel like I should be able to inject an image in.
Use something else
I don't know what this might be. Is what I am trying to do easy or harder than I think?
My problem is that I come from a swift background so am struggling to convert to a SpriteKit mindset. In Swift I would put together a custom UIView with all the UIKit components and add it to the screen. In SpriteKit we don't have the same tools so I don't know the right combinations to put together what I want.
Ideally I want to be able to configure the text popup with an array of text so that a conversation can be had with the user tapping for each new line.
Edit 1: What I have tried so far
Based on #ElTomatos comment I have experimented with adding a SKSpriteNode and an SKLabelNode on top of each other using the following code:
guard let camera = camera else { return }
let dialogueBackground = SKSpriteNode(texture: nil, color: .red, size: CGSize(width: screenSize.width / camera.xScale, height: screenSize.height / 3 / camera.xScale))
dialogueBackground.anchorPoint = CGPoint(x: 0, y: 0)
dialogueBackground.zPosition = 50
dialogueBackground.position = CGPoint(x: -screenSize.width, y: -screenSize.height)
camera.addChild(dialogueBackground)
let label = SKLabelNode(text: "Hello world")
label.zPosition = 100
label.position = CGPoint(x: -screenSize.width, y: 100 - screenSize.height)
camera.addChild(label)
As you can see the view doesn't go to the edge of the screen. Is this something to do with the safe area? It's difficult to get the width and height as the camera doesn't have a CGSize we can use.

SpriteKit: Coloring the Background

i still try to learn Swift and SpriteKit and i have a new question.
So i am following this Tutorial/Video: Noise Field
My project now looks like this: My Project
I have 100 Particle Objects moving around and i want to blend some color of the particles to the white background. Inside the tutorial it is quiet easy. You just create the Background once, and inside the draw function (in SpriteKit this would be the update() function) you give your objects an alpha value like 0.1.
SpriteKit works quiet different. If i change the alpha value under draw my Particles are now almost hidden, but the color is not being "drawn" on the background.
I know this is because SpriteKit works different then the p5 library for javascript. But i wonder how i could get the same effect inside SpriteKit..
So inside the update function i have 2 loops, one for columns and one for rows. I have x columns and y rows - and for each "cell" i create a random CGVector. Now my Particles are moving around based on the CGVector of the cell which is the nearest to the Particles position.
My Particle Class looks like this:
class Particle: SKShapeNode{
var pos = CGPoint(x: 0, y: 0)
var vel = CGVector(dx: 0, dy: 0)
var acc = CGVector(dx: 0, dy: 0)
var radius:CGFloat
var maxSpeed:CGFloat
var color: SKColor
And i have a function which looks like this to show the Particles:
func show(){
self.position = self.pos
let rect = CGRect(origin: CGPoint(x: 0.5, y: 0.5), size: CGSize(width: self.radius*2, height: self.radius*2))
let bezierP = UIBezierPath(ovalIn: rect)
self.path = bezierP.cgPath
self.fillColor = self.color
self.strokeColor = .clear
}
And in the update function i have this loop:
for particle in partikelArr{
particle.updatePos()
particle.show()
}
How could i now "colorize" the white background or "draw" my particle on the background based on the particles position, color, shape and size?
Thanks and best regards
EDIT:
So i know create for each particle a new SKShapeNode inside the update function, so this works and it looks like the Particles have colorized the background:
This was created like this inside the update function:
for particle in partikelArr{
let newP = SKShapeNode(path: particle.path!)
newP.position = particle.pos
newP.fillColor = particle.farbe
newP.strokeColor = .clear
newP.zPosition = 1000
newP.alpha = 0.1
self.addChild(newP)
}
But i do not want to create SKShapeNodes for each Particle (on the screenshot i have used 5 Particles, after some seconds i already have over 800 nodes on the scene). I would like to let my 100 Particles really "draw" their Shape and Color on the white Background node.

SpriteKit: using SKView in UIView instead of initializing a Game project

Completely new to SpriteKit. Currently I have a UIView, and I want to add a sprite node to it (like a small UIImageView, but I want animation for it so using SpriteKit). Therefore I didn't initialize my project to be a game project, as found in almost all of tutorials for SpriteKit. I've found a note here: link and what I have now is sth like:
func initializeImage() {
let imageView = SKView()
imageView.frame = CGRect(x: self.frame.width / 2 - Constants.imageWidth / 2, y: self.frame.height - Constants.imageHeight, width: Constants.imageWidth, height: Constants.imageHeight)
// so place it somewhere in the bottom middle of the whole frame
let sheet = SpriteSheet(texture: ...)
let sprite = SKSpriteNode(texture: sheet.itemFor(column: 0, row: 0))
sprite.position = imageView.center //basically the same position as the imageView.frame's x and y value
let scene = SKScene(size: imageView.frame.size)
scene.backgroundColor = SKColor.clear
scene.addChild(sprite)
imageView.presentScene(scene)
self.frame.addSubview(imageView)
}
The SpriteSheet is similar to this: sprite sheet; it's essentially cutting an image atlas and divide it into smaller images. I tracked the process and this step is indeed giving the smaller image (the var 'sprite'). But if running I only have a black square now (should be the size as defined by Constants). If I set scene.backgroundColor to be white then it's white. May I know how I should proceed from here, as how should I make the sprite showing up?
All of your code looks good except for this:
sprite.position = imageView.center // basically the same position as the imageView.frame's x and y value
That is basically not the position you think it is. The coordinate system in SpriteKit is a) relative to the (SK)scene, not to whatever view the SKView is contained in, and b) flipped vertically relative to the UIKit coordinate system. If you want a sprite centered in the scene, you probably want to set its position based on the scene's size:
sprite.position = CGPoint(x: scene.size.width / 2, y: scene.size.height / 2)
By the way, the external SpriteSheet code might not be needed (and you're more likely to benefit from Apple's optimizations) if you slice up your sprite sheet and put it in an Xcode asset catalog.

Designing physics bodies other than circles

I'm making my first game with SpriteKit and for the enemy aliens (SKSpriteNode subclass) physics bodies I have been using:
self.physicsBody = SKPhysicsBody(circleOfRadius: self.size.width/2)
this has worked so far as most of the aliens are circle-shaped. However, if I were to have ellipse or square aliens what would be the best method of designing their physics bodies? I tried this for square shape:
let squarePath = UIBezierPath(rect: CGRect(x: -64, y: -64, width: 128, height: 128))
self.physicsBody = SKPhysicsBody(polygonFromPath: squarePath.CGPath)
but I don't know if this is the most efficient, and also don't know how to exactly make ellipses. Any suggestions would be great!
Let SpriteKit draw the shape for you!
If you have a sprite and you need to create a PhysicsBody for it just let SpriteKit do it for you. SpriteKit can analyze the texture, find the borders (using the alpha/transparent channel) and finally create a physics body matching the image.
Let's say I add this sprite to my scene
let croc = SKSpriteNode(imageNamed: "croc_walk01")
croc.position = CGPoint(x: frame.midX, y: frame.midY)
addChild(croc)
Automatically creating a PhysicsBody shape
Now I simply add this line
croc.physicsBody = SKPhysicsBody(texture: croc.texture!, size: croc.texture!.size())
And SpriteKit automatically creates the PhysicsBody for me.
Can you see the line line around the sprite? That's it. Let me hide the sprite so you can see it better
croc.hidden = true
Using paths is the only way to create complex physics bodys, however, you can create rectangles with SKPhysicsBody(rectangleOf: CGSize(width: 100, height: 100))
Edit:
Use this to help create efficient paths from images: http://insyncapp.net/SKPhysicsBodyPathGenerator.html
Note: this will only generate the paths for the image, you will need to clean it up your self by deleting paths and connecting the points.

How to add a border to a health bar in SpriteKit?

I have a health bar I created in SpriteKit.
I have a function that creates the health bar and attaches it to an SKSpriteNode(dragonNode)
The health bar I current have implemented is simply a SKSpriteNode with a rectangular shape.
Here is the code
func dragonHealth(dragonNode: SKSpriteNode) -> SKSpriteNode{
healthbar = SKSpriteNode(color: UIColor.greenColor(), size: CGSizeMake(self.frame.size.width * 0.5, self.frame.size.height * 0.015))
healthbar.anchorPoint = CGPointMake(0, 0.5)
healthbar.position = CGPointMake(self.frame.size.width * -0.23, self.frame.size.height * 0.3)
healthbar.runAction(SKAction.resizeToWidth(self.frame.size.width * 0.1, duration: 3))
dragonNode.addChild(healthbar)
return dragonNode
}
Can someone share a way to implement a border to my current health bar. I think it will look better that way.
Why don't you simply add another sprite underneath your healthbar sprite that is slightly bigger and in a different colour. (Make it parent of your main healthbar so they stay/move together).
There also is this tutorial on Ray Wenderlich where they are using health bars, its about half way through the page.
https://www.raywenderlich.com/90520/trigonometry-games-sprite-kit-swift-tutorial-part-1
Hope this helps