@Override public void start(Scene scene) { database = new SpatialArray<Vec2>(32); newSprite( Color.red, 15, 190, new SteerSet<Vec2>( new SteerTo<Vec2>( 500, slowest = new TargetSlowest<Vec2>( database, null, 100, 200, false, 32, SpatialDatabase.ALL_GROUPS, Vec2.FACTORY)), new SteerWander2(500, 0, 100, 150, 80))); for (int i = 0; i < 24; i++) { SteerSprite lamb = newSprite( Color.white, 10, SteerMath.randomFloat(150, 250), new SteerWander2(1000, 0, 100, 150, 80)); lamb.position.set(SteerMath.randomFloat(width), SteerMath.randomFloat(height)); database.add(lamb); } }
@Override public Vector getTarget(SteerSubject subject) { Vector position = target.getTarget(subject); if (SteerMath.isCircleInView( subject.getPosition(), subject.getDirection(), fov, position, targetRadius, fovType)) { return position; } return null; }
@Override public void getForce(float elapsed, SteerSubject<V> subject, V out) { future.set(leader.getPosition()); future.add(leader.getVelocity()); SteerMath.closest(leader.getPosition(), future, subject.getPosition(), closest); float distanceSq = closest.dot(subject.getPosition()); if (distanceSq <= distance * distance) { away(subject, closest, out, this); } }
@Override public void draw(GameState state, Graphics2D gr, Scene scene) { float radius = 200.0f; Vec2 upper = new Vec2(fov.x, fov.y); Vec2 lower = new Vec2(fov.x, -fov.y); Vec2 upperRotated = upper.rotate(direction); Vec2 lowerRotated = lower.rotate(direction); /* Vec2 towards = target.sub( origin ); float ut = upperRotated.cross( towards ); float lt = lowerRotated.cross( towards ); boolean view = (ut <= 0 && lt >= 0 ) || (fov.x < 0.0f && ((ut >= 0 && lt >= 0) || (ut <= 0 && lt <= 0))); boolean circleInView = SteerMath.isCircleInView( origin, direction, fov, circlePos, circleRadius, circleEntirely ); */ gr.setColor(Color.orange); line.setLine( origin.x, origin.y, origin.x + upperRotated.x * radius, origin.y + upperRotated.y * radius); gr.draw(line); line.setLine( origin.x, origin.y, origin.x + lowerRotated.x * radius, origin.y + lowerRotated.y * radius); gr.draw(line); drawCircle(gr, upperRotated.mul(radius).addi(origin), 5, Color.orange); drawCircle(gr, direction.mul(radius).addi(origin), 5, Color.gray); drawCircle(gr, origin, 5, Color.white); drawCircle(gr, target, 5, Color.red); drawCircle(gr, circlePos, circleRadius, Color.yellow); /* gr.drawString( String.format( "fov: {%.2f,%.2f}", fov.x, fov.y ), 2, 12 ); gr.drawString( String.format( "origin.distanceSq(target): %.2f", origin.distanceSq( target ) ), 2, 24 ); gr.drawString( String.format( "direction.dot(towards): %.2f", direction.dot(towards) ), 2, 36 ); gr.drawString( String.format( "in view: %s", view ), 2, 48 ); gr.drawString( String.format( "upperRotated.cross( towards ): %.2f", upperRotated.cross( towards ) ), 2, 60 ); gr.drawString( String.format( "lowerRotated.cross( towards ): %.2f", lowerRotated.cross( towards ) ), 2, 72 ); gr.drawString( String.format( "isCircleInView(entirely=%s): %s", circleEntirely, circleInView ), 2, 84 ); */ Vec2 _V = circlePos.sub(origin); double _a = _V.dot(direction); // how far along the direction the sphere's center is double _b = _a * Math.tan(fovAngle); // radius of the cone at _a double _c = Math.sqrt(_V.lengthSq() - _a * _a); // distance from center of sphere to axis of the cone double _d = _c - _b; // distance from center of sphere to the surface of the cone double _e = _d * Math.cos( fovAngle); // shortest distance from center of the sphere to the surface of the cone boolean _inview = false; if (_e >= circleRadius) { // cull } else if (_e <= -circleRadius) { // totally _inview = true; } else { // partially if (!circleEntirely) { _inview = true; } } Vec2 farAlong = SteerMath.closest(origin, direction.mul(radius).addi(origin), circlePos, new Vec2()); line.setLine(origin.x, origin.y, farAlong.x, farAlong.y); gr.draw(line); line.setLine( farAlong.x + direction.y * _a, farAlong.y - direction.x * _a, farAlong.x - direction.y * _a, farAlong.y + direction.x * _a); gr.draw(line); line.setLine(farAlong.x, farAlong.y, circlePos.x, circlePos.y); gr.setColor(Color.blue); gr.draw(line); int textY = 0; gr.setColor(Color.white); gr.drawString( String.format("how far along: %.2f (expected=%.2f)", _a, farAlong.distance(origin)), 2, textY += 12); gr.drawString(String.format("radius of cone: %.2f", _b), 2, textY += 12); gr.drawString( String.format( "circle->axis of cone: %.2f (expected=%.2f)", _c, farAlong.distance(circlePos)), 2, textY += 12); gr.drawString(String.format("circle->surface of cone: %.2f", _d), 2, textY += 12); gr.drawString(String.format("shortest distance: %.2f", _e), 2, textY += 12); gr.drawString( String.format("inview(entirely=%s): %s", circleEntirely, _inview), 2, textY += 12); gr.drawString( String.format( "fov: {%.2f,%.2f}: %.2f (%.2f)", fov.x, fov.y, fovAngle, Math.toDegrees(fovAngle)), 2, textY += 12); gr.drawString( String.format( "isCircleInView: %s", SteerMath.isCircleInView( origin, direction, Math.tan(fovAngle), Math.cos(fovAngle), circlePos, circleRadius, circleEntirely)), 2, textY += 12); }