繁体   English   中英

Javascript画布-对角弹跳球

[英]Javascript Canvas - Bouncing ball diagonally

因此,基本上,我正在尝试向球添加弹跳,以更新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);
        }


    }

这就是我想要实现的

在此处输入图片说明

我在想,如果我画一条不可见的对角线并将其用作接触点。 那行得通吗?

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

顺便说一句,您为什么不考虑这个最简单的解决方案?

无论如何...

无需画布旋转的“手动”解决方案可以通过简单的数学来完成,但需要许多小步骤。

解决方案包括计算二次曲线的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} );
}

(只需提及沿斜坡上升的球的物理行为就不会像您所说明的那样)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM