I am currently working on a space invaders style game but I have run into a bit of trouble with multiple instances of bullets. At the moment I can only fire one. I have been trying to get it to work with an Array List but I just can't seem to get it to work. The closest I got I got it to working was, it fired multiple bullets but they all spawned from the same location as in the bullets didn't spawn in relation to the ships position. The game also crashed when I removed an object after it exceeded it's boundary. Can anyone help me to see where I am going wrong. Here is some code that I have so far the parts commented out are my attempts at getting the array list to work
import java.util.ArrayList;
import org.newdawn.slick.Input;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.GameContainer;
public class Player extends Entity
{
private int speed = 5;
private ArrayList<Bullet> bulletList;
private boolean firing;
private Bullet bullet;
public Player()
{
bullet = new Bullet();
//bulletList = new ArrayList<Bullet>();
this.setImage("ship");
this.setPosition(350,450);
this.setDimenseions(100, 100);
this.createRectangle();
}
@Override
public void entityLogic(GameContainer gc, int deltaTime)
{
Input input = gc.getInput();
if(input.isKeyDown(Input.KEY_A))
{
this.x -= speed;
}
if(input.isKeyDown(Input.KEY_D))
{
this.x += speed;
}
if(input.isKeyDown(Input.KEY_W))
{
this.y -= speed;
}
if(input.isKeyDown(Input.KEY_S))
{
this.y += speed;
}
if(input.isKeyPressed(Input.KEY_SPACE))
{
firing = true;
bullet.x = this.getX()+40;
//BulletList.add(new Bullet());
}
if(firing)
{
/*Carries out the logic for the bullet*/
//for(Bullet b : bulletList)
//{
//b.entityLogic(gc, deltaTime);
//}
//Moves the bullet negativly along the y axis
bullet.entityLogic(gc, deltaTime);
}
}
@Override
public void entityRendering(Graphics g)
{
g.drawImage(this.getImage(), this.getX(), this.getY());
if(firing)
{
/*Draws each bullet object in the list*/
//for(Bullet b : bulletList)
//{
//b.entityRendering(g);
//}
bullet.entityRendering(g);
}
}
}
First of all forget about your Bullet bullet
instance variable. You don't need it, the list is enough.
Another thing is that you could use a LinkedList
instead that an ArrayList
because you don't need random access and you have to add and remove items frequently, when you iterate over bullets to check for collision use a ListIterator<T>
and remove them on the fly.
Finally it should be something like:
List<Bullet> bullets = new ArrayList<Bullet>();
public void entityLogic(GameContainer gc, int deltaTime) {
// since this method is called many times you should shoot a bullet just every X msec
if (spacebar pressed) {
// you spawn a new bullet according to player position
Bullet bullet = new Bullet(player.x,player.y);
// you add it to the list
bullets.add(bullet);
}
// destroy bullets which are outside the viewport
for (int i = 0; i < bullets.size(); ++i) {
Bullet bullet = bullets.get(i);
if (bullet.isOutsideBounds()) {
bullets.remove(i);
i--;
}
}
public void entityRendering(Graphics g) {
for (Bullet bullet : bullets)
bullets.entityRenering(g);
}
}
This is just to give you the basic idea.
I don't know slick2d and how it manages the rendering and logic threads, if they are two different threads then you should use a syncronized list, eg:
List<Bullet> bullets = Collections.synchronizedList(new ArrayList<Bullet>());