Search code examples
javascripthtmlcanvasmouseevent

Shooting bullets from player towards mouse?


How do I shoot bullets from my Player X and Y towards the mouse x and y?

I can find the angle of the mouse X and Y but I have no idea how to create a bullet which will fly towards the mouse.

The code for the mouse coordinates are (dx, dy).

Also, if you could explain the logic behind what you did and how you did it, I would be greatful.

Thanks!

Fiddle

  var canvas = document.getElementById('canvas');
  var context = canvas.getContext('2d');
  var pressingDown = false;
  var pressingUp = false;
  var pressingLeft = false;
  var pressingRight = false;
  var mouseX, mouseY;

  function Player(x, y) {
    this.x = x;
    this.y = y;
    this.angle;
  }

  Player.prototype.draw = function() {
    context.save();
    context.translate(this.x, this.y);
    context.rotate(this.angle);

    context.beginPath();
    context.fillStyle = "green";
    context.arc(0, 0, 30, 0, 2 * Math.PI);
    context.fill();

    context.fillStyle = "red";
    context.fillRect(0, -10, 50, 20);

    context.restore();
  }

  Player.prototype.update = function(mouseX, mouseY) {
    var dx = mouseX - this.x;
    var dy = mouseY - this.y;
    this.angle = Math.atan2(dy, dx);
  }


  canvas.addEventListener('mousemove', mouseMove);


  function mouseMove(evt) {
    mouseX = evt.x;
    mouseY = evt.y;
  }

  var player = new Player(350, 250);


  function updatePlayer() {
    context.clearRect(0, 0, canvas.width, canvas.height);
    player.draw();
    player.update(mouseX, mouseY);
    updatePlayerPosition();
  }

  document.onkeydown = function(event) {
    if (event.keyCode === 83) //s
      pressingDown = true;
    else if (event.keyCode === 87) //w
      pressingUp = true;
    else if (event.keyCode === 65) //a
      pressingLeft = true;
    else if (event.keyCode === 68) //d
      pressingRight = true;
  }

  document.onkeyup = function(event) {
    if (event.keyCode === 83) //s
      pressingDown = false;
    else if (event.keyCode === 87) //w
      pressingUp = false;
    else if (event.keyCode === 65) //a
      pressingLeft = false;
    else if (event.keyCode === 68) //d
      pressingRight = false;
  }

  updatePlayerPosition = function() {
    if (pressingRight)
      player.x += 1;
    if (pressingLeft)
      player.x -= 1;
    if (pressingDown)
      player.y += 1;
    if (pressingUp)
      player.y -= 1;
  }

  function update() {
    updatePlayer();
  }

  setInterval(update, 0)


Solution

  • <!doctype html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<style>
    			body {
    				background-color: black;
    			}
    			
    			canvas {
    				position: absolute;
    				margin: auto;
    				left: 0;
    				right: 0;
    				border: solid 1px white;
    				border-radius: 10px;
    			}
    		</style>
    	</head>
    	
    	<body>
    		<canvas id="canvas"></canvas>
    		<script type="application/javascript">
    			
    			(function() {
    			
    				"use strict";
    				
    				var canvasWidth = 180;
    				var canvasHeight = 160;
    				var canvas = null;
    				var bounds = null;
    				var ctx = null;
    				var mouseX = 0.0;
    				var mouseY = 0.0;
    				
    				var player = {
    					x: (canvasWidth * 0.5) | 0,
    					y: (canvasHeight * 0.5) | 0,
    					dx: 0.0,
    					dy: 0.0,
    					angle: 0.0,
    					radius: 17.5,
    					
    					tick: function() {
    						this.angle = Math.atan2(mouseY - this.y,mouseX - this.x);
    					},
    					
    					render: function() {
    						ctx.fillStyle = "darkred";
    						ctx.strokeStyle = "black";
    						ctx.translate(this.x,this.y);
    						ctx.rotate(this.angle);
    						ctx.beginPath();
    						ctx.moveTo(this.radius,0.0);
    						ctx.lineTo(-0.5 * this.radius,0.5 * this.radius);
    						ctx.lineTo(-0.5 * this.radius,-0.5 * this.radius);
    						ctx.lineTo(this.radius,0.0);
    						ctx.fill();
    						ctx.stroke();
    						ctx.rotate(-this.angle);
    						ctx.translate(-this.x,-this.y);
    					}
    				};
    				
    				var bullet = {
    					x: (canvasWidth * 0.5) | 0,
    					y: (canvasHeight * 0.5) | 0,
    					dx: 0.0,
    					dy: 0.0,
    					radius: 5.0,
    					
    					tick: function() {
    						this.x += this.dx;
    						this.y += this.dy;
    						
    						if (this.x + this.radius < 0.0
    						||	this.x - this.radius > canvasWidth
    						||	this.y + this.radius < 0.0
    						|| 	this.y - this.radius > canvasHeight)
    						{
    							this.dx = 0.0;
    							this.dy = 0.0;
    						}
    					},
    					
    					render: function() {
    						ctx.fillStyle = "darkcyan";
    						ctx.strokeStyle = "white";
    						ctx.beginPath();
    						ctx.arc(this.x,this.y,this.radius,0.0,2.0*Math.PI,false);
    						ctx.fill();
    						ctx.stroke();
    					}
    				};
    				
    				function loop() {
    					// Tick
    					bullet.tick();
    					player.tick();
    					// Render
    					ctx.fillStyle = "gray";
    					ctx.fillRect(0,0,canvasWidth,canvasHeight);
    					bullet.render();
    					player.render();
    					//
    					requestAnimationFrame(loop);
    				}
    				
    				window.onmousedown = function(e) {
    					// The mouse pos - the player pos gives a vector
    					// that points from the player toward the mouse
    					var x = mouseX - player.x;
    					var y = mouseY - player.y;
    					
    					// Using pythagoras' theorm to find the distance (the length of the vector)
    					var l = Math.sqrt(x * x + y * y);
    					
    					// Dividing by the distance gives a normalized vector whose length is 1
    					x = x / l;
    					y = y / l;
    					
    					// Reset bullet position
    					bullet.x = player.x;
    					bullet.y = player.y;
    					
    					// Get the bullet to travel towards the mouse pos with a new speed of 10.0 (you can change this)
    					bullet.dx = x * 10.0;
    					bullet.dy = y * 10.0;
    				}
    				
    				window.onmousemove = function(e) {
    					mouseX = e.clientX - bounds.left;
    					mouseY = e.clientY - bounds.top;
    				}
    				
    				window.onload = function() {
    					canvas = document.getElementById("canvas");
    					canvas.width = canvasWidth;
    					canvas.height = canvasHeight;
    					bounds = canvas.getBoundingClientRect();
    					ctx = canvas.getContext("2d");
    					loop();
    				}
    			
    			})();
    			
    		</script>
    	</body>
    </html>