SKEffectNode, SpriteKit invert color in Swift - ios

I want to invert the color from the part of the HelloLable which is outside of the boxSprite. I know that it is possible with SKEffectNode but I don't know how.
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
let box = SKSpriteNode()
box.position = CGPoint(x: size.width/2-100, y: size.height/2)
box.color = UIColor.blackColor()
box.size = CGSize(width: 200, height: 200)
addChild(box)
let HelloLable = SKLabelNode()
HelloLable.text = "Hello"
HelloLable.position = CGPoint(x: size.width/2, y: size.height/2)
HelloLable.fontColor = UIColor.whiteColor()
HelloLable.fontSize = 50
addChild(HelloLable)
}

If I understand you correctly, you'd like to make something like this:
I don't think there is a standard solution to do this (maybe you could try blending modes or shaders).
Maybe the easiest solution could be to make 2 labels, one white in the box, and one black under the box, with similar properties, and clip the white one with the box.

Related

SpriteKit scrolling background image showing line between images

I'm learning how to make games in iOS, so I decided to replicate the first level of Mario Bros using my own assets, just to learn how to make them as well.
The issue I'm having right now is that, when creating the scrolling background, using this formula I found on Hacking with Swift, I keep getting a line in between my images.
I've checked that my images have no border in the AI file. (The images are the ones above)
import SpriteKit
import GameplayKit
class GameScene: SKScene {
private var player = SKSpriteNode()
private var bg = SKSpriteNode()
override func didMove(to view: SKView) {
let playerTexture = SKTexture(imageNamed: "player")
player = SKSpriteNode(texture: playerTexture)
player.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
addBackground()
self.addChild(player)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
// MARK: UTILITY FUNCTIONS
func addBackground() {
let bgTexture = SKTexture(imageNamed: "bg")
for i in 0 ... 1 {
bg = SKSpriteNode(texture: bgTexture)
//bg.position = CGPoint(x: (i == 0 ? bgTexture.size().width : bgTexture.size().width - 1) * CGFloat(i), y: self.frame.midY)
bg.position = CGPoint(x: (bgTexture.size().width * CGFloat(i)) - CGFloat(1 * i), y: 0)
bg.size.height = self.frame.height
//bg.anchorPoint = CGPoint.zero
bg.zPosition = -10
self.addChild(bg)
let moveLeft = SKAction.moveBy(x: -bgTexture.size().width, y: 0, duration: 5)
let moveReset = SKAction.moveBy(x: bgTexture.size().width, y: 0, duration: 0)
let moveLoop = SKAction.sequence([moveLeft, moveReset])
let moveForever = SKAction.repeatForever(moveLoop)
bg.run(moveForever)
}
}
}
Just create a new project, copy-paste it and you should see it running
I also changed my GameScene.sks size to: 2688 x 1242
And one last change I made to make the background appear in full screen was to set the LaunchScreen as stated in this answer which seems to be an issue in Xcode 12
I understand that the formula from Hacking with Swift post is making the images overlap by 1px, I've tried removing the 1 * i part from it, yet results are not different.
Other thing I did was to verify the images were "joining" perfectly together, and they do, the lines you can see in the image below are from the AI canvas, both images join in between "cactuses".
I also tried running it into a device in case it might be a bug in the simulator:
Your image has a thin black border on the left handside and along the top, 1 pixel wide. It's black. Remove that and try again.

How to create a physics body for an SKSpriteNode with an interior in Sprite Kit (Swift)

I am currently making an iOS game in which a ball must bounce within a frame defined by the below image:
The game relies on the below method to automatically create and assign a physics body to the frame surrounding the game.
frame.physicsBody = SKPhysicsBody(texture: frameTexture, size: frame.size)
This code, however, assigns a body that encompasses the outside of the image, rather than the interior, and thus treats the blank interior as a solid object. This, in turn, means that the ball cannot be inside the frame and is forced off the screen immediately after being spawned.
Is there any way to give a physics body an interior?
Another post here: SpriteKit SKPhysicsBody with Inner Edges aims to do something similar, but does not involve automatic wrapping around a texture (hence the new question)
You can use init(edgeLoopFrom:) initializer to achieve inner edge friction. you can use this code below:
override func didMove(to view: SKView) {
//Setup scene's physics body (setup the walls)
physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
let back = SKSpriteNode(imageNamed: "1")
back.position = CGPoint(x: frame.midX, y: frame.midY)
back.size = CGSize(width: 500, height: 600)
back.zPosition = -3
let rect = CGRect(origin: CGPoint(x: -back.size.width/2, y: -back.size.height/2), size: back.size)
back.physicsBody = SKPhysicsBody(edgeLoopFrom: rect)
addChild(back)
//Add Red ball "inside" the back sprite
let red = SKShapeNode(circleOfRadius: 20)
red.fillColor = .red
red.strokeColor = .clear
red.position = back.position
red.physicsBody = SKPhysicsBody(circleOfRadius: 20)
red.physicsBody?.restitution = 1
red.physicsBody?.friction = 0
red.zPosition = 1
red.physicsBody?.affectedByGravity = false
addChild(red)
red.physicsBody?.applyImpulse(CGVector(dx: 20, dy: 15))
}
please follow this Question and have a look to the answer given below.
i am providing a screenshot of my project

SKSpriteNode not scalling properly

I'm developing a small game using Swift & SpriteKit. When I add a SKSpriteNode for Restart button, it doesn't scale properly.
The size of Restart button is 100px in height and width. If I don't set scale , it covers the whole screen and make the screen appear white. I figured out that if I setScale to 0.005 only than it appears on screen, but not in proper size.
import Foundation
import SpriteKit
class EndScene: SKScene {
var restartBtn = SKSpriteNode()
override func didMoveToView(view: SKView) {
background()
restartGame()
}
func restartGame() {
restartBtn = SKSpriteNode(imageNamed: "restartBtn")
restartBtn.setScale(0.005)
restartBtn.position = CGPoint(x: self.size.width / 2, y: self.size.height / 4)
restartBtn.zPosition = 1
self.addChild(restartBtn)
}
func background() {
let bkg = SKSpriteNode(imageNamed: "Background")
bkg.size = self.frame.size
bkg.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2)
bkg.zPosition = -2
self.addChild(bkg)
}
}
Here is the output of this code,
Restart Button Output
UPDATE
I put scene!.scaleMode = .AspectFill right inside didMoveToView function and it helped in rendering the shape of the SpriteNode properly. But still I have to setScale(0.001) to make the size of Restart button fit in the screen. Can anyone assist me what line of code I'm still missing?
Instead of using .setScale try using restartBtn.size = CGSize(Width: 50, Height: 50)
This uses the Sprite Kit's resize formula.
I ran into this as well. It happened when I forgot to specify the size of the scene. Instead of calling initWithSize I just wrote init and the scene started to scale down all nodes by x1000. Nodes were visible, but they required a scale of 0.001

Swift: How to fill view with a SK Sprite Node?

I am trying to learn Swift by creating my own game (app), but I am having a problem.
I have a SKSpriteNode which I use as the background for the game. It's an image I've made. My problem is that my background won't fill the view so I get these grey bars outside of the Node.
What is wrong in my code?
override func didMoveToView(view: SKView) {
/* Setup your scene here */
Hintergrund = SKSpriteNode(imageNamed: "PenaltyLocker_BG1")
Hintergrund.size = CGSize(width: view.frame.width, height: view.frame.height)
Hintergrund.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2)
Hintergrund.zPosition = 1
Hintergrund.name = "Hintergrund"
addChild(Hintergrund)
Now when I start the simulator for iPhone it looks like this: http://imgur.com/a/mBOWn
Change to use the size of the SKScene.
self.scene.size.width / self.scene.size.height
Hintergrund.size = CGSize(width: self.scene.size.width, height: self.scene.size.height)
Hintergrund.position = CGPoint(x: self.scene.size.width/2, y: self.scene.size.height/2)
You can also check this tutorial for more info.

show keyboard on SKNode touch

I am trying to do a registration scene inside a game on iOS. what I have so far is this:
Since I couldn't manage to put UITextField inside the Scene that I have, I tried to put SKNodes that activate the keyboard on touch. It would be very useful if someone could help me to put UITextFields inside my game scene (because it would be easier to get a registration scene, and with less code, and also with native support for this).
My code so far is this:
let nameForm:SKSpriteNode = SKSpriteNode(imageNamed: "RegistrationScene_TEST_textviews")
let usernameForm:SKSpriteNode = SKSpriteNode(imageNamed: "RegistrationScene_TEST_textviews")
let passwordForm:SKSpriteNode = SKSpriteNode(imageNamed: "RegistrationScene_TEST_textviews")
let passwordForm2:SKSpriteNode = SKSpriteNode(imageNamed: "RegistrationScene_TEST_textviews")
And when someone touch any of these nodes it should be managed with a method like this:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let touch = touches.anyObject()! as UITouch
let location = touch.locationInView(self.view)
for touch:AnyObject in touches{
if CGRectContainsPoint(nameForm.frame, touch.locationInNode(self)){
//Function to display the keyboard
//Function that saves the keystroke
//Function to display a nameLabel with the saved keystroke
}
//same for the other Forms
//methods for the buttons (DONE)
}
}
If there is any other way to achieve a text input into the game (to save game statistics or something useful for the gameplay) please let me know, any help would be very appreciated
EDIT:
According to Cristian Woerz, i made the following and this solved my problem.
let txtField:UITextField!
txtField = UITextField(frame: CGRect(x: 0, y: 0, width: 200, height: 30));
self.view?.addSubview(txtField!)
Normally, you shouldn't use UIKit-elements in a SpriteKit-game. But For this problem, you can use a UITextfield and add it to your view:
var txtField: UITextField = UITextField(frame: CGRect(x: 0, y: 0, width: 200, height: 30));
self.view.addSubview(txtField)
You could also make your UITextField semi transparent by setting the background-color alpha value to less then the default 1:
txtField.backgroundColor = UIColor(red: 125/255, green: 125/250, blue: 125/250, alpha: 0.5)

Resources