3

I'm developing a small game in Swift 3 with SpriteKit and I want to move the enemies to the direction of the character, but at all times the enemies stop when they arrive at the character's initial position.

I'm doing this:

enemigo.name = "enemigo"
enemigo.position = CGPoint(x: 280, y: 100)
enemigo.xScale = 1/1
enemigo.yScale = 1/15
addChild(enemigo)


let movement1 = CGVector(
    dx: (enemigo.position.x - personaje.position.x)*10,
    dy: (enemigo.position.y - personaje.position.y)*10
)

let actionTransaction = SKAction.move(by: movement1, duration: 20)
enemigo.run(actionTransaction)

How should I move the enemies to a specific direction without stopping at the initial position of the character?

Undo
  • 25,519
  • 37
  • 106
  • 129
HessianMad
  • 549
  • 7
  • 23
  • basically you want the enemy to chase the player? – Fluidity Jan 12 '17 at 01:06
  • I want to move enemy towards my character's direction without stopping @Fluidity – HessianMad Jan 12 '17 at 10:21
  • Ok. You will need to update the enemy's action in your scene's `.update()` method. Otherwise your bad guy only gets one movement... he needs more! Also, here is a great article on doing the proper maths for it: https://www.raywenderlich.com/90520/trigonometry-games-sprite-kit-swift-tutorial-part-1 – Fluidity Jan 12 '17 at 10:46
  • Ok, thanks! @Fluidity – HessianMad Jan 12 '17 at 11:37
  • 1
    @Fluidity It is not that performant nor needed to run SKAction inside an update method. That method is executed 60 times per second. If you use it, then you change position property of a node directly. LIke this : http://stackoverflow.com/a/36235426/3402095 – Whirlwind Jan 12 '17 at 14:58
  • I agree with Whirlwind, why you must use actions inside an update method if you have `zRotation` and `position` references – Alessandro Ornano Jan 14 '17 at 11:49

2 Answers2

2

You've done all the hard work figuring out the vector of direction.

Now you can repeat this moveBy action as often as you like, and the enemy will keep moving in the same direction, further and further, because move(by: CGVector) is relative, not absolute:

let actionTransaction = SKAction.move(by: movement1, duration: 20)

So all you need do is run this forever with a key, so you can then seek it out from anywhere, and stop it whenever you like.

run(SKAction.repeatForever(actionTransaction), withKey: "movingEnemy")
Confused
  • 6,048
  • 6
  • 34
  • 75
  • I have the `let actionTransaction = SKAction.move(by: movement1, duration: 20)` in a function and I call this function in the `sceneDidLoad()`, and it didn't run as what I want. How I should use the `run(SKAction.repeatForever(actionTransaction), withKey: "movingEnemy")`? @Confused – HessianMad Jan 12 '17 at 15:54
  • I think you read the question a tad bit too literally Confused :P – Fluidity Jan 12 '17 at 22:54
  • @HessianMad I don't think any of us still quite understand what you are trying to do. Could you please elaborate? O, me explica en español :), y voy a intentar entenderlo – Fluidity Jan 12 '17 at 23:03
  • @HessianMad you say the same thing 3 times. that you want to keep enemies moving. since thats not what you want, draw a picture of what you do want. – Confused Jan 12 '17 at 23:16
  • @Fluidity, yeah... I should have posted this as a comment... ;) – Confused Jan 13 '17 at 03:02
  • @Fluidity lo que quiero es que el enemigo vaya en dirección a la del jugador sin pararse, es decir, que vaya hacía la dirección del jugador y se salga de la pantalla del juego. ¿Me explico? – HessianMad Jan 13 '17 at 08:53
  • @HessianMad truly, try to draw a diagram. This is something that has multiple possible objectives, and nobody can be sure until you show what you want. I've hit google translate with your Spanish, and it's saying that my answer is what you want. Run it on the enemigo. See if it does what you want. And reduce the duration to something reasonable, like 2 seconds. So it doesn't take 20 seconds to see if it does what you want. – Confused Jan 13 '17 at 12:23
  • @HessianMad Ok, so you *do* want the enemy to leave the game screen, yes? You don't want the enemy to follow the player... no seguir el jugador... Yes? So, solo uno movimiento del enemigo.. only one enemy movement... towards the player, then off the screen. IF so, Confused's answer should work, since you already have the correct math – Fluidity Jan 13 '17 at 18:26
  • you could also try using `physicsBody` and `applyImpulse` – Fluidity Jan 13 '17 at 18:36
1

Alternatively, you could consider using GameplayKit together with SpriteKit. GameplayKit provides standard implementations of common algorithms for games and can be used together with SpriteKit.

Unfortunately I'm not too familiar with it, so I can't give you code. I would suggest having a look at Apple's GameplayKit programming guide. There are functions available for setting a goal of an agent (e.g. an enemy) to move toward a specific location, avoid obstacles, intercept another agent, or flee from an agent, etc.

So while your player moves, some enemies could be programmed to try and catch the player, while other enemies could try to run away from the player. Other enemies could be made to wander around randomly, etc.

So in a nutshell, GameplayKit can add quite powerful functionality to a SpriteKit game. This could mean spending a bit more time upfront thinking about the architecture of your game, but in the end it could be worth it if you will also use the other functionalities of GameplayKit.

JohnV
  • 981
  • 2
  • 8
  • 18