Rotating multiple objects around the origin (JavaScript Canvas)

23 views Asked by At

I am currently building a canvas game. I currently have an issue with setting up players. What im trying to do is basically rotate them around an origin. I can place players, but i am not able to rotate them My current code is

addEventListener("DOMContentLoaded",()=>{
    const canvas = document.getElementById("canvas")
    var h = window.innerHeight
    var w = window.innerWidth
    var playerCircleSize = 40
    canvas.height = h
    canvas.width = w
    console.log(h,w)
    function rad(degree){
        return degree * (Math.PI / 180)
    }
    function render(){
        const ctx = canvas.getContext("2d");
        ctx.fillStyle = "#6e955e";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        function player(position){
            function arc(tr1,tr2,size,fillst){
                this.draw = function(){
                    ctx.beginPath();
                    ctx.save()
                    ctx.translate(tr1,tr2)
                    ctx.rotate(rad(position.rot))
                    ctx.arc(0,0,size, 0, 2 * Math.PI);
                    ctx.fillStyle=fillst
                    ctx.fill()
                    ctx.restore()
                }
            }
            var body = new arc(position.x, position.y,playerCircleSize,"#ffc266")
            var hand1 = new arc(position.x-(playerCircleSize/1.5), position.y-(playerCircleSize/1.4),playerCircleSize/3,"#ffb84d")
            var hand2 = new arc(position.x-(playerCircleSize/-1.5), position.y-(playerCircleSize/1.4),playerCircleSize/3,"#ffb84d")

            hand1.draw()
            hand2.draw()
            body.draw()

        }
        player({
            x: w/2 - (playerCircleSize/2),
            y: h/2 - (playerCircleSize/2),
            rot: 90
        })
        player({
            x: 150,
            y: 300,
            rot: 45
        })
    }
    render()
    window.addEventListener("resize", ()=>{
        h = window.innerHeight
        w = window.innerWidth
        canvas.height = h
        canvas.width = w
        console.log(h,w)
        render()
    });
})

I tried to rotate every element individually, but that didnt work. I am expecting the result to look like this

1

There are 1 answers

0
RAllen On BEST ANSWER

You currently apply rotation to separate parts of the player's body and move them separately, i.e., every circle is rotated around its center. This makes the rotation of the whole player impossible.

To fix this problem, you need to change how you work with coordinates. Your player must be rendered as it is at position [0, 0] and then translated and rotated as you need.

Below is the working version. Notice how I changed the way translations and rotations are applied.

As a side note, I highly recommend moving arc out of player and player out of render. This is like whenever you run render the player and arc objects will be recreated. JS is potentially smart enough to compile these objects once, but to improve code structure, I wouldn't recommend putting these objects inside each other.

Please let me know if this helps.

addEventListener("DOMContentLoaded", () => {
  const canvas = document.getElementById("canvas")
  var h = window.innerHeight
  var w = window.innerWidth
  var playerCircleSize = 40
  canvas.height = h
  canvas.width = w
  console.log(h, w)

  function rad(degree) {
    return degree * (Math.PI / 180)
  }

  function render() {
    const ctx = canvas.getContext("2d");
    ctx.fillStyle = "#6e955e";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    function player(position) {
      function arc(tr1, tr2, size, fillst) {
        this.draw = function() {
          ctx.save()
          ctx.beginPath();
          ctx.arc(tr1, tr2, size, 0, 2 * Math.PI);
          ctx.fillStyle = fillst
          ctx.fill()
          ctx.restore()
        }
      }
      var body = new arc(0, 0, playerCircleSize, "#ffc266")
      var hand1 = new arc((playerCircleSize / 1.5), -(playerCircleSize / 1.4), playerCircleSize / 3, "#ffb84d")
      var hand2 = new arc(-(playerCircleSize / 1.5), -(playerCircleSize / 1.4), playerCircleSize / 3, "#ffb84d")

      ctx.save()
      ctx.translate(position.x, position.y)
      ctx.rotate(rad(position.rot))

      hand1.draw()
      hand2.draw()
      body.draw()
      ctx.restore()

    }
    player({
      x: w / 2 - (playerCircleSize / 2),
      y: h / 2 - (playerCircleSize / 2),
      rot: 90
    })
    player({
      x: 150,
      y: 300,
      rot: 45
    })
  }
  render()
  window.addEventListener("resize", () => {
    h = window.innerHeight
    w = window.innerWidth
    canvas.height = h
    canvas.width = w
    console.log(h, w)
    render()
  });
})
<html>

<body>

  <canvas id="canvas"></canvas>

</body>

</html>