rishi
rishi

Reputation: 640

How to implement rotation of multiple images around an off-centre point in p5.js

I'm making a tower defense game using JavaScript and p5.js library. I have 2 images a base and a gun. The gun is drawn on top of the base to make it appear as a single unit. I need my gun to point towards the enemy(which follows a path). I need help to make the gun rotate on a point(not centre), keeping in mind that there can be several of these towers. I have tried translating(to change centre) and rotating but this doesn't work for many objects and obviously can't keep track of many objects.

I haven't seen any other question regarding this matter either, is there a better solution/alternative to what I'm trying to accomplish?


Required Code


Some Important Variables

var isFireTowerPressed = false;    // checks if tower is placed
var FireTowerPos = [];    // location of every tower => [] - 2d array

Preloaded Stuff

function preload() {
    backgroundImg = loadImage("http://127.0.0.1:8080/img/extra/map1.png");
    [...]
    firetowerbaseImg = loadImage("http://127.0.0.1:8080/img/towers/firetowerbase.png");
    firetowerturretImg = loadImage("http://127.0.0.1:8080/img/towers/firetowergun.png");

}

Draw Every Frame

function draw() 
{

    background(60, 238, 161);
    [...]
    if (isFireTowerPressed == true)    //checks if I have pressed the button to place the tower
    {
        image(firetowerbaseImg, mouseX - 28, mouseY - 28);
        // show range circle
        noFill();
        stroke(0,0,0);
        strokeWeight(1);
        circle(mouseX, mouseY, 300);
    }
    for (var i = 0; i < FireTowerPos.length; i++) 
    {
        image(firetowerbaseImg, FireTowerPos[i][0], FireTowerPos[i][1]);
        image(firetowerturretImg, FireTowerPos[i][0], FireTowerPos[i][1]-20);

    }

}

Mouse Click Event

function mouseClicked()
{

    if (isFireTowerPressed==true && mouseX+28 <= 750) // place-able area
    {
        FireTowerPos.push([mouseX-28, mouseY-28]);
        isFireTowerPressed = false;
    }
}

The picture shows the 2 pictures I'm using(base & gun). I need to be able to rotate the gun towards the enemy

Picture to help visualize problem

Any help is appreciated, thank you

Upvotes: 1

Views: 842

Answers (1)

Julian
Julian

Reputation: 1297

Translating and rotating works for several objects if you also use the push() and pop() methods, from the p5 library, which allow you to store the current settings.

To rotate towards a given point the function atan2(y2 - y1, x2 - x1) is the commonly used method.

To illustrate, I wrote this quick snippet in which the guns will rotate towards the mouse only if the mouse is within range of the gun.

let gunSprite

function preload(){
  gunSprite = loadImage("https://i.imgur.com/ayvg9J2.jpg", ()=>{
    gunSprite.resize(20, 40)
  })
}

let guns = [
  { x: 160, y: 80,  angle: 0, range: 100 },
  { x: 300, y: 200, angle: 0, range: 150 },
  { x: 100, y: 240, angle: 0, range: 120 }
]

function setup(){
  createCanvas(600, 400)
  noFill()
}

function draw(){
  background(200)
  for(let gun of guns)
      drawGun(gun)
}

function drawGun(gun){
  
  const isWithinRange = dist(mouseX, mouseY, gun.x, gun.y) < gun.range
  if(isWithinRange)
    gun.angle = atan2(mouseY - gun.y, mouseX - gun.x) + radians(90)
  
  push()
    translate(gun.x, gun.y)
    rect(-25, -20, 50, 40) // Draw the gun base
    ellipse(0, 0, gun.range*2) // display the gun range
    rotate(gun.angle)
    image(gunSprite, -10, -40) // Set the offset of the gun sprite and draw the gun
  pop()
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js"></script>

Upvotes: 4

Related Questions