Asperger Asperger - 1 year ago 71
Javascript Question

Javascript Canvas: Collision against enemies not entirely working when rotating player

Note: *A complete JSFiddle can be found at the bottom of my post*.

Problem: I am trying to destroy all enemies that touch the blue line in the center of the canvas. However, this is not the case and my implementation is only "half working". When one side works, the other doesnt. How can I fix this problem?

What I tried: Once I set up the basic drawing functions, I calculated the difference between x and y of the colliding objects. Used the pythagorean distance to calculate the distance between the two points. Finally checked if the distance is less or equal to the combined radius of the two objects. Using arctangent I calculated the rotation of the movement of the objects.

Alternative Solution I Thought Of: Using a loop to creating various invisible circles or dots along the blue line that act as a collision receptor. Problem is: it eats more resources and it wouldnt be elegant at all.

The Javascript function of most interest to you would be:

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

The angle is the angle of the rotating blue line (which is a semi circle with a stoke).

this.tangent(player, spawn) <= angle - Math.PI * 1)

This works only for the -- and +- sections. Changing <= to >= does the opposite as expected. I would need to find a way to loop from -1 to 1.

this.tangent(player, spawn) >= angle - Math.PI * 2 && this.tangent(player, spawn) >= angle

works for --, -+, ++ but not for +- (bottom right).

So in the end im utterly confused why my logic doesnt work but I am eager to learn how this can be achieved:

Below the JSFiddle:

I would be happy for a response as I love learning new things in Javascript : )

Edit (03.11.2015): If possible only purely mathematical solutions but feel free to also post other solutions. For the sake of learning new techniques, every piece of information is welcome.

Answer Source

made something simplified on the problem of collision detection between a disk and an arc (edit: with @markE suggestion (for debugging:

some util functions for comparing angles:

function mod(x, value){ // Euclidean modulo
    return x>=0 ? x%value : value+ x%value;

function angularize(x){
    return mod(x+pi, 2*pi)-pi;

collision detection:

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){
        enemy.destroyed = true;
    } else if(delta_with_shield>=0 ){
        // check distance with right extremety of shield's arc
        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 {
        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;
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download