0

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.

gideonparanoid
  • 156
  • 1
  • 3
  • 12

2 Answers2

1

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.

bwroga
  • 5,379
  • 2
  • 23
  • 25
  • Thanks for the response. I see the logic in your suggested code, & in that way of doing things in general, so refactored my code to not need to save & restore the canvas. Instead, it maintains the origin as the centre point of the canvas & draws asteroids using similar trigonometry to as you suggested. I implemented your code into it too, for scanning ahead, but still no joy! I'm not sure why it doesn't work. The newer version: http://gideonjon.es/line-drawing-3.html – gideonparanoid Apr 02 '13 at 18:52
  • 1
    @Psygnosys I looked over your code, and everything seems correct. I'm not sure why it's not working. If I have more time later, I will give it a second look. – bwroga Apr 04 '13 at 13:36
0

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.

Community
  • 1
  • 1
gideonparanoid
  • 156
  • 1
  • 3
  • 12