Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)

like image 873
Brad Avatar asked Nov 26 '25 00:11

Brad


2 Answers

<!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>
like image 103
Mr. Reddy Avatar answered Nov 27 '25 14:11

Mr. Reddy


Moving from point to point.

Given two points p1 and p2, each point as a coordinate (x,y) and a speed value that is the number of pixels per step, there are two methods you can use to move between them.

Cartesian

Calculate the vector from p1 to p2

var vx = p2.x - p1.x;
var vy = p2.y - p1.y;

Then calculate the delta by getting the length of the vector, normalise it (make the vector 1 pixel long) then multiply by the speed

var dist = Math.sqrt(vx * vx + vy * vy);
var dx = vx / dist;
var dy = vy / dist;
dx *= speed;
dy *= speed;

This can be optimized a little by scaling the speed with the distance.

var scale = speed / Math.sqrt(vx * vx + vy * vy);
var dx = vx / dist;
var dy = vy / dist;

Polar

The other way is to get the direction from p1 to p2 and use that create the deltas

var dir = Math.atan2(p2.y - p1.y, p2.x - p1.x);
var dx = Math.cos(dir) * speed;
var dx = Math.sin(dir) * speed;

Animate

Once you have the delta you just need to update the position via addition.

const bullet = {x : p1.x, y : p1.y}; // set the bullet start pos

// then each frame add the delta
bullet.x += dx;
bullet.y += dy;

// draw the bullet
like image 44
Blindman67 Avatar answered Nov 27 '25 14:11

Blindman67



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!