SKSpriteNode not detecting touch events - swift

I can not get the touchesBegan function to fire. It isn't being called when a user touched the node.
import SpriteKit
class SimpleButton: SKSpriteNode {
//called when the user taps the button
override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) {
println("touches began")
}
//called when the user finishes touching the button
override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) {
println("touches ended")
}
override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) {
println("touches moved")
}
}

The answer is, You need to enable touches using the userInteractionEnabled parameter.
let imageTexture = SKTexture(imageNamed: "a_button")
let sprite: SimpleButton = SimpleButton(texture: imageTexture)
sprite.userInteractionEnabled = true // <--- This is required, it defaults to false.
sprite.position = CGPoint(x:CGRectGetMidX(self.frame) - 200, y:CGRectGetMidY(self.frame));
sprite.color = UIColor.blackColor()
sprite.colorBlendFactor = 1.0
self.addChild(sprite)

Related

Make a ball bounce when pressed

I am trying to make a game where you can click a ball using SpriteKit. At the moment, I can click anywhere on the screen and the ball moves up.
I want it to only move or bounce when I click the ball. What am I doing wrong?
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var ball = SKSpriteNode()
var grass = SKSpriteNode()
override func didMove(to view: SKView) {
ball = (self.childNode(withName: "ball") as? SKSpriteNode)!
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 t in touches { self.touchDown(atPoint: t.location(in: self)) }
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
func touchDown(atPoint pos: CGPoint) {
jump()
}
func touchUp(atPoint pos: CGPoint) {
ball.texture = SKTexture(imageNamed: "football-161132_640")
}
func jump() {
ball.texture = SKTexture(imageNamed: "football-161132_640")
ball.physicsBody?.applyImpulse(CGVector(dx: Int.random(in: -5...5), dy: 80))
}
}
Multiple touches:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
if ball.contains(location) {
jump()
}
}
}
Single touch:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: self)
if ball.contains(location) {
jump()
}
}
}

Sprite Kit - how do i make the sprite jump by clicking on the image

I want to make the image jump by clicking on the sprite, rather than clicking the screen to make it jump.
func jump() {
Football?.texture = SKTexture(imageNamed: "Football")
Football?.physicsBody?.applyImpulse(CGVector(dx: 100, dy: 2000))
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
func touchUp(atPoint pos: CGPoint) {
Football?.texture = SKTexture(imageNamed: "Football")
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
this is a really basic way of testing if the sprite is touched
BTW your variable is named Football proper nomenclature says thay you should be using lower case variable names "football"
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first as UITouch! {
let touchLocation = touch.location(in: self)
if Football.contains(touchLocation) {
//jump code here
}
}
}

Touchesmoved - updating multiple elements on single drag

I'm trying to update multiple images upon clicking and dragging over the elements. I've implemented touchesbegan, touchesmoved, and touchesended, but I don't know how to make touchesmoved effect multiple images.
I've been scouring the web, but I haven't been able to find any guides on this. If you could point me in the right direction, or provide me with some basic advice, that would be greatly appreciated.
The following is an example image:
Edit: The following is an example image of what should be possible:
What it should look like.
I'd like to be able to effect the other letters in the same way through the same press, changing their pictures. These pictures are temporary images.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
print("touches began:\(touches)")
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.image = UIImage(named: "slot")!
print("touches moved:\(touches)")
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.image = UIImage(named: "tile")!
print("touches ended")
}
If I understood you correctly, that should be something like this:
class ChangableView: UIView {
private var touchedImageView: UIImageView? {
didSet {
if oldValue == touchedImageView { return }
if let oldValue = oldValue {
oldValue.image = UIImage(named: "tile")!
}
if let newValue = touchedImageView {
newValue.image = UIImage(named: "slot")!
}
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
guard let touch = touches.first else { return }
updateTouchedImageViewWithTouch(touch, event: event)
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
guard let touch = touches.first else { return }
updateTouchedImageViewWithTouch(touch, event: event)
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
touchedImageView = nil
}
}
private extension ChangableView {
func updateTouchedImageViewWithTouch(touch: UITouch, event: UIEvent?) {
let touchPoint = touch.locationInView(self)
let touchedView = self.hitTest(touchPoint, withEvent: event)
touchedImageView = touchedView as? UIImageView
}
}
In addition your UIViewController should have as view a subclass of ChangableView and do not forget to set userInteractionEnabled property to all the UIImageViews to YES.

How can i alter my program to allow this object to only react to a single touch?

I am making a basketball game. My problem is when I shoot the ball, i can then touch the ball in mid-air again, which i do not want. Once the user shoots the ball I do not want touch to have an effect. Here is my code:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?
{
touching = false
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if ball.frame.contains(location){
touchingPoint = location
touching = true
}
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
touchingPoint = location
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
if touching{
let dt:CGFloat = 8.25/29.5
let distance = CGVector(dx: touchingPoint.x-ball.position.x, dy: touchingPoint.y-ball.position.y)
let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
ball.physicsBody!.velocity=velocity
}
}
What can i add to my program so that a touch won't have any effect once the ball has been shot?
after you shoot the ball disable userInteraction
ball.userInteractionEnabled = false
then enable it again when you want them to be able to touch it

How to create background that follows the character in SWIFT?

I am working on this project in Xcode, where I am making animations. I have perfectly working program where little character walks around the screen. If I press on screen, that is direction the character is going. What I want to do here is to add a background image and make it follow where character is going. Basically, I want character to be able to walk around big map while he does not go out of the image. Something like scrollView, but only in gamescene.
P.S. All the code below is working, I just want to add the background image that moves along.
Here is some code for my main gamescene
override func didMoveToView(view: SKView) {
/* Setup your scene here */
// the hero is initialized with a texture
hero = Player(named: "hero_walk_down_0")
hero.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
self.addChild(hero)
if Settings.sharedInstance.virtualPad {
controller = ControllerNode(position: CGPoint(x:0, y: 0))
self.addChild(controller)
}
backgroundColor = SKColor.blueColor()
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if Settings.sharedInstance.virtualPad == false {
hero.destination = location
}
}
}
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
let previousLocation = touch.previousLocationInNode(self)
if Settings.sharedInstance.virtualPad == false {
hero.destination = location
}
}
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
touchesEndedOrCancelled(touches, withEvent: event)
}
override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
touchesEndedOrCancelled(touches, withEvent: event)
}
func touchesEndedOrCancelled(touches: NSSet, withEvent event: UIEvent) {
// when a touch is ended, remove it from the list
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
let previousLocation = touch.previousLocationInNode(self)
if Settings.sharedInstance.virtualPad == false {
hero.destination = nil
}
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
if Settings.sharedInstance.virtualPad {
hero.walk(self.controller!.pressedDirections())
}
else {
if hero.destination != nil {
hero.walkTowards(hero.destination!)
}
}
}
You create two SKNodes - one for the character and one for the background and add them to each group separately.
Whenever you move the SKNode of the character, you replicate the same action on the background node.