I have class:
public class EnemyControl extends AbstractControl implements AnimEventListener {
there, in the controlUpdate method, I start animation like this:
if (spatialControl.getNumChannels()>0) {
// ...some code ...
} else {
spatialControl.addListener(this);
AnimChannel enemyAnimChannel = spatialControl.createChannel();
enemyAnimChannel.setLoopMode(LoopMode.DontLoop);
enemyAnimChannel.setAnim("Two steps");
}
But when animation stops, it starts again in endless loop.
The only way to kill it is here:
@Override
public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
// That is the only way to stop animation currently
control.setEnabled(false);
}
Is it a known issue?
1 Like
DontLoop works for me.
You’d have to provide a little more info for us to be able to help.
Maybe you could post your whole class?
Hi Robbi,
here it is (sorry for bad code, I am still beginner with JME):
package mygame;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
/**
*
* @author guest
*/
public class EnemyControl extends AbstractControl implements AnimEventListener {
private GamePlayAppState gamePlayState;
private Vector3f currentTranslation;
private Vector3f newTranslation;
public EnemyControl(GamePlayAppState state) {
this.gamePlayState = state;
}
@Override
protected void controlUpdate(float tpf) {
if (spatial.getUserData("health") != null) {
if ((int) spatial.getUserData("health") <= 0) {
spatial.removeFromParent();
} else {
moveToBase(spatial, tpf);
}
}
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
private void moveToBase(Spatial spatial, float tpf) {
// Check animation frame and stop movement
AnimControl spatialControl = spatial.getControl(AnimControl.class);
if (spatialControl.getNumChannels()>0) {
AnimChannel spatialChannel = spatialControl.getChannel(0);
float animTime = spatialChannel.getTime();
if ( (animTime > 1.6f) && (animTime < 1.8f)) {
return;
}
if (animTime > 3.2f) {
return;
}
} else {
// Start movement randomly for each Enemy Unit
//Should be done by Userget value, to control it better later
if (FastMath.nextRandomInt(0, 200)==1) {
spatialControl.addListener(this);
AnimChannel enemyAnimChannel = spatialControl.createChannel();
enemyAnimChannel.setLoopMode(LoopMode.DontLoop);
enemyAnimChannel.setAnim("Two steps");
}
return; // (Stop movement
}
//Base starts at X = -3.5 and has size of 0.5 (probably from -3.5 to -3)
// Base starts at Y = -0.5 and has size of 1
currentTranslation = spatial.getLocalTranslation();
float distance = tpf/2;
if (currentTranslation.x < -6f ) {
gamePlayState.playerData.setHealth(gamePlayState.playerData.getHealth() - 1);
spatial.removeFromParent();
//Destroy control and make minus 1 life
} else {
newTranslation = new Vector3f(-distance, 0, 0f);
// if (currentTranslation.y < -0.4 ) {
// newTranslation.y = distance*0.7f;
// }
// if (currentTranslation.y > 0.4) {
// newTranslation.y = -distance*0.7f;
// }
if (newTranslation.y != 0) {
newTranslation.x = -distance*0.7f;
}
spatial.setLocalTranslation(currentTranslation.add(newTranslation));
}
}
@Override
public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
// That is the only way to stop animation currently
control.setEnabled(false);
}
@Override
public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
}
}
Hello @Denis_Tislenko
Denis_Tislenko:
Is it a known issue?
Yes, it is!
When you have a look at the source code of AnimChannel you can see that when you call
enemyAnimChannel.setAnim("Two steps");
That will set the LoopMode to Loop again.
this.blendTime = blendTime;
// activate blending
blendTime = Math.min(blendTime, anim.getLength() / speed);
blendFrom = animation;
timeBlendFrom = time;
speedBlendFrom = speed;
loopModeBlendFrom = loopMode;
blendAmount = 0f;
blendRate = 1f / blendTime;
}else{
blendFrom = null;
}
animation = anim;
time = 0;
speed = 1f;
loopMode = LoopMode.Loop;
notified = false;
}
/**
You can solve this issue by just setting the LoopMode after you called .setAnim();
if (spatialControl.getNumChannels()>0) {
// ...some code ...
} else {
spatialControl.addListener(this);
AnimChannel enemyAnimChannel = spatialControl.createChannel();
enemyAnimChannel.setAnim("Two steps");
enemyAnimChannel.setLoopMode(LoopMode.DontLoop);
}
3 Likes
Wow, perfect Domenic, nice solution!