touchesBegan Swift 2 custom SKSpriteKit Nodes - ios

I am new to creating games and such so as a practice I am making a silly game currently. This game has a briefcase which contains buttons (0-9) I would like to save the value of the number that was pressed in an array. I am unsure of how to use touches began to do a specific action if a specific type is pressed.
ButtonInput:
class ButtonInput: SKSpriteNode{
var value: Int = 0
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
}
loadView():
let briefcase = ButtonInput(imageNamed: "briefcase")
let Button0 = ButtonInput(imageNamed: "Button0")
let Button1 = ButtonInput(imageNamed: "Button1")
let Button2 = ButtonInput(imageNamed: "Button2")
let Button3 = ButtonInput(imageNamed: "Button3")
let Button4 = ButtonInput(imageNamed: "Button4")
let Button5 = ButtonInput(imageNamed: "Button5")
let Button6 = ButtonInput(imageNamed: "Button6")
let Button7 = ButtonInput(imageNamed: "Button7")
let Button8 = ButtonInput(imageNamed: "Button8")
let Button9 = ButtonInput(imageNamed: "Button9")
Button0.value = 0
Button1.value = 1
Button2.value = 2
Button3.value = 3
Button4.value = 4
Button5.value = 5
Button6.value = 6
Button7.value = 7
Button8.value = 8
Button9.value = 9
UPDATE:
I tried making a touches began after hours of research and I came up with this:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject! in touches {
let touchLocation = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(touchLocation)
let name = touchedNode.name
if name == "Button0"
{
userSequence.append(Button0.value)
print("Button0 pressed")
}
if name == "Button1"
{
userSequence.append(Button1.getValue())
print("Button1 pressed")
}
if name == "Button2"
{
userSequence.append(Button2.value)
}
if name == "Button3"
{
userSequence.append(Button3.value)
}
if name == "Button4"
{
userSequence.append(Button4.value)
}
if name == "Button5"
{
userSequence.append(Button5.value)
}
if name == "Button6"
{
userSequence.append(Button6.value)
}
if name == "Button7"
{
userSequence.append(Button7.value)
}
if name == "Button8"
{
userSequence.append(Button8.value)
}
if name == "Button9"
{
userSequence.append(Button9.value)
}
if name == "ButtonEnter"
{
compareSequences()
}
}
}

If you use SpriteKit, I would do something like this:
import SpriteKit
var _button = [SKSpriteNode]()
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
if(self.nodeAtPoint(location).name != nil && self.nodeAtPoint().name != "enter") {
_array.append(self.nodeAtPoint(location).name)
}
}
}
func loadView() {
for(var i = 0; i < 10; i++) {
let tempButton = SKSpriteNode(imageNamed: "Button\(i)")
tempButton.position = CGPoint(x: yourValue, y: yourValue)
tempButton.size = CGSize(width: yourValue, height: yourValue)
tempButton.name = "\(i)"
temButton.zPosition = 2
_button.append(tempButton)
self.addChild(_button.last!)
}
}
This will work if you have no other SKSpriteNode in the game because in the touches began I assume that the sprite touched has a number (0-9). To counter this problem, you could add an if statement to verify that the name is between 0-9.
Hope this help!

You should make buttons in the mainstoryboard, and connect them to the view controller. Then you can write the func for each button inside the connected actions
hope this helps

Related

How can I make an action to occur when two buttons are pressed at the same time?

I want my character to jump whenever I press two buttons at the same time. I've already tried this:
if rightButton.contains(location) && leftButton.contains(location) {
character.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 50))
}
One approach would be:
In your functions that detects the interaction with the button prepare it with a boolean.
Then in your Update function, use a timer to add a range of time where we can say that both buttons are pressed at the same time (100 ms for example).
I'll let you here some pseudocode that I hope it helps.
func RightBtnClick()->Void{
rightBtnPressed = true
}
func LeftBtnClick()->Void{
leftBtnPressed = true
}
func Start()->Void{
rightBtnTimer = 0
leftBtnTimer = 0
}
func Update(deltatime ms:float)->Void{
if(rightBtnPressed){
rightBtnTimer += ms;
if(rightBtnTimer>100){
rightBtnTimer = 0
rightBtnPressed=false
}
}
if(leftBtnPressed){
leftBtnTimer += ms;
if(leftBtnTimer>100){
leftBtnTimer = 0
leftBtnPressed=false
}
}
// Lastly let's check if both are pressed.
if(leftBtnPressed && rightBtnPressed){
DoStuff()
}
}
First of all, make sure in GameViewController.swift you have multitouch enabled.
class GameViewController: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
// ...
if let view = self.view as! SKView?
{
// ...
view.isMultipleTouchEnabled = true
}
}
}
In GameScene give name to your buttons. On tap we will create a list of every node your fingers touched that has a name. If the list contains both right and left button, it means he pressed both at the same time.
class GameScene: SKScene
{
override func didMove(to view: SKView)
{
// add name to each button
left_button.name = "left_button"
right_button.name = "right_button"
}
func buttons_touched(_ touches: Set<UITouch>) -> [String]
{
// get the list of buttons we touched on each tap
var button_list : [String] = []
for touch in touches
{
let positionInScene = touch.location(in: self)
let touchedNode = self.nodes(at: positionInScene)
let buttons = touchedNode.compactMap { (node) -> String in
node.name ?? ""
}.filter({$0 != ""})
button_list += buttons
}
return button_list
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
{
let buttons_tapped = buttons_touched(touches)
if buttons_tapped.contains("right_button") && buttons_tapped.contains("left_button")
{
// jump code
}
}
}
You can simulate multitouch inside Simulator by holding Option button.

Repeat action on a SpriteNode

I would like to repeatedly show one of the two games cards, whenever the user touches the deckOfCards.
I got it working once so far, but when I tap on the deckOfCards again, the card does not change. Trying this with 10 or more card names, didn't work either.
class GameScene: SKScene {
let cardname = ["card2", "ace"]
let randomNumber = Int(arc4random_uniform(13))
var deckOfCards = SKSpriteNode()
var yourCard = SKSpriteNode()
override func didMove(to view: SKView) {
deckOfCards = self.childNode(withName: "deckOfCards") as! SKSpriteNode
yourCard = self.childNode(withName: "yourCard") as! SKSpriteNode
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view?.endEditing(true)
for touch: AnyObject in touches {
let location = touch.location(in: self)
let node : SKNode = self.atPoint(location)
if node.name == "deckOfCards" {
yourCard.texture = SKTexture(imageNamed: "\(cardname[randomNumber])")
}
}
}
randomNumber is a constant outside of touchesBegan. It never changes. Put it inside touchesBegan.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view?.endEditing(true)
for touch: AnyObject in touches {
let location = touch.location(in: self)
let node = self.atPoint(location)
let randomNumber = Int(arc4random_uniform(13))
if node.name == "deckOfCards" {
yourCard.texture = SKTexture(imageNamed: "\(cardname[randomNumber])")
}
}
}

second view controller still react to first ViewController swift 3

I'm developing an app where I had to build my own gesture recognition (Apple's were too precise)
I need to use a second view controller (settings), and when I'm on the second one, it still react to the first one.
Where it's very problematic it's that with these gesture I control things in the house (such as lighting, music or even more), so imagine you click on a button on the second view and it light up the room, or you swipe down on the second view and the music is cut...
I'm using a segue to go to the SecondViewController
self.performSegue(withIdentifier: "SecondViewController", sender:self)
I've created another swift file for the second view controller, where, for now, there is nothing.
Do you have any idea what's going on and how I can solve that?
Thanks!
EDIT: As requested, here is more code :
import UIKit
class ViewController: UIViewController {
//Variables definition
override func viewDidLoad() {
super.viewDidLoad()
ascending = false
UIScreen.main.wantsSoftwareDimming = true
UIScreen.main.brightness = (0.0)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.timer.invalidate()
isPinched = false
super.touchesBegan(touches, with: event)
startTime = getCurrentMillis()
for touch in touches{
let point = touch.location(in: self.view)
for (index,finger) in fingers.enumerated() {
if finger == nil {
fingers[index] = String(format: "%p", touch)
if (finger1.isEmpty){
finger1 = [point.x, point.y]
}
//And so on until finger10
break
}
}
}
//If the gesture is long enough, I have a special recognition (longPress)
timer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(increaseValue), userInfo: nil, repeats: true)
if ascending {
ascending = false
}
else {
ascending = true
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
for touch in touches {
let point = touch.location(in: self.view)
for (index,finger) in fingers.enumerated() {
if let finger = finger, finger == String(format: "%p", touch) {
switch (index){
case 0 :
finger1 += [point.x, point.y]
//And so on until case 9 / finger10
default :
break
}
}
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
endTime = getCurrentMillis()
for touch in touches {
for (index,finger) in fingers.enumerated() {
if let finger = finger, finger == String(format: "%p", touch) {
fingers[index] = nil
break
}
}
}
direction[0] = ""
direction[1] = ""
direction[2] = ""
direction[3] = ""
direction[4] = ""
if finger1.count != 0 {
direction[0] = GestureRecognizer(coordinates: finger1, index: 0)
}
if finger2.count != 0 {
direction[1] = GestureRecognizer(coordinates: finger2, index: 1)
}
if finger3.count != 0 {
direction[2] = GestureRecognizer(coordinates: finger3, index: 2)
}
if finger4.count != 0 {
direction[3] = GestureRecognizer(coordinates: finger4, index: 3)
}
if finger5.count != 0 {
direction[4] = GestureRecognizer(coordinates: finger5, index: 4)
}
if Int64(endTime - startTime) < 600 {
//My gesture recognition
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.directionLabel.text = self.labelUpdate
self.finger1 = []
self.finger2 = []
self.finger3 = []
self.finger4 = []
self.finger5 = []
self.finger6 = []
self.finger7 = []
self.finger8 = []
self.finger9 = []
self.finger10 = []
}
}
//One of the function I call
func swipeLeftTwo(){
request(urlAdress: "Url Adress")
}
func swipeRightFour(){
self.performSegue(withIdentifier: "SecondViewController", sender:self)
}
}
In the second view controller:
import UIKit
class SecondViewController: UIViewController {
#IBOutlet weak var labelTe: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
labelTe.text = "something changed"
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Get Property of SKSpriteNode in Touches

I am trying to read a property off of a SKSpriteNode in the touchesBegan method but the property does not exist. Where as it does on the created object elsewhere.
let enemy = enemy(imageName: "enemy.png",force: "12")
addChild(enemy)
enemy.name = "enemy"
print (enemy.force) // 12
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return
}
let touchLocation = touch.location(in: self)
let touchedNode = self.atPoint(touchLocation) as! SKSpriteNode
if(touchedNode.name == "enemy"){
print(enemy.force) //Force property does not exist
}
}
Knowing that SKSpriteNode don't have a force property, you should use your class name that inherits SKSpriteNode properties (used to make enemy..)
An example could be this:
class Enemy : SKSpriteNode {
var force: Int = 0
...
}
Then in your game scene do:
...
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let touchLocation = touch.location(in: self)
let touchedNode = self.atPoint(touchLocation)
if(touchedNode.name == "enemy" && touchNode is Enemy){
// Yes, I'm absolutely sure this is an enemy node..
let enemy = touchedNode as! Enemy
print(enemy.force)
}
}

How to detect precisely when a SKShapeNode is touched?

I'm working with Swift and SpriteKit.
I have the following situation :
Here, each of the "triangles" is a SKShapenode.
My problem is that I would like to detect when someone touches the screen which triangle is being touched.
I assume that the hitbox of all these triangles are rectangles so my function returns me all the hitboxes touched while I only want to know which one is actually touched.
Is there any way to have a hitbox that perfectly match the shape instead of a rectangle ?
Here's my current code :
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
let touch = touches.first
let touchPosition = touch!.locationInNode(self)
let touchedNodes = self.nodesAtPoint(touchPosition)
print(touchedNodes) //this should return only one "triangle" named node
for touchedNode in touchedNodes
{
if let name = touchedNode.name
{
if name == "triangle"
{
let triangle = touchedNode as! SKShapeNode
// stuff here
}
}
}
}
You could try to use CGPathContainsPoint with a SKShapeNode instead of nodesAtPoint, which is more appropriate:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
let touch = touches.first
let touchPosition = touch!.locationInNode(self)
self.enumerateChildNodesWithName("triangle") { node, _ in
// do something with node
if node is SKShapeNode {
if let p = (node as! SKShapeNode).path {
if CGPathContainsPoint(p, nil, touchPosition, false) {
print("you have touched triangle: \(node.name)")
let triangle = node as! SKShapeNode
// stuff here
}
}
}
}
}
This would be the easiest way of doing it.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
for touch in touches {
let location = touch.locationInNode(self)
if theSpriteNode.containsPoint(location) {
//Do Whatever
}
}
}
The way I do this with Swift 4:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return
}
let touchPosition = touch.location(in: self)
let touchedNodes = nodes(at: touchPosition)
for node in touchedNodes {
if let mynode = node as? SKShapeNode, node.name == "triangle" {
//stuff here
mynode.fillColor = .orange //...
}
}
}

Resources