Congratulations on making it this far. Really, you have accomplish a great feat. The final test of how far you have come is for you to build your first graphical user interface game in Java. I have developed the entire game for you, and in this chapter, I will touch on the purpose of each class. With that knowledge, you will be able to reconstruct the entire project from the ground up.
Building a Fighting Game with a GUI
If you remember the game we discussed in the Abstract Classes & Interface chapter, you will be glad to know we are using the character classes we created then in our game. We are going to mimic the “Conquer” MMORPG game. In Conquer, each character has a name, some set of special skills, a pet, health, attack power, defense power, and the ability to speak. Also, each user can select the type of character they want to be. However, there are two types of characters and users can only choose to be a Human character. A Human character can then have a Pet character. Each character battles until there’s a winner. Our game will emulate all of this.
Because we make use of polymorphism, the model-view-controller programming pattern, and interfaces, the application is quite easy to navigate. I have documented the source code of this project in great detail by commenting virtually every line of code and providing javadocs for each method, class, and interface. With that said, I will not spend much time explaining the intricacies of the project’s code base in this chapter.
The package for this chapter’s supporting code is called “buildingAGame”. Please have it open as we walk through it to at a high level to understand what’s going on. Lets take a look at the fourteen classes and one interface of our game and walk through each class to see how we apply all of the knowledge we’ve accumulated in this book.
The most important part of our game are the characters because there wouldn’t be much action without them. Every player in the game is a character, so we have a Character interface. Any class that intends to create a template for constructing characters that can play in our game must implement our Character interface. To make that implementation easier, we have an abstract AbstractCharacter class which implements the most general methods of the Character interface.
The AbstarctCharacter class must be extended by any class that intends to create a template for constructing characters that can play in our game. The AbstractCharacter class implements all but two of the methods from the Character interface. That means that any class that extends our AbstractCharacter class only has to implement the attack() and train() instance methods from the Character interface. We have left those two methods for subclasses to implement because it is intuitive that different types of characters attack and train in distinct ways: an Archer attacks with arrows, a Warrior attacks with a sword, and a Taoist attacks with magic. While each character has different defensive powers, they all defend the same way — perhaps by holding up their weapon to block an oncoming attack. Furthermore, there are two base types of characters and they are vastly different. For that reason, we have two more abstract classes that extend the AbstractCharacter class.
For our human characters, the ones users can choose to be, we have the abstract Human class from which all classes that intend to create a template for constructing human characters must extend. The Human class is one of two methods that directly extend the AbstractCharacter class. Human characters can have pets and human friends. Aside from that, a human character is much like any other character. For that reason, the only fields distinct to the Human class are a Pet instance field to hold an instance’s pet and a final LinkedList of Human objects for an instance to accumulate friends. The list of friends is final because we want our Human instances to always have a list of friends; it can never be set to null or replaced by accident. The two distinct functions of the Human class have to do with setting and getting friends and a pet. The Archer, FireArcher, Warrior, and Taoist are concrete classes that extend the Human class. Its also important to note that the FireArcher is a special type of archer that extends the Archer class. Its only distinction is its additional firePower instance field which adds to its attack power.
The abstract Pet class is the other class that directly extends the AbstractCharacter class. All classes that intend to create a template for constructing pet characters must extend to be a valid playing character in our game. The pet class’s only distinct field is a Human instance field for storing the owner of an instance. Its only distinct method is its cry() instance method which is an interface for all pets to make their special sound; a Dog can bark and a Lion can roar by invoking cry(). The Dog and Lion concrete classes are currently the the only classes that extend the Pet class.
The game is simple. The user chooses a maximum number of battles for the players to engage in. Each time the user clicks “Next Battle”, the next battle starts between two characters — a random attacker and a random defender. The attacker tries to inflict damage on the defender and only succeeds if the defender has less defensive power than the attacker’s attack power. Whoever wins the battle gains experience. To gain experience for an action, a character must call the gainExperience() instance method and provide a string representing the action they’ve completed as an argument. The action will be used as a key to get the corresponding amount of experience to gain from the AbstractCharacter class’s actionExperiences static HashMap field. That way, all characters get the same amount of experience for completing the same actions.
The last man standing is the winner of the game. The game has an String array which holds the history of winners from each game. A user can only play a maximum of one hundred games each time he or she launches our application because our history array has a fixed length of a one elements. This is simply to illustrate a use of an array and can be changed to a LinkedList if you want to allow users to play your game as many times as they want. Lastly, the game has a graphical user interface (GUI) which it has to set up once each time our application is launched.
The GUI is what allows a Game instance to display real time information about the state of the game and its players to the user; our GameGUI class is used by the Game class to achieve that purpose. As noted before, each Game instance must have an instance of our GameGUI class in order to run. The GameGUI makes use of JavaFX, which allows developers to create desktop, mobile, and web applications nicer than ever before, to display information from an associated Game instance to the user in its views.
Our GameGUI is currently designed with three TextAreas for displaying information about the game and ongoing battles in the game, one TextField for capturing user input, one ListView for displaying the standings of all the characters in the game, a Button to stat the game, and two more buttons to advance through the game. Setting all of that up is a bit more involved, but you’ll be able to understand each part as you read the documentation in the code.
Our application runs on JavaFX components for its GUI and a nice abstract Application class provided by JavaFX for easily launching and starting a application program. Our GUIGameApplication class extends the JavaFX Application class and is at the root of our project. Its only duty is to hold the main method of our program. Its main method has a simple duty of calling the launch() instance method from the Application class. When that method is called, it will call the abstract start() instance method from the Application class to start our application. Our GUIGameApplication must implement that start() method which gives us access to the primaryStage Stage field of the application. We must provide the primaryStage reference to our Game, which will provide its instance of our GameGUI class to display the JavaFX GUI for our game.
And just like that, we are finished. You have learned so much about Java. In fact, you know everything you need to know to start building your own Java applications. Remember that the best way to learn is by doing and having fun while doing so. Your next steps are to play around with our game, take a look at each class in the supporting code for this chapter, read the documentation, and then try to write the entire project again. After that, try to build your own game or add to what we already have here. You are on your way. In the next chapter, we will take a look at some more fun projects we can take on to continue applying your new knowledge of Java programming.