# Topic: points in polygon test (Page 1 of 1)

racerX
Nervous Wreck (II) Inmate

From: Portland Oregon
Insane since: Jun 2006

posted 03-26-2010 21:20

Hi folks, I'm trying to make this little asteroids script work and I'm so close, but I just seem to be overlooking something. I have an array that holds the objects that define the asteroids. I also have an array in the player object that holds the bullets, which are objects also. Simple enough? I thought so. I tested the point in poly function using the player.bullets[0] and it works. So, I tried to iterate through all the bullets and all the asteroids in a loop.

I tried to use while conditionals based on the length of the arrays
var i=arry.length
while(arry[i--]){blah blah blah}

but that didn't work either.

What would an awesome programmer( like you find here at the asylum ) do to handle the collisions?

Here's the script

if you have excanvas.js, it will work in internet explorer, but it's reallly slow.

code:
```<html>
<title></title>
<script type="text/javascript" src="excanvas.js"></script>
<body>
<script>
function pnpoly(xp, yp, x, y) {
var c = 0;
for (i in xp) {
j = i++;
if ((((yp[i] <= y) && (y < yp[j])) || ((yp[j] <= y) && (y < yp[i]))) && (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i])) {
c = !c
}
}
return c
}
var level = 1
var canvas = null;
var c2d = null;
//...
function init() {
thrustFlame = false
asteroids = [{
x: 470,
y: 290,
angle: 1.71,
inertia: .5,
inertiaAngle: 1.2,
points_x: [-30, -27, 5, 15, 30, 15, -5],
points_y: [-5, 15, 30, 27, -5, -25, -30],
hits: 0
},
{
x: 270,
y: 290,
angle: 1.71,
inertia: .75,
inertiaAngle: 1.9,
points_x: [-30, -10, 0, 20, 40, 20, -10],
points_y: [0, -20, -50, -30, 0, 20, 20],
hits: 0
}]
player = {
x: 50,
y: 50,
angle: 1.71,
inertia: 0,
inertiaAngle: 0,
bullets: []
}
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
setInterval(step, 60);
}
function step() {
for (i in asteroids) {
asteroids[i].angle += i % 2 == 0 ? .05 : -.05
asteroids[i].x < 0 ? asteroids[i].x = canvas.width : asteroids[i].x %= canvas.width
asteroids[i].y < 0 ? asteroids[i].y = canvas.height : asteroids[i].y %= canvas.height
asteroids[i].x += Math.sin(asteroids[i].inertiaAngle) * asteroids[i].inertia;
asteroids[i].y += -Math.cos(asteroids[i].inertiaAngle) * asteroids[i].inertia
}
ctx.fillStyle = "rgb(0,0,0)"
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (u = 0; u < asteroids.length; u++) {
ctx.save();
ctx.beginPath()
Asteroid_draw(asteroids[u]);
ctx.closePath();
ctx.strokeStyle = "#eeeeff";
ctx.stroke();
ctx.restore();
}
if (asteroids.length > 0) {
for (num in asteroids) {
if (player.bullets.length > 0) {
for (n in player.bullets) {
if (pnpoly(asteroids[num].points_x, asteroids[num].points_y, player.bullets[n].x - asteroids[num].x, player.bullets[n].y - asteroids[num].y) == true) {
player.bullets.splice(n, 1);
asteroids[num].hits++;
for (z in asteroids[num].points_x) {
asteroids[num].points_x[z] *= .5;
asteroids[num].points_y[z] *= .5;
if (asteroids[num].hits > 2) asteroids.splice(num, 1)
}
}
}
}
}
} else {
level++;
for (i = 0; i < level + 1; i++) {
asteroids.push({
x: 200 * Math.random(),
y: 200 * Math.random(),
angle: Math.random() * 2,
inertia: Math.random() * 3,
inertiaAngle: 1.2,
points_x: [-30, -27, 5, 15, 30, 15, -5],
points_y: [-5, 15, 30, 27, -5, -25, -30],
hits: 0
})
}
}
ctx.save();
ctx.beginPath()
Player_draw(player);
ctx.closePath()
ctx.strokeStyle = "#eeeeff";
ctx.stroke();
ctx.restore()
if (thrustFlame) {
ctx.save();
ctx.beginPath()
Player_drawFlame(player);
ctx.closePath()
ctx.strokeStyle = "#ff0000";
ctx.stroke();
ctx.restore()
thrustFlame = false
}
player.x < 0 ? player.x = canvas.width : player.x %= canvas.width
player.y < 0 ? player.y = canvas.height : player.y %= canvas.height
if (player.inertia > .025) player.inertia -= .025; player.x += Math.sin(player.inertiaAngle) * player.inertia;
player.y += -Math.cos(player.inertiaAngle) * player.inertia
for (i = 0; i < player.bullets.length; i++) {
player.bullets[i].timer++;
player.bullets[i].x < 0 ? player.bullets[i].x = canvas.width : player.bullets[i].x %= canvas.width
player.bullets[i].y < 0 ? player.bullets[i].y = canvas.height : player.bullets[i].y %= canvas.height
player.bullets[i].x += Math.sin(player.bullets[i].inertiaAngle) * player.bullets[i].inertia;
player.bullets[i].y += -Math.cos(player.bullets[i].inertiaAngle) * player.bullets[i].inertia
ctx.save();
ctx.beginPath()
ctx.fillStyle = "rgba(255,255,0,1)"
ctx.arc(player.bullets[i].x, player.bullets[i].y, 1.5, 0, 3.14, true)
ctx.fill()
ctx.closePath()
ctx.restore();
if (player.bullets[i].timer > player.bullets[i].range) player.bullets.shift()
}
}
function Asteroid_draw(obj) {
ctx.translate(obj.x, obj.y)
ctx.rotate(obj.angle);
ctx.moveTo(obj.points_x[0], obj.points_y[0]);
for (i = 0; i < obj.points_x.length - 1; i++) {
ctx.lineTo(obj.points_x[i], obj.points_y[i]);
}
ctx.lineTo(obj.points_x[0], obj.points_y[0])
}
function Player_draw(obj) {
ctx.translate(obj.x, obj.y);
ctx.rotate(obj.angle);
//Points {0,-12}{7,5}{-7,5}
ctx.moveTo(0, -12);
ctx.lineTo(7, 4);
ctx.lineTo(-7, 4);
ctx.moveTo(-7, 4)
ctx.lineTo(0, -12);
}
function Player_drawFlame(obj) {
ctx.translate(obj.x, obj.y);
ctx.rotate(obj.angle);
ctx.moveTo(-2, 2);
ctx.lineTo(0, 12);
ctx.lineTo(2, 2);
}
document.onkeydown = function (event) {
keyDown(event)
};
function keyDown(event) {
event = !event ? window.event : event
if (event.keyCode == 32) {
player.bullets.push({
x: player.x,
y: player.y,
inertia: player.inertia + 10,
inertiaAngle: player.angle,
timer: 0,
range: 40
})
}
if (event.keyCode == 37) {
player.angle -= .1
} /*left*/
else if (event.keyCode == 39) {
player.angle += .1
} /*right*/
else if (event.keyCode == 38) {
thrustFlame = true
var x1 = Math.cos(player.inertiaAngle) * player.inertia;
var y1 = Math.sin(player.inertiaAngle) * player.inertia;
var x2 = Math.cos(player.angle) * .2;
var y2 = Math.sin(player.angle) * .2;
var xR = x1 + x2;
var yR = y1 + y2;
var lengthR = Math.sqrt(xR * xR + yR * yR);
if (lengthR == 0) {
angleR = 0
}
var angleR = Math.acos(xR / lengthR);
if (yR < 0) angleR = 0 - angleR;
player.inertia = lengthR
// player.inertiaAngle = (player.inertiaAngle*19 + player.angle) / 20
player.inertiaAngle = angleR
} /* up*/
else if (event.keyCode == 40) {
player = {
x: 50,
y: 50,
angle: 1.71,
inertia: 0,
inertiaAngle: 0
}
} /*down*/
}
</script>
<canvas id="canvas" width="600" height="600"></canvas>
</body>
</html>```

Paranoid (IV) Inmate

From: Johnstown, PA
Insane since: Mar 2002

posted 03-29-2010 23:42

Eh,

http://stackoverflow.com/questions/217578/point-in-polygon-aka-hit-test

I hate to do that, but...enjoy the answer.

01001101011000010111001101101011011010110110101101101011

Slime

From: Massachusetts, USA
Insane since: Mar 2000

posted 03-30-2010 05:00

After a brief look at your script, everything looks ok except for the line

j = i++;

This modifies i, which might affect the loop behavior and cause it to skip every other line segment. I think you probably want

j = (i + 1) % xp.length;

poi
Paranoid (IV) Inmate

From: Norway
Insane since: Jun 2002

posted 03-30-2010 10:03

And how about using the CanvasRenderingContext2DisPointInPath( x, y ) method ?

Or since you're tracing the polygons anyways, why not fill them, each of them, with a unique (dark) color and check the color of the pixel at the x,y coordinates you want ? The unique color will act as a unique ID for all the polygons and make a lot of things easier.

Oh! And you should not put any game logic in the event handlers because events can be fired much faster than the main loop of your game. The only thing your event handlers should do is set some flags to be interpreted in the main loop of your game.

And don't forget to add <!doctype html> at the beginning of your page

[/edit]

Also, please, try to make it easier for people to look at your work in progress by posting a URL instead of posting a big chunk of code in the forum.

(Edited by poi on 03-30-2010 10:09)

racerX
Nervous Wreck (II) Inmate

From: Portland Oregon
Insane since: Jun 2006

posted 03-30-2010 20:20

Slime said:
After a brief look at your script, everything looks ok except for the line

j = i++;

This modifies i, which might affect the loop behavior and cause it to skip every other line segment. I think you probably want

j = (i + 1) % xp.length;

Thanks so much. That was the problem, I think. It now works on the correct rock. It's not perfect. I'm going to try isPointInPath() again, which was the first way i tried to do the hit test. Thanks for the help, everyone. I've been scratching my head for a few days on this.

poi, would checking the color at the bullet positions require using getImageData? Or is there a method you could recommend using?
Also, if using the colored poly method, would you set only the currently-being-tested polygon in that color? obviously, I don't want to literally fill the polygon, so I'd have to redraw the scene again if I filled the polygon.

Did I misunderstand what you meant? Could you suggest an order of events to follow?

Thanks again, everyone.

Petskull

From: 127 Halcyon Road, Marenia, Atlantis
Insane since: Aug 2000

posted 03-31-2010 08:03

Man- you guy come out of nowhere and then post so fast!

Hey- when you press the Down Arrow in the game, is that vanishing act a bug, or a feature?

racerX
Nervous Wreck (II) Inmate

From: Portland Oregon
Insane since: Jun 2006

posted 03-31-2010 16:35

Yeah, it's supposed to be the hyperspace button. I was going to have it position the player at random points, but I didn't adjust it yet.

racerX
Nervous Wreck (II) Inmate

From: Portland Oregon
Insane since: Jun 2006

posted 03-31-2010 16:42

I fixed it. I forgot to add the bullets array into the object I'm using to set the new player position when hyperspace it hit..

http://www.hardwoodfloorspdx.com/misc/javascript/canvas/asteroids/

q455923354
Obsessive-Compulsive (I) Inmate

From:
Insane since: Jul 2010

posted 07-30-2010 10:09

TP: Spam removed

(Edited by Tyberius Prime on 07-30-2010 12:15)

coach
Nervous Wreck (II) Inmate

From:
Insane since: May 2011

posted 05-31-2011 11:03
Edit TP: spam removed