Reputation: 76899
I'm recreating an old game, similar to Tron, in HTML5 canvas+JS. The main difference is that the snakes don't turn in right angles, they can move in curves (the name's Achtung Die Kurve).
I need to detect collisions, and I don't know how. The rules are really simple, and everything I come up with or read about looks needlessly complicated. Collisions occur when:
A snake runs into another snake's body (or its own) head-first (I emphasize that because, in a very early experiment, my snakes' heads crushed backwards into their own "necks" as soon as they moved :P).
A snake runs into a wall (no inner walls).
How should I go about this? I'm willing to add whatever data is needed to my objects.
Upvotes: 4
Views: 2081
Reputation: 1
I thought that the best option is split the snakes in segments, stored in memory and check the collisions against those segments.
Upvotes: 0
Reputation: 76899
First off, thanks everyone for your responses! I read what you posted, read a little more around, did some thiking and decided to do the following:
I'm going to keep a bytemap representing the game area, and every time a position is occupied, add 1 to the value. Then, I'm going to check in the 3 "outer" corners of the 4 corners of the snake's head (the "inner" corner collides with the rest of the body) for != 1
values.
I think I'll use an invisible canvas and the alpha value to keep my code simple.
Sorry I wrote my own answer to accept: I think it's important to keep a record of the actual solution I'll implement, and none of the answers fully details my decission.
Upvotes: 0
Reputation: 2744
Do you want pixel perfect collision checking? Best thing to do is probably treat the game area as a grid (of whatever resolution you need, pixel-perfect or otherwise) and keep a list for each snake indicating which grid locations each snake takes up. Then store the location of the snake's head and a vector representing its direction, and test the location + vector against all grid locations taken up by snakes. You can make this process efficient by using hash sets if you care to optimize that much.
Upvotes: 0
Reputation: 17365
You can have an in memory 2d boolean array with the size of the canvas pixels (width*height). I the array always populate boolean values of the walls (can be inner walls as well if you care) and the snake's body.
On each iteration, check the position of the snake's head in the array, if the values there are true you have a collision.
You could in theory do this by checking pixel values on the canvas itself but if you want to use background patterns or other uncollidable elements it would not work for you.
Upvotes: 2
Reputation: 141839
I would suggest getting the coordintates of the front of the snake head every time it moves (every frame maybe).
Then use snakeHead.style.display = 'none';
to temporarily hide the snake head (You'll reshow it again before a render)
Then document.elementFromPoint(x, y)
to check which element is right under the front of the snake head. Maybe add a class called collidable or something to all elements that cause a collision and test
var class = ' '+document.elementFromPoint(x, y).className+' ';
if(class.indexOf(' collidable ') > -1){
alert('Collision!');
}
Then of course reshow the snake head:
snakeHead.style.display = 'whatever is was before probably inline';
Just an idea.
elementFromPoint has good browser compatability too: http://www.quirksmode.org/dom/w3c_cssom.html#documentview
Let me know how it play's out :)
Upvotes: 1