Skip to content

Rotation facing mouse not correct with p5 libraries

i am making a javascript shooter game.i want the the player to rotate towards the mouse.it is working, but the rotation was not correct. I tried this with an image, and it works, but with the sprite itself(player1), is not. i have asked this once before but received no answer

I am a beginner in javascript, so help would be appreciated.

I am using the p5.js libraries

Here is my code snippet:

//variables
var player1;
var gun1;
var gun2;


function preload(){
  img = loadImage('rect1.png');
}

function setup(){
    //creating sprites
    player1 = createSprite(200,200,30,30)
    
    gun = createSprite(player1.x,player1.y-20,5,30)
    gun.shapeColor = "black"
    player1.addImage("player",img)
     player1.scale = 0.2
}

function draw(){
  canvas = createCanvas(displayWidth-20, displayHeight-120);
   background("#32CD32");
   push()
  
   gun.x = player1.x;
   gun.y = player1.y-15;

   // functions to move
   //up
  if(keyDown("up")){
    player1.y = player1.y - 5;
  }
  //down
  if(keyDown("down")){
    player1.y = player1.y + 5;
  }
  //right
  if(keyDown("right")){
    player1.x = player1.x + 5;
  }
  //left
  if(keyDown("left")){
    player1.x = player1.x - 5;
  }
  angleMode(DEGREES)
  imageMode(CENTER)
  let a = atan2(mouseY - height / 2, mouseX - width / 2);
       translate(width/2, height/2);
       //rotate(a)
       player1.rotation = a
       //image(img,0,0,40,40)
  pop()
drawSprites();
} 

Answer

I think I’m using a dated version of p5.play, so there’s not much in your code that works for me, but here’s what I think is going on based on what you’re saying.

If you want to understand what the deal is with atan2(), you first have to understand atan(). Basically, you have the ordinary trig functions sin, cos, and tan. Then you have the inverse trig functions arcsin, arccos, and arctan (abbreviated asin, acos, and atan). The arctan function is useful because you can input a slope and it will give you the angle of that slope. There’s a catch, though; atan will only give values between -pi/2 and pi/2. This covers all non-vertical lines, but what if you wanted to use it for a vector or something that has direction? atan2() solves that problem. Instead of taking one input (a ratio: rise/run), it takes two inputs, a rise and a run. This prevents dividing by zero (for vertical lines) and signs of rise and run cancelling. The first input is the rise, and the second is the run. The output is the angle between the vector with those coordinates and the x-axis. So atan2() will give you some angle between -pi and pi.

Now let’s look at what you have put into the atan2() function:

atan2(mouseY - height / 2, mouseX - width / 2);

So the vector you’re considering is the vector from the middle of the canvas to the mouse. If this is what you want, great. If it’s not, maybe consider

atan2(mouseY - player1.y, mouseX - player1.y);

which yields the “heading” (not really the heading) of the vector from the player’s position to the mouse.

There are a couple of other potential problems (I can’t figure out which one it is because p5.play isn’t behaving, or I’m doing something else wrong):

  1. radians/degrees: sometimes this stuff goes wrong. Try printing a and seeing if it’s what you’re looking for. If it’s in degrees, consider saying player1.rotation = radians(a) instead. I know that p5.Vector.fromAngle() doesn’t care about angleMode, maybe sprite.rotation doesn’t either?
  2. I don’t know how drawSprites works, but you might consider putting it inside of the push()/pop() section. When drawing other shapes, this is how you get a rotation about the point (x, y):
let x = 100;
let y = 200;
let a = atan2(mouseY - y, mouseX - x);
push();
translate(x, y);
rotate(a);
square(-10, -10, 20);
pop();

The square is centered at (x,y), and is rotated about (x,y) toward the cursor. It’s necessary that you do it in this order: push, translate, rotate, shape, pop. If you mix up that order, it doesn’t do it right. But what you have is push, translate, pop, shape. I don’t know how sprite.rotate works, so maybe it’s supposed to do what you want. But here is another way to do a rotation. (If you’re going to do it this way, I think you’d have to draw player1 “at (0,0)” after the translation and rotation, before pop)

I hope this helped!