JS Canvas-нарисовать линию под заданным углом
Я хотел бы сделать приложение, где мяч движется под углом, под которым ваша мышь попадает в него. Поэтому, если вы проведете мышью вниз от верхнего левого квадранта на 30 градусов (я думаю, что это будет 180-30 = угол 150 градусов), он будет сбивать мяч таким образом. Я рисовал свои линии как таковые:
function drawAngles () {
var d = 50; //start line at (10, 20), move 50px away at angle of 30 degrees
var angle = 80 * Math.PI/180;
ctx.beginPath();
ctx.moveTo(300,0);
ctx.lineTo(300,600); //x, y
ctx.moveTo(0,300);
ctx.lineTo(600,300);
ctx.moveTo(300,300);
ctx.lineTo(600,100);
ctx.arc(300,300,300,0,2*Math.PI);
ctx.stroke();
}
но это не дает мне представления о том, что такое углы.
затем я перемещаю мяч под этим углом (пока я анимирую его без мыши взаимодействие)
function getAngleX (x) {
return x = x + (50 * Math.cos(Math.PI/6));
}
function getAngleY(y) {
return y = y + (50 * Math.sin(Math.PI/6));
}
//just animate this box to move at an angle from center down at 30 degrees
$(".anotherBox").mouseenter(function(e) {
pos = $(this).position();
box2X = pos.left;
box2Y = pos.top;
$(this).animate({
//top : $(window).outerHeight(),
top : getAngleY(box2Y)+"px",
left: getAngleX(box2X)+"px",
}, "slow");
});
Итак, как я могу нарисовать линию под определенным углом? Я хочу убедиться, что мой мяч следует по этому пути.
2 ответов
Если я угадаю правильно, я думаю, вы хотите, чтобы мышь действовала как бейсбольная бита, и вам нужно измерить текущий угол мыши, то есть сохранить предыдущее положение мыши и сделать некоторые математические расчеты.
вы также должны отслеживать, если вы уже обработали текущее столкновение, чтобы избежать "липкого" шара и следовать за мышью.
http://jsfiddle.net/gamealchemist/z3U8g/
var ctx = cv.getContext('2d');
var ball = {
x:200, y:200,
r : 30,
vx : 0.4, vy:0.4
}
// when mouse moved that distance, ball speed norm will be 1
var speedNorm = 10;
var collisionOnGoing = false;
function collide() {
var dist = sq(ball.x - mx) + sq (ball.y-my);
// too far from ball ?
if (dist > sq(ball.r)) {
collisionOnGoing = false;
return;
}
// return if collision allready handled
if (collisionOnGoing) return;
var mouseDist =Math.sqrt( sq(mx-lastmx) + sq(my-lastmy) );
// no collision if mouse too slow
if (mouseDist<speedNorm/5) return;
// launch the ball in current direction
// with a speed relative to the mouse speed.
var mouseAngle = Math.atan2(my-lastmy, mx-lastmx);
ball.vx= (mouseDist / speedNorm ) * Math.cos(mouseAngle);
ball.vy= (mouseDist / speedNorm ) * Math.sin(mouseAngle);
collisionOnGoing = true;
}
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0,0,400,400);
// collide ball with mouse
collide();
// draw ball
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.r, 0, 6.3);
ctx.fill();
ctx.closePath();
// move
ball.x+=ball.vx;
ball.y+=ball.vy;
// collide with screen
if (ball.x>400) ball.vx=-Math.abs(ball.vx);
if (ball.x<0) ball.vx=Math.abs(ball.vx);
if (ball.y>400) ball.vy=-Math.abs(ball.vy);
if (ball.y<0) ball.vy=Math.abs(ball.vy);
}
animate();
// --- Mouse handling ---
addEventListener('mousemove', mouseMove);
var mx=-1, my=-1, lastmx=-1, lastmy=-1;
var cvRect = cv.getBoundingClientRect();
var cvLeft = cvRect.left;
var cvTop = cvRect.top;
function mouseMove(e) {
lastmx = mx; lastmy=my;
mx=e.clientX - cvLeft;
my=e.clientY - cvTop;
}
function sq(x) { return x*x; }
вы можете использовать различные подходы для достижения этого, но если вы хотите использовать ту же основу для перемещения и рисования, то этот подход может хорошо подойти.
Сначала мы используем функцию для получения значений шага для x и y на основе угла (в радианах):
function getSteps(angle) {
var cos = Math.cos(angle),
sin = Math.sin(angle);
return {
x: cos -sin,
y: sin + cos
}
}
затем, используя эти значения шагов, мы можем масштабировать их, чтобы получить конечную точку, или масштабировать их постепенно, чтобы оживить объект вдоль линии. Простой цикл может выглядеть так (только для пример):
function loop() {
var x = i * step.x, // scale using i
y = i * step.y;
ctx.fillRect(200 + x, 200 + y, 2, 2); // add to origin start point 200, 200
i += 1; // increase i
if (i < length) requestAnimationFrame(loop);
}
Live demo
Если вы просто хотите нарисовать линию под определенным углом, вы можете сделать следующее:
function lineAtAngle(x1, y1, length, angle) {
ctx.moveTo(x1, y1);
ctx.lineTo(x1 + length * Math.cos(angle), y1 + length * Math.sin(angle));
}
затем погладить.
надеюсь, что это помогает!