Search code examples
javascripthtmlcanvashtml5-canvasgame-physics

Follow image to mouse with rotation on Javascript


Follow image to mouse with rotation on Javascript

How make Santa follow to mouse with rotation and own speed, not mouse speed?

Where mouse now - it's destination, where go santa with own speed.

Santa rotate with speed.

How can I do this?

Demo code

game.js

var canvas, ctx, player

function init() {
  canvas = document.getElementById("canvas")
  ctx = canvas.getContext( "2d" )
  resizeCanvas()

  player = new Player( 
     ctx, 
     canvas.width / 2, 
     canvas.height / 2 + 100 
  )

  window.onresize = resizeCanvas
  canvas.onmousemove = mousemove
}

function mousemove( e ) {
   player.x = e.clientX * devicePixelRatio
   player.y = e.clientY * devicePixelRatio
}

function render() {
   ctx.clearRect( 0, 0, canvas.width, canvas.height )
   player.draw()
}

function step() {
   render()
   requestAnimationFrame( step )
}

init()
step()

Solution

  • It's not trivial task with rotation.

    Modified version with some magic: demo

    For distance used Pythagorean theorem.

    Player moving to forward (by current rotation).

      class Player {
        constructor(ctx, x, y) {
          this.x = x
          this.y = y
    
          this.dest = {
            x: 0,
            y: 0
          }
    
          this.width = 200
          this.height = 200
          this.velocity = 12
          this.angularVelocity = 7
          this.rotation = 0
    
          this.ctx = ctx
    
          this.image = new Image()
          this.image.src = "//habrastorage.org/files/447/9b4/6d3/4479b46d397e439a9613ce122a66a506.png"
        }
    
        draw() {
          this.ctx.translate(this.x, this.y)
          this.ctx.rotate(this.rotation + 4.7)
          this.ctx.drawImage(
            this.image,
            -this.width / 2, -this.height / 2,
            this.width, this.height
          )
          this.ctx.rotate(-this.rotation - 4.7)
          this.ctx.translate(-this.x, -this.y)
        }
    
        distance(target) {
          let data = {
            x: target.x - this.x,
            y: target.y - this.y
          }
          data.len = Math.sqrt(data.x * data.x + data.y * data.y)
          return data
        }
    
        rotate(dt) {
          let path = this.distance(this.dest)
          let target = Math.atan2(path.y, path.x)
    
          let delta = this.rotation - target
          if (delta > 0.1 || delta < -0.1) {
    
            var _delta = delta
            if (_delta < 0) {
              _delta += Math.PI * 2
            }
    
            if (delta < -Math.PI || (delta > 0 && delta < Math.PI)) {
              this.rotation -= _delta / this.angularVelocity
            } else {
              this.rotation -= (_delta - Math.PI * 2) / this.angularVelocity
            }
    
            // Reduce character rotation into the -PI thru PI range
            this.rotation = (this.rotation + 3 * Math.PI) % (2 * Math.PI) - Math.PI
          }
        }
    
        step() {
          let distance = this.distance(this.dest).len
          if (distance < this.width / 1.5) {
            this.draw()
            return
          }
    
          let vel = distance / 15
    
          if (vel > this.velocity) {
            vel = this.velocity
          }
    
          this.rotate()
    
          this.x += vel * Math.cos(this.rotation)
          this.y += vel * Math.sin(this.rotation)
    
          this.draw()
        }
    
      }