不知道还有什么要问这个问题。我正在使用HTML格式,并希望从画布的左下角开始绘制射弹的轨迹,以一定的角度拍摄,具有一定的速度(如45degrees
10ms
) 。到目前为止,我主要看到使用
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo((180), 180);
ctx.stroke();
但那只画一条直线?
答案 0 :(得分:3)
维基百科有一些准确的[x,y]轨迹计算:
http://en.wikipedia.org/wiki/Trajectory_of_a_projectile
但是如果你只是想让你的射弹对目标形成弧线,你可以这样做:
如果你想沿着该二次曲线绘制点,你可以使用De Casteljau算法,然后沿着绘制的点绘制你的射弹:
function getQuadraticBezierXYatT(startPt,controlPt,endPt,T) {
var x = Math.pow(1-T,2) * startPt.x + 2 * (1-T) * T * controlPt.x + Math.pow(T,2) * endPt.x;
var y = Math.pow(1-T,2) * startPt.y + 2 * (1-T) * T * controlPt.y + Math.pow(T,2) * endPt.y;
return( {x:x,y:y} );
}
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var p0={x:0,y:ch};
var p2={x:180,y:180};
var distance=25;
var p1;
var nextTime=0;
var delay=1000/60*3;
var pts;
var ptIndex=0;
redraw();
$myslider=$('#myslider');
$myslider.attr({min:0,max:100}).val(distance);
$myslider.on('input change',function(){
distance=parseInt($(this).val());
redraw();
});
$('#plot').click(function(){
pts=plot(p0,p1,p2);
ptIndex=0;
requestAnimationFrame(animatePlot);
});
function animatePlot(time){
// if(time<nextTime){requestAnimationFrame(animatePlot);}
nextTime=time+delay;
if(ptIndex<pts.length){
var p=pts[ptIndex];
ctx.clearRect(0,0,cw,ch);
ctx.beginPath();
ctx.arc(p.x,p.y,2,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(p2.x,p2.y,4,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.fillText('['+p2.x+','+p2.y+']',p2.x+10,p2.y);
ptIndex++;
requestAnimationFrame(animatePlot);
}
}
function plot(p0,p1,p2){
var pts=[];
var lastX=p0.x;
var lastY=p0.y;
for(var T=0;T<500;T++){
var p=getQuadraticBezierXYatT(p0,p1,p2,T/500);
var dx=p.x-lastX;
var dy=p.y-lastY;
if(dx*dx+dy*dy>1){
pts.push({x:p.x,y:p.y});
lastX=p.x;
lastY=p.y;
}
}
return(pts)
}
function redraw(){
p1=pointPerpendicularToMidpoint(p0,p2,distance);
ctx.clearRect(0,0,cw,ch);
ctx.beginPath();
ctx.moveTo(p0.x,p0.y);
ctx.quadraticCurveTo(p1.x,p1.y,p2.x,p2.y);
ctx.stroke();
ctx.beginPath();
ctx.arc(p2.x,p2.y,4,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.fillText('['+p2.x+','+p2.y+']',p2.x+10,p2.y);
}
function pointPerpendicularToMidpoint(p0,p2,distance){
var dx=p2.x-p0.x;
var dy=p2.y-p0.y;
var midpoint={ x:p0.x+dx*0.50, y:p0.y+dy*0.50, };
var angle=Math.atan2(dy,dx);
var perpendicularPoint={
x: midpoint.x+distance*Math.cos(angle-Math.PI/2),
y: midpoint.y+distance*Math.sin(angle-Math.PI/2)
};
return(perpendicularPoint);
}
function getQuadraticBezierXYatT(startPt,controlPt,endPt,T) {
var x = Math.pow(1-T,2) * startPt.x + 2 * (1-T) * T * controlPt.x + Math.pow(T,2) * endPt.x;
var y = Math.pow(1-T,2) * startPt.y + 2 * (1-T) * T * controlPt.y + Math.pow(T,2) * endPt.y;
return( {x:x,y:y} );
}
&#13;
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
Change Curve: <input id=myslider type=range>
<br>
<button id=plot>Plot the curve</button>
<br>
<canvas id="canvas" width=300 height=250></canvas>
&#13;
答案 1 :(得分:2)
你想要的是一个在X和Y方向都有速度的物体。对于每次迭代,您都会因重力而降低Y的速度。对于每次迭代,您可以绘制一条线,请参见下面的示例。
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
c.width = 450;
c.height = 300;
var x = 0;
var y = 300;
var oldX = 0;
var oldY = 300;
var xVel = 10;
var yVel = -20;
var g = 1;
var myInterval = setInterval(function () {
x+=xVel;
y+=yVel;
yVel+=g;
ctx.beginPath();
ctx.moveTo(oldX,oldY);
ctx.lineTo(x,y);
ctx.stroke();
oldX = x;
oldY = y;
if (y>c.height) {clearInterval(myInterval);}
},20);
&#13;
canvas {
border: 1px solid black;
}
&#13;
<canvas id="canvas"></canvas>
&#13;