I’m making an fps game with zombies. I have the models with the animation and texture.
I’ve loaded it using an array of spatial and I set the zombie’s name using setName() → (zombie[index].setName(“Zombie” + index).
My problem is: when I hit a zombie (ex: zombie[0]), the code changes the animation of the last zombie that has spawned (ex: zombie[20]), but I want the zombie[0] change animation. (sorry for my English).
“Your code looks fine from here.”
Or: we can’t debug code that we can’t see.
public class Main extends SimpleApplication {
public Node zombieNode = new Node();
private Spatial zombie[] = new Spatial[50];
private int zombieIndex = 0;
private AnimChannel channel, channelHit;
private AnimControl control, controlHit;
private float tempo = 0, condizioniTempoFloat = 1.1f;
int condizioniTempoInt = 1;
private String path = "Models/Zombie/Zombie_Geo.mesh.j3o";
private final static Trigger TRIGGER_SHOOT = new MouseButtonTrigger(MouseInput.BUTTON_LEFT);
private final static String MAPPING_SHOOT = "Shoot";
public static void main(String[] args) {
Main app = new Main();
app.start();
app.setDisplayFps(false);
app.setDisplayStatView(false);
}
@Override
public void simpleInitApp() {
viewPort.setBackgroundColor(ColorRGBA.White);
rootNode.attachChild(zombieNode);
mouseInit();
}
protected void setUpZombie(String name, String path, Vector3f position){
//Load the model
zombie[zombieIndex] = assetManager.loadModel(path);
zombie[zombieIndex].setName(name + zombieIndex);
zombie[zombieIndex].rotate(1.57f, 0, 0);
zombie[zombieIndex].scale(0.015f);
zombie[zombieIndex].setLocalTranslation(position);
zombieNode.attachChild(zombie[zombieIndex]);
//A box that gives me the zombie index
Box b = new Box(0.5f, 1.4f, 0.9f);
Geometry collisionBox = new Geometry("" + zombieIndex, b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Red);
collisionBox.setMaterial(mat);
collisionBox.setLocalTranslation(position.x, position.y + 1.4f, position.z);
zombieNode.attachChild(collisionBox);
}
private void zombieAnimation(String animazione){
control = zombie[zombieIndex].getControl(AnimControl.class);
channel = control.createChannel();
channel.setAnim("Walking", 0.50f);
channel.setLoopMode(LoopMode.Loop);
channel.setSpeed(1f);
}
private void mouseInit(){
inputManager.addMapping(MAPPING_SHOOT, TRIGGER_SHOOT);
inputManager.addListener(analogListener, new String[]{MAPPING_SHOOT});
}
private AnalogListener analogListener = new AnalogListener() {
String nomeZombie;
int zombieHitIndex;
@Override
public void onAnalog(String name, float intensity, float tpf) {
if (name.equals(MAPPING_SHOOT)){
CollisionResults results = new CollisionResults();
Ray ray = new Ray(cam.getLocation(), cam.getDirection());
//vedere a cosa stai mirando
rootNode.collideWith(ray, results);
if (results.size() > 0){
String nomeZombie = results.getClosestCollision().getGeometry().getName();
CollisionResult target = results.getClosestCollision();
zombieHitIndex = Integer.parseInt(nomeZombie);
System.out.println(zombieHitIndex); //Test the index
hitAnimation(zombieHitIndex);
//I color the box that I've hit (TEST)
Material zombieC = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
zombieC.setColor("Color", new ColorRGBA(0, 1, 0, 0.0f));
target.getGeometry().setMaterial(zombieC);
}
}
}
};
//Change animation of the zombie that has been hit
private void hitAnimation(int zombieHitIndex){
channel.reset(true);
control = zombie[zombieHitIndex].getControl(AnimControl.class);
channel = control.createChannel();
channel.setAnim("ReactionHit", 0.50f);
channel.setLoopMode(LoopMode.Loop);
channel.setSpeed(1f);
}
@Override
public void simpleUpdate(float tpf) {
tempo += tpf; //tempo = time
if (tempo >= condizioniTempoInt && tempo <= condizioniTempoFloat){
//I set up the zombie and the animation
setUpZombie(("Zombie" + zombieIndex), path, new Vector3f(5 * zombieIndex, 0, 0));
zombieAnimation("Walking");
zombieIndex++; //Increment the zombie index
//This two variable are used for spawn zombie every second
condizioniTempoInt++;
condizioniTempoFloat++;
}
}
@Override
public void simpleRender(RenderManager rm) {
}
}
Does the right geometry change color? Or is it also the most recent only?
The right geometry change color, so it’s correct. The problem is the spatial, the animation change only in the last one that has spawned
Does that print the correct value or not?
You attach the collision box to your root zombie node and not to the individual zombie nodes.
It prints the correct print, but in the hitAnimation only last zombie that has spawned change animation. Maybe should I make another AnimControl that contain the “ReactionHit” animation?
Then it seems like somehow your array is built incorrectly?
Basically, keep going along these lines of printing out more and more things. What’s the spatial that is in zombie[] at the hit index, etc…
In the spatial zombie[] cointain the zombie model, the animation and the texture that I’ve applied.
IS the control the same or different… etc… etc…
Check every assumption. Eventually you will find the issue.
Maybe because I use only one channel and one contro. Later I’ll try. Thank you for your time!
private void hitAnimation(int zombieHitIndex){
channel.reset(true);
controlHit = zombie[zombieHitIndex].getControl(AnimControl.class);
channelHit = control.createChannel();
channelHit.setAnim("ReactionHit", 0.50f);
channelHit.setLoopMode(LoopMode.Loop);
channelHit.setSpeed(1f);
}
So I've tried to create a new channel and a new control, but it doesn't work, but I've discovered it a channel and control problem because I tried to do this:
private void hitAnimation(int zombieHitIndex){
zombie[zombieHitIndex].rotate(90, 0, 0); //Rotate the zombie
}
In this case the game rotate the right zombie. I don’t know how to resolve this.
note again: How to type code blocks
Please read it and post code blocks correctly.
As to your problem, I’m not sure… but you keep a lot of stuff around as instance fields that seem unnecessary. So it’s hard to see if things are clobbering each other. That’s why I suggested seeing if the control is actually different.
Shouldn’t you use the controlHit and not the control?
But yes, like pspeed said, those instance fields really mess up everything. Very shady logic.