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.
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:
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.
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.
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.
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;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With