GitHub:https://github.com/alex578344/RocketDefender.git
在我的渲染循环中,我迭代了一系列火箭,当我点击它们时,会显示一个爆炸动画。问题是动画太快了,然而我如何改变动画运行时的浮点值似乎仍然以相同的快速速度显示。
textureAtlas = new TextureAtlas(Gdx.files.internal("ExplosionAnimation.atlas"));
explosionA = new Animation(10f, textureAtlas.getRegions());
public void render(float runTime){
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
cam.update();
batch.setProjectionMatrix(cam.combined);
batch.begin();
//BATCH START
batch.draw(AssetLoader.background, 0, 0 , GWidth,GHeight);
for(Rectangle rocket : rockets) {
batch.draw(AssetLoader.rocket ,rocket.x, rocket.y,
rocket.width, rocket.height);
}
if (Gdx.input.justTouched()){
Vector3 v = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
v = cam.unproject(v);
tap_X = (int) v.x;
tap_Y = (int) v.y;
Gdx.app.log("MyTag", String.valueOf(tap_X));
Gdx.app.log("MyTag", String.valueOf(tap_Y));
}
Iterator<Rectangle> iter = rockets.iterator();
while(iter.hasNext()) {
Rectangle rocket = iter.next();
rocket.y -= 140 * Gdx.graphics.getDeltaTime();
if(rocket.y + 32 < 0) iter.remove();
if (rocket.x - 5 < tap_X && tap_X < rocket.x + rocket.width + 5) {
if (tap_Y > rocket.y - 5 && tap_Y < rocket.y + rocket.height + 5) {
batch.draw(AssetLoader.explosionA.getKeyFrame(runTime, false), rocket.x, rocket.y,
rocket.width, rocket.height);
iter.remove();
}
}
}
//BATCH END
batch.end();
if(TimeUtils.nanoTime() - lastDropTime > 1000000000) spawnRocket();
}
答案 0 :(得分:1)
问题是你只渲染一帧爆炸,然后立即从游戏中移除相应的矩形。就在这里:
if (tap_Y > rocket.y - 5 && tap_Y < rocket.y + rocket.height + 5) {
batch.draw(AssetLoader.explosionA.getKeyFrame(runTime, false), rocket.x, rocket.y,
rocket.width, rocket.height);
iter.remove();
}
另请注意,您不能简单地将runTime
用于所有爆炸动画,因为它们将彼此同步,如果它不是循环动画,那么在游戏中几秒后它们将会所有这些都只是永远显示动画的最后一帧。
您可以采取多种不同的方法来解决此问题。这是一个:
不使用Rectangle,而是使用像这样的Rectangle子类,它可以让你跟踪这个单独火箭的动画时间以及它是否已经爆炸:
public class Rocket extends Rectangle {
public boolean exploded = false;
public float explosionAge = 0;
public Rocket(float x, float y, float width, float height) {
super(x, y, width, height);
}
public Rocket(Rectangle rect) {
super(rect);
}
}
所以你将为所有火箭队使用这个级别而不是Rectangle。将您的rockets
数组更改为<Rocket>
类型。
然后在你的循环中,而不是在点击时绘制和移除火箭,只需将其翻转为exploded
布尔值。然后对于爆炸火箭,您可以增加它们的年龄,绘制动画,并在动画完成后将其移除。 (我在这里假设一个非循环动画。)
此外,删除绘制所有火箭的循环。我们将绘制步骤移动到底部循环中,因此它可以决定是绘制普通火箭还是爆炸:
float deltaTime = Gdx.graphics.getDeltaTime();
Iterator<Rocket> iter = rockets.iterator();
while(iter.hasNext()) {
Rocket rocket = iter.next();
rocket.y -= 140 * deltaTime;
if (!rocket.exploded){
if(rocket.y + 32 < 0) {
iter.remove();
continue;
}
if (rocket.x - 5 < tap_X && tap_X < rocket.x + rocket.width + 5) {
if (tap_Y > rocket.y - 5 && tap_Y < rocket.y + rocket.height + 5) {
rocket.exploded = true;
rocket.explosionAge = -deltaTime; //This is so the first frame will start from 0, since deltaTime is added before it's drawn below
}
}
}
if (rocket.exploded){
rocket.explosionAge += deltaTime;
if (rocket.explosionAge > AssetLoader.explosionA.getAnimationDuration()){
iter.remove();
continue;
}
batch.draw(AssetLoader.explosionA.getKeyFrame(rocket.explostionAge, false),
rocket.x, rocket.y, rocket.width, rocket.height);
} else {
batch.draw(AssetLoader.rocket,
rocket.x, rocket.y, rocket.width, rocket.height);
}
}
上面的示例是对当前代码的最小更改。但实际上我会建议不要混淆游戏世界更新和渲染。如果您需要更改某些行为,则会更难调试并找到代码。相反,我会使用update
方法来更新火箭的位置及其爆炸状态,并使用单独的draw
方法来简单地绘制它们。