Each Forward player keeps an estimate of the ball's velocity with respect to itself by noting the ball's relative location every 6 frames and subtracting from the old relative location. This is used to chase after the ball more accurately.
Once the Forward is in possesion of the ball, it attempts to dribble the ball into the center of the opponent's goal.
package Riddler.Flash; import sockey.SoccerClient; import java.awt.*; public final class Forward extends SoccerClient { final int DRIBBLING=2; final int RECEIVING=3; final int SENDFWDS= 7; int state= RECEIVING; // are we DRIBBLING or RECEIVING? int dist[]= new int[3]; // relative distances of the 3 forwards Point loc= new Point(0,0); // scratch Point for general use int me; // ID of this player's position int closest; // ID of Forward closest to the ball int radius; // radius of the player int ballradius; // radius of the ball Point oldball= new Point(); // where the ball was last time we looked Point ballvel= new Point(); // how fast ball is going (pix/sec) int balltime= 0; // when to look at the ball again int maxvel= 10; // maximum velocity of this Forward /** * Values you'd like to initialize for this player go here */ public void init() { super.init(); radius= getRadius(); ballradius= getBallRadius(); } /** * The only message we receive is the distance from the ball of the * forwards. Save the info away in an array. */ public void receiveMessage(int from, String msg, int a, int b, int c) { dist[from]= a; } /** * Move to the absolute field position (x,y) at full speed * (like wannabe, except not PID controller) */ public void moveTo(int x, int y) { // -loc is where we are. (x,y) is where we want to be. ping(ID_CENTER, loc, false); loc.translate(x, y); cart2polar(loc, loc); accelerate(loc.y, 100); } public void regroup() { super.regroup(); // Really all we're trying to do here is figure out how fast our // player can go. getVel(v); if (v.x*v.x+v.y*v.y >= maxvel*maxvel) { maxvel= (int)Math.sqrt(v.x*v.x+v.y*v.y)+1; debugMsg("maxvel is now: "+maxvel); } } public void step() { ping(ID_BALL, pt, true); int bang= pt.y; me= getPosition(); // tell the other players how far away the ball is from me. sendMessage(SENDFWDS, null, pt.x, 0, 0); // which forward player is closest to the ball? closest= (dist[0]<dist[1]) ? ((dist[0]<dist[2]) ? 0 : 2) : ((dist[1]<dist[2]) ? 1 : 2); ping(ID_BALL, pt, false); // check for ball velocity: check every 6 frames (1/10 second) int frameno= getTime(); if (frameno>balltime) { if (frameno-balltime>12) { // we've lost some time... reset everything ballvel.x= 0; ballvel.y= 0; } else { // find ball velocity: ballvel.x= (pt.x-oldball.x)*60/(frameno-(balltime-6)); ballvel.y= (pt.y-oldball.y)*60/(frameno-(balltime-6)); } oldball.x= pt.x; oldball.y= pt.y; balltime= frameno+6; } ping(ID_CENTER, loc, false); pt.x-= loc.x; pt.y-= loc.y; switch (state) { case RECEIVING: { // If we're the closest to the ball, go for the ball if (closest==me) { // where will the ball be by the time we get there? // time to get there is dist[me]/maxvel moveTo(pt.x+ballvel.x*dist[me]/maxvel, pt.y+ballvel.y*dist[me]/maxvel); } else { // otherwise, move parallel to the ball, along a // field longitude line. if (me== ID_PCTR) { moveTo(pt.x, 0); } else if (me== ID_PFWDL) { moveTo(pt.x, -size.height/3); } else { moveTo(pt.x, size.height/3); } } // Set angle so that the ball would bounce off our face // into the center of the goal ping(ID_THEIR_GOAL, loc, true); // angle to goal is loc.y, angle to ball is bang. // Angle halfway between is loc.y+(bang-loc.y)/2 int pointoff= anglesub(bang, loc.y); if (pointoff<-135 || pointoff>135) { setAngGoal(bang+((pointoff<0)?30:-30)); } else { setAngGoal(loc.y+pointoff/2); } // if ball is really close (ready to kick), start dribbling. if (dist[me]<radius+ballradius && pointoff<50 && pointoff>-50) { state= DRIBBLING; debugMsg("I got it!"); } break; } case DRIBBLING: { ping(ID_THEIR_GOAL, loc, true); // diff is relative angle to the ball: + is to left, - to right int diff= anglesub(bang, getAng()); // we want to face the goal, but angle to dribble the ball // closer to the center of our face. int goal= loc.y-diff/3; // if we lost the ball (not kickable), we need to chase the ball if (dist[me]>radius+ballradius) { // angle to kick the ball into the goal diff= anglesub(bang, loc.y); goal= loc.y+diff/2; moveTo(pt.x, pt.y); } else { // othewise, dribble the ball into the goal moveTo(size.width/2, 0); } setAngGoal(goal); // if ball is too far away, we've lost it. Go back to receiving if (dist[me]>radius*2 || closest!=me) { state= RECEIVING; debugMsg("Chasing..."); } break; } } } }