WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

100 days of Swift - Day 63 - Project 17 - Space Race - Challenge 1

Forums > 100 Days of Swift

@teine  

Sorry to say I'm befuddled by the first challenge, did the other 2 no problem, but I'm really not sure what your asking for.

  1. Stop the player from cheating by lifting their finger and tapping elsewhere – try implementing touchesEnded() to make it work.

TouchesEnded - happens when the user picks up their finger...

Is this about event bubbling? Is the idea to cancel/handle the event so it doesn't run touches moved? ok hint plz.

Or just explode the spaceship if they lift their finger? That seems rather punishing and unintuitive.

The cheat to me, it seems to happen on touchesBegan/Moving, where it doesn't check that the user actually tapped the spaceship.. (a check nicely shown in Proj 14)

I'm really at a loss at what I should be understanding in touchesEnded. At touchEnded, it's already moved the space ship... I could move the update to position code to Ended, but then it would only update on finger lifted

i must be going down a blind alley, please help me back on track, thanks.

1      

Not sure how many hints do you want :-) But the key is to implement both touchesBegan and touchesEnded when checking if the player is indeed touching the spaceship and not trying to cheat.

1      

@teine  

huh, thanks will do that :D

So there's no special "one-liner hack" for touchesEnded, i was missing?

1      

@teine  

I ended up sticking with touchesMoved, using excepts from Paul's code for node in nodes(at:touch.location(in self)) { if node == player { //update player.position

Is that bad from from a performance angle? The above code seemed clear & consise to me...

Using touchesBegan/Ended seemed cluttered, and possibly bad for multitouch?

if it had a bool touchedShip set on tBegan, update ship's position if touchedShip is true in tMoved, the set it to false in tEnded...

but... how well would that handle leaving a finger on the screen, then add a new touch, or multi touch? I may be over thinking things... it just seemed to complicate things in this case.

1      

I think your approach is perfectly viable, what I did was a very similar thing:

  1. I created var isPlayerTouched: Bool
  2. in touchesBegan - if the touched node is the ship: isPlayerTouched = true.
  3. in touchesEnded - if the touched node is the ship: isPlayerTouched = false.

That way, I can control when the ship can be moved and when not. So in my case, touchesMoved works with the ship node only when isPlayerTouched = true.

EDIT: Ah, now I remember. My first approach was identical to yours. However, I noticed that my finger was 'losing' the ship when I was moving it very fast. The above method got rid of all the problems.

2      

Hello everyone!

I kept what Paul wrote on touchesMoved() and I implemented touchesEnded() like so:

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if !touches.isEmpty {
            for touch in touches {
                let location = touch.location(in: self)
                for node in nodes(at: location) {
                    if node.name == "player" {
                        debugPrint("Player node found")
                        player.position.y = node.position.y
                        player.position.x = node.position.x
                    }
                }
            }
        } else { return }
    }

I'm not really sure why but it works sometimes. I've done several tests and the times it doesn't work is because:

  1. I touch/tap several times on the same spot.
  2. I tap and hold.

I also feel like all the player.positions are being stored/remembered because the method fails more as time goes on.

Any insights?

1      

I use this formula to calculate distance between 2 CGPoint in touchMoved"var location = touch.position(in: self)" and "player.position": func CGPointDistanceSquared(from: CGPoint, to: CGPoint) -> CGFloat { return (from.x - to.x) (from.x - to.x) + (from.y - to.y) (from.y - to.y) }

if it is > 5000 or some thing, you can modify it. it will return from touchMoved function. So that player can not cheat to lift finger then moved finger in a distance that too far the original one.

1      

i decided to use the logic if the touchesBegan location of the touch contains the rocket than move the rocket else don't move the rocket.. So keeping with paul's original code for touchesMoved(), i added touchesBegan that returns a boolean to detect if touchesBegan contains the rocket frame if player.frame.contains(location) is true, then allow for touchesMove else don't move the rocket.

1      

Hacking with Swift is sponsored by Emerge

SPONSORED Why are Swift reference types bad for app startup time, and what’s the performance cost of protocol conformances? That’s just a couple of the topics you can learn about on the Emerge blog — written by the app performance experts behind Emerge’s advanced app optimization and monitoring tools, based on their experience of working at companies like Apple, Airbnb, Snap, and Spotify.

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.