Question

I'm working on a game for a university assignment. The idea is that you defend the centre circle from the incoming asteroids (lines) by drawing a line (click, drag & release to draw a line) which blocks them. An asteroid hitting a line should destroy both the asteroid the line.

The problem I'm currently having is that the collision isn't being detected.

I have arrays of objects of both lines & asteroids. The lines consist of simply start & end x & y, the asteroids consist of a random speed & a random angle (their incoming angle) - the context is rotated, the asteroid drawn, & then it reset for the next line.

To detect collision, I use getImageData & check in front of the asteroids however many pixels the line will progress in that iteration (basically, their speed) & if the colour is red, it will destroy the asteroid - I haven't got round to destroying the line yet, will tackle that hurdle when I come to it (suggestions are welcome though).

function asteroids_draw() {
            for (var i = 0; i < asteroids.length; i++) {
                //  Drawing setup
                context.save();
                context.translate(width / 2, height / 2);
                context.rotate(asteroids[i].angle);             

                //  Detecting close asteroids
                if ((asteroids[i].distance - asteroids[i].speed) < planet.size) {
                    asteroids.splice(i, 1);
                    game_life_lost();
                    context.restore();      
                    return;

                } else if ((asteroids[i].distance - asteroids[i].speed) < 150){
                    asteroids[i].colour = '#FF0000';
                }

                //  Scanning ahead for lines                    
                for (var j = 0; j < asteroids[i].speed; j++) {
                    if (context.getImageData(asteroids[i].distance - j, 0, 1, 1).data[0] == 255) {                          
                        asteroids.splice(i, 1);
                        context.restore();      
                        return;
                    }
                }                   

                //  Drawing asteroid
                context.beginPath();
                context.moveTo(asteroids[i].distance -= asteroids[i].speed, 0);
                context.lineTo(trig, 0);
                context.strokeStyle = asteroids[i].colour; 
                context.stroke();               
                context.closePath();

                context.restore();      
            }
        }

The problem is, the asteroids never collide with the lines & I can't for the life of me see why, or see another simple way of doing it. Any advice would be much appreciated, thanks in advance.

Was it helpful?

Solution 2

I thought about the problem some more, & realised this method of doing things definitely isn't the best way. It should be doable without a view - a la Model View Controller design pattern. The best way to solve it would be to use maths!

There's simple maths for the intersection of two lines, but this needs intersection of two lines in a range. I found an algorithm which simplifies this further, using eight coordinates - the start x & y & the end x & y of the two lines.

I've posted the results. Thanks for the help.

OTHER TIPS

I think your problem is that when you rotate the context, previously drawn items(lines) don't get rotated, only objects drawn after the rotation are rotated. See this page for more info.

You could try performing your asteroid/line intersection test before you translate and rotate the canvas, and use cosine and sine to find the x and y coordinates of the pixels you want to get image data from.

var pixelLocation = 
    [Math.cos(asteroids[i].angle) * j, Math.sin(asteroids[i].angle) * j];
if (context.getImageData(pixelLocation[0], pixelLocation[1], 1, 1).data[0] == 255) {

Just make sure your angle is in radians before passing to cos and sin.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top