Needing help with coding an object following the player by turning towards him

Hello, originally this is a problem I found when doing 3D games. I got the formula xPos=sin(turn)*speed+xPos and zPos=cos(turn)*speed+zPos from here, it is a formula to move a playable figure. The turn is made from the calculation how far the mouse is away from the middle of the display. I wanted to code an “Enemy” who chases the player figure with this formula, so he would turn towards the player. To present my problem, I coded it into 2D. I just exchanged z with y, and created following code:
Main code:

Player player1;
Enemy enemy1;
void setup(){
  size(displayWidth,displayHeight); 
  player1=new Player();
  enemy1=new Enemy(500,500);
}
void draw(){
  background(#FFFFFF);
  player1.drawPlayer();
  enemy1.drawEnemy();
  enemy1.moveEnemy();
}
void keyPressed(){
  player1.movePlayer();
}

The player:

float xPlayer=800;
float yPlayer=20;
class Player{
  Player(){
  }
  void drawPlayer(){
    ellipse(xPlayer,yPlayer,10,10);
  }
  void movePlayer(){
    if(key=='a'){
      xPlayer=xPlayer-10;}
    if(key=='d'){
      xPlayer=xPlayer+10;}
    if(key=='s'){
      yPlayer=yPlayer+10;}
    if(key=='w'){
      yPlayer=yPlayer-10;}
  }
}

and now the enemy:

float xDirection;
float yDirection;
float enemyRot;
float speed=0;
class Enemy{
  float xEnemy;
  float yEnemy;
  Enemy(float x,float y){
    xEnemy=x;
    yEnemy=y;
  }
  void drawEnemy(){
    fill(#FF0000);
    ellipse(xEnemy,yEnemy,20,20);
    xDirection=sin(enemyRot)*200+xEnemy;
    yDirection=cos(enemyRot)*200+yEnemy;
    ellipse(xDirection,yDirection,5,5);
  }
  void moveEnemy(){
      enemyRot=acos(((xDirection-xEnemy)*(xPlayer-xEnemy)+(yDirection-yEnemy)*(yPlayer-yEnemy))/(sqrt(sq(xDirection-xEnemy)+sq(yDirection-yEnemy))*sqrt(sq(xPlayer-xEnemy)+sq(yPlayer-yEnemy))));
      xEnemy=sin(enemyRot)*speed+xEnemy;
      yEnemy=cos(enemyRot)*speed+yEnemy;
    
      //when xPlayer< xEnemy, a - must be before acos(...). Then it functions like it shoud with the x-coordinates. But cos(...)*speed + yEnemy creates trouble: It just won't fit, It does not matter if I 
      //put a - before cos(...) or if I subtract 90. It just won't fit!
  }
}

As you can see, I made a fixated point, which is always before the enemy, showing the direction he is looking at. I used the vector-angle-formula I learned in school to calculate the angle between the Enemy-Direction-vector and the Enemy-Player-Vector. I soon realized, that sometimes I have to put a “-” before the acos, to make negative angles for the sin(turn)*speed+xPos formula, when needed. But something strange is up with cos. At first I thought, I woud just have to make it negative sometimes, but it did not work always, then I tried it with substracting 90 from the turn, cos(turn-90)… I sat days on this problem, trying to find a formula which says when I have to put a “-” before cos or acos and when 90 needs to be substracted. I just do not know what to do anymore. Everything I assume turns out to be wrong. Of course, I just could code

if(xPlayer>xEnemy){
xEnemy++;}
if(xPlayer<xEnemy){
xEnemy--;}
if(yPlayer>yEnemy){
yEnemy++;}
if(yPlayer<yEnemy){
yEnemy--;}

But, as I said, it is a 3D problem, I need that enemy to look at the playable figure. Anything else would just look bad.
Thank you for your time.

1 Like

just a remark

I don’t know if that matters but cos and sin need to be swapped here

xPos=cos(turn)*speed+xPos and 
zPos=sin(turn)*speed+zPos

(all in radians)

I know this is not the formula for the enemy but here you need to swap cos and sin too

I don’t know what your intention is with the enemy but here is my version

// https://discourse.processing.org/t/how-do-i-measure-the-angle-of-a-vertex/34511/2
//https://discourse.processing.org/t/how-do-i-measure-the-angle-of-a-vertex/34511
//https://processing.org/reference/atan2_.html

Player player1;
Enemy enemy1;

void setup() {
  size(displayWidth, displayHeight); 
  player1=new Player();
  enemy1=new Enemy(500, 500);
}

void draw() {
  background(#FFFFFF);
  player1.drawPlayer();
  enemy1.drawEnemy();
  enemy1.moveEnemy();
}

void keyPressed() {
  player1.movePlayer();
}

// ---

class Player {

  float xPlayer=800;
  float yPlayer=20;

  Player() {
  }

  void drawPlayer() {
    fill(255, 0, 0); 
    ellipse(xPlayer, yPlayer, 10, 10);
  }

  void movePlayer() {
    if (key=='a') {
      xPlayer=xPlayer-10;
    }
    if (key=='d') {
      xPlayer=xPlayer+10;
    }
    if (key=='s') {
      yPlayer=yPlayer+10;
    }
    if (key=='w') {
      yPlayer=yPlayer-10;
    }
  }
}

// ---

class Enemy {


  float xDirection;
  float yDirection;
  float enemyRot;
  float speed=0;

  float a ; 

  float xEnemy;
  float yEnemy;

  Enemy(float x, float y) {
    xEnemy=x;
    yEnemy=y;
  }

  void drawEnemy() {
    fill(255, 0, 255); 

    pushMatrix(); 

    translate(xEnemy, yEnemy);
    a = atan2(player1.yPlayer-yEnemy, player1.xPlayer-xEnemy);
    rotate(a);
    rect(-30, -5, 60, 10);

    translate(38, 0);
    ellipse(0, 0, 7, 7);

    popMatrix();

    //---
    xDirection=cos(a)*0.92;
    yDirection=sin(a)*0.92;

    xEnemy+=xDirection;
    yEnemy+=yDirection;
  }

  void moveEnemy() {
    //
  }//func
  //
}//class
//

Thank you very much, your code worked, and I think I understand it. I did not know about the atan2 function, so I created two vectors originating at the same point, the direction-enemy-vector and the player-enemy-vector and tried to find out the angle via the formula :
angle = acos(scalarproduct of the vectors/ product of the amounts of each vector) I did not know, that cos and sin had to be changed, because for the player in other games, it worked perfectly fine. I got the formula

xPos=sin(turn)*speed+xPos and 
zPos=cos(turn)*speed+zPos

from you. You taught it me back then, and it still works perfectly fine. Thank you very much for your help all the time :smile:
Do you know if there is a similar function to atan2 in python?
Thank you for your help.

1 Like

You are welcome

atan2 : it’s on the py reference