每当我将用于动画目的的精灵地图集上传到overlapps2d版本0.1.2-snapshot中的场景时。我的应用程序崩溃了以下行(稍微编辑):
java.lang.NoSuchMethodError: No virtual method getKeyFrame(F)Lcom/badlogic/gdx/graphics/g2d/TextureRegion; in class Lcom/badlogic/gdx/graphics/g2d/Animation; or its super classes (declaration of 'com.badlogic.gdx.graphics.g2d.Animation' appears in /data/data/xxx.xxx.xxx/files/instant-run/dex/slice-gdx-1.9.5_xxx-classes.dex)
它在我的代码中指向了这一行:
sceneLoader.getEngine().update(Gdx.graphics.getDeltaTime());
这可能是版本不匹配的问题,因为overlap2d已经超过一年没有更新,但libgdx刚刚更新了一个月前?崩溃只发生在动画图像上,否则app运行正常。我查看了错误引用的libgdx文件,这就是它的样子:
package com.badlogic.gdx.graphics.g2d;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.Array;
public class Animation<T> {
/** Defines possible playback modes for an {@link Animation}. */
public enum PlayMode {
NORMAL,
REVERSED,
LOOP,
LOOP_REVERSED,
LOOP_PINGPONG,
LOOP_RANDOM,
}
/** Length must not be modified without updating {@link #animationDuration}. See {@link #setKeyFrames(T[])}. */
T[] keyFrames;
private float frameDuration;
private float animationDuration;
private int lastFrameNumber;
private float lastStateTime;
private PlayMode playMode = PlayMode.NORMAL;
/** Constructor, storing the frame duration and key frames.
*
* @param frameDuration the time between frames in seconds.
* @param keyFrames the objects representing the frames. */
public Animation (float frameDuration, Array<? extends T> keyFrames) {
this.frameDuration = frameDuration;
T[] frames = (T[]) new Object[keyFrames.size];
for (int i = 0, n = keyFrames.size; i < n; i++) {
frames[i] = keyFrames.get(i);
}
setKeyFrames(frames);
}
/** Constructor, storing the frame duration and key frames.
*
* @param frameDuration the time between frames in seconds.
* @param keyFrames the objects representing the frames. */
public Animation (float frameDuration, Array<? extends T> keyFrames, PlayMode playMode) {
this(frameDuration, keyFrames);
setPlayMode(playMode);
}
/** Constructor, storing the frame duration and key frames.
*
* @param frameDuration the time between frames in seconds.
* @param keyFrames the objects representing the frames. */
public Animation (float frameDuration, T... keyFrames) {
this.frameDuration = frameDuration;
setKeyFrames(keyFrames);
}
/** Returns a frame based on the so called state time. This is the amount of seconds an object has spent in the
* state this Animation instance represents, e.g. running, jumping and so on. The mode specifies whether the animation is
* looping or not.
*
* @param stateTime the time spent in the state represented by this animation.
* @param looping whether the animation is looping or not.
* @return the frame of animation for the given state time. */
public T getKeyFrame (float stateTime, boolean looping) {
// we set the play mode by overriding the previous mode based on looping
// parameter value
PlayMode oldPlayMode = playMode;
if (looping && (playMode == PlayMode.NORMAL || playMode == PlayMode.REVERSED)) {
if (playMode == PlayMode.NORMAL)
playMode = PlayMode.LOOP;
else
playMode = PlayMode.LOOP_REVERSED;
} else if (!looping && !(playMode == PlayMode.NORMAL || playMode == PlayMode.REVERSED)) {
if (playMode == PlayMode.LOOP_REVERSED)
playMode = PlayMode.REVERSED;
else
playMode = PlayMode.LOOP;
}
T frame = getKeyFrame(stateTime);
playMode = oldPlayMode;
return frame;
}
/** Returns a frame based on the so called state time. This is the amount of seconds an object has spent in the
* state this Animation instance represents, e.g. running, jumping and so on using the mode specified by
* {@link #setPlayMode(PlayMode)} method.
*
* @param stateTime
* @return the frame of animation for the given state time. */
public T getKeyFrame (float stateTime) {
int frameNumber = getKeyFrameIndex(stateTime);
return keyFrames[frameNumber];
}
/** Returns the current frame number.
* @param stateTime
* @return current frame number */
public int getKeyFrameIndex (float stateTime) {
if (keyFrames.length == 1) return 0;
int frameNumber = (int)(stateTime / frameDuration);
switch (playMode) {
case NORMAL:
frameNumber = Math.min(keyFrames.length - 1, frameNumber);
break;
case LOOP:
frameNumber = frameNumber % keyFrames.length;
break;
case LOOP_PINGPONG:
frameNumber = frameNumber % ((keyFrames.length * 2) - 2);
if (frameNumber >= keyFrames.length) frameNumber = keyFrames.length - 2 - (frameNumber - keyFrames.length);
break;
case LOOP_RANDOM:
int lastFrameNumber = (int) ((lastStateTime) / frameDuration);
if (lastFrameNumber != frameNumber) {
frameNumber = MathUtils.random(keyFrames.length - 1);
} else {
frameNumber = this.lastFrameNumber;
}
break;
case REVERSED:
frameNumber = Math.max(keyFrames.length - frameNumber - 1, 0);
break;
case LOOP_REVERSED:
frameNumber = frameNumber % keyFrames.length;
frameNumber = keyFrames.length - frameNumber - 1;
break;
}
lastFrameNumber = frameNumber;
lastStateTime = stateTime;
return frameNumber;
}
/** Returns the keyframes[] array where all the frames of the animation are stored.
* @return The keyframes[] field. */
public T[] getKeyFrames () {
return keyFrames;
}
protected void setKeyFrames (T... keyFrames) {
this.keyFrames = keyFrames;
this.animationDuration = keyFrames.length * frameDuration;
}
/** Returns the animation play mode. */
public PlayMode getPlayMode () {
return playMode;
}
/** Sets the animation play mode.
*
* @param playMode The animation {@link PlayMode} to use. */
public void setPlayMode (PlayMode playMode) {
this.playMode = playMode;
}
/** Whether the animation would be finished if played without looping (PlayMode#NORMAL), given the state time.
* @param stateTime
* @return whether the animation is finished. */
public boolean isAnimationFinished (float stateTime) {
int frameNumber = (int)(stateTime / frameDuration);
return keyFrames.length - 1 < frameNumber;
}
/** Sets duration a frame will be displayed.
* @param frameDuration in seconds */
public void setFrameDuration (float frameDuration) {
this.frameDuration = frameDuration;
this.animationDuration = keyFrames.length * frameDuration;
}
/** @return the duration of a frame in seconds */
public float getFrameDuration () {
return frameDuration;
}
/** @return the duration of the entire animation, number of frames times frame duration, in seconds */
public float getAnimationDuration () {
return animationDuration;
}
根据我的理解,关键帧是从图像地图集中检索帧并根据时间改变它以产生运动的幻觉。
答案 0 :(得分:3)
使用以前版本的libgdx,即1.9.4。在libgdx版本1.9.5动画类中有一些更改,没有使用overlap2d快照版本更新,所以你遇到了问题。
降级根项目的build.gradle中的版本。希望它可能会有所帮助。
感谢。