I'm trying to figure out how to detect a touch anywhere on the screen with a subclass of SKScene so that I can transition. How do I do so?
Thanks
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let location = touch.location(in: self)
print(location)
//if your touch location = a button or anything it transitions to a new scene
if location = //Startbutton {
let transition = SKTransition.reveal(with: .down, duration: 0.75)
let gameScene = GameScene(size: size)
gameScene.scaleMode = scaleMode
view?.presentScene(gameScene, transition: transition)
Prints the users touch location... hope that helps a bit m8
Related
I'm making a game and at the moment I have a MenuScene and a GameScene. If I play the GameScene on its own, everything is displaying correctly. If I set the MenuScene as default and then press start the GameScene is out of position. As if it has been dragged slightly to the bottom left corner.
My Code for the transition:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if let location = touch?.location(in: self) {
let nodesArray = self.nodes(at: location)
if nodesArray.first?.name == "newGameButton" {
let transition = SKTransition.flipHorizontal(withDuration: 0.5)
let gameScene = GameScene(size: self.size)
gameScene.scaleMode = scaleMode
self.view?.presentScene(gameScene, transition: transition)
}
}
}
From searching the issue I see others had the same problem, because they didn't set the scene mode. But I have this "gameScene.scaleMode = scaleMode", I also tried "gameScene.scaleMode = .aspectFill"
My settings for both scenes are the same in the attributes inspector, so not sure what I'm doing wrong. Is it programmable error or settings error. I have added photos. Any help appreciated. Thank you.
I managed to fix it. I changed the Transition code.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if let location = touch?.location(in: self) {
let nodesArray = self.nodes(at: location)
if nodesArray.first?.name == "newGameButton" {
//let gameScene = GameScene(size: self.size)
let gameScene = GameScene(fileNamed: "GameScene")!
let transition = SKTransition.flipHorizontal(withDuration: 0.5)
gameScene.scaleMode = scaleMode
self.view?.presentScene(gameScene, transition: transition)
}
}
}
Now the scene is displaying correctly. Hopefully won't lead to any other issues.
Ok so currently in my game I have a ball that can be thrown. However, I want to make so that the user can only throw the ball past a certain point. I have been trying this for a while but I can't figure it out. How can I do this?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first as! UITouch?
let location = touch?.location(in: self)
if ball.frame.contains(location!) {
touchPoint = location!
touching = true
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first as! UITouch?
let location = touch?.location(in: self)
touchPoint = location!
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
touching = false
}
override func update(_ currentTime: TimeInterval) {
if touching {
let dt:CGFloat = 2.8/60.0
let distance = CGVector(dx: touchPoint.x-ball.position.x, dy: touchPoint.y-ball.position.y)
let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
ball.physicsBody!.velocity=velocity
}
}
Here, I have an image of my game so far. Currently, the ball can be dragged, thrown, or swiped anywhere on the screen. However, I want to make so the ball can only be touched, thrown, or dragged below the middle of the screen. But I want the ball to continue being thrown if the user's finger accidently goes about the limit.
you will have to adjust the coordinates for your bottom area based on actual size and game scene anchorPoint. for example "100" in the sample assumes that your scene has an anchorPoint of (0,0) and the size of the bottom scroll area is 100.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first as UITouch! {
let location = touch.location(in: self)
guard location < 100 else { return }
//if ball.frame.contains(location!) {
touchPoint = location!
touching = true
//}
}
}
I'm trying to present a ViewController after a button is pressed on an SKScene. How can I make this work?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if let location = touch?.location(in: self) {
let node = self.nodes(at: location)
if node[0].name == "newGameButton" {
let transition = SKTransition.flipHorizontal(withDuration: 0.5)
let gameScene = GameScene(size: self.size)
self.view!.presentScene(QuestionViewController, transition: transition)
}
}
I have three nodes lineBlock of the same class MovableBlock on the screen. I want to rotate the lineBlock node someone is touching on the screen.
I've solved this for moving the correct lineBlock node in touchedMoved:
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
touch = touches.first!
positionInScene = self.touch?.location(in: self)
let previousPosition = self.touch?.previousLocation(in: self)
let translation = CGVector(dx: (positionInScene?.x)! - (previousPosition?.x)!, dy: (positionInScene?.y)! - (previousPosition?.y)!)
if touchedNode?.name?.contains("LineBlock") == true {
(touchedNode as! MovableBlock).selected = true
(touchedNode as! MovableBlock).parent!.parent!.run(SKAction.move(by: translation, duration: 0.0))
}
}
But I have not been able to do the same within my UIRotationRecognizer function. In my rotate function, it simply rotates the first node, regardless of which lineBlock (of class MovableBlock) I am touching:
func rotate(_ sender: UIRotationGestureRecognizer){
if lineBlock.selected == true {
lineBlock.run(SKAction.rotate(byAngle: (-(self.rotationRecognizer?.rotation)!*2), duration: 0.0))
rotationRecognizer?.rotation = 0
}
}
For reference, here's how I define touchedNode (in touchBegan):
touches: Set<UITouch>, with event: UIEvent?) {
touch = touches.first!
positionInScene = self.touch?.location(in: self)
touchedNode = self.atPoint(positionInScene!)
UIGestureRecognizers have a location(in:UIView) method. You can use self.view?.convert(sender.location(in: self.view), to: self) to get the UIRotationGestureRecognizer's location and use logic similar to that in touchesBegan.
convert(_:to:) will make sure that the point is in your scene's coordinate space.
I am trying to do a transition between game menu and the first level.
But instead of all Level1 (it is built by using an Level1.sks file(here I have designed a level) and Level1.swift(here I have created my "hero" etc.)) on the screen appears just hero, but no locations that was designed in Level1.sks.
How I can resolve this problem?
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if (playbutton .containsPoint(location)){
runAction(SKAction.playSoundFileNamed("play.wav", waitForCompletion: false))
let transition = SKTransition.revealWithDirection(SKTransitionDirection.Down, duration: 1)
let scene = Level1(size: CGSizeMake(1024, 768))
scene.scaleMode = SKSceneScaleMode.AspectFill
self.scene?.view?.presentScene(scene, transition: transition)
transition.pausesOutgoingScene = true
}
You need to unarchive the sks file into an SKScene object so that the elements from the file can be loaded into the scene.
XCode usually generates a method called unarchiveFromFile in the SKScene's .swift file.
The following code should work:
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if (playbutton .containsPoint(location)){
runAction(SKAction.playSoundFileNamed("play.wav", waitForCompletion: false))
if let scene = Level1.unarchiveFromFile("GameScene") as? GameScene {
let transition = SKTransition.revealWithDirection(SKTransitionDirection.Down, duration: 1)
scene.scaleMode = SKSceneScaleMode.AspectFill
self.scene?.view?.presentScene(scene, transition: transition)
transition.pausesOutgoingScene = true
}
}
}
}