# “Destroy the Asteroid” Game

I made this game for my computer science class.

Here is my professor's requirements:

1. Write a Processing program that draws a triangle in the middle of the window.
2. Rotate the triangle when the left and right arrow keys are pressed using the translate and rotate methods.
3. When the spacebar is hit, create a torpedo that appears to shoot out one of the vertices of the triangle. Note: if you do not want a continuous stream of torpedoes generate when the space bar is held down, you can use the PApplet’s keyReleased method instead of the keyPressed method.
4. Create some number of large ellipses to represent asteroids. Have the asteroids move in random directions around the window, wrapping around when they cross one of the window’s boundaries.
5. Have the torpedoes destroy the asteroids when they collide. (Using an ellipse for the torpedo will probably make the collision detection easier.) When the asteroids are destroyed, create a Particle System centered at the center of the asteroid to make it look like there was an explosion.
6. Keep track of points based on the number of asteroids destroyed and display the total points in the window.
7. When an asteroid collides with the spaceship, destroy the spaceship and create a Particle System at the center of the colliding ship.
8. Include a button to restart the game when the spaceship is destroyed.

What kind of improvement should I make?

Main:

import java.util.ArrayList;
import java.util.Iterator;
import processing.core.PApplet;

public class spaceMain extends PApplet {

ArrayList<Torpedoes> TorpedoesList = new ArrayList<Torpedoes>();
ArrayList<Asteroids> AsteroidsList = new ArrayList<Asteroids>();
ArrayList<ParticleSystems> theList = new ArrayList<ParticleSystems>();
ArrayList<Asteroids> smallList = new ArrayList<Asteroids>();

float width = 1000;
float height = 600;
float angle;
float numAsteroids = 10;
float rXPos;
float rYPos;

int score;

boolean sAlive = true;
boolean gameIsOver = false;

SpaceShip theSpaceShip;

public void setup(){
initializeGame();
textSize(26);
}//end set up

public void initializeGame(){
angle = 0;
score = 0;
rXPos = 440;
rYPos = 140;

theSpaceShip = new SpaceShip(0, 0,angle);

while(AsteroidsList.size() < numAsteroids){
Asteroids theAsteroid = new Asteroids(random(0,1000), random(0,600),random(50,80));
while(theAsteroid.getXPos() > width/2 - 100 && theAsteroid.getXPos() < width/2 + 100 ){
theAsteroid = new Asteroids(random(0,1000), random(0,600),random(50,80));
} //end while
}//end while

Iterator<ParticleSystems> Piterator = theList.iterator();
while(Piterator.hasNext()){
Piterator.next();
Piterator.remove();
}//end while

sAlive = true;
gameIsOver = false;

}//end initializeGame

public void draw(){

background(19,19,70);

if(gameIsOver){
text("You Lose !", 450, 100);

Iterator<Asteroids> Asiterator = AsteroidsList.iterator();
while(Asiterator.hasNext()){
Asiterator.next();
Asiterator.remove();
}//end while

Iterator<Torpedoes> Toiterator = TorpedoesList.iterator();
while(Toiterator.hasNext()){
Toiterator.next();
Toiterator.remove();
}//end while

fill(0,255,0);
rect(rXPos,rYPos, width/6, height/10);
fill(0,0,0);
text("Start again?",450,180);
}else {
text("score :" +score, 200,200);
}//end else if

fill(127,127,127);
pushMatrix();
translate(width/2, height/2);
rotate(angle);
if(sAlive){
theSpaceShip.display(this);
}//end if
popMatrix();

for(Torpedoes theTorpedo: TorpedoesList){
theTorpedo.display(this);
theTorpedo.shootOut();
}//end for

for(Asteroids theAsteroid: AsteroidsList){
theAsteroid.display(this);
theAsteroid.aMove();
}//end for

for(ParticleSystems theParticleSystem: theList){
theParticleSystem.display(this);
theParticleSystem.update();
}//end for

destroySpaceShip();
destroyAsteroid();

}//end draw

public void keyPressed(){
if(key == ' '){
}else if(key == CODED){
if(keyCode == LEFT){
angle = angle - (float)0.2;
} else if(keyCode == RIGHT){
angle = angle + (float)0.2;
}//end if
}//end else if
}//end keyPressed

public void destroySpaceShip(){

for(Asteroids theAsteroid: AsteroidsList){
if(distance(theAsteroid.getXPos(), theAsteroid.getYPos(), width/2, height/2) <= theAsteroid.getLength() ){
sAlive = false;
gameIsOver = true;
}//end if
}//end for
}//end destroySpaceShip

public void destroyAsteroid(){

Iterator<Torpedoes> Titerator = TorpedoesList.iterator();
while(Titerator.hasNext()){
Torpedoes theTorpedo = Titerator.next();
Boolean collided = false;

Iterator<Asteroids> Aiterator = AsteroidsList.iterator();
while(Aiterator.hasNext()){
Asteroids theAsteroid = Aiterator.next();
if(distance(theAsteroid.getXPos(), theAsteroid.getYPos(), theTorpedo.getXPos(), theTorpedo.getYPos()) <= 50){
score = score + 1;
Aiterator.remove();
collided = true;
}//end if
}//end while

if(collided){
Titerator.remove();
if(TorpedoesList.size() < numAsteroids){
for(int i=0; i<1; i++){
Asteroids theAsteroid = new Asteroids(random(0,1000), random(0,600),random(50,80));
while(theAsteroid.getXPos() > width/2 - 200 && theAsteroid.getXPos() < width/2 + 200){
theAsteroid = new Asteroids(random(0,1000), random(0,600),random(50,80));
} //end while
}//end for
}//end if
}//end if
}//end while

}//end destroyAsteriods

float distance(float Ax, float Ay, float Tx, float Ty){
return sqrt(sq(Ax-Tx) + sq(Ay-Ty));
}//end distance

public void mousePressed(){
if(gameIsOver && mouseX <= rXPos+width/6 && mouseX >= rXPos && mouseY <= rYPos+height/10 && mouseY >= rYPos){
initializeGame();
}//end if
}//end mousePressed

public void settings(){
size(1000,600);
}// end settings

public static void  main(String[] args){
PApplet.main("spaceMain");
}//end run processing
}//end class


SpaceShip:

import processing.core.PApplet;

public class SpaceShip {

float xPos;
float yPos;
float angle;

SpaceShip(float xInit, float yInit, float aInit){
xPos = xInit;
yPos = yInit;
angle = aInit;
}//end constructor

void display(PApplet proc){
proc.triangle(xPos+50, yPos, xPos-50, yPos-50, xPos-50, yPos+50);
proc.fill(127,127,127);
proc.stroke(127,127,127);
}//end of display

void up(){
xPos = xPos + (float)Math.cos(angle)*10;
yPos = yPos + (float)Math.sin(angle)*10;
}//end up

void down(){
xPos = xPos - (float)Math.cos(angle)*10;
yPos = yPos - (float)Math.sin(angle)*10;
}//end down

float getXPos(){
return xPos;
}//end getxPos

float getYPos(){
return yPos;
}//end getyPos
}//end spaceship class


Torpedoes:

import processing.core.PApplet;

public class Torpedoes {
float xPos;
float yPos;
float angle;

float xDir;
float yDir;

Torpedoes(float xInit, float yInit, float aInit){
xPos = xInit;
yPos = yInit;
angle = aInit;
xDir = (float)Math.cos(angle);
yDir = (float)Math.sin(angle);
}//end constructor;

void display(PApplet proc){
proc.fill(255,0,0);
proc.pushMatrix();
proc.translate(xPos, yPos);
proc.rotate(angle);
proc.ellipse(0, 0, 40,20);
proc.popMatrix();

}//end display

void shootOut(){
xPos = xPos + 4*xDir;
yPos = yPos + 4*yDir;

}//end shoot out

float getXPos(){
return xPos;
}//end getxPos

float getYPos(){
return yPos;
}//end getyPos

}//end classTorpedoes


Asteroids:

import processing.core.PApplet;

public class Asteroids {

float xPos;
float yPos;
float length;

float xDir = (float)Math.random()*2-1;
float yDir = (float)Math.random()*2-1;

int red;
int green;
int blue;

boolean alive = true;

Asteroids(float xInit, float yInit, float lInit){
xPos = xInit;
yPos = yInit;
length = lInit;
}//end constructor

void display(PApplet proc){
proc.fill(230,230,20);
proc.stroke(230,230,20);
proc.ellipse(xPos, yPos, length,length);
}//end display

void aMove(){
xPos = xPos + 2*xDir;
yPos = yPos + 2*yDir;

if(xPos < 0 || xPos > 1000){
xDir = - xDir;
}//end if

if(yPos < 0 || yPos > 600){
yDir = - yDir;
}//end if
}//end aMove

float getXPos(){
return xPos;
}//end getxPos

float getYPos(){
return yPos;
}//end getyPos

float getLength(){
return length;
}//end getLength

}//end class


Particles:

import processing.core.PApplet;

public class Particles {

float xPos;
float yPos;

float xDir;
float yDir;

float lifeSpan = 255;

Particles(float xPosInit, float yPosInit, float xDirInit, float yDirInit){
xPos = xPosInit;
yPos = yPosInit;
xDir = xDirInit;
yDir = yDirInit;
}//end constructor

void update(){
xPos = xPos + xDir;
yPos = yPos + yDir;
lifeSpan = lifeSpan - 3;
}// end update

void display(PApplet proc){
proc.fill(255,0,0, lifeSpan);
proc.stroke(255,0,0, lifeSpan);
proc.ellipse(xPos, yPos, 5, 5);
}//end display

boolean isAlive(){
return (lifeSpan > 0);
}
}//end class


ParticleSystems:

import java.util.ArrayList;
import java.util.Iterator;

import processing.core.PApplet;

public class ParticleSystems {
ArrayList<Particles> particlesList = new ArrayList<Particles>();

float xOrigin;
float yOrigin;
int numParticles;

ParticleSystems(float xInit, float yInit, int numInit){
xOrigin = xInit;
yOrigin = yInit;
numParticles = numInit;

while(particlesList.size() < numParticles){
}//end while
}//end construction

(float) Math.random()*2 -1,(float) Math.random()*2 -1));

void display(PApplet proc){
for(Particles theParticle: particlesList){
theParticle.display(proc);
}//end for
}//end display()

void update(){
Iterator <Particles> piterator = particlesList.iterator();

int index = particlesList.size()-1;
while(index >= 0){
Particles theParticle = particlesList.get(index);
theParticle.update();
if(! theParticle.isAlive()){
particlesList.remove(index);
}//end if
index--;
}//end while
}//end update

}//end class


# Formatting & look:

## Use proper access modifiers

All you methods and fields use the default package level visibility. Decreasing the scope of items to the lowest possible scope is recommended for clearer code. This is as simple of marking you methods and fields private or public where needed.

## Start field/variable names with a lowercase letter

ArrayList<Torpedoes> TorpedoesList = new ArrayList<Torpedoes>();
ArrayList<Asteroids> AsteroidsList = new ArrayList<Asteroids>();
...
Iterator<Torpedoes> Titerator = TorpedoesList.iterator();
...
Iterator<Asteroids> Aiterator = AsteroidsList.iterator();


ArrayList<Torpedoes> torpedoesList = new ArrayList<Torpedoes>();
ArrayList<Asteroids> asteroidsList = new ArrayList<Asteroids>();
...
Iterator<Torpedoes> tIterator = torpedoesList.iterator();
...
Iterator<Asteroids> aIterator = asteroidsList.iterator();


## Marking fields final when they are write once

ArrayList<Torpedoes> TorpedoesList = new ArrayList<Torpedoes>();
ArrayList<Asteroids> AsteroidsList = new ArrayList<Asteroids>();
ArrayList<ParticleSystems> theList = new ArrayList<ParticleSystems>();
ArrayList<Asteroids> smallList = new ArrayList<Asteroids>();
...
ArrayList<Particles> particlesList = new ArrayList<Particles>();


By marking fields final, you cover the meaning that they should be edited using the methods only, as opposite to reinitiating them.

public class spaceMain extends PApplet {
...
PApplet.main("spaceMain");


A common practise is to start class names with uppercase letters

# Logic issues

## Manual clearing of Collection

        Iterator<Asteroids> Asiterator = AsteroidsList.iterator();
while(Asiterator.hasNext()){
Asiterator.next();
Asiterator.remove();
}//end while

Iterator<Torpedoes> Toiterator = TorpedoesList.iterator();
while(Toiterator.hasNext()){
Toiterator.next();
Toiterator.remove();
}//end while


The above can be made smaller using:

AsteroidsList.clear();
TorpedoesList.clear();


## Updating in the draw loop

You are updating your entities in your main draw loop, this will cause jitter in the movement of the entities as they are affected by the main fps.

## Don't use boxed objects if unboxed exist

Boolean collided = false;


When using boolean with a uppercase letter, you are boxing the results, this means that a object is used instead a primitive. Using objects is slower than primitives, and should be avoided.

## Distances should be compared using the squared version

            if(distance(theAsteroid.getXPos(), theAsteroid.getYPos(), width/2, height/2) <= theAsteroid.getLength() ){
...
if(distance(theAsteroid.getXPos(), theAsteroid.getYPos(), theTorpedo.getXPos(), theTorpedo.getYPos()) <= 50){


Doing number * number is a cheap operation, doing sqrt(number) is a heavy operation. Avoid sqrt in favor of pow.