Javascript Canvas:在旋转玩家时对抗不完全正常工作的敌人

Asp*_*ger 14 javascript canvas collision

注意:*可以在我的帖子底部找到一个完整的JSFiddle*.

问题:我试图摧毁触摸画布中心蓝线的所有敌人.然而,事实并非如此,我的实施只是"半工作".当一方工作时,另一方不工作.我该如何解决这个问题?


我尝试过:一旦我设置了基本的绘图功能,我就计算了碰撞对象的x和y之间的差异.使用毕达哥拉斯距离来计算两点之间的距离.最后检查距离是否小于或等于两个物体的组合半径.使用arctangent我计算了物体运动的旋转.


我想到的替代解决方案:使用循环创建沿着蓝线的各种不可见的圆或点,充当碰撞受体.问题是:它占用了更多的资源,而且根本不会优雅.


您最感兴趣的Javascript函数将是:

function (player, spawn) {
    return (this.distance(player, spawn) <= player.radius + spawn.radius) && (this.tangent(player, spawn) <= angle - Math.PI * 1);
}
Run Code Online (Sandbox Code Playgroud)

角度是旋转蓝线的角度(它是带有行程的半圆).

this.tangent(player, spawn) <= angle - Math.PI * 1)
Run Code Online (Sandbox Code Playgroud)

这仅适用于 - 和+ - 部分.改变<= to> =与预期相反.我需要找到一种从-1循环到1的方法.

this.tangent(player, spawn) >= angle - Math.PI * 2 && this.tangent(player, spawn) >= angle
Run Code Online (Sandbox Code Playgroud)

适用于 - , - +,+但不适用于+ - (右下).

所以最后我完全混淆了为什么我的逻辑无法工作但我渴望了解如何实现这一目标:


在JSFiddle下面:

http://jsfiddle.net/mzg635p9/

我很乐意回复,因为我喜欢在Javascript中学习新东西:)

编辑(03.11.2015):如果可能只有纯粹的数学解决方案,但也可以发布其他解决方案.为了学习新技术,我们欢迎每一条信息.

cau*_*aub 6

对磁盘和弧之间的碰撞检测问题进行了简化http://jsfiddle.net/crl/2rz296tf/31(编辑:@markE建议http://jsfiddle.net/crl/2rz296tf/32/) (用于调试:http://jsfiddle.net/crl/2rz296tf/27/)

一些用于比较角度的util函数:

function mod(x, value){ // Euclidean modulo http://jsfiddle.net/cLvmrs6m/4/
    return x>=0 ? x%value : value+ x%value;
}

function angularize(x){
    return mod(x+pi, 2*pi)-pi;
}
Run Code Online (Sandbox Code Playgroud)

碰撞检测:

var d_enemy_player = dist(enemy.pos, player.pos)
if (d_enemy_player>player.shieldradius-enemy.radius && d_enemy_player<player.shieldradius+enemy.radius){ 
    //only worth checking when we are approaching the shield distance
    var angle_enemy = atan2(enemy.pos.y-player.pos.y, enemy.pos.x-player.pos.x)

    var delta_with_leftofshield = angularize(angle_enemy-player.angle-player.shieldwidth)
    var delta_with_rightofshield = angularize(angle_enemy-player.angle+player.shieldwidth)
    var delta_with_shield = angularize(angle_enemy-player.angle)

    if (delta_with_leftofshield<0 && delta_with_rightofshield>0){
        console.log('boom')
        enemy.destroyed = true;
    } else if(delta_with_shield>=0 ){
        // check distance with right extremety of shield's arc
        console.log('right')
        var d_rightofshield_enemy = dist(enemy.pos, {x:player.pos.x+player.shieldradius*cos(player.angle+player.shieldwidth), y:player.pos.y+player.shieldradius*sin(player.angle+player.shieldwidth)});
        if (d_rightofshield_enemy<enemy.radius){
            console.log('right boom')
            enemy.destroyed = true;
        }
    } else {
        console.log('left')
        var d_leftofshield_enemy = dist(enemy.pos, {x:player.pos.x+player.shieldradius*cos(player.angle-player.shieldwidth), y:player.pos.y+player.shieldradius*sin(player.angle-player.shieldwidth)});
        if (d_leftofshield_enemy<enemy.radius){
            console.log('left boom')
            enemy.destroyed = true;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的解决方案 - upvote.为完整起见,您可能需要考虑屏蔽线宽.F.ex,看看敌人在这个稍微修改过的演示中如何滑过盾牌的边缘:https://jsfiddle.net/m1erickson/72ct5gop/ (2认同)