Package: com.multiversesocial.hyperview
Class: com.multiversesocial.hyperview.CollisionManager
Source: src/com/multiversesocial/hyperview/CollisionManager.java

CollisionManager

HyperView V3.2 — class
version V3.2 class

Summary

The collision manager behind SplineConstants.COLLIDE_AT_END and the Gob flag GOB_COLLISION_OUTLINE. HyperView.collisionPass() calls collide(view) once per display frame, right after the loop that steps and draws the Gobs, on the display thread. collide() looks at the view’s Gob list gob[0 .. totalGobs) only, which is the list of the current Dispatch frame (Dispatch.begin() swaps that list); Gobs of a backed-up frame never collide with the Gobs of a nested one.

The tests are made cheapest first: bounding box reject, then pointInPoly() of each vertex of A’s outline against B’s polygon and of B’s against A’s. pointInPoly() is a small static even-odd ray crossing test using only integer arithmetic, with no allocation per call. The outline is set with Gob.setOutline(), or traced from the GobThe outline is set with Gob.setOutline(); without one it is the Gob’s bounding box (see Gob).rsquo;s image when it has the flag GOB_COLLISION_OUTLINE; without either it is the GobThe outline is set with Gob.setOutline(); without one it is the Gob’s bounding box (see Gob).rsquo;s bounding box (see Gob).

Source file: CollisionManager.java

Rules

V3.23: contact response, damage, explosion, walls

Hierarchy

Extends: none

Implements: Runnable, HyperConstants, ThreadReport

Referenced HyperView classes

Declaration & members

public class CollisionManager implements Runnable, HyperConstants, ThreadReport

Declared in src/com/multiversesocial/hyperview/CollisionManager.java, lines 1–984. 41 field(s), 2 constructor(s), 27 method(s). Every member has an anchor you can link to (e.g. CollisionManager.html#m-collide-HyperView).

Fields (41)

DeclarationValue / initializerDescriptionSource
int candNNumber of entries in cand.line 124
Gob[] cand= new Gob[64]Taking part Gobs of the current pass, reused and cleared at the end of each pass.line 123
double[] cen= new double[4]No comment in source.line 505
volatile static Thread collisionManagerTaskThe older thread design; nothing starts it.line 61
int collisionNum= 0Contacts detected by this manager (all passes).line 64
HyperView curViewThe view of the last pass.line 62
public static double damageScale= 1.0Damage = impact energy * damageScale * Gob.damageFactor (energy = 0.5 * reduced mass * closing speed^2).line 94
public static double damageThreshold= 0.0Impacts with less energy than this do no damage (resting contact, gentle touches).line 96
public static boolean edgeTest= trueTest edges for crossings when no vertex is inside the other polygon (plus-sign case). Applies to every view.line 74
public static volatile int explosionCount= 0Explosions made by the physics (all views, this JVM).line 107
public static int explosionMillis= 700Length of the default explosion (CollisionAnimGob) of a Gob whose hit points ran out, milliseconds.line 105
public static int fxMillis= CollisionAnimGob.DEFAULT_MILLISLength of the CollisionAnimGob in milliseconds (600).line 76
int hitXContact point found by touch() (hitX, hitY).line 125
int hitYy of the contact point found by touch() (see hitX).line 125
public static volatile int impactCount= 0Physical impacts resolved (all views, this JVM).line 109
int iteration= 0Collision passes made (also reported through getRunInfo()).line 69
public int lastBoxHitsPairs which survived the bounding box reject in the last pass (point-in-poly was run on them).line 117
public int lastCandidatesGobs which took part in the last pass.line 115
public int lastNewContactsNew contacts in the last pass.line 119
long lastRun= 0Time of the previous pass (milliseconds); reported by getRunInfo().line 66
long lastStepMs= 0Llength of the current pass's physics step in framesline 111
public int lastTouchingGobs touching something in the last pass.line 121
public static int maxFx= 64Do not add another CollisionAnimGob while this many are showing in the view.line 78
public static double maxStepFrames= 4.0Longest step in frames when realTimeStep is on.line 101
long now= 0Time of the current pass in milliseconds (set by collide()).line 65
double[] nrm= new double[2]No comment in source.line 507
public static boolean realTimeStep= falsefalse (default): one physics step per collision pass (velocity = pixels per display frame, deterministic). true: the step length is the real time since the last pass in units of 1/60 s (clamped to maxStepFrames).line 99
RunInfo runInfo= new RunInfo((Object)this)Thread report; part of the older thread design.line 60
int runLag= 0RunInfo value of the older thread design; not changed by collide().line 67
public static double separationSlop= 1.0Extra pixels two bodies are pushed apart beyond their overlap, so the integer outlines stop touching.line 103
long startTime= 0RunInfo value of the older thread design; not changed by collide().line 68
double stepFrames= 1.0length of the current pass's physics step in framesline 110
int totalGobsNo comment in source; not used by collide().line 63
int waitTime= 200Wait time of the older thread loop in milliseconds.line 70
public static int wallBottom= 0No comment in source.line 92
public static int wallLeft= 0The wall rectangle of WALLS_BOUNCE in view pixels: left, top, and right / bottom (exclusive). right or bottom <= 0: the view's width / height.line 89
public static int wallRight= 0No comment in source.line 91
public static final int WALLS_BOUNCE= 1 (constant)Edges of the view: physical Gobs bounce off them (RESPONSE_STOP Gobs stop).line 84
public static final int WALLS_NONE= 0 (constant)Edges of the view: Gobs leave it (the default, as before).line 82
public static int walls= WALLS_NONEWhat happens at the edges of the view for physical Gobs that the pass moves.line 86
public static int wallTop= 0No comment in source.line 90

Constructors (2)

SignatureDescriptionSource
CollisionManager()Package-private; empty.line 148
CollisionManager(HyperView tView)Package-private; sets curView. HyperView.collisionPass() creates one on first use.line 153

Methods (27)

SignatureDescriptionSource
static void applyVelocity(Gob g, double nvx, double nvy, boolean stop)set a physical Gob's velocity after an impact; a Spline driven one is now owned by the physicsline 655
static void centroid(Gob g, double[] out)the area centroid of the world outline of g (vertex average for a degenerate polygon)line 348
public int collide(HyperView v)One collision pass over the Gob list of the current Dispatch frame. Ages the CollisionAnimGobs (and removes finished ones), collects the taking part Gobs, clears their GOB_COLLIDED, rebuilds their world outlines, then tests every pair (bounding box, then touch()), flags, counts and spawns the CollisionAnimGob for new contacts. Returns the number of new contacts.line 729
double contactNormal(Gob a, Gob b, double[] out)The contact normal of two overlapping outlines: the separating axis of least overlap (SAT) over the edge normals of both polygons, pointing from a to b, written to out[0..1]. Returns the overlap (penetration depth) along it, >= 0. For convex outlines this is the exact minimum translation; for concave ones (traced art) the overlap of the convex hulls on the same axes (an upper bound of the true penetration). Falls back to the centroid direction when an outline has no area.line 516
boolean contact(Gob a, Gob b)Is this a NEW contact (did they not touch in the previous pass)? Always records that they touch now, in both Gobs’ contact lists.line 935
public static void explode(HyperView v, Gob g, Gob from)Explode g now: Gob.exploded is set, Gob.onExplode(from) is asked; unless it handled the explosion, a CollisionAnimGob the size of the Gob plays at its centre and the Gob is removed (Gob.remGob). Selection is cleared if g was selected.line 694
static int free(Gob g)A free (or reusable: destroyed or stale partner) slot in g’s contact list; the list grows by doubling.line 961
public RunInfo getRunInfo()Fills the RunInfo from now, runLag, lastRun, startTime, waitTime, iteration. Implements ThreadReport.getRunInfo().line 191
public void initialize()Older thread design: creates the thread without starting it; RunInfo state RT_PAUSED.line 140
static boolean isAlive()True if the manager thread object exists.line 186
static void motion(Gob g, double frames)Per pass, before the outline is rebuilt: move a physical Gob by its velocity, or measure the velocity of a Spline driven / kinematic one. frames = the length of this step in frames.line 421
static boolean movable(Gob g)may the pass move g (separation, walls)?line 394
static long orient(int px, int py, int qx, int qy, int cx, int cy)> 0 if c is left of the line p to q, < 0 right, 0 on it.line 923
public static boolean pointInPoly(Polygon p, int x, int y)Same for a java.awt.Polygon; uses its arrays directly (no copy).line 242
public static boolean pointInPoly(int[] px, int[] py, int n, int x, int y)Is x,y inside (or exactly on the edge of) the polygon px[0..n-1],py[0..n-1]? Even-odd ray crossing test: a ray from x,y towards +x crosses the polygon edges an odd number of times when the point is inside. Works for concave polygons and self crossing outlines (even-odd rule). Integer arithmetic only (cross products in long, so no rounding and no overflow while the coordinates are within +-1,000,000,000), no allocation, no division: small and static so the JIT inlines it into the vertex loops. Points on an edge or vertex count as inside. n < 3 is never inside.line 215
boolean respond(Gob a, Gob b)a and b touch (their outlines overlap) and at least one is physical: bounce / stop, damage, separate. Returns true if a physical impact (closing speed > 0) happened.line 589
public synchronized void run()Waits in waitTime steps until the thread is replaced; does no detection. Implements Runnable.run().line 169
void separate(Gob a, Gob b, double nx, double ny, double depth)push a and b apart along n (a to b) by their overlap, shared by inverse mass among the bodies which may moveline 672
static void shift(Gob g, double dx, double dy)move g by dx,dy pixels (float position) and rebuild its world outlineline 410
static int slot(Gob g, Gob o)Index of o in g’s contact list, or -1.line 952
static boolean splineDriven(Gob g)is the Gob moved by a Spline right now (an attached Spline that physics has not taken over)?line 388
public synchronized void start()Older thread design: creates and starts the manager thread (nothing calls it).line 127
public synchronized void stop()Older thread design: stops the thread.line 158
static void syncExact(Gob g)keep the exact position in step with x,y when somebody else moved the Gobline 400
boolean touch(Gob a, Gob b)Do the outlines of a and b overlap? Vertices of a in b, vertices of b in a (each pre-rejected by the other’s bounds), then edge crossings if edgeTest. Sets hitX, hitY.line 847
public static void updateOutline(Gob g)Rebuilds g.worldX/worldY/worldN and the bounding box from the Gob’s outline, position (x,y) and size (width,height; they differ from widthBase,heightBase for z-buffered Gobs, so the outline is scaled by width/widthBase and height/heightBase). Arrays are allocated once and reused. Default (no outline set): the box x,y .. x+width-1,y+height-1.line 257
static void wallBounce(HyperView v, Gob g)walls of the viewline 473

Examples

Real usage from the HyperView 3.2 source (file and line shown; source path src/com/multiversesocial/hyperview/). Tests: test/com/multiversesocial/hyperview/CollisionTest.java (point-in-poly, flagging, spawn, no spurious collisions) and the collide step of InfoRunTest.

The display loop calls the pass — HyperView.java, line 2304

  // V3.21: collision pass for Gobs whose Spline has COLLIDE_AT_END (or which have GOB_COLLISION_OUTLINE). Only the Gob list
  // of the current Dispatch frame (gob[0..totalGobs)) is looked at. See CollisionManager.
  collisionPass();

A Gob with an outline and a COLLIDE_AT_END Spline — InfoSteps.java, lines 958–962

  s.setOutline(poly);
  Spline sp = new Spline(d.curView,v,new int[] {x0,x1},new int[] {y0,y1},(int[])null,
   Spline.CURVE_LINEAR,SplineConstants.COLLIDE_AT_END);
  s.addSpline(sp);

Reading the result

  if(s.isCollided())  { /* touching now */ }
  int n = s.getCollisionCount();      // separate contacts so far
  Gob other = s.getCollidedWith();    // partner of the latest new contact, or null
  boolean in = CollisionManager.pointInPoly(xs,ys,xs.length,px,py);
Hits--