I recently picked up libgdx and I'm obsessed. So far it's been smooth sailing until I've tried to implement an explosion animation based on an event. The game I'm developing is a simple space asteroid shooter, my method currently is checking for a bullet hit on an asteroid, creating a new explosion object, then rendering with that objects coordinates using an iterator. I've read that you have to set runTime to 0 after the animation is finished so the animation will restart. However I'm continually getting only the last frame, and then it disappears because I remove my explosion object based on the animation being finished. So it is being removed on time correctly, however the animation does not start on the right frame. Can anyone give me some insight?
Here is my PlayScreen class which uses a PlayRenderer and a PlayWorld, (PlayRenderer rendering our objects, PlayWorld containing our objects and updating accordingly)
public class PlayScreen implements Screen {
private Game game;
private PlayWorld world;
private PlayRenderer renderer;
private float runTime;
public PlayScreen(Game game){
this.game = game;
world = new PlayWorld(game);
renderer = new PlayRenderer(world);
}
@Override
public void show() {
}
@Override
public void render(float delta) {
runTime += delta;
renderer.render(runTime);
world.update(delta);
}
PlayWorld class which is where I have collision detection contained
public class PlayWorld {
private Game game;
private Player player;
private Array<Bullet> bullets;
private Array<Explosion> explosions;
private ScrollBackground bg1, bg2;
private Crater crater1, crater2, crater3, crater4, crater5;
private float runTime;
public static float explosionX, explosionY;
public static boolean shot;
public PlayWorld(Game game){
this.game = game;
initPlayer();
initBackground();
initBullets();
initExplosions();
initCraters();
Gdx.input.setInputProcessor(new PlayHandler(player, bullets));
}
private void initPlayer(){
player = new Player(SSGame.GAME_WIDTH / 2 - 19, 500, 38, 34);
}
private void initBackground(){
bg1 = new ScrollBackground(0, 0, 25);
bg2 = new ScrollBackground(0, -640, 25);
}
private void initBullets(){
bullets = new Array<Bullet>();
}
private void initExplosions(){
explosions = new Array<Explosion>();
}
private void initCraters(){
crater1 = new Crater(50, -36, 31, 36);
crater2 = new Crater(100, -50, 31, 36);
crater3 = new Crater(170, -85, 31, 36);
crater4 = new Crater(250, -125, 31, 36);
crater5 = new Crater(75, -200, 31, 36);
}
public void update(float delta){
runTime += delta;
player.update(delta);
bg1.update(delta);
bg2.update(delta);
updateBullets(delta);
updateCraters(delta);
updateCollisions(runTime, delta);
updatePlayerCollisions();
}
private void updateBullets(float delta){
for(Iterator<Bullet> itr = bullets.iterator(); itr.hasNext();){
Bullet b = itr.next();
b.update(delta);
if(b.getY() < -17){
itr.remove();
}
}
}
private void updateCraters(float delta){
crater1.update(delta);
crater2.update(delta);
crater3.update(delta);
crater4.update(delta);
crater5.update(delta);
}
private void updateCollisions(float runTime, float delta){
for(Iterator<Bullet> itr = bullets.iterator(); itr.hasNext();){
Bullet b = itr.next();
if(b.getY() > 0){
if(b.getRect().overlaps(crater1.getRect())){
Explosion e = new Explosion(crater1.getX(), crater1.getY());
explosions.add(e);
itr.remove();
crater1.reset();
Bullet.score++;
}else if(b.getRect().overlaps(crater2.getRect())){
Explosion e = new Explosion(crater2.getX(), crater2.getY());
explosions.add(e);
itr.remove();
crater2.reset();
Bullet.score++;
}else if(b.getRect().overlaps(crater3.getRect())){
Explosion e = new Explosion(crater3.getX(), crater3.getY());
explosions.add(e);
itr.remove();
crater3.reset();
Bullet.score++;
}else if(b.getRect().overlaps(crater4.getRect())){
Explosion e = new Explosion(crater4.getX(), crater4.getY());
explosions.add(e);
itr.remove();
crater4.reset();
Bullet.score++;
}else if(b.getRect().overlaps(crater5.getRect())) {
Explosion e = new Explosion(crater5.getX(), crater5.getY());
explosions.add(e);
itr.remove();
crater5.reset();
Bullet.score++;
}
}
}
}
private void updatePlayerCollisions(){
if(player.getRect().overlaps(crater1.getRect())){
game.setScreen(new GameOverScreen(game));
}else if(player.getRect().overlaps(crater2.getRect())){
game.setScreen(new GameOverScreen(game));
}else if(player.getRect().overlaps(crater3.getRect())){
game.setScreen(new GameOverScreen(game));
}else if(player.getRect().overlaps(crater4.getRect())){
game.setScreen(new GameOverScreen(game));
}else if(player.getRect().overlaps(crater5.getRect())){
game.setScreen(new GameOverScreen(game));
}
}
public Player getPlayer(){
return player;
}
public ScrollBackground getBg1(){
return bg1;
}
public ScrollBackground getBg2(){
return bg2;
}
public Array<Bullet> getBullets(){
return bullets;
}
public Crater getCrater1(){
return crater1;
}
public Crater getCrater2(){
return crater2;
}
public Crater getCrater3(){
return crater3;
}
public Crater getCrater4(){
return crater4;
}
public Crater getCrater5(){
return crater5;
}
public Array<Explosion> getExplosions(){
return explosions;
}
And finally my PlayRenderer class which is passed runTime, which is = delta, this is where I believe the issue is, however I cannot figure it out, I've inserted a few print statements so someone may be able to put me on the right path
public class PlayRenderer {
private PlayWorld world;
//Objects
private Player player;
private ScrollBackground bg1, bg2;
private Array<Bullet> bullets;
private Array<Explosion> explosions;
private Crater crater1, crater2, crater3, crater4, crater5;
//Assets
private TextureRegion player_texture;
private TextureRegion background;
private TextureRegion bullet;
private TextureRegion crater;
private Animation explosion;
private Array<Animation> explosionAnimArray;
private BitmapFont font;
private float animTime;
private OrthographicCamera cam;
private SpriteBatch batch;
public PlayRenderer(PlayWorld world){
this.world = world;
initEquipment();
initAssets();
initObjects();
}
private void initEquipment(){
cam = new OrthographicCamera();
cam.setToOrtho(true, SSGame.GAME_WIDTH, SSGame.GAME_HEIGHT);
batch = new SpriteBatch();
batch.setProjectionMatrix(cam.combined);
}
private void initAssets(){
player_texture = AssetLoader.ship;
background = AssetLoader.bg;
bullet = AssetLoader.bullet_basic;
crater = AssetLoader.crater;
explosion = AssetLoader.explosion;
explosionAnimArray = new Array<Animation>();
font = AssetLoader.font;
}
private void initObjects(){
player = world.getPlayer();
bg1 = world.getBg1();
bg2 = world.getBg2();
bullets = world.getBullets();
crater1 = world.getCrater1();
crater2 = world.getCrater2();
crater3 = world.getCrater3();
crater4 = world.getCrater4();
crater5 = world.getCrater5();
explosions = world.getExplosions();
}
public void render(float runTime){
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderBackground();
renderBullets();
renderPlayer();
renderCraters();
renderExplosions(runTime);
renderFont();
}
private void renderPlayer(){
batch.begin();
batch.enableBlending();
batch.draw(player_texture, player.getX(), player.getY());
batch.end();
}
private void renderBackground(){
batch.begin();
batch.draw(background, bg1.getX(), bg1.getY());
batch.draw(background, bg2.getX(), bg2.getY());
batch.end();
}
private void renderBullets(){
for(Iterator<Bullet> itr = bullets.iterator(); itr.hasNext();){
Bullet b = itr.next();
batch.begin();
batch.draw(bullet, b.getX(), b.getY());
batch.end();
}
}
private void renderCraters(){
batch.begin();
batch.draw(crater, crater1.getX(), crater1.getY());
batch.draw(crater, crater2.getX(), crater2.getY());
batch.draw(crater, crater3.getX(), crater3.getY());
batch.draw(crater, crater4.getX(), crater4.getY());
batch.draw(crater, crater5.getX(), crater5.getY());
batch.end();
}
public void renderExplosions(float runTime){
for(Iterator<Explosion> itr = explosions.iterator(); itr.hasNext();){
Explosion e = itr.next();
batch.begin();
batch.draw(explosion.getKeyFrame(runTime), e.getX(), e.getY());
System.out.println("" + runTime);
batch.end();
if(explosion.isAnimationFinished(runTime)){
runTime = 0;
System.out.println("RUNTIME: " + runTime);
itr.remove();
}
}
}
private void renderFont(){
batch.begin();
font.setColor(Color.WHITE);
font.draw(batch, "" + Bullet.score, 300, 20);
batch.end();
}
}
Here are my print reports for debugging:
MAIN MENU
BEGIN
EXPLOSION
EXPLOSION
1.974246
RUNTIME: 0.0
0.0
1.9911842
RUNTIME: 0.0
EXPLOSION
EXPLOSION
4.626008
RUNTIME: 0.0
0.0
4.6428485
RUNTIME: 0.0
EXPLOSION
7.264123
RUNTIME: 0.0