0

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/p5@1.4.0/lib/p5.js"></script>
  <script src="sketch2.js"></script>
</head>
</html>
thesimg
  • 328
  • 1
  • 12
  • Comment out your camera code and it should work, although there are other problems, like `LEFT` not being a valid `rectMode`: "rectMode() was expecting CORNER|CORNERS|CENTER|RADIUS for the first parameter, received string instead". What is the camera supposed to do? – ggorlen Sep 05 '21 at 14:23
  • @ggorlen Hmm, missed that `rectMode` issue, wasn't popping up in the console. Thanks for the catch! The camera in its most basic form is to track with the player as it moves around the map, when movement code is implemented, but I additionally was trying to use it for 1. showing recoil in the opposite direction of the gun and 2. moving slightly in the opposite direction of the mouse to provide a larger view on the side of the mouse. (I can provide a complete version of the project so far to provide context if it would help) – thesimg Sep 05 '21 at 17:01
  • Thanks, the extra context helps. I guess it seems like your code is working except for the viewport, so maybe the question appears to be how to do the viewport? There's a [canonical post on viewports](https://stackoverflow.com/questions/16919601/html5-canvas-camera-viewport-how-to-actually-do-it/) that's agnostic of P5 -- have you seen that? For firing recoil, it might be best to just move the player a bit rather than the viewport? After all, when you shoot a gun it's the object or person firing it that's pushed back, not the whole environment/scene. – ggorlen Sep 05 '21 at 18:50
  • Here's the [complete project](https://editor.p5js.org/thesimg/sketches/dXH1D8lfj) -- hopefully it will work as I have just copied everything from VSC onto the online editor which I don't have much experience with. I've disabled all of the extra viewport movement so it is down to the most basic form. Your suggestion about moving the player rather than the environment makes sense, I will make those changes in the future. I'll check out that post on viewports, haven't seen that before. – thesimg Sep 05 '21 at 22:34

1 Answers1

0

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));
Paul Wheeler
  • 18,988
  • 3
  • 28
  • 41