I am using an ArrayList to handle objects and at each interval of 120 frames, I am adding a new object of the same type at a random location along the z-axis of 60. The problem is, it doesn't add just 1. It depends on how many are in the list. If I kill the Fox before the time interval when one is supposed to spawn comes, then no Fox will be spawned. If I don't kill any foxes, it grows exponentially. I only want one Fox to be added every 120 frames. This problem never happened before when I created new ones and added them to the environment. Any insights?
Here is my code:
/**** FOX CLASS ****/
import env3d.EnvObject;
import java.util.ArrayList;
public class Fox extends Creature
{
private int frame = 0;
public Fox(double x, double y, double z)
{
super(x, y, z);
// Must use the mutator as the fields have private access
// in the parent class
setTexture("models/fox/fox.png");
setModel("models/fox/fox.obj");
setScale(1.4);
}
public void move(ArrayList<Creature> creatures, ArrayList<Creature> dead_creatures, ArrayList<Creature> new_creatures)
{
frame++;
setX(getX()-0.2);
setRotateY(270);
if (frame > 120) {
Fox f = new Fox(60, 1, (int)(Math.random()*28)+1);
new_creatures.add(f);
frame = 0;
}
for (Creature c : creatures) {
if (this.distance(c) < this.getScale()+c.getScale() && c instanceof Tux) {
dead_creatures.add(c);
}
}
for (Creature c : creatures) {
if (c.getX() < 1 && c instanceof Fox) {
dead_creatures.add(c);
}
}
}
}
import env3d.Env;
import java.util.ArrayList;
import org.lwjgl.input.Keyboard;
/**
* A predator and prey simulation. Fox is the predator and Tux is the prey.
*/
public class Game
{
private Env env;
private boolean finished;
private ArrayList<Creature> creatures;
private KingTux king;
private Snowball ball;
private int tuxcounter;
private int kills;
/**
* Constructor for the Game class. It sets up the foxes and tuxes.
*/
public Game()
{
// we use a separate ArrayList to keep track of each animal.
// our room is 50 x 50.
creatures = new ArrayList<Creature>();
for (int i = 0; i < 10; i++) {
creatures.add(new Tux((int)(Math.random()*10)+1, 1, (int)(Math.random()*28)+1));
}
for (int i = 0; i < 1; i++) {
creatures.add(new Fox(60, 1, (int)(Math.random()*28)+1));
}
king = new KingTux(25, 1, 35);
ball = new Snowball(-400, -400, -400);
}
/**
* Play the game
*/
public void play()
{
finished = false;
// Create the new environment. Must be done in the same
// method as the game loop
env = new Env();
// Make the room 50 x 50.
env.setRoom(new Room());
// Add all the animals into to the environment for display
for (Creature c : creatures) {
env.addObject(c);
}
for (Creature c : creatures) {
if (c instanceof Tux) {
tuxcounter++;
}
}
env.addObject(king);
env.addObject(ball);
// Sets up the camera
env.setCameraXYZ(30, 50, 55);
env.setCameraPitch(-63);
// Turn off the default controls
env.setDefaultControl(false);
// A list to keep track of dead tuxes.
ArrayList<Creature> dead_creatures = new ArrayList<Creature>();
ArrayList<Creature> new_creatures = new ArrayList<Creature>();
// The main game loop
while (!finished) {
if (env.getKey() == 1 || tuxcounter == 0) {
finished = true;
}
env.setDisplayStr("Tuxes: " + tuxcounter, 15, 0);
env.setDisplayStr("Kills: " + kills, 140, 0);
processInput();
ball.move();
king.check();
// Move each fox and tux.
for (Creature c : creatures) {
c.move(creatures, dead_creatures, new_creatures);
}
for (Creature c : creatures) {
if (c.distance(ball) < c.getScale()+ball.getScale() && c instanceof Fox) {
dead_creatures.add(c);
ball.setX(-400);
ball.setY(-400);
ball.setZ(-400);
kills++;
}
}
// Clean up of the dead tuxes.
for (Creature c : dead_creatures) {
if (c instanceof Tux) {
tuxcounter--;
}
env.removeObject(c);
creatures.remove(c);
}
for (Creature c : new_creatures) {
creatures.add(c);
env.addObject(c);
}
// we clear the ArrayList for the next loop. We could create a new one
// every loop but that would be very inefficient.
dead_creatures.clear();
new_creatures.clear();
// Update display
env.advanceOneFrame();
}
// Just a little clean up
env.exit();
}
private void processInput()
{
int keyDown = env.getKeyDown();
int key = env.getKey();
if (keyDown == 203) {
king.setX(king.getX()-1);
} else if (keyDown == 205) {
king.setX(king.getX()+1);
}
if (ball.getX() <= -400 && key == Keyboard.KEY_S) {
ball.setX(king.getX());
ball.setY(king.getY());
ball.setZ(king.getZ());
}
}
/**
* Main method to launch the program.
*/
public static void main(String args[]) {
(new Game()).play();
}
}
/**** CREATURE CLASS ****/
/* (Parent class to Tux, Fox, and KingTux) */
import env3d.EnvObject;
import java.util.ArrayList;
abstract public class Creature extends EnvObject
{
private int frame;
private double rand;
/**
* Constructor for objects of class Creature
*/
public Creature(double x, double y, double z)
{
setX(x);
setY(y);
setZ(z);
setScale(1);
rand = Math.random();
}
private void randomGenerator()
{
rand = Math.random();
}
public void move(ArrayList<Creature> creatures, ArrayList<Creature> dead_creatures, ArrayList<Creature> new_creatures)
{
frame++;
if (frame > 12) {
randomGenerator();
frame = 0;
}
// if (rand < 0.25) {
// setX(getX()+0.3);
// setRotateY(90);
// } else if (rand < 0.5) {
// setX(getX()-0.3);
// setRotateY(270);
// } else if (rand < 0.75) {
// setZ(getZ()+0.3);
// setRotateY(0);
// } else if (rand < 1) {
// setZ(getZ()-0.3);
// setRotateY(180);
// }
if (rand < 0.5) {
setRotateY(getRotateY()-7);
} else if (rand < 1) {
setRotateY(getRotateY()+7);
}
setX(getX()+Math.sin(Math.toRadians(getRotateY()))*0.5);
setZ(getZ()+Math.cos(Math.toRadians(getRotateY()))*0.5);
if (getX() < getScale()) setX(getScale());
if (getX() > 50-getScale()) setX(50 - getScale());
if (getZ() < getScale()) setZ(getScale());
if (getZ() > 50-getScale()) setZ(50 - getScale());
// The move method now handles collision detection
if (this instanceof Fox) {
for (Creature c : creatures) {
if (c.distance(this) < c.getScale()+this.getScale() && c instanceof Tux) {
dead_creatures.add(c);
}
}
}
}
}
The rest of the classes are a bit trivial to this specific problem.