thesimg
thesimg

Reputation: 338

p5.js rotate towards mouse using atan2() has innacurate rotation

I have recently started a new project using p5.js and am running into issues with rotation, which you can view in the code snippet below.

The rectangle rotating around the player is slightly incorrect in its rotation amount as you can see when you move the mouse slowly around it, it is off by a few degrees. I don't know if this is a simple fix or not because I am relatively new to p5.

It also seems that the panning of the camera is angled in the wrong direction along with the recoil after the shot, not sure if those are the same issues or different unrelated things.

Thanks in advance!

new p5();

var advancedCamera = true;

var p;

var cam = {
  x: 200,
  y: 200,
  gunx: 0,
  guny: 0,
  biasx: 0,
  biasy: 0,
};

var clicked = false;

function setup() {
  createCanvas(400, 400);
  noStroke();
  angleMode(degrees);

}

function draw() {
  background(40);
  cam.x = round(lerp(cam.x, (width / 2) - (p.x + (p.w / 2)) + cam.gunx, 0.1));
  cam.y = round(lerp(cam.y, (height / 2) - (p.y + (p.h / 2)) + cam.guny, 0.1));

  if (advancedCamera) {
    cam.biasx = round(dist(mouseX, mouseY, 200, 200) / 6 * sin(atan2(mouseY - 200, mouseX - 200) + 270));
    cam.biasy = round(-dist(mouseX, mouseY, 200, 200) / 6 * cos(atan2(mouseY - 200, mouseX - 200) + 270));
  }

  push();
  translate(cam.x, cam.y);
  if (advancedCamera) {
    translate(cam.biasx, cam.biasy);
  }

  for (var i = 0; i < bullets.length; i++) {
    bullets[i].pack();
    if (bullets[i].dead) {
      bullets.splice(i, 1);
    }
  }
  p.draw();
  pop();

  if (clicked) {
    cam.gunx = 40 * sin(atan2(mouseY - 200, mouseX - 200) + radians(90));
    cam.guny = -40 * cos(atan2(mouseY - 200, mouseX - 200) + radians(90));
    p.ammo -= 1;
    bullets.push(new bullet(p.x + 10, p.y + 10, (atan2(mouseY - 200, mouseX - 200))));
  }

  if (cam.gunx !== 0 && !clicked) {
    cam.gunx /= 1.6;
  }
  if (cam.guny !== 0) {
    cam.guny /= 1.6;
  }
  clicked = false;
}

mousePressed = function() {
  clicked = true;
};

var bullets = [];

function bullet(x, y, rot) {
  this.x = x;
  this.y = y;

  this.rot = rot;
  this.speed = 5;
  this.damage = 1;

  this.rad = 2;

  this.dead = false;

  bullet.prototype.draw = function() {
    fill(255, 0, 0);
    ellipse(this.x, this.y, this.rad * 2, this.rad * 2);
  };
  bullet.prototype.update = function() {
    this.x += this.speed * sin(this.rot + radians(90));
    this.y -= this.speed * cos(this.rot + radians(90));

    if (dist(this.x, this.y, p.x, p.y) > 300) {
      this.dead = true;
    }
  };
  bullet.prototype.pack = function() {
    this.draw();
    this.update();
  };
}

var p = (function() {
  p = {};

  p.x = 0; //Player Y
  p.y = 0; //Player X

  p.maxHealth = 10;
  p.health = 10;
  p.maxAmmo = 20;
  p.ammo = 20;

  p.w = 20; //Player width
  p.h = 20; //Player height

  p.draw = function() { //Draw player
    rectMode(LEFT);
    fill(255);
    rect(p.x, p.y, 20, 20);

    push();
    translate(p.x + 10, p.y + 10);
    rotate(atan2(200 - mouseY, 200 - mouseX) + radians(90));
    rectMode(CENTER);

    fill(0, 200, 0);
    rect(0, 20, 10, 20);

    translate(0, 200);
    fill(200, 0, 0, 60);
    //rect(0, 20, 1, 400);

    rectMode(LEFT);
    pop();
  };

  return p;
})();
//Player
html,
body {
  margin: 0;
  padding: 0;
  background: rgb(20, 20, 20);
}

canvas {
  display: block;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>sketch</title>

  <link rel="stylesheet" type="text/css" href="style.css">
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.js"></script>
  <script src="sketch2.js"></script>
</head>
</html>

Upvotes: 1

Views: 619

Answers (1)

Paul Wheeler
Paul Wheeler

Reputation: 20150

In essence, the center of your player is not where you think it is on the screen. You're using 200, 200 as the center of the player when calculating the angle to the mouse with atan2 however, it looks to me like it is at 196, 206:

// This makes the green rectangle behave as expected
rotate(atan2(206 - mouseY, 196 - mouseX) + radians(90));

Upvotes: 0

Related Questions