SpriteKit creating a button issues - swift

Im attempting to use some of the code from a solution found on this page for creating a button Create Button in SpriteKit: Swift
class GameScene: SKScene {
let button = SKSpriteNode(imageNamed: "yourImgName")
override func didMoveToView(view: SKView) {
button.name = "btn"
button.size.height = 100
button.size.width = 100
button.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) + 50)
self.addChild(button)
//Adjust button properties (above) as needed
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first
let positionInScene = touch!.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name {
if name == "btn" {
let yourNextScene = YourNextScene(fileNamed: "YourNextScene")
self.view?.presentScene(yourNextScene!)
}
}
}
}
and the current code that I have is supposed to make the player jump when the button is pressed, but nothing is currently happening when its pressed
import SwiftUI
import SpriteKit
import UIKit
class GameScene: SKScene {
override func didMove(to view: SKView) {
let button = SKSpriteNode(imageNamed: "playerOBJ")
let player = SKSpriteNode(imageNamed: "playerOBJ")
let playerRadius = player.frame.width / 2.0
player.position = CGPoint(x: 200, y: 500)
player.name = "Jimmy"
addChild(player)
player.physicsBody = SKPhysicsBody(circleOfRadius: playerRadius)
player.physicsBody?.allowsRotation = false
player.physicsBody?.friction = 0
player.physicsBody?.restitution = 0
player.zPosition = 100
// Button
button.name = "btn"
button.size.height = 100
button.size.width = 100
button.position = CGPoint(x: 100, y: 100)
self.addChild(button)
// Physics
physicsBody = SKPhysicsBody(edgeLoopFrom: frame.inset(by: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)))
Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { _ in
player.physicsBody?.applyForce(CGVector(dx: 100, dy: 1000))
}
func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first
let positionInScene = touch!.location(in: self)
let touchedNode = self.atPoint(positionInScene)
if let name = touchedNode.name {
if name == "btn" {
player.physicsBody?.applyForce(CGVector(dx: 0, dy: 10000))
}
}
}
}
override func update(_ currentTime: TimeInterval) { }
}
I'm thinking that maybe this is an issue with the press not being resitered at all but I'm not fully sure

Your main problem is you put all of your code inside the didMove function. You put the touchesBegan function inside the didMove function. When the didMove function finishes, touchesBegan goes away so none of your touches are going to be handled in the game.
You also declared the button and the player as local variables inside the didMove function.
override func didMove(to view: SKView) {
let button = SKSpriteNode(imageNamed: "playerOBJ")
let player = SKSpriteNode(imageNamed: "playerOBJ")
// Rest of function omitted
}
When the didMove function finishes, the button and player go away too. You also have the same image name for the player and button.
The fix is to make the button and player variables properties of the GameScene class. Move touchesBegan out of the didMove function too.
class GameScene: SKScene {
// Declare button and player here.
var button = SKSpriteNode()
var player = SKSpriteNode()
override func didMove(to view: SKView) {
// Initialize button, player, and everything else here.
}
func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
// Code in touchesBegan func goes here.
}
}

Related

Letting user chose which image a button has?

I´m new to coding and I´ve created a game with a black button in the main class. I want to create a setting class where the user can click on a blue button to change the black button in the main class or on a red button to change the black button in the main class to red.
Here is the main class:
class Mainclass: SKScene{
var gameButton = SKSpriteNode(imageNamed: "blackDot") //current button image
}
Here is the setting class:
class Settings: SKScene {
override func didMove(to view: SKView) {
self.backgroundColor = SKColor.white
let blueButton = SKSpriteNode(imageNamed: "blueDot") //button to select
blueButton.position = CGPoint(x: self.size.width * 0.2, y: self.size.height * 0.8)
blueButton.setScale(0.53)
self.addChild(blueButton)
let redButton = SKSpriteNode(imageNamed: "redDot") //button to select
redButton.position = CGPoint(x: self.size.width * 0.4, y: self.size.height * 0.8)
redButton.setScale(0.53)
self.addChild(redButton)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let locationUser = touch.location(in: self)
if atPoint(locationUser) == blueButton {
//Change the button image in the Mainclass from black to blue if user tap on blueButton
}
if atPoint(locationUser) == redButton {
//Change the button image in the Mainclass from black to red if user tap on redButton
}
}
}
}
So we have two scenes, called GameScene.swift and SettingsScene.swift and corresponding .sks files called GameScene.sks and SettingsScene.sks. Also we have three images, called default_button, purple_button and blue_button (stored in our .xcassets folder).
Here is the SettingsScene.swift:
import SpriteKit
class SettingsScene: SKScene {
var purpleButton = SKSpriteNode.init(imageNamed: "purple_button")
var blueButton = SKSpriteNode.init(imageNamed: "blue_button")
override func didMove(to view: SKView) {
backgroundColor = .purple
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let location = touches.first?.location(in: self) {
if purpleButton.contains(location) {
UserDefaults.standard.set("purple_button", forKey: "button")
}else if blueButton.contains(location){
UserDefaults.standard.set("blue_button", forKey: "button")
}else{
if let mainScene = GameScene(fileNamed:"GameScene") {
//transition to Settings scene
self.view?.presentScene(mainScene)
}
}
}
}
}
This scene has two buttons, and when a user tap on one of them, we will remember which one is tapped by storing appropriate image name in user defaults, for example:
UserDefaults.standard.set("purple_button", forKey: "button")
Later on we will read from a persistent storage (in GameScene didMoveTo:view method) and use what is found there.
Also, user defaults are not erased when app is closed by the user, so next time the a user launches the app, he will have his settings saved and ready to use.
So after selecting one of the buttons from the Settings scene, and transitioning to the GameScene, you will your button set to whatever you have previously chosen. Here is the GameScene:
import SpriteKit
class GameScene: SKScene {
let button = SKSpriteNode.init(imageNamed: "default_button")
override func didMove(to view: SKView)
{
if let buttonImageName = UserDefaults.standard.string(forKey: "button") {
//set what is found in settings
button.texture = SKTexture.init(imageNamed: buttonImageName)
}
backgroundColor = .white
addChild(button)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let location = touches.first?.location(in: self) {
if button.contains(location) {
}else{
if let settingScene = SettingsScene(fileNamed:"SettingsScene") {
//transition to Settings scene
self.view?.presentScene(settingScene)
}
}
}
}
}

Making my game object bounce forever?

So I am trying to make a ping pong game and I am able to get the ball moving and bouncing but the ball slows down. Whats the code to keep the balls velocity at a constant? Here's what I got:
var ball = SKSpriteNode()
var enemy = SKSpriteNode()
var main = SKSpriteNode()
override func didMove(to view: SKView) {
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width)
ball = self.childNode(withName: "ball") as! SKSpriteNode
enemy = self.childNode(withName: "enemy") as! SKSpriteNode
main = self.childNode(withName: "main") as! SKSpriteNode
ball.physicsBody?.applyImpulse(CGVector(dx: 20, dy: 20))
let border = SKPhysicsBody(edgeLoopFrom: self.frame)
border.friction = 0
border.restitution = 1
self.physicsBody = border
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
main.run(SKAction.moveTo(x: location.x, duration: 0.2))
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
main.run(SKAction.moveTo(x: location.x, duration: 0.2))
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
enemy.run(SKAction.moveTo(x: ball.position.x, duration: 1.0))
}
}
My physics settings are set to the following:
physics definition
Thanks in advance!

My Sprite won't perform the actions I tell it to?

I am making an app in Xcode 7 using Swift and SpriteKit. My idea is to have a spaceship that moves with the finger, or basically just follows it, yet I'm having trouble. This is the code:
import Foundation
import SpriteKit
class secondScene: SKScene {
override func didMoveToView(view: SKView) {
// var timer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: Selector(spawnBullets()), userInfo: nil, repeats: true)
//buttons
let leftbutton = SKSpriteNode(imageNamed: "LeftArrow")
leftbutton.position = CGPoint(x: self.frame.size.width*0.2, y: self.frame.size.height*0.1)
leftbutton.size = CGSize(width: 220, height: 80)
leftbutton.color = SKColor.blueColor()
leftbutton.zPosition = 100
self.addChild(leftbutton)
let rightbutton = SKSpriteNode(imageNamed: "RightArrow")
rightbutton.position = CGPoint(x: self.frame.size.width*0.8, y: self.frame.size.height*0.1)
rightbutton.size = CGSize(width: 220, height: 80)
rightbutton.color = SKColor.blueColor()
rightbutton.zPosition = 100
self.addChild(rightbutton)
//spaceship
let spaceship = SKSpriteNode(imageNamed: "spaceship")
spaceship.zPosition = 100
spaceship.size = CGSize(width: 200, height: 120)
spaceship.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height*0.15)
self.addChild(spaceship)
}
let spaceship = SKSpriteNode(imageNamed: "spaceship")
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
spaceship.position.x = location.x
}
}
}
I run this and to me it seems like my spaceship should follow my finger, yet it doesn't. It just stays in the position I specifies before. I've got no errors and I'm out of ideas. Any thoughts?
Remove this line in your spaceship code in didMoveToView
let spaceship = SKSpriteNode(imageNamed: "spaceship")
so that you are actually using the global property you created above touchesBegan.
You probably also want to include/move your code in touchesMoved.
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
spaceship.position.x = location.x
}
}
Hope this helps

Apply impulse depending on rotation - Swift

I am currently creating a 2D game in which I have a cannon staying at the bottom of the screen that fires projectiles to some targets in the upper part of the screen. The user can rotate the cannon in order to aim for the targets. I want the projectile to be fired to the location that the canon faces. I have no idea how to do that and I need your help... Heres my code ->
import SpriteKit
class GameScene: SKScene {
var canon = SKSpriteNode()
var projectile = SKSpriteNode()
var touching = false
var locked = false
var location = CGPoint()
override func didMoveToView(view: SKView) {
/* Setup your scene here */
projectile.position = canon.position
projectile.color = UIColor.whiteColor()
projectile.size = CGSize(width: 50, height: 50)
projectile.physicsBody?.affectedByGravity = false
projectile.physicsBody?.linearDamping = 1
projectile.physicsBody?.dynamic = true
addChild(projectile)
canon.zPosition = 2
canon = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: 50, height: 200))
canon.position = CGPoint(x: self.size.width/2.0, y: 10)
addChild(canon)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
touching = true
let touch = touches.first as UITouch!
location = touch.locationInView(self.view)
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
rotateCanon(location.x)
projectile.zRotation = canon.zRotation
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
touching = false
}
func rotateCanon(locationx:CGFloat) {
if locationx <= frame.width/5 && touching {
print(1)
canon.runAction(SKAction.rotateByAngle(0.01, duration: 0.1))
}
if locationx > frame.width/5 && touching {
print(2)
canon.runAction(SKAction.rotateByAngle(-0.01, duration: 0.1))
}
}
}`
Thanks a lot if you can help that would be awesome :D

Single click needed to run function instead of double click SpriteKit

Im making a flappy bird clone and when the bird dies, the spriteNode with restart button pop ups, but the fist click is stoping animation (if there any) and second click forse the restart() function
heres how i make SpriteNode menu with button:
let menu = SKSpriteNode(texture: self.groundTex)
menu.name = "menu"
menu.position = CGPoint(x: 0, y: 0)
menu.zPosition = 20
let restartButton = SKSpriteNode(texture: self.heroTexture)
restartButton.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame));
restartButton.zPosition = 40
restartButton.name = "restart"
let moveMenu = SKAction.moveTo(CGPoint(x: self.frame.size.width / 2, y: self.frame.size.height / 2), duration: 1.0)
self.menuNode.addChild(menu)
menuNode.addChild(restartButton)
self.addChild(menuNode)
menu.runAction(SKAction.sequence([
moveMenu,
SKAction.waitForDuration(NSTimeInterval(1.0)),
makeGameEnd
]), withKey: "gameover"
here is how i detect touch:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first
let location = touch?.locationInNode(self)
let node: SKNode = nodeAtPoint(location!)
if node.name == "restart" {
restart()
}
UPDATE
my restart():
func restart() {
let scene = GameScene(size: self.size)
scene.scaleMode = .AspectFill
self.view?.presentScene(scene)
}
You can check for a double tap like this
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first
let location = touch?.locationInNode(self)
let node: SKNode = nodeAtPoint(location!)
if touch.tapCount % 2 == 0 {
if node.name == "restart" {
restart()
}
}
}