Steeringbehavior Java
SteeringBehavior.java
multiverse/src/multiverse/mars/behaviors
package multiverse.mars.behaviors; import java.util.*; import multiverse.msgsys.*; import multiverse.server.objects.*; import multiverse.server.math.*; import multiverse.server.util.*; import multiverse.server.engine.*; import multiverse.server.plugins.MobManagerPlugin; // Class: SteeringBehavior // Auth: Sara Pickell // Should be used to maintain separation, alignment and cohesion. // Version 1 uses the messages from entering and exiting the radius // Future versions should handle on spawn and be limited to a certain // template. // It's unknown whether the first version will even work. public class SteeringBehavior extends Behavior implements MessageCallback, Runnable { public SteeringBehavior(){ super(); mrange = 8000; } // constructor when given spawn data public SteeringBehavior(SpawnData spawn, int sep, int align, int coh){ super(); // get the range of the spawn radius. mrange = spawn.getSpawnRadius(); // get the relative amounts of separation, alignment and cohesion. separation = sep; alignment = align; cohesion = coh; } int mrange; int separation = 0; int alignment = 0; int cohesion = 0; // initialize the message filtering crap public void initialize() { super.initialize(); //This filter lets through only messages that occur when something steps into //someone's reaction radius, and only when that someone is this mob. // SP, I copied this from a tutorial. I understand what it's doing. // I still don't feel entirely comfortable with the MV message architecture, though. SubjectFilter filter = new SubjectFilter(obj.getOid()); filter.addType(ObjectTracker.MSG_TYPE_NOTIFY_REACTION_RADIUS); eventSub = Engine.getAgent().createSubscription(filter, this); } long eventSub = 0; boolean activated; // override the activate method. // adds debug logging and gets a tracker for stuff within range @Override public void activate() { Log.debug("FactionBehavior.activate: adding reaction radius for mob"); // Tells the manager to send messages when something comes within mrange units of this mob MobManagerPlugin.getTracker(obj.getInstanceOid()).addReactionRadius(obj.getOid(), mrange); activated = true; run(); } @Override public void deactivate() { // we lock down the thread and turn it off lock.lock(); try { activated = false; // if we're still subscribed for events cancel the sub if (eventSub != 0) { Engine.getAgent().removeSubscription(eventSub); eventSub = 0; } } finally { // use finally to be absolutely sure we unlock the thread lock.unlock(); } } // override the handleMessage method // we'll be doing some debug logging and locking the thread @Override public void handleMessage(Message msg, int arg1) { if (Log.loggingDebug) Log.debug("Received a Steering message: " + msg.getMsgType()); lock.lock(); try { // if we aren't activated, don't even bother trying if (activated == false) { return ; } if (msg.getMsgType().equals(ObjectTracker.MSG_TYPE_NOTIFY_REACTION_RADIUS)) { // if we have the message, do something freaky weird ObjectTracker.NotifyReactionRadiusMessage message = (ObjectTracker.NotifyReactionRadiusMessage)msg; // set a long to hold the subject id // sometimes you still need to use getSubject due // to it not always being treated like a long. // hell if I know why. long messageObjOid = message.getSubject(); // if we're logging our debug code, send out some info on the message if (Log.loggingDebug) Log.debug("Steering: Notify Reaction Radius Message Received" + obj.getOid() + " msgObjOid " + messageObjOid + " msgOid " + messageObjOid); // if the object is ourself, we'll be ignoring it. if (obj.getOid().equals(message.getSubject())) { return ; } else if (message.getInRadius() == false) { // if it's an old object then it must be leaving our space percobjs.remove(multiverse.server.objects.MVObject.getObject(message.getSubject())); return ; } else if (message.getWasInRadius() == false) { // if it's a new arrival, we'll want to handle it // in this case handling it means adding it to // a list of nearby objects percobjs.add(multiverse.server.objects.MVObject.getObject(message.getSubject())); } } } finally { lock.unlock(); } return ; } List<MVObject> percobjs; // we need to run separation, cohesion, and alignment on our list @Override public void run() { lock.lock(); try{ Point tempPoint = new Point(separation()); tempPoint.add(new Point(cohesion())); sendMessage(tempPoint, 2000); } finally { lock.unlock(); } } // send a message protected void sendMessage(Point waypoint, int speed) { // I assume this is where tell the mob to actually perform the action Engine.getAgent().sendBroadcast(new BaseBehavior.GotoCommandMessage(obj, waypoint, speed)); } // The separation() method is responsible for keeping things apart. public multiverse.server.math.MVVector separation(){ MVVector SteeringForce = new MVVector(0, 0, 0); for(int a=0; a < percobjs.size(); ++a) { MVVector agentVect = new MVVector(percobjs.get(a).getCurrentLoc()); MVObject o = new MVObject(obj.getOid()); MVVector toAgent = agentVect.sub(o.getCurrentLoc()); SteeringForce = SteeringForce.add(toAgent.normalize().getX()/toAgent.length(), 0, toAgent.normalize().getZ()/toAgent.length()); } return SteeringForce; } // The alignment() method is responsible for keeping things moving in a single direction. public multiverse.server.math.MVVector alignment(){ MVVector AverageHeading = new MVVector(0, 0, 0); float total = 0; for(int a=0; a < percobjs.size(); ++a) { MVVector agentVect = new MVVector(percobjs.get(a).getDirection()); AverageHeading = AverageHeading.add(agentVect); ++total; } AverageHeading.setX(AverageHeading.getX()/total); AverageHeading.setZ(AverageHeading.getZ()/total); AverageHeading.setY(0); return AverageHeading; } // The cohesion() method is responsible for keeping things together. public multiverse.server.math.MVVector cohesion(){ MVVector CenterMass = new MVVector(0, 0, 0); float total = 0; for(int a=0; a < percobjs.size(); ++a) { MVVector agentVect = new MVVector(percobjs.get(a).getCurrentLoc()); CenterMass = CenterMass.add(agentVect); ++total; } CenterMass.setX(CenterMass.getX()/total); CenterMass.setZ(CenterMass.getZ()/total); CenterMass.setY(0); return CenterMass; } private static final long serialVersionUID = 1L; }
page_revision: 7, last_edited: 1216180505|%e %b %Y, %H:%M %Z (%O ago)





