Как повернуть стрелку, чтобы она указывала на положение мыши на экране - PullRequest
0 голосов
/ 14 апреля 2020

Я пытаюсь добавить вектор направления в свою игру с разбивкой кирпичей в начале каждого уровня, чтобы игрок мог стрелять в определенном направлении c.

Я создал новый файл для нарисовать и обновить вектор, но я не могу найти способ обновить его, чтобы он двигался с курсором.

В настоящее время моя игра будет рисовать вектор в вертикальном положении. То, что я хочу сделать, это создать прослушиватель событий, который сохраняет положение мыши по x и y при каждом обновлении, а затем поворачивать вектор на основе разницы углов между вертикальным вектором и вектором, который должен быть сделан, используя позиции x и y: мышь.

Вот простая стрелка, которую я рисую в векторном файле.

draw(ctx) {

    ctx.save();
    ctx.translate(this.paddleCenter.x, this.paddleCenter.y);
    ctx.rotate(this.angle * Math.PI/ 180 );
  ctx.beginPath();
    ctx.strokeStyle = 'red';
    ctx.fillStyle = 'red';
    ctx.lineWidth = 2;

    ctx.moveTo( 0, 0 );
    ctx.lineTo( this.pointer.x , this.pointer.y ); 
    ctx.lineTo( this.pointer.x - 10, this.pointer.y + 10);
    ctx.arcTo( this.pointer.x, this.pointer.y, this.pointer.x + 10, this.pointer.y + 10, 20);
    ctx.lineTo( this.pointer.x, this.pointer.y);
    ctx.stroke();
    ctx.fill();
    ctx.restore();


}

В отдельном файле у меня есть все мои прослушиватели событий. Я знаю, что это должно выглядеть примерно так:

document.addEventListener('pointerover', (event) => {

        vector.moveVector(event.clientX, event.clientY);

    })

, где

moveVector(x, y) {

    this.pointer.x = x;
    this.pointer.y = y
}

, но это не обновляет игру. Я предполагаю, что это потому, что моя функция обновления игры не перерисовывает объекты в игре, пока не будет достигнут следующий уровень.

Что мне нужно включить в функцию обновления вектора (deltaTime), чтобы вектор перемещался с мышью? Я на правильном пути или есть лучший способ заставить его работать?


ОБНОВЛЕНИЕ

Мне удалось заставить его работать.

На входе. js

document.addEventListener('pointerdown', (event) => {

        game.vector.mousePointer.x = event.clientX;
        game.vector.mousePointer.y = event.clientY;

    });

На векторе. js

 update(deltaTime) {

   this.angle = this.moveVector();

}

moveVector() {

 //Calculate angle to rotate vector
 // 0 angle denotes arrow pointing left
 let gameY = this.paddleCenter.y;
 let gameX = this.paddleCenter.x;
 let mouseY = this.mousePointer.y;
 let mouseX = this.mousePointer.x;
 let theta = 0;

 if (this.mousePointer.x < this.paddleCenter.x && this.mousePointer.y < this.paddleCenter.y){
 theta = Math.atan((gameY - mouseY) / (gameX - mouseX)) * 180 / Math.PI; };

else if (this.mousePointer.x > this.paddleCenter.x && this.mousePointer.y < this.paddleCenter.y){
 theta = 180 - Math.atan((gameY - mouseY) / (mouseX - gameX)) * 180 / Math.PI; };

else if (this.mousePointer.x < this.paddleCenter.x && this.mousePointer.y > this.paddleCenter.y ) {
 theta = 0 };

else if (this.mousePointer.x > this.paddleCenter.x && this.mousePointer.y > this.paddleCenter.y) {
 theta = 180 };

return theta 
};

Однако у меня есть больше проблем, над которыми я сейчас работаю.

Я не могу заставить вектор указывать, просто используя указатель на прослушиватель событий. когда я использую указатель, вектор указывает направление, в котором моя мышь вернулась на экран. Если я наведу курсор мыши на экран самой игры, он не обновится автоматически.

Кроме того, стрелка моего нарисованного вектора не вращается. Поэтому, когда я размышляю на экране, часть вектора будет повернута в правильное положение, но часть стрелки останется не повернутой.

Если у вас есть предложения по устранению этих проблем, я был бы признателен.

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

Мне понадобилось время, чтобы понять это:

//<![CDATA[
/* js/external.js */
let get, post, doc, html, bod, nav, M, I, mobile, S, Q, aC, rC, tC; // for use on other loads
addEventListener('load', ()=>{
get = (url, success, context)=>{
  const x = new XMLHttpRequest;
  const c = context || x;
  x.open('GET', url);
  x.onload = ()=>{
    if(success)success.call(c, JSON.parse(x.responseText));
  }
  x.send();
}
post = function(url, send, success, context){
  const x = new XMLHttpRequest;
  const c = context || x;
  x.open('POST', url);
  x.onload = ()=>{
    if(success)success.call(c, JSON.parse(x.responseText));
  }
  if(typeof send === 'object' && send && !(send instanceof Array)){
    if(send instanceof FormData){
      x.send(send);
    }
    else{
      const fd = new FormData;
      for(let k in send){
        fd.append(k, JSON.stringify(send[k]));
      }
      x.send(fd);
    }
  }
  else{
    throw new Error('send argument must be an Object');
  }
  return x;
}
doc = document; html = doc.documentElement; bod = doc.body; nav = navigator; M = tag=>doc.createElement(tag); I = id=>doc.getElementById(id);
mobile = nav.userAgent.match(/Mobi/i) ? true : false;
S = (selector, within)=>{
  var w = within || doc;
  return w.querySelector(selector);
}
Q = (selector, within)=>{
  var w = within || doc;
  return w.querySelectorAll(selector);
}
aC = function(){
  const a = [].slice.call(arguments), n = a.shift();
  n.classList.add(...a);
  return aC;
}
rC = function(){
  const a = [].slice.call(arguments), n = a.shift();
  n.classList.remove(...a);
  return rC;
}
tC = function(){
  const a = [].slice.call(arguments), n = a.shift();
  n.classList.toggle(...a);
  return tC;
}
// you can put the following on another page using a load Event - besides the end load
function Arrow(canvasElement, arrowWidth = 25, arrowHeight = 75, lineWidth = 3, strokeStyle = '#000', lineCap = 'round'){
  let bc = canvasElement.getBoundingClientRect(), ctx = canvasElement.getContext('2d');
  const w = bc.width, h = bc.height, ha = arrowWidth/2;
  canvasElement.width = w; canvasElement.height = h; ctx.lineWidth = lineWidth;
  ctx.strokeStyle = strokeStyle; ctx.lineCap = lineCap;
  let x = w/2, hh = h/2, y = hh-arrowHeight/2, hit = false;
  this.clear = ()=>{
    ctx.clearRect(0, 0, w, h);
  }
  const arrowTop = ()=>{
    ctx.beginPath(); ctx.moveTo(x, y);
  }
  this.make = ()=>{
    this.clear(); arrowTop(); ctx.lineTo(x, y+arrowHeight); ctx.stroke(); 
    arrowTop(); ctx.lineTo(x-ha, y+ha); ctx.stroke();
    arrowTop(); ctx.lineTo(x+ha, y+ha); ctx.stroke();
    return this;
  }
  this.rotate = deg=>{
    ctx.save(); ctx.translate(x, hh); ctx.rotate(Math.PI/180*deg);
    ctx.translate(-x, -hh); this.make(); ctx.restore();
    return this;
  }
  const hitRotate = e=>{
    if(!hit){
      return;
    }
    bc = canvasElement.getBoundingClientRect();
    this.rotate(90+Math.atan2(e.clientY-bc.top-hh, e.clientX-bc.left-x)*180/Math.PI);
  }
  const hitStart = e=>{
    hit = true; hitRotate(e);
  }
  const hitStop = ()=>{
    hit = false;
  }
  this.touch = ()=>{
    canvasElement.ontouchstart = hitStart;
    canvasElement.ontouchmove = e=>{
      hitRotate(e.touches[0]);
    }
    canvasElement.ontouchend = hitStop;
    return this;
  }
  this.mouse = ()=>{
    canvasElement.onmousedown = hitStart;
    canvasElement.onmousemove = hitRotate;
    canvasElement.onmouseup = canvasElement.onmouseout = hitStop;
    return this;
  }
}
const arrow = new Arrow(I('can'));
arrow.rotate(45);
if(mobile){
  arrow.mobile();
}
else{
  arrow.mouse();
}
}); // end load
//]]>
/* css/external.css */
*{
  box-sizing:border-box; padding:0; margin:0;
}
html,body{
  width:100%; height:100%; background:#ccc;
}
.main{
  padding:10px;
}
#can{
  display:block; width:480px; height:270px; background:#fff; margin:0 auto;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
  <head>
    <meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1, user-scalable=no' />
    <title>Title Here</title>
    <link type='text/css' rel='stylesheet' href='css/external.css' />
    <script src='js/external.js'></script>
  </head>
<body>
  <div class='main'>
    <canvas id='can'></canvas>
  </div>
</body>
</html>

PS

Вы можете игнорировать большую часть кода над конструктором Arrow, но сохраняйте и используйте его повторно.

0 голосов
/ 14 апреля 2020

Можно подумать над этим вопросом, рассматривая координаты мыши как вектор положения.

Таким образом, получив угол от вектора, вы можете использовать его для поворота контекста или для рисования указатель на основе этого угла.

var getAngle = function(x, y){
    const angle = Math.atan2(y, x)/Math.PI*180;
    return (360+Math.round(angle))%360; // corrects for angles between 180 ~ 360
}

// you can plug in the mouse coordinate in this
getAngle(-10,10); // returns 135
...