How to move enemy towards a moving player?
You have to update enemy position
and zRotation
property in each update: method call.
Seeker and a Target
Okay, so lets add some nodes to the scene. We need a seeker and a target. Seeker would be a missile, and target would be a touch location. I said you should do this inside of a update: method, but I will use touchesMoved method to make a better example. Here is how you should setup the scene:
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
let missile = SKSpriteNode(imageNamed: "seeking_missile")
let missileSpeed:CGFloat = 3.0
override func didMoveToView(view: SKView) {
missile.position = CGPoint(x: frame.midX, y: frame.midY)
addChild(missile)
}
}
Aiming
To implement the aiming you have to calculate the how much you have to rotate a sprite based on its target. In this example I will use a missile and make it point towards the touch location. To accomplish this, you should use atan2 function, like this ( inside touchesMoved:
method):
if let touch = touches.first {
let location = touch.locationInNode(self)
//Aim
let dx = location.x - missile.position.x
let dy = location.y - missile.position.y
let angle = atan2(dy, dx)
missile.zRotation = angle
}
Note that atan2 accepts parameters in y,x order, rather than x,y.
So right now, we have an angle in which missile should go. Now lets update its position based on that angle (add this inside touchesMoved:
method right below the aiming part):
//Seek
let vx = cos(angle) * missileSpeed
let vy = sin(angle) * missileSpeed
missile.position.x += vx
missile.position.y += vy
And that would be it. Here is the result:
Note that in Sprite-Kit the angle of 0 radians specifies the positive x axis. And the positive angle is in the counterclockwise direction:
Read more here.
This means that you should orient your missile to the right rather than upwards . You can use the upwards oriented image as well, but you will have to do something like this:
missile.zRotation = angle - CGFloat(M_PI_2)
How to make enemies turn and move towards player when near? Unity3D
change the look at target:
void Update () {
Vector3 lookAt = Player.position;
lookAt.y = transform.position.y;
transform.LookAt(lookAt);
}
this way the look at target will be on the same height as your object.
How can I move my enemy by following my Player position with only 1 coordinate
if (Vector2.Distance(transform.position, target.position) > 200)
{
transform.position = Vector2.MoveTowards(transform.position, target.position, speed * Time.deltaTime);
}
else
{
// i want my enemy following my player with only Y coordinate right here, not moving forward anymore
transform.position = Vector2.MoveTowards(transform.position, new Vector2(transform.position.x, target.position.y), speed * Time.deltaTime);
}
Game enemy move towards player
Create a vector in the direction that you want the enemy to move. That's easy:
dir.x = player.x - enemy.x;
dir.y = player.y - enemy.y;
Now normalize this vector. That means divide the terms by the magnitude (the hypotenuse) of the vector.
hyp = sqrt(dir.x*dir.x + dir.y*dir.y);
dir.x /= hyp;
dir.y /= hyp;
Now you just need to add that vector to the enemy's position, multiplied by the speed you want the enemy to move:
enemy.x += dir.x*speed;
enemy.y += dir.y*speed;
Here's how it works - if you add that initial vector to the enemy's position it will instantly be transported to the player. You obviously want to enemy to move at a slower speed. When you normalize the vector, you make it's magnitude (essentially the hypotenuse of the triangle it forms) equal to 1. So now, adding the direction vector moves the enemy by one unit. Multiply that 1 unit by the enemy's speed, and now it's moving at the correct speed.
Edit: all of this extends to 3D as well. You just need a z-component.
Further edits to comment on your code:
You are doing a lot of extra work. You have enough information once you calculate the hypotenuse to move the enemy towards the player. You don't need to use any trig at all - see my code above. You are also calculating (sort of) the magnitude twice:
float hypotenuse = sqrt((xDistance * xDistance) + (yDistance * yDistance));
...
(playerX - enemyX)*(playerX - enemyX)+(playerY - enemyY)*(playerY - enemyY)
The second time it's the distance squared which is a nice optimization, but unnecessary here because you've already calculated the distance and the distance squared.
Here's what I would do:
float xDistance = playerX-enemyX;
float yDistance = playerY-enemyY;
float hypotenuse = sqrt((xDistance * xDistance) + (yDistance * yDistance));
if(hypotenuse < 400){
YPos += timeFactor*200*(yDistance/hypotenuse);
XPos += timeFactor*200*(xDistance/hypotenuse);
}
You'll notice that by removing the abs() I've also managed to remove the if(playerY > enemyY), etc parts.
Problems with moving an enemy towards a character in pygame
Since pygame.Rect
is supposed to represent an area on the screen, a pygame.Rect
object can only store integral data.
The coordinates for Rect objects are all integers. [...]
The fraction part of the movement gets lost when the movement is add to the position of the rectangle.
If you want to store object positions with floating point accuracy, you have to store the location of the object in separate variables and to synchronize the pygame.Rect
object. round
the coordinates and assign it to the location (e.g. .topleft
) of the rectangle:
hunter_rect = pygame.Rect(500, 500, 48, 60)
hunter_x, hunter_y = hunter_rect.topleft
# [...]
while True:
# [...]
hunter_x -= xchange
hunter_y -= ychange
hunter_rect.topleft = round(hunter_x), round(hunter_y)
# [...]
Problems making enemy follow moving player
Ok, so it was actually Premier Bromanov who answered this, thanks, but I can't accept a comment, which it was, so I will just do this to make it more clear, if anyone should come by and want the answer too.
The math i did was a bit wrong, and here is how my code ended up looking like:
this.UpdateAngle = function() {
this.dx = player.x - this.x;
this.dy = player.y - this.y;
this.distance = Math.sqrt((this.dx*this.dx) + (this.dy*this.dy));
this.angle = Math.atan2(this.dy,this.dx) * 180 / Math.PI;
}
this.UpdateSpeed = function() {
this.speedX = this.speed * (this.dx/this.distance);
this.speedY = this.speed * (this.dy/this.distance);
}
this.Move = function() {
this.UpdateAngle();
this.UpdateSpeed();
this.x += this.speedX;
this.y += this.speedY;
}
Thanks again to Premier Bromanov, this is his answer, and also to everyone else, this was my first post and i am glad how fast i got a response! (I was the slowest one here) :D
Related Topics
Convert String to Date in Swift
How to Add Type Constraints to a Swift Protocol Conformance Extension
How to Convert Unix Epoch Time to Date and Time in iOS Swift
Checking If an Object Is a Given Type in Swift
Cannot Assign Property in Method of Struct
How to Detect Which Skspritenode Has Been Touched
How to Convert Array of Bytes [Uint8] into Hexa String in Swift
What's the Cleanest Way of Applying Map() to a Dictionary in Swift
Share Data Between Main App and Widget in Swiftui For iOS 14
How to Change the Textual Representation Displayed For a Type in Swift
Swift - Spritekit Cgpoint Alignment