Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы он был сосредоточен только на одной проблеме.
Закрыт 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>
Как то так:
по клику добавляем снаряд, придаем ему направление и на каждый тик прибавляем направление к положению и удаляем снаряды когда они вылетают за пределы канвы...
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: последняя версия здесь
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Почему иногда функции присваивается какое-то значение, например:
Верно ли утверждать, что (--x)++ представляет собой некоторый эквивалент (x-1)? Т е
Есть два DataGridViewВ одном главные записи, во втором детали по нему