Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

http://jsfiddle.net/mzg635p9/

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.

like image 206
Asperger Avatar asked Oct 31 '15 18:10

Asperger


People also ask

What is a collision vector in video games?

This vector is nothing more than the difference in x and y between the two colliding objects. You can see it as an arrow with length and direction. With vectors, the length is also called magnitude. Calculate the collision vector like this: In the example of the two game objects, the collision vector will look like this:

How to avoid collision between two objects moving at the same speed?

In short, make sure the speed is never larger than the smallest game object, so it can't pass through. For many types of games this is a great solution and it requires minimal effort. The other solution is to perform collision detection with the projected path instead of the current position of the two objects.

Can every object collide with every other object?

Not every object can collide with every other object. For example, a ship won’t collide with it’s own bullet, the same goes for an enemy ship. So we need to check to see if the two objects should collide before we check to see if they are colliding.

How to solve the problem of collision detection in games?

For many types of games this is a great solution and it requires minimal effort. The other solution is to perform collision detection with the projected path instead of the current position of the two objects. Try to visualize the path of a bullet as a line. The length of the line is equal to the distance the bullet will travel.


1 Answers

made something simplified on the problem of collision detection between a disk and an arc http://jsfiddle.net/crl/2rz296tf/31 (edit: with @markE suggestion http://jsfiddle.net/crl/2rz296tf/32/) (for debugging: http://jsfiddle.net/crl/2rz296tf/27/)

some util functions for comparing angles:

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;
}

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){
        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;
        }
    }
}
like image 91
caub Avatar answered Oct 19 '22 05:10

caub