Description

I have created a video game called DragonFlier. In it, you’re a dragon flying around trying to collect eggs when they are ripe (don’t eat them too early or they’re poisonous and you’ll lose some life!). (The eggs start out white but when they’re dark blue with a red dot, they’re ready to eat.) If you eat the egg when it’s ripe, you get one point. If you wait too long, the eggs hatch into creatures that will try to bite you. You can try to shoot the creatures, but your fireball takes a few seconds to recharge, so if you’ve fired it recently, you’ll only shoot out little harmless puffs of smoke for a while. Right now there are 12 eggs hidden in the caverns, so the maximum points you can get is 12. (Though to get them all, you’ll have to find them and figure out the right order to collect them!) You can press R to restart.

Imagine that you have just been hired at the company that makes this video game, and they want you to make some improvements to it.

Your assignment here is this:

  1. Read through all the classes and try to understand the game. That’s part of the assignment and it mimics how you might be expected to pick things up if you ever were hired as a programmer. There may be programming concepts we haven’t directly covered in class. Sometimes you might have to try to look things up that you don’t understand. (Though I’ve tried to be good about my comments to make it clear for you. Hopefully, you see the importance of good comments!)
  2. The game requires a generic ArrayList class, but you’re not allowed to use Java’s built-in ArrayList, so you’ll have to supply your own. Your ArrayList needs to be generic and implemented with a linked list. (If you see Java’s ArrayList being imported, you need to comment out that import statement.)
  3. The game currently does not display any instructions on how to play it. You’ll fix that. To that end, here’s what you’ll do:
    1. First, create a new class called MessageBox that extends the DragonGameShape class.
    2. The MessageBox class will be used for displaying a black rectangle with a yellow border on the screen with some white words inside of it. The yellow border should be 5 pixels thick. When it’s displayed, it shouldn’t block the life meter or score at the top, it shouldn’t cover the dragon, and it shouldn’t be right up against the side of the frame, but have a little buffer of maybe 20 pixels.
    3. The MessageBox will be ? the width of the frame, and 80% of its height. So you’ll have to pass in info about the current frame width and height to the MessageBox’s constructor. (Don’t hardcode the MessageBox’s width and height — what if someone changed the size of the frame?)
    4. A MessageBox object will need to have access to the dragon in order to know which way the dragon is facing so that it can display the box on the left or right side of the screen, so that it looks like the dragon is looking at the box. (Other classes, like the Fireball and Egg also have access to the dragon, so you can look at them for models.)
    5. The MessageBox will also have to be passed a message (a String) that it will display.
    6. Make sure that when the MessageBox is drawn on the screen, all the words (no matter what the words are) are displayed nicely (with a reasonable sized font), and not going off the edge of the MessageBox. You’ll have to write some method for wrapping the text. Make sure it doesn’t wrap text in the middle of a word.
    7. The MessageBox will have a Swing Timer (a Timer from the Swing graphics package) so that when it is displayed, the timer starts and when the timer is done, it stops displaying. How long should the timer be? Well, the average adult reads around 250 words per minute (around 4 words per second), so let’s set the timer so that it takes how many words are in the message and displays the message for (number of words / 4) seconds. (The Egg class and the Fireball class both use Swing Timers so you can see how they’re used there.) Don’t forget to have import javax.swing.Timer; at the top. (Hint: Java’s StringTokenizer class is useful for breaking up a String into words (tokens) and counting them. This class might also be useful for your text-wrapping method above.)
    8. There will also need to be another method in the MessageBox for turning the display on or off (and if you’re turning it off, then it also needs to stop the timer early if the timer is going). (Why do you need this method? See below: the DragonFlier2 class will be modified so that when you press the ‘i’ button, you can turn on or off the display of instructions.)
    9. The MessageBox’s move() method will just change its x location based on which way the dragon is facing. (And make sure, in DragonFlier2, to call this move method at the same time you call all the other shapes’ move methods.)
    10. Your MessageBox class needs to have good comments — including JavaDoc comments for every method!
  4. Modify the DragonFlier2 class so that there is a MessageBox object that has the instructions for the game in it’s message. You’ll want this object to be a private instance variable of the GamePane class, like the dragon is.
    1. You’ll have to write these instructions out yourself. Make them clear, but succinct. Don’t just cut and paste what I wrote at the top of this document. Make sure it tells the users what the different buttons do.
  5. Modify the GamePane class so that when the user hits the ‘i’ key, this will display the MessageBox with the instructions (and it will display it to the left or right of the dragon, depending on what way the dragon is facing). Or, if the instructions are already being displayed, hitting the ‘i’ key will make the box go away (and will turn off its timer). You’ll have to look at how we bind particular keys to particular actions to see how to do this. (For example, typing the space bar causes the dragon to shoot a fireball (or a puff of smoke).)

UPLOAD a zip file containing ArrayList.java, MessageBox.java, your modified DragonFlier2.java, (and anything else that you made that is required to run the game.)

NOTE: This game is the intellectual property of me, David Nixon. Do NOT post it to the internet or your personal portfolio.

A zip file with all the classes (except for MessageBox, which you will create) and the images is here: DragonFlier For Students.zip

HINTS AND OTHER INFO:

  • A word about Swing Timers:
    • https://docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html (Links to an external site.) <– there’s the official documentation.
    • Swing is a package in Java that’s used to make applications with graphics and windows and such. There are lots of classes within the Swing package. But the class we’re interested in here is the Timer class. We import it with import javax.swing.Timer;
    • (Note: don’t get confused with Java’s Timer class in the util package. That one gets imported with import java.util.Timer; But it works differently, so don’t import that one. We want the SWING timer.)
    • When you create a Swing Timer, you send its constructor two things: (1) an int with the number of milliseconds until the timer goes off, and (2) an ActionListener object (in other words, some object that implements the ActionListener interface.) If an object is an ActionListener, then it must have the ActionPerformed method (that’s the only method in that interface). When the timer goes off, then it will call the ActionListener’s ActionPerformed method.
      • Note: there are 1000 milliseconds in 1 second.
    • After you create the timer, then you must call the start() method to start it. (You can also call the stop() method to turn off the timer.)
    • If you want the timer to reset and start again after it goes off (for example, if you want something to keep happening every 10 seconds), then you can call .setRepeats(true) on your timer. The default is TRUE — repeating the timer when it’s done. So if you DON’T want the timer to keep repeating, you might need to call setRepeats(false).
    • Let’s talk about the ActionListener object that you pass in to the Timer’s constructor:
      • If you wanted to, you could define this object in its own class file, and name it whatever you want (so long as it says “implements ActionListener” at the top and it has an ActionPerformed method). Or you could just define it as an inner class of whatever class is creating the Timer. Sometimes you see people make the class that creates the Timer itself implement the ActionListener interface, so when they create the timer, the second parameter is just “this”. (That only works if there’s only one timer you want to create and hence you only need one ActionPerformed method to be called.) But, since we need multiple Timers, and since the ActionListener class is so small (it only needs one method, the ActionPerformed method) another approach (one that you’ll see me do several times in the DragonFlier program) is that when I create the timer, I create and define a brand new ActionListener object right there in the Timer constructor’s parameter list. So you’ll see something like:
      • Timer myTimer = new Timer(5000, new ActionListener() {….//all the code for the ActionListener class, in particular, its ActionPerformed method… });
        • Where you see the “new ActionListener() {….}” is where I am defining a new ActionListener class and creating a new instance of that class all in one fell swoop. It’s called an anonymous object because I never assign a variable name to it. — which is fine because I only need to use it this one time.
    • So, if you wanted to make a Timer that would print “Hello! The timer went off!” after 10 seconds, you could do something like this:

Timer myTimer = new Timer(10000, new ActionListener() {

public void actionPerformed(ActionEvent e) {

System.out.println(“Hello! the timer went off!”);

}

}

);

    • You don’t need to worry about the ActionEvent object inside the actionPerformed method, since the Timer will automatically call the ActionPerformed method and pass it the appropriate parameter.
  • Another hint (not about Swing Timers): Your messageBox’s draw() method is going to get continuously called, every 5 milliseconds.
    • (How do I know this? Because it should be called in the same method where background.draw() and fireball.draw() and dragon.draw() are called — in the paintComponent() method. And the paintComponent method is called by the repaint() method. And the repaint() method is called every 5 milliseconds by the timer in the GamePane’s constructor.)
    • So, if the messageBox’s draw method is going to get continuously called, but you only want it to draw the messageBox on the screen when the person presses the button, then you should have a variable in the messageBox called something like displayOn, and then in the draw method, you can check that variable and only draw when displayOn == true. Then when the person presses the button, it can toggle the displayOn variable.