Topic: points in polygon test Pages that link to <a href="https://ozoneasylum.com/backlink?for=31745" title="Pages that link to Topic: points in polygon test" rel="nofollow" >Topic: points in polygon test\

 
Author Thread
racerX
Nervous Wreck (II) Inmate

From: Portland Oregon
Insane since: Jun 2006

IP logged posted posted 03-26-2010 21:20 Edit Quote

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>
<head>
<title></title>
<script type="text/javascript" src="excanvas.js"></script>
</head>
<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;
//...
window.onload = init;
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>

Maskkkk
Paranoid (IV) Inmate

From: Johnstown, PA
Insane since: Mar 2002

IP logged posted posted 03-29-2010 23:42 Edit Quote

Eh,

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

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



- AIM: MASKKKK

01001101011000010111001101101011011010110110101101101011

Slime
Lunatic (VI) Mad Scientist

From: Massachusetts, USA
Insane since: Mar 2000

IP logged posted posted 03-30-2010 05:00 Edit Quote

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

IP logged posted posted 03-30-2010 10:03 Edit Quote

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.

[edit]

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

IP logged posted posted 03-30-2010 20:20 Edit Quote

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
Maniac (V) Mad Scientist

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

IP logged posted posted 03-31-2010 08:03 Edit Quote

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

IP logged posted posted 03-31-2010 16:35 Edit Quote

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

IP logged posted posted 03-31-2010 16:42 Edit Quote

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..

here's a link
http://www.hardwoodfloorspdx.com/misc/javascript/canvas/asteroids/

q455923354
Obsessive-Compulsive (I) Inmate

From:
Insane since: Jul 2010

IP logged posted posted 07-30-2010 10:09 Edit Quote

TP: Spam removed

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

coach
Nervous Wreck (II) Inmate

From:
Insane since: May 2011

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


Post Reply
 
Your User Name:
Your Password:
Login Options:
 
Your Text:
Loading...
Options:


« BackwardsOnwards »

Show Forum Drop Down Menu