zoenamatata
zoenamatata

Reputation: 63

how to stop sprite movement when touch activity is still happening

I have a blue square sprite and a letter A shaped tile map. The blue square should be able to move freely inside the map.

My goal is to limit the blue square sprite inside the tile map even when the touch activity is still happening.

The problem is when the blue square sprite moves with a touch in a certain direction, if the touch is still ongoing, the sprite will travel outside the red tiles.

enter image description here

solution I have tried

logic:

  1. create a boolean flag (isNeighbourTileNil) to detect if the neighbouring tile is nil (not on the red tile) in the update()

    • I have no problem for this step.
  2. if isNeighbourTileNil is true, then the player sprite should stop moving even when the touch is still moving/happening.

    • I have trouble with this step. The challenge I am having is, bool variable isNeighbourTileNil is updated by every frame. However, touch event (touchesBegan() -> touchesMoved() -> touchesEnded()) is a linear process, meaning i could not pass an ever changing variable like isNeighbourTileNil to touchesMoved() function and to stop player movement from there.

here is the code I have tried:

 override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches{
            if(i==0){
                firstTouch = touch.location(in: self)
            }
            if(i==1){
                secondTouch = touch.location(in: self)
            }
            i = i+1
        }
        direction = directionCalculator(firstTouch, secondTouch)
        print(direction)
        if isNeighbourTileNil == false {
            moveInDirection(direction, 10.0, 10.0, -10.0, -10.0)
        }
    }
override func update(_ currentTime: TimeInterval) {
        // Called before each frame is rendere
        let playerPosition = player.position
        let column = mainTileMap.tileColumnIndex(fromPosition: playerPosition)
        let row = mainTileMap.tileRowIndex(fromPosition: playerPosition)
        let currentTile = mainTileMap.tileDefinition(atColumn: column, row: row)
        currentTileTuple.column = column
        currentTileTuple.row = row

        if !self.isMonsterCollisionDetected {
            self.detectMonsterCollisions()
        }
        detectMapCollision()

        if isNeighbourTileNil == true {
            print("player should stop moving")
            player.removeAllActions()
        }
    }

Upvotes: 0

Views: 192

Answers (1)

bg2b
bg2b

Reputation: 1979

This is a bit complicated and details depend on how you have things set up so I'm not going to write a bunch of code, but I'd suggest organizing things as follows:

  1. Have a variable called canMove or something like that which should be true when the player is in a state where it can move.
  2. Add a UISwipeGestureRecognizer for recognizing each swipe. Google "uigesturerecognizer spritekit" for examples of how to do this. This will call back to your code when a swipe happens and give you the direction that the player wants to move. Ignore swipes when canMove is false.
  3. When you're notified of a swipe and canMove is true, see if the player can move in the wanted direction according to the neighboring tiles. If not, ignore the swipe.
  4. Finally the case when canMove is true and the swipe indicates a valid direction... Set canMove to false and trigger an animation of the movement of the player to the new square, running an SKAction.move(to:duration:) or whatever. Run the action with a completion handler that sets canMove back to true when the action finishes.

Upvotes: 1

Related Questions