Permalink
Browse files

fixed boundary collisions. Finally

  • Loading branch information...
1 parent 9ebbd6a commit 0b3e577519a81d9c399019a399d0767312d7bfc6 @Pomax committed Jun 7, 2012
Showing with 240 additions and 114 deletions.
  1. +7 −7 Actor.pde
  2. +7 −35 Boundary.pde
  3. +61 −40 CollisionDetection.pde
  4. +1 −0 GameLoader.pde
  5. +1 −1 LevelLayer.pde
  6. +0 −5 Position.pde
  7. +2 −1 Positionable.pde
  8. +5 −5 Sprite.pde
  9. +1 −1 SpritePath.pde
  10. +40 −3 State.pde
  11. +5 −6 TilingSprite.pde
  12. +33 −9 debugfunctions.pde
  13. +77 −1 spriteengine.pde
View
@@ -192,20 +192,19 @@ abstract class Actor extends Positionable {
* surfaces.
*/
void attachTo(Boundary boundary, float[] correction) {
-// println("attaching to boundary "+boundary);
// record attachment
boundaries.add(boundary);
- // first, stop the actor
+ // stop the actor
float ix = this.ix - (fx*ixF),
iy = this.iy - (fy*iyF);
stop(correction[0], correction[1]);
- // then impart a new impulse as redirected by the boundary.
+ // then impart a new impulse, as redirected by the boundary.
float[] rdf = boundary.redirectForce(ix, iy);
addImpulse(rdf[0], rdf[1]);
- // finally, notify call the blocked handler
+ // finally, call the blocked handler
gotBlocked(boundary, correction);
}
@@ -218,11 +217,12 @@ abstract class Actor extends Positionable {
/**
* collisions may force us to stop this
- * actor's movement.
+ * actor's movement. the actor is also
+ * moved back by dx/dy
*/
void stop(float dx, float dy) {
- x += dx;
- y += dy;
+ x = round(x+dx);
+ y = round(y+dy);
ix = 0;
iy = 0;
}
View
@@ -101,41 +101,13 @@ class Boundary extends Positionable {
* supported by this boundary?
*/
boolean supports(Positionable thing) {
- // are all corner dot products above "just above 0"?
- float dotx = xw-x,
- doty = yh-y,
- otlen = sqrt(dotx*dotx + doty*doty),
- tx, ty, dx, dy, len, dotproduct=-2;
-
- float[] current = thing.getBoundingBox();
-
- // normalised boundary vector
- dotx /= otlen;
- doty /= otlen;
-
- // note: we want the dot product with the
- // vector that is perpendicular to the boundary!
- float p = PI/2, cosp = cos(p), sinp = sin(p),
- pdx = dotx*cosp - doty*sinp,
- pdy = dotx*sinp + doty*cosp;
-
- // how many corners are blocked in [current]?
- float proximity = -2;
- for(int i=0; i<8; i+=2) {
- tx = current[i];
- ty = current[i+1];
- dx = tx-x;
- dy = ty-y;
- len = sqrt(dx*dx+dy*dy);
- dx /= len;
- dy /= len;
- dotproduct = dx*pdx + dy*pdy;
- if (dotproduct > proximity) {
- proximity = dotproduct;
- }
- }
-// println("dot-proximity to boundary: "+proximity);
- return abs(proximity) < 0.01;
+ float epsilon = 1;
+ float[] bbox = thing.getBoundingBox();
+ if (minx - epsilon > bbox[2]) return false;
+ if (miny - epsilon > bbox[5]) return false;
+ if (maxx + epsilon < bbox[0]) return false;
+ if (maxy + epsilon < bbox[1]) return false;
+ return true;
}
/**
View
@@ -4,17 +4,12 @@
* it's handled by this static computing class.
*/
static class CollisionDetection {
- // recycled in getLineRectIntersection()
- private static float[] current_dots = {0,0,0,0,0,0,0,0};
- private static float[] previous_dots = {0,0,0,0,0,0,0,0};
- private static ArrayList<float[]> intersections = new ArrayList<float[]>();
- private static float[] bbox = {0,0,0,0,0,0,0,0};
- private static float[] ZERO_DIFFERENCE = {0,0};
- // constant for indicating a coordinate is an intersection
- final static int INTERSECTION = 0;
- // constant for indicating a coordinate is a full contained coordinate
- final static int CONTAINED = 1;
+ /**
+ * Static classes need global sketch binding
+ */
+ private static PApplet sketch;
+ public static void init(PApplet s) { sketch = s; }
/**
* Perform actor/boundary collision detection
@@ -24,7 +19,16 @@ static class CollisionDetection {
if (a.isAttachedTo(b)) { return; }
float[] correction = blocks(b,a);
- if(correction != null) { a.attachTo(b, correction); }
+ if(correction != null) {
+ /*
+ sketch.stroke(0);
+ sketch.line(a.getX()-10, a.getY()-10, a.getX()+10, a.getY()+10);
+ sketch.line(a.getX()-10, a.getY()+10, a.getX()+10, a.getY()-10);
+
+ sketch.stroke(255,0,0);
+ sketch.line(a.getX(), a.getY(), a.getX()+correction[0], a.getY()+correction[1]);
+ */
+ a.attachTo(b, correction); }
}
/**
@@ -42,6 +46,20 @@ static class CollisionDetection {
return CollisionDetection.getLineRectIntersection(line, current, previous);
}
+// =================================================================
+
+ private static float[] current_dots = {0,0,0,0,0,0,0,0};
+ private static float[] previous_dots = {0,0,0,0,0,0,0,0};
+ private static ArrayList<float[]> intersections = new ArrayList<float[]>();
+ private static float[] checkLines = {0,0,0,0,0,0,0,0};
+ private static float[] ZERO_DIFFERENCE = {0,0};
+
+ // constant for indicating a coordinate is an intersection
+ final static int INTERSECTION = 0;
+
+ // constant for indicating a coordinate is a full contained coordinate
+ final static int CONTAINED = 1;
+
/**
* Line-through-box intersection algorithm.
@@ -152,36 +170,41 @@ static class CollisionDetection {
// Right then. Case (2) or (3)?
if (B_previous == 4) {
+ int currentCase = 2;
// for (2) and (3) the approach is essentially
// the same, except that we need different bounding
// boxes to determine the intersection. For (2) we
// can use the [current] bounding box, but for (3)
// we need to construct a new box that is spanned by
// the two points next to the "hot" corner in both
// [previous] and [current].
- arrayCopy(current,0,bbox,0,8);
+ checkLines = new float[8];
+ arrayCopy(current,0,checkLines,0,8);
// if we're seeing case (3), set up bbox correctly.
- if (B_current == 0) {
+ if (B_current < 4) {
// println("case 3");
+ currentCase = 3;
// two of these edges are guaranteed to not have intersections,
// since otherwise the intersection would be inside either
// [previous] or [current], which is case (2) instead.
- bbox = new float[]{previous[(corner+2)%8],previous[(corner+3)%8],
- previous[(corner+6)%8],previous[(corner+7)%8],
- current[(corner+6)%8], current[(corner+7)%8],
- current[(corner+2)%8], current[(corner+3)%8]}; }
- else {
+ checkLines = new float[]{previous[(corner)%8], previous[(corner+1)%8],
+ previous[(corner+2)%8], previous[(corner+3)%8],
+ current[(corner+2)%8], current[(corner+3)%8],
+ current[(corner)%8], current[(corner+1)%8]};
+ }
+ else
+ {
// println("case 2");
}
// Now that we have the correct box, perform line/line
// intersection detection for each edge on the box.
intersections.clear();
- float x1=bbox[0], y1=bbox[1], x2=x1, y2=y1;
- for (int i=0; i<8; i+=2) {
- x2 = bbox[(i+2)%8];
- y2 = bbox[(i+3)%8];
+ float x1=checkLines[0], y1=checkLines[1], x2=x1, y2=y1;
+ for (int i=0, last=checkLines.length; i<last; i+=2) {
+ x2 = checkLines[(i+2)%last];
+ y2 = checkLines[(i+3)%last];
float[] intersection = getLineLineIntersection(ox,oy,tx,ty, x1,y1,x2,y2, false);
if (intersection!=null) {
intersections.add(intersection);
@@ -209,23 +232,21 @@ static class CollisionDetection {
// println("***");
float[] ideal = getLineLineIntersection(px,py,cx,cy, i1[0],i1[1],i2[0],i2[1], false);
if (ideal == null) {
-/*
- debugfunctions_drawBoundingBox(previous);
- debugfunctions_drawBoundingBox(current);
- ellipse(i1[0],i1[1],3,3);
- ellipse(i2[0],i2[1],3,3);
- ellipse(px,py,3,3);
- ellipse(cx,cy,3,3);
- println("hot line : "+px+","+py+","+cx+","+cy);
- println("intersect: "+i1[0]+","+i1[1]+","+i2[0]+","+i2[1]);
- float angle = atan2(i2[1]-i1[1], i2[0]-i1[0]),
- cosma = cos(-angle),
- sinma = sin(-angle);
- float[] tr = translateRotate(px,py,cx,cy, i1[0],i1[1],i2[0],i2[1], angle,cosma,sinma);
- println("translated: "+tr[0]+","+tr[1]+","+tr[2]+","+tr[3]+","+tr[4]+","+tr[5]+","+tr[6]+","+tr[7]+","+tr[8]);
- exit();
-*/
-// println("error could not find the ideal point");
+ println("error: could not find the case "+currentCase+" ideal point based on corner ["+corner+"]");
+ /*
+ println("tried to find the intersection between:");
+ println("[1] "+px+","+py+","+cx+","+cy+" (blue)");
+ println("[2] "+i1[0]+","+i1[1]+","+i2[0]+","+i2[1]+" (green)");
+ //debugfunctions_drawBoundingBox(current,sketch);
+ //debugfunctions_drawBoundingBox(previous,sketch);
+ debugfunctions_drawBoundingBox(checkLines,sketch);
+
+ sketch.noLoop();
+ sketch.stroke(0,200,255);
+ sketch.line(px,py,cx,cy);
+ sketch.stroke(0,255,0);
+ sketch.line(i1[0],i1[1],i2[0],i2[1]);
+ */
return new float[]{px-cx, py-cy};
}
return new float[]{ideal[0]-cx, ideal[1]-cy};
@@ -254,7 +275,7 @@ static class CollisionDetection {
*/
static float[] getLineLineIntersection(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, boolean colinearity)
{
- float epsilon = 0.000000001;
+ float epsilon = 0.001;
// convert lines to the generatised form [a * x + b + y = c]
float a1 = -(y2 - y1), b1 = (x2 - x1), c1 = (x2 - x1) * y1 - (y2 - y1) * x1;
float a2 = -(y4 - y3), b2 = (x4 - x3), c2 = (x4 - x3) * y3 - (y4 - y3) * x3;
View
@@ -19,6 +19,7 @@ void setup() {
levelSet = new HashMap<String, Level>();
SpriteMapHandler.init(this);
SoundManager.init(this);
+ CollisionDetection.init(this);
initialize();
}
View
@@ -263,7 +263,7 @@ abstract class LevelLayer {
s.draw(x,y,w,h);
}
} else {
- drawBackground((int)width, (int)height);
+ debugfunctions_drawBackground((int)width, (int)height);
}
// ---- boundaries
View
@@ -99,11 +99,6 @@ class Position {
float[] obounds = other.getBoundingBox();
if(bounds==null || obounds==null) return null;
- if (false) {
- debugfunctions_drawBoundingBox(bounds);
- debugfunctions_drawBoundingBox(obounds);
- }
-
float xmid1 = (bounds[0] + bounds[2])/2;
float ymid1 = (bounds[1] + bounds[5])/2;
float xmid2 = (obounds[0] + obounds[2])/2;
View
@@ -310,7 +310,8 @@ abstract class Positionable extends Position implements Drawable {
// mostly for debugging purposes
String toString() {
- return "current: " + toString() + "\n" +
+ return width+"/"+height + "\n" +
+ "current: " + super.toString() + "\n" +
"previous: " + previous.toString() + "\n";
}
}
View
@@ -109,14 +109,14 @@ class Sprite extends Positionable {
* center point.
*/
void align(int _halign, int _valign) {
- if(_halign==LEFT) { halign=-width/2; }
+ if(_halign==LEFT) { halign=width/2; }
else if(_halign==CENTER) { halign=0; }
- else if(_halign==RIGHT) { halign=width/2; }
+ else if(_halign==RIGHT) { halign=-width/2; }
ox = halign;
- if(_valign==TOP) { valign=-height/2; }
+ if(_valign==TOP) { valign=height/2; }
else if(_valign==CENTER) { valign=0; }
- else if(_valign==BOTTOM) { valign=height/2; }
+ else if(_valign==BOTTOM) { valign=-height/2; }
oy = valign;
}
@@ -203,7 +203,7 @@ class Sprite extends Positionable {
* number for the last frame in the set.
*/
int getCurrentFrameNumber() {
- if(!path.looping && framesServed == path.size()) {
+ if(path.size() > 0 && !path.looping && framesServed == path.size()) {
if(state!=null) { state.finished(); }
animated = false;
return numFrames-1;
View
@@ -14,7 +14,7 @@ class SpritePath {
int servedFrame = 0;
// is this path cyclical?
- boolean looping = true;
+ boolean looping = false;
boolean noRotation = false;
// private class for frame information
View
@@ -26,16 +26,53 @@ class State {
sprite.setState(this);
Computer.states();
}
+
+ /**
+ * add path points to a state
+ */
+ void addPathPoint(float x, float y, float sx, float sy, float r, int duration) {
+ sprite.addPathPoint(x, y, sx, sy, r, duration); }
- // bind this state to an actor
+ /**
+ * add a linear path to the state
+ */
+ void addPathLine(float x1, float y1, float sx1, float sy1, float r1,
+ float x2, float y2, float sx2, float sy2, float r2,
+ float duration) {
+ sprite.addPathLine(x1,y1,sx1,sy1,r1, x2,y2,sx2,sy2,r2, duration); }
+
+ /**
+ * add a curved path to the state
+ */
+ void addPathCurve(float x1, float y1, float sx1, float sy1, float r1,
+ float cx1, float cy1,
+ float cx2, float cy2,
+ float x2, float y2, float sx2, float sy2, float r2,
+ float duration,
+ float slowdown_ratio) {
+ sprite.addPathCurve(x1,y1,sx1,sy1,r1, cx1,cy1,cx2,cy2, x2,y2,sx2,sy2,r2, duration, slowdown_ratio); }
+
+ /**
+ * incidate whether or not this is a looping path
+ */
+ void setLooping(boolean l) {
+ sprite.setLooping(l);
+ }
+
+
+ /**
+ * bind this state to an actor
+ */
void setActor(Actor _actor) {
actor = _actor;
actor.width = sprite.width;
actor.height = sprite.height;
}
- // when the sprite is moved by its path,
- // let the actor know of its updated position.
+ /**
+ * when the sprite is moved by its path,
+ * let the actor know of its updated position.
+ */
void setActorOffsets(float x, float y) {
actor.setTranslation(x, y);
}
Oops, something went wrong.

0 comments on commit 0b3e577

Please sign in to comment.