One Shot Wall Smoothing implementation
This is the thread's initial revision.
Some Ideas[edit]
-- Iterative technique --
I pull these from my memory of some of the offerings on Old-RoboWiki. Use a wall-stick to project point in front of you some distance. If it falls outside the bounds of the current arena, adjust the direction of your wall-stick either clockwise (+1 latDir) or counterclockwise (-1 latDir)
//May be attributed to PEZ static double wallSmooth(Point center, int velDir, double heading, int latDir) {
//Adjust the heading if going backwards heading += (velDir-1)/2*Helpers.PI; int counter = 0; while(!arena.contains(project(center, WALL_STICK, heading))) { heading += 0.01 * latDir; } return Utils.normalAbsoluteAngle(heading);
}
A refinement of my post on the prior wiki -- Single-Shot Smoothing --
//Given some point in the arena, and some heading, how long is the ray cast to the wall in front of you //This returns a measurement of mega-pixels given a 600 X 800 arena. :)
static double calcWallSpace(final Point eCenter, double eGoing) { eGoing = Utils.normalAbsoluteAngle(eGoing); final double wallDistLat = eGoing < Helpers.PI ? (PLAY_WIDTH+18d-eCenter.getX()) / (Helpers.cos((Helpers.PI/2d - eGoing))) : eCenter.getX() / (Helpers.cos((3d*Helpers.PI/2d - eGoing))); eGoing = Utils.normalRelativeAngle(eGoing); final double wallDistVirt = Math.abs(Utils.normalRelativeAngle(eGoing)) < Helpers.PI / 2d ? (PLAY_HEIGHT+18d-eCenter.getY()) / (Helpers.cos(eGoing)) : eCenter.getY() / (Helpers.cos(Helpers.PI - eGoing)); return(float)(Math.min(wallDistLat, wallDistVirt) / MAX_DIST); }
//Given same data as iterative example //As written, will have no effect on desired absolute heading if distance to forward wall is greater than 200 pixels (0.2 MP) in a standard arena
//This inverts wallSpace measurement and cubes it in order to maintain a tight enough turning curve
static double wallSmooth(final Point center, final int velDir, double heading, final int latDir) { final double wallSpace; final Point future = project(center, velDir * 165d, heading);
// Note:: PlayHeight = getBattleFieldHeight() - 36
boolean top = future.getY() > PLAY_HEIGHT + 18d, bottom = future.getY() < 18, left = future.getX() < 18, right = future.getX() >= PLAY_WIDTH + 18d; //NOTE: I invert the heading for negative velocities in the next line final double wallSpaceFact = (1d - (wallSpace=Math.min(0.2d, calcWallSpace(center, Utils.normalAbsoluteAngle((heading = (heading + (velDir-1)/2 * Helpers.PI))))) * 5.2d)*wallSpace*wallSpace); double desiredAngle = heading;
switch(latDir) { case 1: if(top && right) top = false; if(left && top) left = false; if(bottom && left) bottom = false; if(right && bottom) right = false;
if(top) desiredAngle += Utils.normalRelativeAngle(Helpers.HALF_PI - heading) * wallSpaceFact;
else if(right) desiredAngle += Utils.normalRelativeAngle(Helpers.PI - heading) * wallSpaceFact;
else if(bottom) desiredAngle += Utils.normalRelativeAngle(Helpers.THREE_OVER_TWO_PI - heading) * wallSpaceFact;
else if(left) desiredAngle += Utils.normalRelativeAngle(Helpers.TWO_PI - heading) * wallSpaceFact;
break; case -1: if(top && right) right = false; if(left && top) top = false; if(bottom && left) left = false; if(right && bottom) bottom = false;
if(top) desiredAngle += Utils.normalRelativeAngle(Helpers.THREE_OVER_TWO_PI - heading) * wallSpaceFact; else if(right) desiredAngle += Utils.normalRelativeAngle(0d - heading) * wallSpaceFact; else if(bottom) desiredAngle += Utils.normalRelativeAngle(Helpers.HALF_PI - heading) * wallSpaceFact; else if(left) desiredAngle += Utils.normalRelativeAngle(Helpers.PI - heading) * wallSpaceFact;
break; default: System.out.println("quit it please"); break; }
return Utils.normalAbsoluteAngle(desiredAngle); }
Both of these methods take the same parameters and result in an absolute desired angle of travel so as to avoid the wall with the desired lateral direction relative to the enemy.