Add nodes where touches began - swift

I´m making a game with Swift.
I need to add nodes where I press the screen, I know this is not from other planet but I can't do it.

Highly simplified example could look like this:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let location = touch.location(in: self)
let node = SKNode()
node.position = location
addChild(node)
}

Here is how you can add an remove labels by tapping:
class ViewController: UIViewController{
private var labels = [UILabel]()
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return
}
for label in labels {
if label.frame.contains(touch.location(in: view)) {
label.removeFromSuperview()
return
}
}
let label = UILabel()
view.addSubview(label)
labels.append(label)
label.text = "touch"
label.sizeToFit()
label.center = touch.location(in: view)
}
}

Related

Draggable object jumps a bit when I try to highlight a button

I have 2 UIImageView who are placed on storyboard and setup in code via frames. I have also a UIButton and an optional draggableView: UIView?. What I'm trying to do:
Drag a view - seems to be working fine
Highlight my button when I hover draggableView over it and disable highlight if we moving away from it. Highlight seems to be happening, but my draggableView goes kinda underneath a button and does a very noticeable jump into its starting position before dragging. After that if we continue dragging - position continues to update properly.
Here is the code for touches
override func viewDidLoad() {
...
img01.isUserInteractionEnabled = true
img02.isUserInteractionEnabled = true
...
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {return}
if img01.bounds.contains(touch.location(in: img01)) {
draggableView = img01
} else if img02.bounds.contains(touch.location(in: img02)) {
draggableView = img02
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let draggableView = draggableView else {return}
guard let touch = touches.first else {return}
draggableView.center = touch.location(in: view)
if btnMain.bounds.contains(touch.location(in: btnMain)) {
print("Case 4")
btnMain.isHighlighted = true
} else {
print("Case 5")
btnMain.isHighlighted = false
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
draggableView = nil
btnMain.isHighlighted = false
}
What causes that jump to initial position and is there a way to kinda... make draggableView noticeably on top of anything? Thanks.

How to detect cgPath in cgRect

I can detect only start point(touchBegan) that contain in c1 and end point(touchEnded) that contain in c2 but I can't detect path between them in c3, How should I do ?
Application image
override func layoutSubviews() {
self.clipsToBounds = true
self.isMultipleTouchEnabled = false
self.contentMode = .scaleToFill
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
swiped = false
lastPoint = touch?.location(in: self)
firstPoint = lastPoint
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
swiped = true
let currentPoint = touch?.location(in: self)
lastPoint = currentPoint
linePoint = lastPoint
drawShapeLayer(from: lastPoint, to: currentPoint!)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if !swiped {
drawShapeLayer(from: lastPoint, to: lastPoint!)
}
if c1.contains(firstPoint) && c3.contains(linePoint) && c2.contains(lastPoint){
AlertView.instance.showAlert(title: "Hooray!", message: "You made it!", alertType : .success)
}
else {
AlertView.instance.showAlert(title: "Oops!", message: "You've almost got it.", alertType : .failure)
}
}
}
As per my comments above, I think the there is a logic error in touchesMoved and you need to reorder the code if you are trying to draw a three point line, and then later check that each point is in a specific view area.
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
swiped = true
currentPoint = touch.location(in: self)
drawShapeLayer(from: lastPoint, to: currentPoint)
lastPoint = currentPoint
linePoint = currentPoint
}
}
(Also safely unwrapped touch to remove the optional and avoid crashes in the v unlikely scenario where touches.first is nil)

Drag - drop custom SKSpriteNode position issue

I'm my game I'm using a custom SKSpriteNode which the player are going to be able to drag and drop at a position of his/hers desire.
My custom node is made of this code in file DraggableNode.swift:
class DraggableNode : SKSpriteNode {
var nodeSelected : SKNode?
init() {
let texture = SKTexture(imageNamed: "draggableNode_1")
super.init(texture: texture, color: UIColor.white, size: texture.size())
self.isUserInteractionEnabled = true
self.zPosition = 1
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: self)
let touchedNodes = self.nodes(at: location)
for node in touchedNodes.reversed() {
nodeSelected = node
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first, let node = self.nodeSelected {
let touchLocation = touch.location(in: self)
node.position = touchLocation
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
nodeSelected = nil
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
nodeSelected = nil
}
}
In my GameScene.swift I add the custom node in this way:
let node = DraggableNode()
node.position = CGPoint(x: randomX, y: randomY)
self.addChild(node)
Now, the problem is that when I start to drag the node it's all jump and is placed a total random place - sometimes even out of the screenarea.
I wonder if the problem consists of the fact that it's a custom node inherited from a SKSpriteNode?
If anyone can point me in the right direction, I'd be a happy man :-)

Move SKSpriteNode on Touch to create Button effect

I am currently creating the main menu of a mobile game, and it works fine however To make it look nicer I would like to add an effect when I touch one of my SKSpriteNodes which is an image of a button. I would like it to slightly move down then back up before transitioning to the game, im having some difficulty. Currently when the button is pressed it changed scenes to the game scene.
class MainMenuScene: SKScene{
let startGame = SKSpriteNode(imageNamed: "StartButton")
override func didMove(to view: SKView) {
let background = SKSpriteNode(imageNamed: "Menu")
background.size = self.size
background.position = CGPoint(x: self.size.width/2, y:self.size.height/2)
background.zPosition = 0
self.addChild(background)
startGame.position = CGPoint(x: self.size.width/2, y: self.size.height*0.6)
startGame.zPosition = 1
startGame.name = "startButton"
self.addChild(startGame)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch: AnyObject in touches{
let pointOfTouch = touch.location(in: self)
let nodeITapped = atPoint(pointOfTouch)
if nodeITapped.name == "startButton" {
let sceneToMoveTo = GameScene(size: self.size)
sceneToMoveTo.scaleMode = self.scaleMode
let myTransition = SKTransition.fade(withDuration: 0.5)
self.view!.presentScene(sceneToMoveTo, transition: myTransition)
}
}
}
}
You could make your logic in the function touchesEnded and then you call a SKAction in your button, passing the moveToScene logic as completion.
Something like:
var shouldMoveToNewScene: Bool = False
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch: AnyObject in touches{
let pointOfTouch = touch.location(in: self)
let nodeITapped = atPoint(pointOfTouch)
shouldMoveToNewScene = nodeITapped.name == "startButton" ? True : False
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard shouldMoveToNewScene, touces.count == 1 else { return }
startButton.run(myAnimation, completion: {
moveToScene()
})
}
private func moveToScene() {
//do your transition scene logic here
{
I haven't tried it yet, but hopefully you could get the idea.
If you're not familiar with SKAction you should consider follow this guide.

I want to change the image of the button as long as user taps on the button?

I want change the image of a button as long as the user taps on it, but change the image back to the original if he releases his finger from the screen(I´m using Sprite-Kit)
My code:
var SettingButton = SKSpriteNode(imageNamed: "SettingButton1.0")
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let locationUser = touch.location(in: self)
if atPoint(locationUser) == SettingButton{
let SettingButton = SKSpriteNode(imageNamed: "SettingButton2.0") //change the image
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let locationUser = touch.location(in: self)
if atPoint(locationUser) == SettingButton{
//change image back to original
}
}
}
Try swapping the texture of the SpriteNode
var buttonTextureUp = SKTexture(imageNamed: "SettingButton1.0")
var buttonTextureDown = SKTexture(imageNamed: "SettingButton2.0")
var settingButton = SKSpriteNode(texture: buttonTextureUp)
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let locationUser = touch.location(in: self)
if atPoint(locationUser) == settingButton {
settingButton.texture = buttonTextureDown //change the image
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let locationUser = touch.location(in: self)
if atPoint(locationUser) == settingButton{
settingButton.texture = buttonTextureUp //change image back to original
}
}
}