Стрельба в направлении курсора [закрыт]

98
25 февраля 2021, 09:40
Закрыт. Данный вопрос необходимо конкретизировать. Ответы на него в данный момент не принимаются.

Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы он был сосредоточен только на одной проблеме.

Закрыт 1 год назад.

Улучшить вопрос

Помогите реализовать стрельбу из центра окружности в направлении курсора

https://codepen.io/hopman/pen/agJKow

var canvas = document.getElementById("canvas"); 
      var ctx = canvas.getContext("2d"); 
      var arcX  = 100; 
      var arcY = 100; 
      var lineX = 0; 
      var lineY = 0; 
      var speed = 10; 
      var vector = { 
        top: false, 
        bottom: false, 
        left: false, 
        right: false 
      } 
      var KEY_COD = { 
        w: 87, 
        d: 68, 
        s: 83, 
        a: 65 
      }; 
     
      function keyDownHandler (e) { 
        if (KEY_COD.w == e.keyCode) { 
          vector.top = true; 
        } 
        if (KEY_COD.d == e.keyCode) { 
          vector.left = true; 
        } 
        if (KEY_COD.s == e.keyCode) { 
          vector.bottom = true; 
        } 
        if (KEY_COD.a == e.keyCode) { 
          vector.right = true; 
        } 
      }; 
     
      function keyUpHandler (e) { 
        if (KEY_COD.w == e.keyCode) { 
          vector.top = false; 
        } 
        if (KEY_COD.d == e.keyCode) { 
          vector.left = false; 
        } 
        if (KEY_COD.s == e.keyCode) { 
          vector.bottom = false; 
        } 
        if (KEY_COD.a == e.keyCode) { 
          vector.right = false; 
        } 
      } 
     
      document.addEventListener('keydown', keyDownHandler) 
      document.addEventListener('keyup', keyUpHandler) 
      canvas.addEventListener('mousemove', function (e) { 
         lineX = e.layerX; 
         lineY = e.layerY; 
      }) 
     
      function draw () { 
        if (vector.top && arcY >= 50 + speed) { 
          arcY -= speed; 
        } 
        if (vector.left && arcX < canvas.width - 50) { 
          arcX += speed; 
        } 
        if (vector.bottom && arcY < canvas.height - 50) { 
          arcY += speed; 
        } 
        if (vector.right && arcX >= 50 + speed) { 
          arcX -= speed; 
        } 
        ctx.clearRect(0, 0, canvas.width, canvas.height); 
        ctx.beginPath(); 
        ctx.arc(arcX, arcY, 50, 0, 2 * Math.PI); 
        ctx.stroke(); 
     
        ctx.beginPath(); 
        ctx.moveTo(arcX,arcY); 
        ctx.lineTo(lineX,lineY); 
        ctx.stroke(); 
      } 
     
      setInterval(draw, 10)
<canvas id="canvas" width="1200" height="700"></canvas>

Answer 1

Как то так:

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

var bullets=[];  // массив снарядов
...
// по клику добавляем информацию о  снаряде в массив  
canvas.addEventListener('click', function (e) {
    let x = e.layerX - arcX;
    let y = e.layerY - arcY;
    let max = Math.max(Math.abs(x), Math.abs(y));
    bullets.push({
        to: [x/max, y/max], // нормализованный вектор движения
        pos: [arcX, arcY],  // положение 
    });
})
...
function draw() {
    ...
    bullets.forEach(b => {
        //сдвигаем снаряд на значение вектора 
        b.pos[0] += b.to[0];  
        b.pos[1] += b.to[1]; 
        // рисуем его
        ctx.beginPath();
        ctx.arc(...b.pos, 5, 0, 2 * Math.PI);
        ctx.stroke();
    })
    // удаляем снаряды покинувшие канву
    bullets = bullets.filter(b =>{
        return b.pos[0]>0 && b.pos[0]<canvas.width &&
               b.pos[1]>0 && b.pos[1]<canvas.height
    })
    // для отладки - подсчет снарядов
    count.textContent = bullets.length
}

var canvas = document.getElementById("canvas"); 
  var ctx = canvas.getContext("2d"); 
  var arcX  = 100; 
  var arcY = 100; 
  var lineX = 0; 
  var lineY = 0; 
  var speed = 10; 
  var vector = {top: false, bottom: false, left: false, right: false} 
  var KEY_COD = {w: 87, d: 68,s: 83, a: 65}; 
 
  var bullets = [];  // массив снарядов 
    
  function keyDownHandler (e) { 
    if (KEY_COD.w == e.keyCode) vector.top = true; 
    if (KEY_COD.d == e.keyCode) vector.left = true; 
    if (KEY_COD.s == e.keyCode) vector.bottom = true; 
    if (KEY_COD.a == e.keyCode) vector.right = true; 
  }; 
 
  function keyUpHandler (e) { 
    if (KEY_COD.w == e.keyCode) vector.top = false; 
    if (KEY_COD.d == e.keyCode) vector.left = false; 
    if (KEY_COD.s == e.keyCode) vector.bottom = false; 
    if (KEY_COD.a == e.keyCode) vector.right = false; 
  } 
 
  document.addEventListener('keydown', keyDownHandler) 
  document.addEventListener('keyup', keyUpHandler) 
   
  canvas.addEventListener('mousemove', function (e) { 
     lineX = e.layerX; 
     lineY = e.layerY; 
  }) 
 
  canvas.addEventListener('click', function (e) { 
     let x = e.layerX - arcX; 
     let y = e.layerY - arcY; 
     let max = Math.max(Math.abs(x), Math.abs(y)); 
      
     // по клику добавляем информацию о  снаряде в массив   
     bullets.push({ 
       to: [x/max,y/max], // нормализованный вектор движения 
       pos: [arcX,arcY], // положение  
     }); 
  }) 
 
  function draw () { 
    if (vector.top && arcY >= 50 + speed)  arcY -= speed; 
    if (vector.left && arcX < canvas.width - 50) arcX += speed; 
    if (vector.bottom && arcY < canvas.height - 50) arcY += speed; 
    if (vector.right && arcX >= 50 + speed) arcX -= speed; 
     
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
    ctx.beginPath(); 
    ctx.arc(arcX, arcY, 22, 0, 2 * Math.PI); 
    ctx.stroke(); 
 
    ctx.beginPath(); 
    ctx.moveTo(arcX,arcY); 
    ctx.lineTo(lineX,lineY); 
    ctx.stroke(); 
 
    bullets.forEach(b => { 
        //сдвигаем снаряд на значение вектора  
        b.pos[0] += b.to[0];   
        b.pos[1] += b.to[1];  
         
        // рисуем его 
        ctx.beginPath(); 
        ctx.arc(...b.pos, 5, 0, 2 * Math.PI); 
        ctx.stroke(); 
    }) 
 
    // удаляем снаряды покинувшие канву 
    bullets = bullets.filter(b =>{ 
        return b.pos[0] > 0 && b.pos[0] < canvas.width && 
               b.pos[1] > 0 && b.pos[1] < canvas.height 
    }) 
         
    // для отладки - подсчет снарядов 
    count.textContent = bullets.length 
  } 
 
  setInterval(draw, 10)
body{user-select:none;margin:0}canvas {border:solid}
<span id="count"></span><br> 
<canvas id="canvas" width="645" height="165"></canvas>

PS: для создания анимации лучше использовать requestAnimationFrame

Вот мое видение реализации чего-то подобного, реализовал инерцию движения большого круга и подсократил код, перенес отрисовку в requestAnimationFrame

var ctx = canvas.getContext("2d"); 
var arcX = 100, arcY = 100, lineX = 0, lineY = 0,  
    r = 25, br = 5, bullets = []; 
var vector = [ 
  [[ 0, -1], 87],  
  [[ 0,  1], 83],  
  [[-1,  0], 65], 
  [[ 1,  0], 68] 
].map(el => ({ 
    direction: el[0], 
    keyCode: el[1], 
    speed: 0, 
    active: -1 
})) 
  
let keyHandler = (e, active) => vector.forEach(v => v.keyCode === e.keyCode && (v.active = active)) 
document.addEventListener('keydown', e => keyHandler(e, 1)) 
document.addEventListener('keyup', e => keyHandler(e, -1)) 
canvas.addEventListener('mousemove',  e => { 
   lineX = e.layerX, lineY = e.layerY; 
}) 
 
canvas.addEventListener('click',  e => { 
   let x = e.layerX - arcX, y = e.layerY - arcY; 
   let max = Math.max(Math.abs(x), Math.abs(y)); 
   let a = Math.atan2(y,x); 
   // по клику добавляем информацию о  снаряде в массив   
   bullets.push({ 
     to: [x/max, y/max], // нормализованный вектор движения 
     pos: [arcX+Math.cos(a)*r*1.5, arcY+Math.sin(a)*r*1.5], // положение  
     explode: 0 
   }); 
}) 
 
draw(); // тут только рисуем 
setInterval(tick, 10); // обсчитываем положения с фиксированным шагом 
 
function draw() { 
 
  ctx.clearRect(0, 0, canvas.width, canvas.height); 
  ctx.beginPath(); 
  ctx.arc(arcX, arcY, r-2, 0, 2 * Math.PI); 
  ctx.stroke(); 
 
  let x = lineX - arcX, y = lineY - arcY; 
  let a = Math.atan2(y,x); 
 
  ctx.beginPath(); 
  ctx.moveTo(arcX,arcY); 
  ctx.lineTo(arcX+Math.cos(a)*r*1.3, arcY+Math.sin(a)*r*1.3); 
  ctx.stroke(); 
 
  bullets.forEach(b => { 
      ctx.beginPath(); 
      ctx.arc(b.pos[0], b.pos[1], br, 0, 2 * Math.PI); 
      b.explode ? ctx.fill() : ctx.stroke(); 
  }) 
 
  // для отладки - подсчет снарядов 
  count.textContent = bullets.length 
 
  // это откладывает вызов функции `draw` до следующего момента,  
  //когда браузер будет готов нарисовать следующий кадр 
  requestAnimationFrame(draw)  
} 
 
function tick () { 
 
  vector.forEach(v => { 
    v.speed = Math.min(5, Math.max(v.speed + 0.1*v.active, 0)) 
    arcX = Math.min(canvas.width-r, Math.max(arcX + v.direction[0]*v.speed, 0+r)); 
    arcY = Math.min(canvas.height-r, Math.max(arcY + v.direction[1]*v.speed, 0+r)); 
  }) 
   
  bullets.filter(b => b.explode === 0).forEach(b => { 
      //сдвигаем снаряд на значение вектора  
      b.pos[0] += b.to[0];   
      b.pos[1] += b.to[1];  
  }) 
 
  bullets.forEach((b1, i) => { 
       
    if (b1.explode)  
      b1.explode += 0.1; 
       
    for (var j=i+1; j<bullets.length; j++) { 
      let b2 = bullets[j]; 
      let dx = b2.pos[0] - b1.pos[0];  
      let dy = b2.pos[1] - b1.pos[1]; 
      if (dx*dx+dy*dy<100) 
        b1.explode = b2.explode = 1; 
    } 
       
    if(b1.pos[0] < br || b1.pos[0] > canvas.width-br || 
       b1.pos[1] < br || b1.pos[1] > canvas.height-br)   
        b1.explode = 1; 
  }) 
 
}
body{user-select:none;margin:0}canvas {border:solid}
<span id="count"></span><br> 
<canvas id="canvas" width="645" height="165"></canvas>

UPD: последняя версия здесь

READ ALSO
Инициализация функций [дубликат]

Инициализация функций [дубликат]

Почему иногда функции присваивается какое-то значение, например:

97
Использование --x++ допустимо?

Использование --x++ допустимо?

Верно ли утверждать, что (--x)++ представляет собой некоторый эквивалент (x-1)? Т е

106
Перевести SQL-запрос в LINQ

Перевести SQL-запрос в LINQ

Есть два DataGridViewВ одном главные записи, во втором детали по нему

94