0

我正在使用PhysicsJS创建一个杂耍游戏。我只有一个球(圆形)和一只鞋(使用凸多边形形状的方形)。鞋子设置为固定并在 mousemove 上沿 x 轴移动。

正方形:

square = Physics.body('convex-polygon', {
    x: 250,
    y: 400,
    vertices: [
        { x: -68, y: 29 },
        { x: 68, y: 29 },
        { x: 69, y: -29 },
        { x: -68, y: -29 }
    ],
    angle: -0.2,
    view: shoeImage,
    fixed: true,
    restitution: 1
});

world.add(square);

鼠标移动事件:

jQuery('canvas').on('mousemove', function (e) {
    var offset = $(this).offset();
    var relativeX = (e.pageX - offset.left);
    square.state.pos.set(relativeX, 400);
});

我还在鞋子上添加了一个点击事件以产生“踢球效果”。到目前为止,我已经通过更改square.state.angular.pos并使用函数将其设置回之前的角度位置来完成此操作setTimeout

jQuery('canvas').on('click', function (e) {
    if (square.state.angular.pos == -0.2) {
        square.state.angular.pos = 0.3;
    }
    else {
        square.state.angular.pos = -0.2;
    }

    setTimeout(function() { resetShoe(square); }, 500);
});

function resetShoe(square) {
    if (square.state.angular.pos == -0.2) {
        square.state.angular.pos = 0.3;
    }
    else {
        square.state.angular.pos = -0.2;
    }
}

你可以看到它在这里工作。它工作得很好,但我希望这是动画而不是定格动画。我只是想不出办法。

4

2 回答 2

0

您的总体思路是正确的,但是有更好的方法可以做到这一点。

如果您订阅“integrate:positions”事件(这是行为所做的),您可以逐步更改每一步的位置,直到达到您想要的位置。

rotate: function( endAng, vel ){

    var shoe = this; // depending on how you implement this...

    if ( vel === 0 ){
        return; // ... you'll never get there
    }

    // stop any previous animation attempt
    world.unsubscribe('integrate:positions', this.rotateCallback);

    this.endAng = endAng % (Math.PI * 2); // mod by 2Pi since it's circular position
    this.vel = vel;

    world.subscribe('integrate:positions', this.rotateCallback, this);
},

rotateCallback: function( data ){
    var shoe = this; // depending on how you implement this...
    var pos = shoe.state.angular.pos % (Math.PI * 2); // mod by 2Pi since it's circular position

    pos = shoe.state.angular.pos = pos + this.vel * data.dt; // change in pos = velocity x change in time

    // stop at the end
    if ( 
        this.vel > 0 && pos > this.endAng || // increasing
        this.vel < 0 && pos < this.endAng // decreasing
    ){
        world.unsubscribe(data.topic, data.handler);
    }
}

这些是某些对象上的方法……但这取决于您如何实现它。我假设您在鞋身上使用这些,但您也可以做出“踢”行为并将其作为参数传递给鞋子......但这可能是不必要的。

尚未测试,因此可能存在边缘情况错误。但应该是一般的想法。

注意:在physicsjs 的测试版中会有更好的方法来做到这一点……但在那之前这是一个好方法。

于 2014-03-21T17:17:14.670 回答
0

好的,所以我想出了解决这个问题的方法。我按照文档中显示的示例进行操作,其中可以创建新的子类型并拥有自己的功能

我用一个函数创建了一个鞋子子类型convex-polygonkick

Physics.body('shoe', 'convex-polygon', function( parent ){

    return {

        kick: function (operator) {
            if (operator == "add") {
                if (this.state.angular.pos < 0.3) {
                    this.state.angular.pos += 0.1;
                    timer = setTimeout(function() { square.kick("add"); }, 20);
                }
                else {
                    timer = setTimeout(function() { square.kick("subtract"); }, 20);
                }
            }

            if (operator == "subtract") {
                if (this.state.angular.pos > -0.2) {
                    this.state.angular.pos -= 0.1;
                    timer = setTimeout(function() { square.kick("subtract"); }, 20);
                }
                else {
                    clearTimeout(timer);
                }
            }
        }
    };
});

kick 函数将角度增加到 0.3 并将角度减小到原始角度 -0.2。可能有更好的方法来做到这一点。

所以当点击事件被触发时,kick 函数被调用:kick("add");

jQuery('canvas').on('click', function (e) {

    clearTimeout(timer);

    world.subscribe('step', function( data ){
        square.kick("add");
        // only execute callback once
        world.unsubscribe( 'step', data.handler );
    });
});

clearTimeout用于消除鞋子的重复动画,以防鼠标重复点击。

于 2014-03-21T14:32:47.867 回答