For this assignment we will continue building our DisAsteroids computer game. The main goal will be to create a data structure to support a spaceship, asterioids, and an occasional alien or two. You will provide a paintComponent() callback routine that can draw all of these objects from your data structure. Your program will need to create a main window and a canvas window for drawing.
Since all objects share these commonalities, it makes sense to create
an abstract base class to represent them. This base class should have
a constructor to set the initial position and velocity, and it should
have an abstract draw() method that takes a
Graphics2D object as a parameter.
Spaceship Subclass: Next, create a class for your spaceship.
This class will extend the GameElement base class and may
add some additional instance variables (such as "lives"
remaining). The Spaceship class should override the superclass's draw
routine and should have a constructor that specifies initial values
for its instance variables.
Asteroid Subclass: Create a subclass to represent an asteroid. Override the draw method and add some additional instance variables for things like size and color.
Alien Subclass: Create a subclass to represent alien spaceships that occasionally fly across the screen and shoot at your spaceship.
You will want to provide some sort of data structure (a list or an
array should suffice) that will store all of the game objects. This
data structure should use references to the GameElement
base class rather than to specific subclasses. Your
Game.paintComponent() method will then simply cycle
through the list and ask each object to draw itself in turn.
All drawing must be done inside the paintComponent() callback, which may be called at any time. For example, it will be called when the window is exposed or resized; it may also be triggered manually when the state of the game changes due to a user command. Your routine should always be prepared to draw the game from scratch, using data you have stored inside your objects.
Your game should be playable using keyboard keys. These can be the arrow keys, alphanumeric keys, or any other plausible set of keys. For this assignment, choose a set of keyboard keys to control the spaceship (rotate in place left or right, accelerate, decelerate, fire a bullet, and warp to a random location on the screen). Be sure to document these keys in your readme file. Create a keyboard listener that updates the spaceship and then redraws the drawing area when any of your keys are pressed.
As discussed in class, note that getting keyboard events in the canvas window requires some extra programming, especially if you have any other widgets or panels beside the canvas. You need to make sure your canvas area, rather than some other widget, has the keyboard "focus" in order to receive keyboard events. To do this, create a mouseEntered() [or mousePressed()] callback for your canvas, and, each time it is called, it should call YOUR_CANVAS.requestFocus(). This will assign the keyboard focus to the canvas each time the mouse enters it [or clicks in it]. You can also use a FocusListener.
Your main program, which is a public static method in your class called Main, should simply instantiate an object of class Main. Your constructor for Main will then set up your window, instantiate and initialize the objects you need, such as the Game object (which in turn instantiates the spaceship, asteroids, and aliens), show the window, and then let the window system take over and wait for callbacks. The window should close and the application should quit when a user clicks on the close icon (the "X" in the far upper-right corner of the window title bar).
Once the program is running, it will simply display the drawing area, redrawing it as necessary, and waiting for callbacks from user input on the keyboard.
Your program design should exploit the features of object-oriented programming (encapsulation of code and data, support for abstract data types, polymorphism/overloading, inheritance). In particular, object-oriented programming provides us a good way to handle the various data needed in callback routines. You should use objects to encapsulate each interactive widget with the routines and data you need to use it.
You should provide an object for each interactive widget or small group of widgets you create. That object should hold anything you need to remember about the widget from one callback to another, all the data pertinent only to the command for that widget or that you need to operate this control, (including, in most cases, a pointer to the graph or other outside object to perform the actual action the user requested), and the widget's own listener callback routines.
If you have several widgets that share some behavior or properties, you should organize your objects into an appropriate inheritance hierarchy.
You will have other data that must be accessed by several widgets, particularly shared information about the state of the program or global information about the state of the user interface. Provide additional classes and objects for holding this kind of information.
Remember to trigger your drawing to repaint itself explicitly whenever one of your commands causes a change in the state of the graph that should be reflected on the screen. And remember that the way to change the screen is first to change the data stored in the Graph or other classes and then to trigger the repaint.
You should follow these general Java programming practices:
And, finally, for uniformity please name your Java class that has your main program in it Main, in file Main.java
ownwhich other objects)
usesor collaboration relationships (which objects use which other objects to perform functions)
secretsof each of your classes (i.e., what design decisions are entirely encapsulated within that class).
Submit this documentation electronically in text form. Include it as part of the readme file that you submit with your assignment.
These diagrams may be trivial for this assignment, but will become more interesting with later assignments.
As in the previous assignment, note that creating excellent, nontrivial software requires creativity beyond what your customers, or professor, can explicitly mandate. In general, great software satisfies a set of general requirements or requests, and then adds something beyond that. Grading for the assignments will reflect this fact. Satisfying exactly the bare minimum for each assignment will merit a grade of approximately 75% or 85%, depending on the specific assignment. The remaining points will be awarded for additional work that adds the special something. This is not necessarily easy to do. You will be both the software designer and the software developer in this course. It's not just the implementation that is important, but also the design of the application. If you do this, include a brief description in your readme file, as noted in the submission instructions.