Calculate overlap of two colliding objects? - javascript

UPDATE: I found this enormously helpful article explaining canvas per-pixel collision detection.
I'm working on a collision system for a javascript game using HTML5 canvas. Each object has an image as a sprite and when a non-transparent pixel of any one object overlaps another, the collision code is triggered. But before anything else the objects need to be moved so that they are just touching each other and no longer triggering a collision. I need help calculating the overlap of any two objects in terms of x and y in order to move one accordingly. Here's what we know:
The coordinates of the collision point relative to each object
The positions of the objects (and therefore the distance between them)
The width and height of the objects
The velocity of the objects in the x and y directions (a vector)
Another note: the images for these objects are uneven shapes, no perfect circles, but the radius from the center to the collision point can be calculated.
EDIT: I haven't seen a lot of response, so I'll be more specific. In the image below, two objects are colliding. The overlap area is in red. How would you go about finding the lengths of the green lines?

I'm honestly clueless about HTML 5 and how you can make games in pure HTML 5. But you would also need to know a velocity (IE, their direction. This way you can send them backwards from where they came)
If it was in a standard programming language, one method would be to use a while loop (moving the sprite back until the collision == false). Another method would be a more complicated calculation of how far the intersection is and subtract individual x and y values so they are not collided.
EDIT:
Then the easiest way is like I said, to put the object thats moving in a while loop that moves it backwards 1 pixel in each axis until its collision tests false. Example:
int x1 = 500; //x location on screen
int y2 = 500; //y location
public boolean fixOffSetX(Sprite s) {
int x2 = s.getX();
int y2 = s.getY();
//not writing the whole thing
//enter a while loop until its not colliding anymore
while(collision is still true) {
x--; or x++;
//depending on direction
//(which is why you need to know velocity/direction of your sprites)
//do the same for the Y axis.
}
}
//This method will return if the 2 sprites collided, you do this one
public boolean collisionTest(Sprite s1, Sprite s2) {}
You should look at doing very basic collisions, since it is a VERY complicated part of programming

If this is still an issue, I've found information about the subject in an e-book called Foundation Game Design with HTML5 en Javascript. Here: link to relevant pages. Hope this helps anyone in the future.

Related

Tile Filling Algorithm for Game

Background:
I am working on a tile-based game in Javascript where a character freely moves around the map (no diagonal - Left/Right/Up/Down) and fills in tiles as he moves around the map. There are three tile types -- tiles you've filled (blue), your current path (red), and empty ones (black). There are also enemies (stars) that move around the map as well, but only in empty areas. The objective is to fill as much of the map as possible.
Map is sized as roughly 40x40 tiles. There is a 1 tile thick border around the entire outside of the map that is already "filled" (blue).
I have established that a flood-fill algorithm will work for filling up areas of tiles when needed. However, my problem is as follows:
PROBLEM STATEMENT:
I want to only fill a sectioned-off part of the map if there are no enemies in it.
My Question:
I could run flood-fill algorithm and stop it if it reaches a tile occupied by an enemy -- however, is this the most efficient approach (for a real time game)?
IF YES, how do I determine where to start the algorithm from in a systematic way since there are multiple areas to check and the character doesn't have to move in a perfectly straight line (can zig-zag up/down/right/left, but can't move diagonally).
Picture Example 1 (pics explain better):
Note: red areas turn blue (filled) once you reach another filled area. In example below, there are no enemies in the contained area, so the area is filled.
Picture Example 2:
In this second example, there is an enemy within the contained area (and on the outside area - not shown) so nothing but the line is filled.
Summary: What is the best approach for doing this type of filling? Is flood fill the best choice for determining whether to fill or not -- 40x40 makes for a pretty large calculation. If yes, how do I determine what tile do I start with?
Let me suggest a different way of looking at your problem.
Going by the description of your game, it seems like the user's main, perhaps only, "verb" (in game design terms) is to draw a line that divides the open area of the field into two sections. If either of these two sections is free of enemies, that section gets filled in; if neither section is free of enemies, the line remains but both sections remain open. There are no other conditions determining whether a section gets filled or not, right?
So the most efficient way to solve this problem, I would think, is simply to draw a continuous line, which may make corners but only moves in horizontal or vertical directions, from one of your enemies to every other enemy in turn. We'll call this line the "probe line". From here on, we're using the approach of Derek's suggested "Ray casting algorithm": We look at the number of times the "probe line" crosses the "border line", and if the number of crossings is ever odd, it means you have at least one enemy on each side of the line, and there's no filling.
Note, though, that there's a difference between the two lines coinciding and the two lines crossing. Picture a probe line that goes from the coordinates (0,10) to (39,10) , and a border line that goes down from (5,0) to (5,10) and then goes right to (13,10). If it goes down from there towards (13,39), the two lines are crossing; if instead it goes upwards toward (13,0), they're not.
After a lot of thought, I strongly suggest that you store the "border line", and construct the "probe line", in terms of line segments - rather than trying to determine from which cells are filled which line segments created them. That will make it much harder than it has to be.
Finally, one odd game design note to be aware of: unless you constrict the user's control so that he cannot bring the border line back to within one cell of itself, then a single border line drawn by a user might end up sectioning off the field into more than two sections - there could be sections created by the border line looping right back on itself. If you allow that, it could very drastically complicate the calculation of where to fill. Check the following diagram I made via Derek's fiddle (thank you, Derek!):
As you can see, one border line has actually created three sections: one on the upper side of the line, one below the line, and one formed by the line itself. I'm still thinking about how that would affect things algorithmically, for that to be possible.
EDIT: With a) time to think about the above creation-of-multiple-sections-by-loops, and b) the Simulation of Simplicity resource brought up by Derek, I think I can outline the simplest and most efficient algorithm that you're likely to get.
There's one subproblem to it which I'll leave to you, and that is determining what your new sections are after the player's actions have drawn a new line. I leave that to you because it's one that would have had to be solved before a solution to your original problem (how to tell if there are enemies within those sections) could have been called.
The solution, presented here as pseudocode, assumes you have the border of each section stored as line segments between coordinates.
Create a list of the sections.
Create a list of the enemies.
Continue as long as neither list is empty:
For each enemy in the enemy list:
Designate "Point A" as the coordinates of the enemy, PLUS 0.5 to both x and y.
For each section in the section list:
Designate "Point B" as the upper-left-most coordinate, PLUS 0.5 to both x and y.
Count how many of the section border segments cross a line between A and B.
If the answer is even:
remove this section from the section list
skip forward to the next enemy
If any sections remain in the list, they are free of enemies. Fill them in.
The addition of the 0.5 to the coordinates of the "probe line" are thanks to Derek's SoS resource; they eliminate the difficult case where the lines coincide rather than simply crossing or not crossing.
If you have the points of the border of your shape that lies on the same y as the enemy, then you can simply count the number of borders, starting from either left or right to the enemy. If it's odd then it's inside. If it's even then it's outside.
Since you are using a grid system this should be easy to implement (and very fast). This algorithm is called the Ray casting algorithm.
Here's a simple example I created: http://jsfiddle.net/DerekL/8QBz6/ (can't deal with degenerate cases)
function testInside(){
var passedBorder = 0,
passingBorder = false;
for(var x = 0; x <= enemy[0]; x++){
if(board[x][enemy[1]] === 1) passingBorder = true;
else if(board[x][enemy[1]] === 0 && passingBorder){
passingBorder = false;
passedBorder++;
}
}
return !!(passedBorder%2);
}
For example, you have this shape which you have determined:
removed
Guess what I found, (slightly modified)
//simple enough, it only needs the x,y of your testing point and the wall.
//no direction or anything else
function testInside3() {
var i, j, c = 0;
for (i = 0, j = wallList.length-1; i < wallList.length; j = i++) {
if ( ((wallList[i][1]>enemy[1]) ^ (wallList[j][1]>enemy[1])) &&
(enemy[0] < (wallList[j][0]-wallList[i][0]) * (enemy[1]-wallList[i][1]) / (wallList[j][1]-wallList[i][1]) + wallList[i][0]) )
c = !c;
}
return !!c;
}
http://jsfiddle.net/DerekL/NvLcK/
This is using the same ray casting algorithm I mentioned, but this time the "ray" is now mathematical using the following inequality for x and a condition for y:
(X2 - X1)(Py - Y1)
Px < ────────────────── + X1
Y2 - Y1
which is derived by combining these two:
Ray:
x(t) = Px + t, y(t) = Py, where t > 0 (the ray goes to the right)
Edge:
x(u) = (X2 - X1)u + X1, y(u) = (Y2 - Y1)u + Y1, where 0 <= u <= 1
And the condition for y:
(Y1 > Py) ⊕ (Y2 > Py)
which is equivalent to:
(Y1 ≥ Py > Y2) ∨ (Y2 ≥ Py > Y1)
and yadi yadi yada some other interesting technical stuff.
Seems like this is the default algorithm in many native libraries. The method used to dealing with degenerate cases is called Simulation of Simplicity, described in this paper (section 5.1).
Nevertheless, here's the result generated with the algorithm testing every coordinate:
If it's easy to determine where the borders of a region to possibly fill are, you can use the following approach:
Assign each edge a clockwise directionality. That is, construct a vector for each edge that starts on its corners and has a direction such that a clockwise path around the region is described by these vectors.
For each enemy:
Construct a vector starting from the enemy and ending on the closest edge. We'll call this an enemy_vector.
Calculate the cross product of the enemy_vector and the vector corresponding to the closest edge. The sign of the cross product will tell you whether the enemy is inside the region: if it's positive, the enemy is outside of it, and if it's negative it isn't!
EXAMPLE:
Suppose we have the following region and enemy to evaluate the inside-ness of.
We can encode the region as a series of vectors that give it a clockwise orientation, like so:
So how do we use that to determine the side of the region inhabited by the enemy? We draw a vector from it (which I've colored red) to the nearest edge (which I've colored green)...
...and take the cross product of the red vector and the green vector. Application of the right-hand rule tells us that (red) x (green) > 0, so the enemy must be outside the region!

JavaScript "pixel"-perfect collision detection for rotating sprites using math (probably linear algebra)

I'm making a 2D game in JavaScript. For it, I need to be able to "perfectly" check collision between two sprites which have x/y positions (corresponding to their centre), a rotation in radians, and of course known width/height.
After spending many weeks of work (yeah, I'm not even exaggerating), I finally came up with a working solution, which unfortunately turned out to be about 10,000x too slow and impossible to optimize in any meaningful manner. I have entirely abandoned the idea of actually drawing and reading pixels from a canvas. That's just not going to cut it, but please don't make me explain in detail why. This needs to be done with math and an "imaginated" 2D world/grid, and from talking to numerous people, the basic idea became obvious. However, the practical implementation is not. Here's what I do and want to do:
What I already have done
In the beginning of the program, each sprite is pixel-looked through in its default upright position and a 1-dimensional array is filled up with data corresponding to the alpha channel of the image: solid pixels get represented by a 1, and transparent ones by 0. See figure 3.
The idea behind that is that those 1s and 0s no longer represent "pixels", but "little math orbs positioned in perfect distances to each other", which can be rotated without "losing" or "adding" data, as happens with pixels if you rotate images in anything but 90 degrees at a time.
I naturally do the quick "bounding box" check first to see if I should bother calculating accurately. This is done. The problem is the fine/"for-sure" check...
What I cannot figure out
Now that I need to figure out whether the sprites collide for sure, I need to construct a math expression of some sort using "linear algebra" (which I do not know) to determine if these "rectangles of data points", positioned and rotated correctly, both have a "1" in an overlapping position.
Although the theory is very simple, the practical code needed to accomplish this is simply beyond my capabilities. I've stared at the code for many hours, asking numerous people (and had massive problems explaining my problem clearly) and really put in an effort. Now I finally want to give up. I would very, very much appreciate getting this done with. I can't even give up and "cheat" by using a library, because nothing I find even comes close to solving this problem from what I can tell. They are all impossible for me to understand, and seem to have entirely different assumptions/requirements in mind. Whatever I'm doing always seems to be some special case. It's annoying.
This is the pseudo code for the relevant part of the program:
function doThisAtTheStartOfTheProgram()
{
makeQuickVectorFromImageAlpha(sprite1);
makeQuickVectorFromImageAlpha(sprite2);
}
function detectCollision(sprite1, sprite2)
{
// This easy, outer check works. Please ignore it as it is unrelated to the problem.
if (bounding_box_match)
{
/*
This part is the entire problem.
I must do a math-based check to see if they really collide.
These are the relevant variables as I have named them:
sprite1.x
sprite1.y
sprite1.rotation // in radians
sprite1.width
sprite1.height
sprite1.diagonal // might not be needed, but is provided
sprite2.x
sprite2.y
sprite2.rotation // in radians
sprite2.width
sprite2.height
sprite2.diagonal // might not be needed, but is provided
sprite1.vectorForCollisionDetection
sprite2.vectorForCollisionDetection
Can you please help me construct the math expression, or the series of math expressions, needed to do this check?
To clarify, using the variables above, I need to check if the two sprites (which can rotate around their centre, have any position and any dimensions) are colliding. A collision happens when at least one "unit" (an imagined sphere) of BOTH sprites are on the same unit in our imaginated 2D world (starting from 0,0 in the top-left).
*/
if (accurate_check_goes_here)
return true;
}
return false;
}
In other words, "accurate_check_goes_here" is what I wonder what it should be. It doesn't need to be a single expression, of course, and I would very much prefer seeing it done in "steps" (with comments!) so that I have a chance of understanding it, but please don't see this as "spoon feeding". I fully admit I suck at math and this is beyond my capabilities. It's just a fact. I want to move on and work on the stuff I can actually solve on my own.
To clarify: the 1D arrays are 1D and not 2D due to performance. As it turns out, speed matters very much in JS World.
Although this is a non-profit project, entirely made for private satisfaction, I just don't have the time and energy to order and sit down with some math book and learn about that from the ground up. I take no pride in lacking the math skills which would help me a lot, but at this point, I need to get this game done or I'll go crazy. This particular problem has prevented me from getting any other work done for far too long.
I hope I have explained the problem well. However, one of the most frustrating feelings is when people send well-meaning replies that unfortunately show that the person helping has not read the question. I'm not pre-insulting you all -- I just wish that won't happen this time! Sorry if my description is poor. I really tried my best to be perfectly clear.
Okay, so I need "reputation" to be able to post the illustrations I spent time to create to illustrate my problem. So instead I link to them:
Illustrations
(censored by Stackoverflow)
(censored by Stackoverflow)
OK. This site won't let me even link to the images. Only one. Then I'll pick the most important one, but it would've helped a lot if I could link to the others...
First you need to understand that detecting such collisions cannot be done with a single/simple equation. Because the shapes of the sprites matter and these are described by an array of Width x Height = Area bits. So the worst-case complexity of the algorithm must be at least O(Area).
Here is how I would do it:
Represent the sprites in two ways:
1) a bitmap indicating where pixels are opaque,
2) a list of the coordinates of the opaque pixels. [Optional, for speedup, in case of hollow sprites.]
Choose the sprite with the shortest pixel list. Find the rigid transform (translation + rotation) that transforms the local coordinates of this sprite into the local coordinates of the other sprite (this is where linear algebra comes into play - the rotation is the difference of the angles, the translation is the vector between upper-left corners - see http://planning.cs.uiuc.edu/node99.html).
Now scan the opaque pixel list, transforming the local coordinates of the pixels to the local coordinates of the other sprite. Check if you fall on an opaque pixel by looking up the bitmap representation.
This takes at worst O(Opaque Area) coordinate transforms + pixel tests, which is optimal.
If you sprites are zoomed-in (big pixels), as a first approximation you can ignore the zooming. If you need more accuracy, you can think of sampling a few points per pixel. Exact computation will involve a square/square collision intersection algorithm (with rotation), more complex and costly. See http://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm.
Here is an exact solution that will work regardless the size of the pixels (zoomed or not).
Use both a bitmap representation (1 opacity bit per pixel) and a decomposition into squares or rectangles (rectangles are optional, just an optimization; single pixels are ok).
Process all rectangles of the (source) sprite in turn. By means of rotation/translation, map the rectangles to the coordinate space of the other sprite (target). You will obtain a rotated rectangle overlaid on a grid of pixels.
Now you will perform a filling of this rectangle with a scanline algorithm: first split the rectangle in three (two triangles and one parallelogram), using horizontal lines through the rectangle vertexes. For the three shapes independently, find all horizontal between-pixel lines that cross them (this is simply done by looking at the ranges of Y values). For every such horizontal line, compute the two intersections points. Then find all pixel corners that fall between the two intersections (range of X values). For any pixel having a corner inside the rectangle, lookup the corresponding bit in the (target) sprite bitmap.
No too difficult to program, no complicated data structure. The computational effort is roughly proportional to the number of target pixels covered by every source rectangle.
Although you have already stated that you don't feel rendering to the canvas and checking that data is a viable solution, I'd like to present an idea which may or may not have already occurred to you and which ought to be reasonably efficient.
This solution relies on the fact that rendering any pixel to the canvas with half-opacity twice will result in a pixel of full opacity. The steps follow:
Size the test canvas so that both sprites will fit on it (this will also clear the canvas, so you don't have to create a new element each time you need to test for collision).
Transform the sprite data such that any pixel that has any opacity or color is set to be black at 50% opacity.
Render the sprites at the appropriate distance and relative position to one another.
Loop through the resulting canvas data. If any pixels have an opacity of 100%, then a collision has been detected. Return true.
Else, return false.
Wash, rinse, repeat.
This method should run reasonably fast. Now, for optimization--the bottleneck here will likely be the final opacity check (although rendering the images to the canvas could be slow, as might be clearing/resizing it):
reduce the resolution of the opacity detection in the final step, by changing the increment in your loop through the pixels of the final data.
Loop from middle up and down, rather than from the top to bottom (and return as soon as you find any single collision). This way you have a higher chance of encountering any collisions earlier in the loop, thus reducing its length.
I don't know what your limitations are and why you can't render to canvas, since you have declined to comment on that, but hopefully this method will be of some use to you. If it isn't, perhaps it might come in handy to future users.
Please see if the following idea works for you. Here I create a linear array of points corresponding to pixels set in each of the two sprites. I then rotate/translate these points, to give me two sets of coordinates for individual pixels. Finally, I check the pixels against each other to see if any pair are within a distance of 1 - which is "collision".
You can obviously add some segmentation of your sprite (only test "boundary pixels"), test for bounding boxes, and do other things to speed this up - but it's actually pretty fast (once you take all the console.log() statements out that are just there to confirm things are behaving…). Note that I test for dx - if that is too large, there is no need to compute the entire distance. Also, I don't need the square root for knowing whether the distance is less than 1.
I am not sure whether the use of new array() inside the pixLocs function will cause a problem with memory leaks. Something to look at if you run this function 30 times per second...
<html>
<script type="text/javascript">
var s1 = {
'pix': new Array(0,0,1,1,0,0,1,0,0,1,1,0),
'x': 1,
'y': 2,
'width': 4,
'height': 3,
'rotation': 45};
var s2 = {
'pix': new Array(1,0,1,0,1,0,1,0,1,0,1,0),
'x': 0,
'y': 1,
'width': 4,
'height': 3,
'rotation': 90};
pixLocs(s1);
console.log("now rotating the second sprite...");
pixLocs(s2);
console.log("collision detector says " + collision(s1, s2));
function pixLocs(s) {
var i;
var x, y;
var l1, l2;
var ca, sa;
var pi;
s.locx = new Array();
s.locy = new Array();
pi = Math.acos(0.0) * 2;
var l = new Array();
ca = Math.cos(s.rotation * pi / 180.0);
sa = Math.sin(s.rotation * pi / 180.0);
i = 0;
for(x = 0; x < s.width; ++x) {
for(y = 0; y < s.height; ++y) {
// offset to center of sprite
if(s.pix[i++]==1) {
l1 = x - (s.width - 1) * 0.5;
l2 = y - (s.height - 1) * 0.5;
// rotate:
r1 = ca * l1 - sa * l2;
r2 = sa * l1 + ca * l2;
// add position:
p1 = r1 + s.x;
p2 = r2 + s.y;
console.log("rotated pixel [ " + x + "," + y + " ] is at ( " + p1 + "," + p2 + " ) " );
s.locx.push(p1);
s.locy.push(p2);
}
else console.log("no pixel at [" + x + "," + y + "]");
}
}
}
function collision(s1, s2) {
var i, j;
var dx, dy;
for (i = 0; i < s1.locx.length; i++) {
for (j = 0; j < s2.locx.length; j++) {
dx = Math.abs(s1.locx[i] - s2.locx[j]);
if(dx < 1) {
dy = Math.abs(s1.locy[i] - s2.locy[j]);
if (dx*dx + dy+dy < 1) return 1;
}
}
}
return 0;
}
</script>
</html>

Determining the point and angle at which two circles intersect.

I have recently started playing with canvas after seeing how easy it can be. My first project was just to keep a circle in its boundaries as it moves around. I made a few more things involving the movement of circles and now...
I'm currently working on bouncing two circles off of each other when they hit. You can see the example of that here: http://jsfiddle.net/shawn31313/QQMgm/7/
However, I would like to use a little more real world physics. At the moment, when the circles hit each other they just reverse their path.
As shown here:
// Dont be confused, this is just the Distance Formula
// We compare the distance of the two circles centers to the sum of the radii of the two
// circles. This is because we want to check when they hit each other on the surface
// and not the center.
var distance = Math.sqrt(Math.pow(c1.x - c2.x, 2) + Math.pow(c1.y - c2.y, 2));
var r1 = c1.rad;
var r2 = c2.rad;
if (distance < r1 + r2) {
// Change the slope of both circle
// I would like to figure out a more effecience way of bouncing the circles back
// However, I have no idea how to determine the angle the ball was struck,
// and with that information bounce it off at that angle
c1.xi = -c1.xi; // path is reversed
c1.yi = -c1.yi;
c2.xi = -c1.xi;
c2.yi = -c1.yi;
}
However, I would like the circles to go in opposite direction determined by the point and angle of intersection.
I am only in the 9th grade and not sure how the formula for something like this would look. But I know that it is possible because this kind of physics is present in many games. An example would be an 8-ball game. When the balls hit each other, they move across the table according to how the balls hit each other.
I would appreciate any tips on how to do this or if I should wait until I have a stronger understanding of Physics and Math in general.
too bad we can't draw a very simple scheme.
As far as physics is concerned, you know that the total momentum is conserved, see
http://en.wikipedia.org/wiki/Momentum
There is a good illustration and formulas here http://en.wikipedia.org/wiki/Elastic_collision#Two-_and_three-dimensional
You can simplify formulas if the two object have the same weight.
so now, let's consider the reference frame in which c2 is fixed and center in (0,0).
c1 velocity in this reference would be :
c1.xfi=c1.xi-c2.xi
c1.yfi=c1.yi-c2.yi
Now you have a collision when the distance between the two is the sum of radius. Consider the tangent plane of the two circles.
You now have to decompose the velocity of c1 into a tangent component, which is conserved, and a perpendicular (following the line between c1 and c2), which is transfered to c2.
Then you need to go back to your original reference frame.
(sorry i didn't give you the exact formulas but they are on the links I provided)
If I were doing this myself, I would implement the motion using Newtons law of restitution. Essentially this is a coefficient that relates approach and separation speed of 2 particles before/after impact and it has a value that depends on the material properties of your particles.
Your analysis will essentially amount to identifying the point of impact, then breaking down the approach velocities into components that are parallel and perpendicular to the line of centres of the circle at the point of impact.
The momentum of the particles is conserved perpendicular to the line of centres (so the velocities in that direction remain unchanged by the collision) and the law of restitution applies to the velocities parallel to the line of centres. Thus if you fix the coefficient of restitution (it has to be between 0 and 1) to some value of your choice you can use this law to calculate the separation speeds along the line of centres of your particles after collision using the value of the approach speeds.
If your particles are all of the same mass and radius then the calculations become simpler. You can model elastic collisions by setting the coefficient to 1 (this indicates that separation speed of the particles is the same as the approach speed) which is probably the easiest place to start. By changing the value you will see different behaviour between particles after collisions.
Sorry not to be able to write this all down in formula for you, but this is not really the appropriate place for it. Living in the UK I have no idea what "9th grade" is so I can't assess if the above is too advanced for your current level of education. Here in the UK this type of problem would typically be covered at A-level mathematics education level.
Hopefully though it will give you an indication of the terms and topics that you can teach yourself/ research in order to achieve your goal.

Help with simulating depth in HTML5 Canvas

Basically, I'm trying to do 3D projection on a 2D canvas with simulation of depth. As a general rule, bodies that are further away are "shaded" more and smaller than bodies that are closer to the viewer. The only thing missing is having bodies that are further away always drawn behind bodies that are closer.
Sometimes, bodies that are further away are drawn behind closer bodies, but there are always small bodies that get drawn in front of larger ones, meaning that the ones that are further away sometimes appear in front of bodies that are supposed to be closer.
I try to solve it by sorting the bodies by the z-position. The bodies array is an array of objects with 0 containing an array of the body's position, 0 being x, 1 being y, 2 being z. I first have the position of the bodies updated according to rotations in the x, y, and z axes, stored into the np value of the body object, then do the sorting, and draw the bodies. I've tried changing how the array is sorted, changing the order of the loop, but still no cigar.
Just wondering if anyone can point me in the right direction to get this 3D "engine" behaving correctly. Any help is appreciated. Some quick notes: Rotations along the three axes are accomplished using the Q/A, W/S, and E/D keys, zooming in and out of the z-axis is accomplished using the R/F keys, and the default rotation about the z-axis can be accomplished using the P key. What I'm trying to do is located here:
http://jsbin.com/aholu/5/
You're sorting on the original xyz values instead of the transformed np values. I got it to look right by switching...
bodies.sort(function(a,b) {return a[0][2]-b[0][2]});
to
bodies.sort(function(a,b) {return a.np[1]-b.np[1]});
with change see http://home.comcast.net/~trochoid/mod5.html
I don't follow all of your code so this may not be a total solution. Specifically, I thought it'd be sorted on np[2] for the transformed z value, but np[1] gives correct looking results. I guess maybe you switch these coords. Also, it looks like you're transforming and projecting the z value and the code fix above sorts on this projected z value. It seems to work out ok but I've never projected the z value itself, just use the transformed z to project xy. Anyways, Looks good!
Trochoid. I had to access from a different computer and still haven't registered, so I have to add this as an answer instead of a comment.
If you notice, the axis of rotation for x and y are rotated when you rotate any other axis (eg. if you press W to rotate, then rotate a different axis, then press W again, you will notice that the helix in your code rotates the same way). T
his is not so with the z axis. No matter how you rotate the x and y axes, the z axis will always rotate "right-to-left" (eg. in default configuration, helix is spiraling along z-axis, or axis rotated using the E/D keys, but if you rotate the helix along any other axis, rotating using the E/D keys no longer spirals the helix).
I don't know why the behavior would be different in that axis, so I would like your assistance to get that rotation working properly. Thank you.
I am aware that this is not answering the original question, but depending on what you are trying to acchieve in general be aware that there is also 'parallax scrolling' (example) (esp. in CSS3 (example).

Pixel Perfect Collision Detection in HTML5 Canvas

I want to check a collision between two Sprites in HTML5 canvas. So for the sake of the discussion, let's assume that both sprites are IMG objects and a collision means that the alpha channel is not 0. Now both of these sprites can have a rotation around the object's center but no other transformation in case this makes this any easier.
Now the obvious solution I came up with would be this:
calculate the transformation matrix for both
figure out a rough estimation of the area where the code should test (like offset of both + calculated extra space for the rotation)
for all the pixels in the intersecting rectangle, transform the coordinate and test the image at the calculated position (rounded to nearest neighbor) for the alpha channel. Then abort on first hit.
The problem I see with that is that a) there are no matrix classes in JavaScript which means I have to do that in JavaScript which could be quite slow, I have to test for collisions every frame which makes this pretty expensive. Furthermore I have to replicate something I already have to do on drawing (or what canvas does for me, setting up the matrices).
I wonder if I'm missing anything here and if there is an easier solution for collision detection.
I'm not a javascript coder but I'd imagine the same optimisation tricks work just as well for Javascript as they do for C++.
Just rotate the corners of the sprite instead of every pixel. Effectively you would be doing something like software texture mapping. You could work out the x,y position of a given pixel using various gradient information. Look up software texture mapping for more info.
If you quadtree decomposed the sprite into "hit" and "non-hit" areas then you could effectively check to see if a given quad tree decomposition is all "non-hit", "all hit" or "possible hit" (ie contains hits and non-hit pixels. The first 2 are trivial to pass through. In the last case you then go down to the next decomposition level and repeat the test. This way you only check the pixels you need too and for large areas of "non-hit" and "hit" you don't have to do such a complex set of checks.
Anyway thats just a couple of thoughts.
I have to replicate something I already have to do on drawing
Well, you could make a new rendering context, plot one rotated white-background mask to it, set the compositing operation to lighter and plot the other rotated mask on top at the given offset.
Now if there's a non-white pixel left, there's a hit. You'd still have to getImageData and sift through the pixels to find that out. You might be able to reduce that workload a bit by scaling the resultant image downwards (relying on anti-aliasing to keep some pixels non-white), but I'm thinking it's probably still going to be quite slow.
I have to test for collisions every frame which makes this pretty expensive.
Yeah, I think realistically you're going to be using precalculated collision tables. If you've got space for it, you could store one hit/no hit bit for every combination of sprite a, sprite b, relative rotation, relative-x-normalised-to-rotation and relative-y-normalised-to-rotation. Depending on how many sprites you have and how many steps of rotation or movement, this could get rather large.
A compromise would be to store the pre-rotated masks of each sprite in a JavaScript array (of Number, giving you 32 bits/pixels of easily &&-able data, or as a character in a Sring, giving you 16 bits) and && each line of intersecting sprite masks together.
Or, give up on pixels and start looking at eg. paths.
Same problem, an alternative solution. First I use getImageData data to find a polygon that surrounds the sprite. Careful here because the implementation works with images with transparent background that have a single solid object. Like a ship. The next step is Ramer Douglas Peucker Algorithm to reduce the number of vertices in the polygon. I finally get a polygon of very few vertices easy and cheap to rotate and check collisions with the other polygons for each sprite.
http://jsfiddle.net/rnrlabs/9dxSg/
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var img = document.getElementById("img");
context.drawImage(img, 0,0);
var dat = context.getImageData(0,0,img.width, img.height);
// see jsfiddle
var startPixel = findStartPixel(dat, 0);
var path = followPath(startPixel, dat, 0);
// 4 is RDP epsilon
map1 = properRDP(path.map, 4, path.startpixel.x, path.startpixel.y);
// draw
context.beginPath();
context.moveTo(path.startpixel.x, path.startpixel.x);
for(var i = 0; i < map.length; i++) {
var p = map[i];
context.lineTo(p.x, p.y);
}
context.strokeStyle = 'red';
context.closePath();
context.stroke();

Categories