3D touch equivalence for iPad - ios

I have attempted to develop a game using swift that leverages the 3D touch hardware of iPhones. However, as I was submitting my app to the App Store, it got rejected because the game wasn't playable on iPads.
My question is, what is the best way of implementing a similar functionality for non 3D touch devices? The way I am doing right now is by implementing the following method
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if self.didStartGame, let touch = touches.first {
let maximumPossibleForce = touch.maximumPossibleForce
let force = touch.force
let normalizedForce = min(force/maximumPossibleForce * 2.5, 1)
// Added game-related code here to modify scene accordingly
}
}
When running the latter on non 3D touch devices, debugging the value of touch.maximumPossibleForce returns 0.

You cannot detect force touch on devices that that don't support it.
But maybe you could use the majorRadius property on UITouch. It gives you the radius of the touch.
With the radius you can allow users that don't have a 3d touch device to control your game with the angle of their finger:
This is the code for the above example:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let pseudoForce = touches.first?.majorRadius else { return }
label.text = "\(pseudoForce)"
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let pseudoForce = touches.first?.majorRadius else { return }
label.text = "\(pseudoForce)"
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
label.text = "-"
}

Related

Button changing after image moves over it?

I am making a "slide to confirm" button, the set up is a custom UIButton + a regular UIImageView, the image is passed to the button and the button listen to touches and move the image accordingly.
Everything is working great except for one detail after the button is released everything should go back to their initial state, yet the button stay changed as if its alpha was halved
i commented the alpha because the button was going to hide but i disabled that once i run into this problem, the problem happens regardless of setting the alpha or not.
This is the code for the custom button
class SlideButton: UIButton {
var arrowImage: UIImageView?
var initialLocation: CGPoint?
var initialArrowPosition: CGPoint?
func setArrow(arrow:UIImageView){
arrowImage = arrow
initialArrowPosition = arrow.frame.origin
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
let touch = touches.first!
let location = touch.location(in: self.superview)
initialLocation = location
UIView.animate(withDuration: 0.2) {
//self.alpha = 0.0
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
UIView.animate(withDuration: 0.3) {
self.arrowImage!.frame.origin = self.initialArrowPosition!
//self.alpha = 1.0
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first!
let currentLocation = touch.location(in: self.superview)
arrowImage!.frame.origin.x = initialArrowPosition!.x - initialLocation!.x + (currentLocation.x)
}
}
You are remembering to call super for one of your touches methods:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
But for the other touches methods you've forgotten to do that, so you've broken the core functionality of the button.
you might have to also add an override to touchesCancelled because you might not always hit the touchesEnded endpoint.

Swift: record touch force, size, duration

For a data analysis project, I want to track the measurements for touch force, size and duration in a log-file for a simple app (I use the Foodtracker app from the Apple Documentation Website).
I know that I can get the force, size and duration from UITouch. But
how do I access UITouch to get these measurements?
and how do I write these measurements into a log-file?
1. How do I access UITouch to get these measurements?
You'll have to override the touch handlers in your view controller.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
let touch = touches.first!
print("\(touch.force)")
print("\(touch.majorRadius)")
print("\(touch.timestamp)")
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
let touch = touches.first!
print("\(touch.force)")
print("\(touch.majorRadius)")
print("\(touch.timestamp)")
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesCancelled(touches, with: event)
let touch = touches.first!
print("\(touch.force)")
print("\(touch.majorRadius)")
print("\(touch.timestamp)")
}
2. How do I write these measurements into a log-file?
For that checkout this post: Read and write a String from text file

How to check if a child node has been touched Swift 3

I have sprites moving across the screen, and if they are clicked then they disappear (i.e deleted).
I have overridden the touchesBegan func as follows:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("touch")
let touch = touches.first!
let location = touch.location(in: self)
for child in self.children {
if child.position == location {
child.removeFromParent()
}
}
}
This doesn't seem to have any effect, can someone tell me where I am going wrong?
In which class did you implement this method?
If it was in SKNode itself, you simply do:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.removeFromParent()
}
However, if this method is in SKScene, this way that was implemented would probably not work. Because child.position returns a point (x, y) where the touch was made. And you're trying to compare the touch point and position of the SKNode (center point), it's unlikely to work.
Instead of using this way, try using .nodeAtPoint, a method of SKScene.
For this you will need to put a value in the 'name' property of your SKNode:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("touch")
let touch = touches.first!
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name
{
if name == "your-node-name"
{
touchedNode.removeFromParent()
}
}
}
Font: How do I detect if an SKSpriteNode has been touched

Exceeding the maximum number of touches makes the program not to call the touchesEnded method?

Ive just started learning programming in general and ran into a problem:
I have read some articles about that the iPhones are only capable of tracking 5 touches or so... But I realised that when I touch the screen with e.g. 7 fingers at once, my program-let stops working.
So, anyone knows, which parts of the code malfunctions when I am touching the screen way too many times at once?
(I am a newbie.)
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first!
touchLocation = touch.locationInNode(self)
nrTouches += touches.count
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
nrTouches -= touches.count
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first!
touchLocation = touch.locationInNode(self)
}
override func update(currentTime: CFTimeInterval) {
if nrTouches > 0 {
touchingLabel.text = "touching"
} else {
touchingLabel.text = "not touching"
}
}
So, in the case I am touching with 7 fingers at once, "touching" will be displayed all the time.
tankyuu
You're missing touchesCancelled, which gets called when the 6th finger is put down:
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
if let touches = touches {
nrTouches -= touches.count // same logic as touchesEnded
}
}
An interesting note: The iPad can handle 11 touch events. More on that here.

How to apply a basic vector to physics body in Swift 2.0

I am making a very simple space game; I can't seem to get the last line to work. Ideally, I want to get the spacey to move to up when the screen is touched. Here is my code:
func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch: AnyObject in touches {
touch.locationInNode(self)
spacey.physicsBody!.velocity = (CGVectorMake(0, 0))
spacey.physicsBody!.applyImpulse(0, atPoint: 25)
Does anyone have any idea how to do this?
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch in touches {
_ = touch.locationInNode(self)
spacey.physicsBody!.velocity = CGVectorMake(0, 0)
spacey.physicsBody!.applyImpulse(CGVectorMake(0, 25))
The solution was to change touch in touches to use _ in swift 2.0

Resources