从玩家向鼠标发射子弹?

问题描述 投票:0回答:3

如何从玩家 X 和 Y 向鼠标 x 和 y 发射子弹?

我可以找到鼠标 X 和 Y 的角度,但我不知道如何创建一颗飞向鼠标的子弹。

鼠标坐标的代码是(dx,dy)。

另外,如果您能解释一下您所做的事情背后的逻辑以及如何做到这一点,我将不胜感激。

谢谢!

小提琴

  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)

javascript html canvas mouseevent
3个回答
9
投票

<!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>


5
投票

从一个点移动到另一个点。

给定两个点

p1
p2
,每个点作为坐标 (x,y) 和一个
speed
值(每步的像素数),您可以使用两种方法在它们之间移动。

笛卡尔

计算从 p1 到 p2 的向量

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

然后通过获取向量的长度来计算增量,对其进行归一化(使向量为 1 像素长),然后乘以速度

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

这可以通过根据距离缩放速度来稍微优化。

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

极地

另一种方法是获取从 p1 到 p2 的方向并使用它创建增量

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

动画

一旦获得了增量,您只需通过加法更新仓位即可。

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

0
投票

我会使用笛卡尔方法(参见 Blindman67 的帖子),只是因为简单。如果做错了什么,调试起来会更容易,并且可以轻松封装到可以多次使用的辅助函数中。最后,它很好,因为使用它不需要知道三角学,这对某些人来说可能是个问题。

© www.soinside.com 2019 - 2024. All rights reserved.