4

I am currently building a 2D Asteroid game using Java and Codename One with a heavy focus on OOP patterns. I'm having trouble, however, trying to dynamically create new objects (in my case the Object I want to add is a superclass GameObject) to add to an ArrayList. As you can see in void init() method of GameWorld.java, I created a list that holds types of GameObject which include subclasses of Asteroids, Ships, Spacestations.

The program asks for a command keyboard input in the class such as 'a', which is then supposed to add a new Asteroid (subclass of GameObject) object into the ArrayList. The user should be able to add as many Asteroids as they want to allocate to the ArrayList.

My question is: How do I do this without already declaring a variable called AsteroidTest of type Asteroid like I have currently been doing in my addAsteroid() function of the class GameWorld? Thanks!

GameWorld.java

package com.mycompany.a1;

import java.util.ArrayList; //For ArrayList Usage

public class GameWorld {

public void init() {
    ArrayList<GameObject> list = new ArrayList<GameObject>();
}
//other methods here to manipulate Game objects and data
public void addShip() {
    Ship ShipTest = new Ship();  

    list.add(ShipTest);

    System.out.println(ShipTest.getLocation());
}

public void addAsteroid(){
    Asteroid AsteroidTest = new Asteroid();

    list.add(AsteroidTest);


    System.out.println(AsteroidTest.getLocation());
}


public void addSpaceStation(){

}
}

Game.java

package com.mycompany.a1;

import com.codename1.ui.events.ActionListener;
import com.codename1.ui.Label;
import com.codename1.ui.TextField;
import com.codename1.ui.events.ActionEvent;
import java.lang.String;
import com.codename1.ui.Form;

public class Game extends Form{
private GameWorld gw;

public Game (){
    gw  = new GameWorld();
    gw.init();
    play();

}

private void play(){

    Label myLabel=new Label("Enter a Command:"); this.addComponent(myLabel);
    final TextField myTextField=new TextField();
    this.addComponent(myTextField);
    this.show();
    myTextField.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent evt) {
            String sCommand=myTextField.getText().toString();
            myTextField.clear();
            switch (sCommand.charAt(0)){
            case 's':
                gw.addShip();
                break;
            case 'a':
                gw.addAsteroid();
                break;
            case 'b':
                gw.addSpaceStation();
                break;
            //add code to handle rest of the commands
            } //switch
        } //actionPerformed
    } //new ActionListener()
            ); //addActionListener
    } //play
  //code to enter text field and receive keyboard input 
}

GameObject.java Superclass. Subclasses include Asteroids, Ships, Missles, SpaceStation

package com.mycompany.a1;

public abstract class GameObject {
private double x;
private double y;

public GameObject(){
    x = 0;
    y = 0;
}

public double getX(){
    return x;
}

public void setX(double newX){
    x = newX;
}

public double getY(){
    return y;
}

public void setY(double newY){
    y = newY;
}

public String getLocation(){
    return "(" + x + ", " + y + ")";

 }
}

Asteroid.java

 package com.mycompany.a1;

 import java.util.Random;

 public class Asteroid extends MovableObject {

 private Random rand = new Random();


 public Asteroid() {
    setX(rand.nextInt(1023) + rand.nextDouble());

    setY(rand.nextInt(767) + rand.nextDouble());// TODO Auto-generated 
  constructor stub
  }

 }
Oguz
  • 1,867
  • 1
  • 17
  • 24
Ben Yan
  • 61
  • 1
  • 9
  • 1
    `list.add(new Asteroid());` – Kevin Anderson Sep 29 '17 at 01:39
  • @KevinAnderson Wow is it really that simple? I'm also getting an error for the ArrayList list variable. The error says that "the value of local variable list is not used". – Ben Yan Sep 29 '17 at 01:54
  • It should be saying that `list` is not defined. You defined `list` locally in the `init()` method, but that definition isn't visible outside of `init()`. You want `list` to be defined as a member variable of your class. If you don't understand why, the topic you need to study is "scope of variables". – Kevin Anderson Sep 29 '17 at 02:07
  • Ahh I don't know why I defined list in that method, I declared it as a member variable of the class and everything works now. Thanks so much Kevin wish I could upvote you! – Ben Yan Sep 29 '17 at 02:27

1 Answers1

1

It is quite simple:

public void addAsteroid(){
  this.list.add(new Asteroid());
}

but if you want to print location, you must do it while the new asteroid is created, so in the constructor:

public GameObject(){
  x = 0;
  y = 0;
  System.out.println("(" + x + ", " + y + ")");
}

Moreover:

  • declare ArrayList<GameObject> list as List<GameObject> to use abstraction NOT specific implementation
  • declare List<GameObject> list as private field in GameWorld class
  • consider to work with constructor rather then with public void init()
  • in case of concurency problems, use java.util.concurrent.CopyOnWriteArrayList<E> instead of traditional List
  • consider to use second constructor in GameObject that handles creation of an object with initaial cordinates + remove setX and setY methods + introduce moveTo(double x, double y) method to be more clear with intentions
  • @maciejlesiak Thank you for the advice! I don't understand your first point however; what is the exact adantange of utilizing List as opposed to using the ArrayList List? And I will definitely add the second constructor for the X and Y coordinates that is a much smarter than what I currently have. – Ben Yan Oct 11 '17 at 04:53
  • It is common practice to use abstractions (interfaces, abstract classes etc) rather than specific implementation as a variable type. That way, you can hide implementation (so client of your class does not care if you are using ArrayList or LinkedList or other List in the implementation). What is most important that you use some list, that's why there should be an interface. If you want to read more about it, please refer to SOLID principles, specially DIP https://en.wikipedia.org/wiki/Dependency_inversion_principle – maciejlesniak Oct 12 '17 at 22:04