How to delete objects by touch in swift Xcode - ios

I am trying to delete an image that is moving by touch and only that image. I spawn multiple images of that same image and I only want to delete the ones that are being touched. How can I do this? Any ideas? I am running IOS app Game and SpriteKit.
import SpriteKit
`class GameScene: SKScene {
override func didMoveToView(view: SKView) {
/* Setup your scene here */
let myLabel = SKLabelNode(fontNamed:"Chalkduster")
myLabel.text = "Hello, World!"
myLabel.fontSize = 45
myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
self.addChild(myLabel)
}
func generateNode() {
let Bullet = SKSpriteNode(imageNamed: "Bullets")
Bullet.name = "generatedNode"
}
func touchesCancelled(touches: NSSet, withEvent event: UIEvent?) {
let touch = touches.anyObject() as! UITouch?
if let location = touch?.locationInNode(self)
{
for Bullet in self.nodesAtPoint(location)
{
if Bullet.name == "generatedNode"
{
Bullet.removeFromParent()
}
}
}
}
}
func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}

Related

Unable to move sprite left or right in SpriteKit

https://github.com/bmh3110/JackTheGiantGame
I'm unable to move my sprite left or right when the screen is touched. I'm just starting this game and I can't even get it to work. I've had this problem for a few days and it's getting really frustrating.
GameplayScene.swift
import SpriteKit
class GameplayScene: SKScene {
var player : Player?
var canMove = false
var moveLeft = false
var center : CGFloat?
override func didMoveToView(view: SKView) {
center = (self.scene?.size.width)! / (self.scene?.size.height)!
player = self.childNodeWithName("Player") as? Player!
}
override func update(currentTime: NSTimeInterval) {
managePlayer()
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
if location.x > center {
moveLeft = false
} else {
moveLeft = true
}
}
canMove = true
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
func managePlayer() {
if canMove {
player?.movePlayer(moveLeft)
}
}
}
Player.swift
import SpriteKit
class Player: SKSpriteNode {
func movePlayer(moveLeft: Bool) {
if moveLeft {
self.position.x = self.position.x - 7
} else {
self.position.x = self.position.x + 7
}
}
}
In the touchesEnded function set canMove = false

Allow multiple instances of an SKAction

I am trying to create a "Space Invaders" game in swift, when the user touches the screen a bullet is shot from the ship, but when I try to touch it again while the bullet is moving across the screen I have an NSException and the game breaks. How do I set up the action so that there can be multiple instances of the action, so that the shooter is semi automatic. Below is my current scene controller.
import SpriteKit
class GameScene: SKScene {
let background = SKSpriteNode(imageNamed: "background")
let heroShip = SKSpriteNode(imageNamed: "heroShip")
let bullet = SKSpriteNode(imageNamed: "bullet")
override func didMoveToView(view: SKView) {
/* Setup your scene here */
background.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame))
heroShip.position = CGPointMake(self.size.width/6.0, self.size.height/2.0)
self.heroShip.zPosition = 1.0
self.addChild(background)
self.addChild(heroShip)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
bullet.position = CGPointMake(heroShip.position.x + bullet.size.width/2, heroShip.position.y)
let action = SKAction.moveToX(self.frame.width + self.bullet.size.width, duration: 0.5)
self.addChild(bullet)
bullet.runAction(action, completion: {
self.bullet.removeAllActions()
self.bullet.removeFromParent()
})
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
If you want to have multiple bullets shot from one ship, you have to create multiple instances of a bullet. What you have now is bullet property of GameScene class which is a mistake.
You probably want to instantiate bullets dynamically in your IBAction
So try something like this:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let bullet = SKSpriteNode(imageNamed: "bullet")
bullet.position = CGPointMake(heroShip.position.x + bullet.size.width/2, heroShip.position.y)
let action = SKAction.moveToX(self.frame.width + bullet.size.width, duration: 0.5)
self.addChild(bullet)
bullet.runAction(action, completion: {
bullet.removeAllActions()
bullet.removeFromParent()
})
}
and remove
let bullet = SKSpriteNode(imageNamed: "bullet")
from the top of the class

How to tap correct SKSpriteNode in automated test?

How to tap the correct SKSpriteNode in my iOS game created in swift (XCode 7, SpriteKit)? Finding the node seems not to be the issue, since in the test, 'exists' returns true. When I change my test to "app.tap()" then it does work. Except I have multiple SKSpriteNodes, so this does not solve my problem.
Below you can find code snippets. I hope you can help me with my problem. Any suggestions/hints are welcome.
Code snippet from my SKScene:
override func didMoveToView(view: SKView) {
var newGameButton : SKSpriteNode!
newGameButton = SKSpriteNode(imageNamed: "button")
newGameButton.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)+5)
newGameButton.size = CGSizeMake(200.0, 40.0)
newGameButton.name = "newGame"
newGameButton.isAccessibilityElement = true
newGameButton.userInteractionEnabled = true
newGameButton.accessibilityLabel = "newGame"
self.addChild(newGameButton)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first as UITouch!
let location = touch.locationInNode(self)
let nodes = self.nodesAtPoint(location)
for node in nodes {
if (node.name == "newGame") {
viewController.beginNewGame()
break
}
}
}
Current setup in UITest:
import XCTest
class MemoryPlayUITests: XCTestCase {
override func setUp() {
super.setUp()
continueAfterFailure = false
XCUIApplication().launch()
}
override func tearDown() {
super.tearDown()
}
func testStartNewGame() {
let app = XCUIApplication()
let newGameButton = app.otherElements["newGame"]
XCTAssertEqual(newGameButton.label, "newGame")
XCTAssertTrue(newGameButton.exists)
newGameButton.tap()
...{test logic to test if new game is started}
}
}

How do I use buttons or a slider to rotate a sprite?

I am making a game for iOS in Swift with SpriteKit, the game is currently just a ball moving around with a sword.
I have anchored the sword to the bottom of the sword, but I need to know how to control the direction of rotation with 2 buttons or a slider of some sort.
Here is my code:
import SpriteKit
let sprite = SKSpriteNode(imageNamed:"Player")
let weapon = SKSpriteNode(imageNamed: "weapon")
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
let initialPlayerLocation = CGPoint(x: self.frame.width/2, y: self.frame.height/2)
/* Setup your scene here */
//player
sprite.setScale(1.0)
sprite.position = initialPlayerLocation
sprite.zPosition = 20
self.addChild(sprite)
//weapon
weapon.setScale(1.0)
weapon.position = initialPlayerLocation
weapon.zPosition = -20
weapon.anchorPoint = CGPointMake(0.5,0.0);
self.addChild(weapon)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
var move = SKAction.moveTo(location, duration:1.0)
sprite.runAction(move)
weapon.runAction(move)
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
Okay, I think I understand what you are trying to do. It involves a lot of code, but in theory it is pretty simple. We detect if the touch is inside the left or right buttons (which in this example, I've made them SKSpriteNodes), and then set boolean values for the update method to use and rotate the weapon node (I'm assuming this is the sword you were talking about).
I've also included a variable that lets you set the speed of rotation. As you did not say what speed you were looking for, I left it up to you.
At the top of the program:
let sprite = SKSpriteNode(imageNamed:"Player")
let weapon = SKSpriteNode(imageNamed: "weapon")
let leftButton = SKSpriteNode(imageNamed: "leftButton")
let rightButton = SKSpriteNode(imageNamed: "rightButton")
var leftPressed = false
var rightPressed = false
let weaponRotateSpeed = 0.01 // Change this for rotation speed of weapon
And then modify touchesBegan to look like this:
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
if (leftButton.containsPoint(p: location))
leftPressed = true
else if (rightButton.containsPoint(p: location))
rightPressed = true
else {
var move = SKAction.moveTo(location, duration:1.0)
sprite.runAction(move)
weapon.runAction(move)
}
}
In update, add this code:
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
if (leftPressed && rightPressed) {
// Do nothing, as both buttons are pressed
} else if (leftPressed) {
weapon.zRotation -= weaponRotateSpeed
} else if (rightPressed) {
weapon.zRotation += weaponRotateSpeed
}
}
We want to stop the weapon from rotating when we detect when the finger has moved off the button like so:
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
if (leftButton.containsPoint(p: location))
leftPressed = true
else
leftPressed = false
if (rightButton.containsPoint(p: location))
rightPressed = true
else
rightPressed = false
}
}
And at last, we need to detect when your finger has left the screen:
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if (leftButton.containsPoint(p: location))
leftPressed = false
if (rightButton.containsPoint(p: location))
rightPressed = false
}
}

SpriteKit Transition Won't Work

I'm trying to add a transition to my SpriteKit scene, but it won't work. My second scene is called "myScene." Here's my code:
func didBeginContact(contact: SKPhysicsContact) {
let collision:UInt32 = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask)
if collision == (playerCategory | crateCategory) {
NSLog("Game Over")
self.scene?.view?.paused = true
var myscene = myScene(size: self.size)
var transition = SKTransition.doorsCloseHorizontalWithDuration(0.5)
myscene.scaleMode = SKSceneScaleMode.AspectFill
self.scene!.view?.presentScene(myscene, transition: transition)
}
if (contact.bodyA.categoryBitMask == bubbleCategory) {
let node = contact.bodyB.node
//Other remove routine
node?.removeAllActions()
node?.removeFromParent()
} else if (contact.bodyB.categoryBitMask == bubbleCategory) {
let node = contact.bodyB.node
//Other remove routine
node?.removeAllActions()
node?.removeFromParent()
}
}
What's the problem here?
This will present the scene and it works fine for me every time. This will not return nil for the scene so it will transition smoothly. You can also set ignoreSiblingOrder to whatever you want with this line: skView?.ignoresSiblingOrder = true //or false
Here is my GameScene:
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
self.backgroundColor = UIColor.redColor()
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
println("touch occured in gamescene")
let scene:SKScene = myScene()
let skView = self.view as SKView?
skView!.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
scene.size = skView!.bounds.size
skView!.presentScene(scene)
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}

Resources