Javascript画布 - 对角弹跳球

时间:2014-05-01 18:01:20

标签: javascript math canvas html5-canvas

所以基本上我试图将弹跳添加到更新x和y位置的球而不是旋转画布。

这可能,只是吗?

这就是我所拥有的,正确地向上,向下,向左和向右。但对角线显然需要更多的工作。

kick: function(fps, dir, settings){

        var options = {
            speed: 15,
            gravity: .98,
            friction: .99,
            airDrag: .98,
            elasticity: .8,
            angle: 340,
            radius: this.sWidth
        }

        options = deepExtend(options, settings);

        var radians = options.angle * Math.PI/ 180,
            vx = Math.sin(radians) * options.speed,
            vy = Math.cos(radians) * options.speed;

        this.ballStartPosX = this.ball.pos[0];
        this.direc = dir;

        this.vx = vx;
        this.vy = vy;
        this.friction = options.friction;
        this.airDrag = options.airDrag;
        this.elasticity = options.elasticity;
        this.gravity = options.gravity;

        this.shootBall = setInterval(this.shoot.bind(this), fps);
    },

shoot: function () {
        this.ball.pos[0] += this.vx;

        switch(this.direc.toString()) {
            case 'up': this.ball.pos[1] -= this.vy;
            break;
            case 'down': this.ball.pos[1] += this.vy;
            break;
            case 'left': this.ball.pos[0] -= this.vy;
            break;
            case 'right': this.ball.pos[0] += this.vy;
            break;
            case 'up,right': this.ball.pos[1] -= this.vy; this.ball.pos[0] += this.vy;
            break;
            case 'up,left': this.ball.pos[1] -= this.vy; this.ball.pos[0] -= this.vy;
            break;
            case 'down,right': this.ball.pos[1] += this.vy; this.ball.pos[0] += this.vy;
            break;
            case 'down,left': this.ball.pos[1] += this.vy; this.ball.pos[0] -= this.vy;
            break;
        }

        if (this.ball.pos[0] > this.ballStartPosX) {
            this.ball.pos[0] = this.ballStartPosX;
            this.vx = -(this.vx)*this.elasticity;
        }

        this.vx += this.gravity;


        if (this.ball.pos[0] >= this.ballStartPosX) {
            this.vy *= this.friction;
        }


        var speed = Math.sqrt(this.vx*this.vx + this.vy*this.vy);

        if (speed < this.friction) {
            speed = 0;
            clearInterval(this.shootBall);
        }


    }

这就是我想要实现的目标

enter image description here

我想的是,如果我绘制一条不可见的对角线并将其用作触摸点。那会有用吗?

1 个答案:

答案 0 :(得分:0)

最简单的解决方案是使用旋转的二次曲线。

顺便说一下,你为什么不理会这个最简单的解决方案呢?

总之...

&#34;手册&#34;没有画布旋转的解决方案可以通过简单的数学运算完成,但需要很多小步骤。

解决方案包括计算二次曲线的3个控制点,然后沿着该二次曲线设置球的动画。

以下是带注释的代码示例和演示:http://jsfiddle.net/m1erickson/gQ8RC/

此代码执行1次反弹,但可以重复多次反弹。

// get references to the canvas and its context
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");

// save PI*2 to a variable since it's used often
var PI2=Math.PI*2;

// declare the starting and ending points of an imaginary line
var p1={x:20,y:250};
var p2={x:200,y:200};

// declare where a bounce will start & end along that line
// pct1==20%==bounce starts 20% of the way between p1 & p2
// pct2==60%==bounce ends 60% of the way between p1 & p2
var pct1=0.20;
var pct2=0.60;

// calculate deltaX & deltaY of an imaginary line
// containing starting point (p1) & ending point (p2)
var dx=p2.x-p1.x;
var dy=p2.y-p1.y;

// calculate starting point of bounce (20% from p1 towards p2)
var x1=p1.x+dx*pct1;
var y1=p1.y+dy*pct1;

// calculate ending point of bounce (60% from p1 towards p2)
var x2=p1.x+dx*pct2;
var y2=p1.y+dy*pct2;

// calculate mid point of bounce ((60-20)/2% from p1 towards p2)
var pctMidpoint=pct1+(pct2-pct1)/2;
var midX=p1.x+dx*pctMidpoint;
var midY=p1.y+dy*pctMidpoint;

// define a distance (d) for the control point of a quadratic curve
// d will indirectly determine how "high" the bounce will be
var d=75;

// calculate a quadratic curve control point on the tangent line at distance d
var ra=Math.atan2(dy,dx);  // radian angle of the imaginary line
var ta=ra-Math.PI/2;       // radian angle tangent to the imaginary line
var controlX=midX+d*Math.cos(ta);
var controlY=midY+d*Math.sin(ta);

// set up an animation that redraws a ball along 
// the calculated quadratic curve

// T will be an interval used to determine where on the quadratic curve 
// to calculate an x,y point
var T=0;

// just testing...tDirection will reverse the ball when it reaches the end of the curve
var tDirection=1;

// start the animation
requestAnimationFrame(animate);

// animate a ball along the quadratic curve
function animate(){

    // request another animation frame
    requestAnimationFrame(animate);

    ctx.clearRect(0,0,canvas.width,canvas.height);

    // calculate the balls next x,y along the curve
    var point=getQuadraticBezierXYatT(
        {x:x1,y:y1},
        {x:controlX,y:controlY},
        {x:x2,y:y2},
        T/100
    );

    // draw the ball
    ctx.beginPath();
    ctx.arc(point.x,point.y,5,0,PI2);
    ctx.closePath();
    ctx.fillStyle="blue";
    ctx.fill();

    // Move the ball to the next interval on the curve
    // Reverse direction when the ball reaches the start/end of the curve
    T+=tDirection;
    if(T<0 || T>100){
        tDirection*=-1;
        T+=tDirection;        
    }

}

// calculate an x,y point along a quadratic curve at interval T
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} );
}

(只是提到沿斜坡上升的球不会像你所说的那样在物理上表现)