Permalink
Browse files

found the collision detection edge case. fixed it. still annoyed with…

… IEEE floats.
  • Loading branch information...
1 parent fe43800 commit 8c49feeacbf478ea256d9ea7225e6e496e5f6195 @Pomax committed Jul 7, 2012
View
@@ -274,8 +274,14 @@ abstract class Actor extends Positionable {
* moved back by dx/dy
*/
void stop(float dx, float dy) {
- x += dx;
- y += dy;
+ // we need to prevent IEEE floats polluting
+ // the position information, so even though
+ // the math is perfect in principle, round
+ // the result so that we're not going to be
+ // off by 0.0001 or something.
+ float resolution = 50;
+ x = int(resolution*(x+dx))/resolution;
+ y = int(resolution*(y+dy))/resolution;
ix = 0;
iy = 0;
aFrameCount = 0;
View
@@ -75,39 +75,47 @@ static class CollisionDetection {
// complicated intersection detections checks.
// determine range w.r.t. the starting point of the boundary.
- float[] dotProducts1 = getDotProducts(x1,y1,x2,y2, previous);
+ float[] dotProducts_S_P = getDotProducts(x1,y1,x2,y2, previous);
+ float[] dotProducts_S_C = getDotProducts(x1,y1,x2,y2, current);
// determine range w.r.t. the end point of the boundary.
- float[] dotProducts2 = getDotProducts(x2,y2,x1,y1, previous);
+ float[] dotProducts_E_P = getDotProducts(x2,y2,x1,y1, previous);
+ float[] dotProducts_E_C = getDotProducts(x2,y2,x1,y1, current);
// determine 'sidedness', relative to the boundary.
- float[] dotProducts3 = getDotProducts(x1,y1,x1+rdx,y1+rdy, previous);
- float[] dotProducts4 = getDotProducts(x1,y1,x1+rdx,y1+rdy, current);
+ float[] dotProducts_P = getDotProducts(x1,y1,x1+rdx,y1+rdy, previous);
+ float[] dotProducts_C = getDotProducts(x1,y1,x1+rdx,y1+rdy, current);
// compute the relevant feature values based on the dot products:
- int inRangeS = 4, inRangeE = 4, above = 0, aboveAfter = 0;
+ int inRangeSp = 4, inRangeSc = 4,
+ inRangeEp = 4, inRangeEc = 4,
+ abovePrevious = 0, aboveCurrent = 0;
for(int i=0; i<8; i+=2) {
- if (dotProducts1[i] < 0) { inRangeS--; }
- if (dotProducts2[i] < 0) { inRangeE--; }
- if (dotProducts3[i] <= 0) { above++; }
- if (dotProducts4[i] <= 0) { aboveAfter++; }}
+ if (dotProducts_S_P[i] < 0) { inRangeSp--; }
+ if (dotProducts_S_C[i] < 0) { inRangeSc--; }
+ if (dotProducts_E_P[i] < 0) { inRangeEp--; }
+ if (dotProducts_E_C[i] < 0) { inRangeEc--; }
+ if (dotProducts_P[i] <= 0) { abovePrevious++; }
+ if (dotProducts_C[i] <= 0) { aboveCurrent++; }}
- if(debug) sketch.println(sketch.frameCount +"> dotproduct result: "+inRangeS+"/"+inRangeE+"/"+above+"/"+aboveAfter);
+ if(debug) sketch.println(sketch.frameCount +"> dotproduct result: start="+inRangeSp+"/"+inRangeSc+", end="+inRangeEp+"/"+inRangeEc+", sided="+abovePrevious+"/"+aboveCurrent);
// make sure to short-circuit if the actor cannot
// interact with the boundary because it is out of range.
- if (inRangeS == 0 || inRangeE == 0) {
+ boolean inRangeForStart = (inRangeSp == 0 && inRangeSc == 0);
+ boolean inRangeForEnd = (inRangeEp == 0 && inRangeEc == 0);
+ if (inRangeForStart || inRangeForEnd) {
if(debug) sketch.println(sketch.frameCount +"> this boundary is not involved in collisions for this frame (out of range).");
return null;
}
// if the force goes against the border's permissible direction, but
// both previous and current frame actor boxes are above the boundary,
// then we don't have to bother with intersection detection.
- if (above==4 && aboveAfter==4) {
+ if (abovePrevious==4 && aboveCurrent==4) {
if(debug) sketch.println(sketch.frameCount +"> this box is not involved in collisions for this frame (inherently safe 'above' locations).");
return null;
- } else if(0 < above && above < 4) {
+ } else if(0 < abovePrevious && abovePrevious < 4) {
if(debug) sketch.println(sketch.frameCount +"> this box is not involved in collisions for this frame (never fully went through boundary).");
return null;
}
@@ -119,7 +127,7 @@ static class CollisionDetection {
// actor frame is on the blocking side of a boundary, and
// 'aboveAfter' is 0, meaning its current frame is on the other
// side of the boundary, then a collision MUST have occurred.
- if (above==4 && aboveAfter==0) {
+ if (abovePrevious==4 && aboveCurrent==0) {
// note that in this situation, the overlap may look
// like full containment, where the actor's bounding
// box is fully contained by the boundary's box.
View
@@ -335,11 +335,13 @@ abstract class Positionable extends Position implements Drawable {
float[] redirected = new float[]{ix, iy};
for(int b=boundaries.size()-1; b>=0; b--) {
Boundary boundary = boundaries.get(b);
+ if(!boundary.disabled) {
+ redirected = boundary.redirectForce(redirected[0], redirected[1]);
+ }
if(boundary.disabled || !boundary.supports(this)) {
detachFrom(boundary);
continue;
}
- redirected = boundary.redirectForce(redirected[0], redirected[1]);
}
ix = redirected[0];
iy = redirected[1];
View
@@ -9,10 +9,20 @@ abstract class Trigger extends Positionable {
String triggername="";
+ Trigger(String name) {
+ triggername = name;
+ }
+
Trigger(String name, float x, float y, float w, float h) {
super(x,y,w,h);
triggername = name;
}
+
+ void setArea(float x, float y, float w, float h) {
+ setPosition(x,y);
+ width = w;
+ height = h;
+ }
boolean drawableFor(float x, float y, float w, float h) {
return x<=this.x+width && this.x<=x+w && y<=this.y+height && this.y<=y+h;
View
@@ -274,8 +274,14 @@ abstract class Actor extends Positionable {
* moved back by dx/dy
*/
void stop(float dx, float dy) {
- x += dx;
- y += dy;
+ // we need to prevent IEEE floats polluting
+ // the position information, so even though
+ // the math is perfect in principle, round
+ // the result so that we're not going to be
+ // off by 0.0001 or something.
+ float resolution = 50;
+ x = int(resolution*(x+dx))/resolution;
+ y = int(resolution*(y+dy))/resolution;
ix = 0;
iy = 0;
aFrameCount = 0;
@@ -875,39 +881,47 @@ static class CollisionDetection {
// complicated intersection detections checks.
// determine range w.r.t. the starting point of the boundary.
- float[] dotProducts1 = getDotProducts(x1,y1,x2,y2, previous);
+ float[] dotProducts_S_P = getDotProducts(x1,y1,x2,y2, previous);
+ float[] dotProducts_S_C = getDotProducts(x1,y1,x2,y2, current);
// determine range w.r.t. the end point of the boundary.
- float[] dotProducts2 = getDotProducts(x2,y2,x1,y1, previous);
+ float[] dotProducts_E_P = getDotProducts(x2,y2,x1,y1, previous);
+ float[] dotProducts_E_C = getDotProducts(x2,y2,x1,y1, current);
// determine 'sidedness', relative to the boundary.
- float[] dotProducts3 = getDotProducts(x1,y1,x1+rdx,y1+rdy, previous);
- float[] dotProducts4 = getDotProducts(x1,y1,x1+rdx,y1+rdy, current);
+ float[] dotProducts_P = getDotProducts(x1,y1,x1+rdx,y1+rdy, previous);
+ float[] dotProducts_C = getDotProducts(x1,y1,x1+rdx,y1+rdy, current);
// compute the relevant feature values based on the dot products:
- int inRangeS = 4, inRangeE = 4, above = 0, aboveAfter = 0;
+ int inRangeSp = 4, inRangeSc = 4,
+ inRangeEp = 4, inRangeEc = 4,
+ abovePrevious = 0, aboveCurrent = 0;
for(int i=0; i<8; i+=2) {
- if (dotProducts1[i] < 0) { inRangeS--; }
- if (dotProducts2[i] < 0) { inRangeE--; }
- if (dotProducts3[i] <= 0) { above++; }
- if (dotProducts4[i] <= 0) { aboveAfter++; }}
+ if (dotProducts_S_P[i] < 0) { inRangeSp--; }
+ if (dotProducts_S_C[i] < 0) { inRangeSc--; }
+ if (dotProducts_E_P[i] < 0) { inRangeEp--; }
+ if (dotProducts_E_C[i] < 0) { inRangeEc--; }
+ if (dotProducts_P[i] <= 0) { abovePrevious++; }
+ if (dotProducts_C[i] <= 0) { aboveCurrent++; }}
- if(debug) sketch.println(sketch.frameCount +"> dotproduct result: "+inRangeS+"/"+inRangeE+"/"+above+"/"+aboveAfter);
+ if(debug) sketch.println(sketch.frameCount +"> dotproduct result: start="+inRangeSp+"/"+inRangeSc+", end="+inRangeEp+"/"+inRangeEc+", sided="+abovePrevious+"/"+aboveCurrent);
// make sure to short-circuit if the actor cannot
// interact with the boundary because it is out of range.
- if (inRangeS == 0 || inRangeE == 0) {
+ boolean inRangeForStart = (inRangeSp == 0 && inRangeSc == 0);
+ boolean inRangeForEnd = (inRangeEp == 0 && inRangeEc == 0);
+ if (inRangeForStart || inRangeForEnd) {
if(debug) sketch.println(sketch.frameCount +"> this boundary is not involved in collisions for this frame (out of range).");
return null;
}
// if the force goes against the border's permissible direction, but
// both previous and current frame actor boxes are above the boundary,
// then we don't have to bother with intersection detection.
- if (above==4 && aboveAfter==4) {
+ if (abovePrevious==4 && aboveCurrent==4) {
if(debug) sketch.println(sketch.frameCount +"> this box is not involved in collisions for this frame (inherently safe 'above' locations).");
return null;
- } else if(0 < above && above < 4) {
+ } else if(0 < abovePrevious && abovePrevious < 4) {
if(debug) sketch.println(sketch.frameCount +"> this box is not involved in collisions for this frame (never fully went through boundary).");
return null;
}
@@ -919,7 +933,7 @@ static class CollisionDetection {
// actor frame is on the blocking side of a boundary, and
// 'aboveAfter' is 0, meaning its current frame is on the other
// side of the boundary, then a collision MUST have occurred.
- if (above==4 && aboveAfter==0) {
+ if (abovePrevious==4 && aboveCurrent==0) {
// note that in this situation, the overlap may look
// like full containment, where the actor's bounding
// box is fully contained by the boundary's box.
@@ -2740,11 +2754,13 @@ abstract class Positionable extends Position implements Drawable {
float[] redirected = new float[]{ix, iy};
for(int b=boundaries.size()-1; b>=0; b--) {
Boundary boundary = boundaries.get(b);
+ if(!boundary.disabled) {
+ redirected = boundary.redirectForce(redirected[0], redirected[1]);
+ }
if(boundary.disabled || !boundary.supports(this)) {
detachFrom(boundary);
continue;
}
- redirected = boundary.redirectForce(redirected[0], redirected[1]);
}
ix = redirected[0];
iy = redirected[1];
@@ -4177,10 +4193,20 @@ abstract class Trigger extends Positionable {
String triggername="";
+ Trigger(String name) {
+ triggername = name;
+ }
+
Trigger(String name, float x, float y, float w, float h) {
super(x,y,w,h);
triggername = name;
}
+
+ void setArea(float x, float y, float w, float h) {
+ setPosition(x,y);
+ width = w;
+ height = h;
+ }
boolean drawableFor(float x, float y, float w, float h) {
return x<=this.x+width && this.x<=x+w && y<=this.y+height && this.y<=y+h;
@@ -4201,7 +4227,7 @@ abstract class Trigger extends Positionable {
void removeTrigger() { remove = true; }
abstract void run(LevelLayer level, Actor actor, float[] intersection);
-}
+}
/**
* Possible the simplest class...
* A viewbox simply defines a region of
View
@@ -23,7 +23,7 @@ class MainBackgroundLayer extends MarioLayer {
addTube(304,height-100,null);
int pos = 1914;
- addTube(pos,height-100,new LayerTeleportTrigger("main layer", pos+2,height-120,28,2, 2020+16,32));
+ addTube(pos,height-100,new LayerTeleportTrigger("main layer", 2020+16,32));
addGoal(2060,height-100);
}
View
@@ -28,16 +28,17 @@ abstract class MarioBlock extends BoundedInteractor {
}
void setupBoundaries() {
- float xa = (getX() - width/2),
- xb = (getX() + width/2),
- ya = (getY() - height/2),
- yb = (getY() + height/2);
+ float xa = (getX() - width/2),
+ xb = (getX() + width/2)-1,
+ ya = (getY() - height/2),
+ yb = (getY() + height/2)-1;
+
addBoundary(new Boundary(xa, yb-1, xa, ya+1));
- addBoundary(new Boundary(xa+1, ya, xb-1, ya));
+ addBoundary(new Boundary(xa, ya, xb, ya));
addBoundary(new Boundary(xb, ya+1, xb, yb-1));
// the bottom boundary is special, because we want
// to know whether things collide with it.
- addBoundary(new Boundary(xb-1, yb, xa+1, yb), true);
+ addBoundary(new Boundary(xb, yb, xa, yb), true);
}
// generate something
Oops, something went wrong.

0 comments on commit 8c49fee

Please sign in to comment.