Cat and mouse sketch - Source code
Mouse.pde
In this simulation the mouse is a state driven autonomous agent so we could use the Vehicle class for this agent but we need an extra variable to say whether the mouse is alive or dead. This variable will be used when the cat looks for a mouse - no need to consider dead mice! The best way to do this is to create a new class called Mouse that inherits from Vehicle. That way a Mouse object behaves just like a Vehicle object, but can also do anthing we put in the Mouse class.
So in line 3 below we have added a boolean attribute to the mouse class.
The constructor (lines 5-11) is essential for any class that inherits from Vehicle and the first line should always be a call to the parent class constructor i.e.
super(position, radius, velocity, max_speed, heading, mass, max_turn_rate,
max_force);
Since any mouse entity is going to be state driven agents they need a FSM and rather than expect the class user to remember this the Mouse class activates its FSM in line 10.
The MousePic class is the custom renderer for Mouse objects and since custom renderers have been discussed in other programming guides I won't say much more here. I will point out lines 37-41 which are used to draw any steering behaviour hints, although not needed in the completed sketch it does no harm in leaving this code and being able to visualise these hints are a great aid in tweaking the agents behaviour.
public class Mouse extends Vehicle {
boolean alive = true;
public Mouse(Vector2D position, double radius, Vector2D velocity,
double max_speed, Vector2D heading, double mass,
double max_turn_rate, double max_force) {
super(position, radius, velocity, max_speed, heading, mass, max_turn_rate,
max_force);
addFSM();
}
} // End of Mouse class
public class MousePic extends PicturePS {
int head, eye, whiskers;
float size;
public MousePic(PApplet app, float size, int body, int eye, int whiskers) {
super(app);
this.size = size;
this.head = body;
this.eye = eye;
this.whiskers = whiskers;
}
public MousePic(PApplet app, float size) {
this(app, size, color(160), color(255, 200, 200), color(0));
}
public void draw(BaseEntity user, float posX, float posY, float velX,
float velY, float headX, float headY, float etime) {
// Draw and hints that are specified and relevant
if (hints != 0) {
Hints.hintFlags = hints;
Hints.draw(app, user, velX, velY, headX, headY);
}
// Determine the angle the tank is heading
float angle = PApplet.atan2(headY, headX);
// Prepare to draw the entity
pushStyle();
ellipseMode(PApplet.CENTER);
pushMatrix();
translate(posX, posY);
rotate(angle);
// Draw the entity
stroke(whiskers);
strokeWeight(1);
line(0.4f*size, -0.5f*size, 0.6f*size, 0.5f*size);
line(0.6f*size, -0.5f*size, 0.4f*size, 0.5f*size);
strokeWeight(0.5f);
fill(head);
arc(0.15f*size, 0, 0.3f*size, 1.2f*size, PApplet.HALF_PI - 0.4f, 3* PApplet.HALF_PI + 0.4f, PApplet.CHORD);
arc(0, 0, 0.7f*size, 0.7f*size, PApplet.HALF_PI, 3* PApplet.HALF_PI);
arc(0, 0, 1.1f*size, 0.7f*size, 3* PApplet.HALF_PI, PApplet.TWO_PI);
arc(0, 0, 1.1f*size, 0.7f*size, 0, PApplet.HALF_PI);
fill(whiskers);
ellipse(0.55f*size, 0, 0.2f*size, 0.2f*size);
fill(eye);
ellipse(0.12f*size, 0.15f*size, 0.2f*size, 0.22f*size);
ellipse(0.12f*size, -0.15f*size, 0.2f*size, 0.22f*size);
// Finished drawing
popMatrix();
popStyle();
}
} // End of MousePic class