Does anybody know how to detect a forced touch/click on the remote control with tvOS?
I want to use the click in a Sprite Kit scene to open a 'game paused alert'. I have no UIKit controls which have the focus and will react on the click.
I'm already using the 'normal' touch events on the remote control to move my sprites around.
Apple suggests using UIPressesEvent's to detect presses/clicks.
override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
for item in presses {
if item.type == .Select {
self.view.backgroundColor = UIColor.greenColor()
}
}
}
override func pressesEnded(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
for item in presses {
if item.type == .Select {
self.view.backgroundColor = UIColor.whiteColor()
}
}
}
override func pressesChanged(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
// ignored
}
override func pressesCancelled(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
for item in presses {
if item.type == .Select {
self.view.backgroundColor = UIColor.whiteColor()
}
}
}
Related
I am trying to detect presses in swift, and I am unable to detect a press. Here is my code:
override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
print("test1")
}
override func pressesChanged(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
print("test2")
}
override func pressesEnded(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
print("test3")
}
override func pressesCancelled(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
print("test4")
}
After executing the code on a physical apple tv and on a simulator, the console remains empty. Why are presses not being detected? Any help would be appreciated.
I have found the answer, but I am not sure why the override method didn't work.
let press:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(pressed))
press.allowedPressTypes = [NSNumber(value: UIPressType.select.rawValue)]
view.addGestureRecognizer(press)
I have a subclassed node called LocationNode, where touch is enabled. It looks like this.
class LocationNode: SKSpriteNode, CustomNodeEvents {
func didMoveToScene() {
self.isUserInteractionEnabled = true
}
}
I haven't overriden touchesBegan in this subclass file, because I want to control all touch events like this in the actual scene file:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touchLocation = touches.first!.location(in: self)
let touchedNode = self.atPoint(touchLocation)
//if touchedNode.name != nil {
print("touched")
//}
}
When I try do this, however, it doesn't work. How can I control touch events for a subclassed node in the scene file?
EDIT:
Here's what my override function looks like in the scene.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touchLocation = touches.first!.location(in: self)
let touchedNode = self.atPoint(touchLocation)
print("TOUCHED")
}
You could implement this code below in your custom class, in this case LocationNode, to have a "return of touches" to the parent class, then you can handle the touches in both places (also to the main scene) :
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
print("touched!")
}
guard let parent = self.parent else { return }
parent.touchesBegan(touches, with: event)
}
I am trying to respond to a press in a subclass of SKScene. I can override the responder pressesEnded inside of my ViewController just fine, but when I move my pressesEnded override into my SKScene sub class I no longer receive any calls.
Below is my pressesEnabled override, which works as intended inside of ViewController
override func pressesEnded(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
print("press")
}
Anybody know how to receive button presses inside of a SKScene?
You need to forward your press events from your ViewController to the SKScene, like so...
override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
gameScene.pressesBegan(presses, withEvent: event)
}
override func pressesEnded(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
gameScene.pressesEnded(presses, withEvent: event)
}
Then in gameScene (SKScene) do something like:
override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
for press in presses {
switch press.type {
case .UpArrow:
print("Up Arrow")
case .DownArrow:
print("Down arrow")
case .LeftArrow:
print("Left arrow")
case .RightArrow:
print("Right arrow")
case .Select:
print("Select")
case .Menu:
print("Menu")
case .PlayPause:
print("Play/Pause")
}
}
}
override func pressesEnded(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
print("Presses Ended.")
}
The "Arrow" presses are sent when the user taps the edges of the touchpad, but aren't recognized in the simulator. "Select" is sent when the center of the touchpad is tapped.
I hope this helps!
Use pressesBegan to map a physical button (Menu, PlayPause), and pressesBegan or pressesEnded for the trackpad of the Apple TV Remote (left, right, etc).
If you press on a "button" of the trackpad and move to another location and release, the method pressesEnded is not called, you can't do this with a physical button.
Presses Began:
override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
print("Press began")
for item in presses {
if item.type == .PlayPause {
print("PlayPause")
}
}
}
Presses Ended:
override func pressesEnded(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
print("Press Ended")
for item in presses {
if item.type == .RightArrow {
print("Right Arrow")
}
}
}
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.
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)