CIS 1200

Homework 9: Make Your Own Game

Component Due Date
Project proposal Thursday, November 21st at 11:59 PM EST
Project code and README.txt Monday, December 9th at 11:59 PM EST
Game demo to your TA Reading Days / Final Exam Period
Note: No late submissions will be accepted for the project proposal or the project code and README.txt.

Assignment Overview

In this assignment, you will create your own game using the Java Swing GUI framework. Though you will choose the game and implement it from scratch, your implementation must be well designed and must integrate multiple programming concepts from this course. Use this project as a chance to show off everything you’ve learned and to build a significant application of your own design. You will demo your game and explain your design to one of your TAs in a one-on-one session.

Have fun doing this assignment! This has historically been students’ favorite project of CIS 1200, and you are more than welcome to go a little overboard if you choose. :-) Many students invent a totally new game as part of this project, and these are always a ton of fun to show off. (Conversely, it is totally fine not to go overboard!)

Here are some checkpoints for this assignment. This is the largest and most open-ended assignment, so try to do a little each day and start early!

  • Checkpoint 0: Read through this writeup and the rubric. Begin brainstorming games you’d like to create.

  • Checkpoint 1: Decide what game you will build and your four core game concepts. Begin writing your project proposal.

  • Checkpoint 2: Read through the starter code and understand how the sample games are implemented. Begin designing your game’s classes, methods, and data structures.

  • Checkpoint 3: Discuss any necessary changes from your project proposal with your TA (make sure to look through each concept you propose for any comments your TA leaves even if you get an 8/8 for your submission). Start implementing the methods and classes necessary to store your game’s state and the Swing components for the GUI.

  • Checkpoint 4: By now, you should have a functional GUI and a basic working game. Continue implementing the rest of your game features (e.g. file I/O, displaying instructions).

  • Checkpoint 5: Conduct final tests and check for any bugs. Don’t forget to write your README!

Project Requirements

You are completely free to either implement an existing game or come up with your own unique, super-duper awesome game.

No matter what kind of game you build, it must meet the following criteria:

  • Project Proposal [6%]. This proposal will lay out your plan for implementing your game. See below for more details.

  • README.txt and File Structure Screenshot [4%]. You will submit the README.txt document and a screenshot of your file structures along with your code, detailing your game and any changes you needed to make to your design. Make sure it’s consistent with your actual game. Your README should include the four concepts that you implemented. We provide a blank README for you to fill out in the starter code.

  • Instructions Window [4%]. Your game must provide easy-to-find instructions in a pop-up window. The window must either by openable by a button in your game or opened automatically at the start of the game. Information to write in the window includes:

    • A brief explanation of the game you implemented.
    • An explanation of how to play the game, including how the keyboard and/or mouse should be used.
    • Anything cool you’ve implemented that you want to make sure we don’t miss.

    Some students overlook this part of the project, but it’s extremely helpful in the grading process and is an easy five points if you’re short on time!

  • Mouse and/or Keyboard Controls [5%]. You will need to implement mouse and/or keyboard game controls as appropriate for your game. Try to make the player’s experience a good one.

  • Game State [9%]. The game should have a way of displaying the game’s current status.

    • This could include running score, number of lives, time elapsed, etc.
    • Values should be updated appropriately as the game progresses.
    • There should be a detectable end state to your game. This could include winning, losing, running out of time, etc.
  • Testing [3%]. You must implement at least 3 tests to test your game. Keep in mind that your tests should be disjoint, meaning that they should test different parts of your game. Timer-based games can be tested too! For example, you could create models of your game state and test that they update correctly.

  • Style [5%]. You will receive feedback from the stylechecker upon submission. There is no manually graded style for this homework.

  • 4 Distinct Design Concepts [16% per concept, 64% in all]. The point of the game project is to synthesize many of the concepts that we’ve learned over the semester and apply them in the context of game design. Check out the concept descriptions to see what’s available!

    Your game must implement four distinct design concepts; we will not accept any double counting.

Your code must compile for you to receive more than 12% on this assignment! Do not wait until the last minute to make huge changes to your code, and make sure you save working versions as you progress through your implementation.

You must use Java Swing for this assignment. Submissions without Java Swing will only get points for the project proposal (8%). You may not use the PennDraw library from CIS 1100.

Part 1: Project Proposal

Part of your grade for this assignment will come from a project proposal which you will submit in advance of the project deadline. This is the only mandatory way to receive feedback on your game before you start implementing it. It is due early in the process - you will submit it as a form on Gradescope.

Your project proposal will include a brief description of how you will use four distinct design concepts in your game. If you’re having trouble coming up with four concepts for a game idea, don’t give up right away! We can help you out in office hours or on Ed.

If you took CIS 1100 and made a game, you will receive a zero on this assignment if you implement that same game for CIS 1200. You also cannot reuse code from past homework assignments if that code is instrumental to the concepts that your game implements. For example, you cannot simply copy and paste PennPals code to implement a user registration system in your game and receive credit for implementing the Collections or Maps concept.

Here is an example project proposal for Tic-tac-toe. Note that you are not allowed to choose Tic-tac-toe for your game, since we provide its code for you in the example files.

Please go through this write-up and the full rubric that we will use to grade your game before writing your proposal.

Here are some common games (and their usual design concepts) that many students enjoy implementing:

  • Brickbreaker (timer-based*; 2D Arrays, I/O, Inheritance and Subtyping, Collections or Maps)
  • Minesweeper (turn-based*; 2D Arrays, I/O, Testable Component, Recursion)
  • Chess (turn-based*; 2D Arrays, Collections or Maps, Inheritance and Subtyping, I/O, Testable Component, Complex Game Logic)
  • Checkers (turn-based*; 2D Arrays, I/O, Testable Component, Collections or Maps)
  • Othello (turn-based*; 2D Arrays, I/O, Testable Component, Collections or Maps)
  • Pacman (timer-based*, challenging; 2D Arrays, I/O, Inheritance and Subtyping, Collections or Maps, Testable Component)
  • 2048 (turn-based*; 2D Arrays, I/O, Collections or Maps, Testable Component)
  • Battleship (turn-based*; 2D Arrays, I/O, Collections or Maps, Testable Component)

* Turn-based or timer-based are not potential categories for satisfying the requirements.

You are welcome to implement one of these games, another existing game, or a completely original, super-duper awesome game of your own invention.

Please note that you are NOT allowed to implement Connect Four, Snake, or Wordle and will not receive any credit for this assignment if you do so.

Submission instructions for the Project proposal

  1. Take the time to plan out a few games you’d like to make.
  2. Look at the required design concepts and the rubric and see if you can come up with uses for each of them in your potential games.
  3. Choose one game, and fill out the form on Gradescope. We will not accept late submissions for the project proposal.
  4. Once the proposal’s been graded, make sure to check each concept for comments from your TA. Getting the full 8/8 on Gradescope only means that you’ve submitted the proposal on time – there still may be significant changes you have to make to your concepts.

Design Concepts

You’ll need to decompose your game design so that it makes use of four of the following concepts, then justify your choices in the project proposal. You must use four unique concepts - there are no exceptions to this!

Your four design concepts must be used for different aspects of the game. For example, if you are using a 2D array to hold game pieces and then use a collection later to (redundantly) hold the same pieces, this will either count for Collections or 2D Arrays, but not both.

Any design concept related to game state must be properly encapsulated.

Core Concepts from CIS 1200

These concepts have been covered in class or in past homework assignments. You should feel comfortable using any of them in your game design.

2D Arrays

The internal game state of most grid-based games can be easily modeled by a 2D array representing the rows and columns of the grid.

It is important to take into consideration whether or not a 2D array is necessary to model your state and what data it should store. If you choose to use this concept, refer to what you learned in Pennstagram for a better understanding of how to properly use 2D arrays.

Your use of arrays must be sufficiently interesting and model a significant part of the game state - your TA will give individualized feedback on your proposal.

Take a look at the 2D Arrays rubric here.

Collections and/or Maps

This concept includes the use of data structures that implement Java’s Collection interface or Map interface.

Many games can use collections or maps to model their state. You won’t receive credit just for using a collection; what matters is choosing the appropriate data structure for the piece of state you are modeling. The data structure you choose should make it easy to manipulate and retrieve the game state, so make sure that you can justify why your choice is a good one.

Take a look at the Collections and/or Maps rubric here.

File I/O

You might choose to design your own text or binary file format and have your game read and write files using that format. This format must store all of your game’s state, and your game needs to incorporate both input and output for full credit. Storing anything less than full game state will not receive credit unless explicitly approved ahead of time.

You are allowed to use CSVs or related file structures, but what you store in them must be more complicated than what is done in the TwitterBot homework. Using classes such as ObjectOutputStream and ObjectInputStream for I/O is not sufficient for this assignment. You must design and implement the structure of your file yourself, such as having the first line be the number of rows and the second line be the number of columns, and then having each subsequent line be a row of the game board.

One sufficiently complex use of I/O is enabling persistent state between runs of your game. For example, in a game like Tic-Tac-Toe (provided in the example code), you would store the entire game board and the history of all moves made. If someone were to quit the game and re-open it, they could resume the playing previous game as if they had never quit.

Another sufficiently complex use of I/O could be to store level designs, where a text format specifies features of the level (rather than hard-coding levels into your game’s source code). The file would have to include enough information to set up your entire game state.

A leaderboard is insufficient to satisfy the requirements.

The filepaths you specify for this concept must be relative, not absolute. This means that you should specify paths like fileFolder/file.txt instead of C:/Users/username/1200Project/fileFolder/file.txt. This is because the former is usable without adjustment on any computer, while the latter requires the user to have the same hard drive structure as you. Your project should assume that the project folder is the root directory (1200Project in the aforementioned example). For more detailed information, check out this page from Oracle.

Much like TwitterBot’s FileLineIterator, you must handle all edge cases and ensure your game does not crash due to bad or poorly formatted input. If you encounter a FileNotFoundException, your game should display an error window rather than just displaying the stack trace in the console.

Not that you must NOT use built-in serialization and deserialization classes (like ObjectOutputStream and ObjectInputStream) to read/write their game state from/to a file

If you use a temporary collection in your I/O concept separate from your game state, you cannot count this use of collections for the Collections concept.

Take a look at the File I/O rubric here.

Inheritance and Subtyping

This concept involves use of Java’s subtyping features to group and organize different entities in your game, then differentiating subclass behavior using dynamic dispatch. You will need to justify why you decided to design your classes and interfaces in your chosen hierarchy in order to get credit.

There should be a natural subtyping relationship being modeled in your game. The relationship should not be so simple that it could easily be represented by a field (like the color or speed of a piece). Inheritance should be used to model the functionality of different entities in your game, not just on graphical appearances or attributes.

For example, say you are making a tower defense game and have the IceTower and Sniper subclasses implementing the Tower interface. Invalid and valid uses of this concept could be as follows:

  • Invalid: The only differences between IceTower and Sniper are attributes such as attack speed, damage, and appearance. Notice that these are fields and do not require dynamic dispatch or significantly differentiated method behavior.
  • Valid: Your different defenders attack in different ways. IceTower attacks by slowing all enemies within a radius; Sniper attacks via strong attacks to a single enemy at a time. These behaviors are unique enough to require significant changes to an attack() method that is present in the Tower interface. Note that this makes use of dynamic dispatch.

Your new interface/abstract class must have a new method that its subtypes implement in a significantly differentiated fashion. In the example above, this refers to the Tower interface’s attack() method.

You are not allowed to use GameObj as the sole basis of your inheritance - if you do, you will receive 0 points for this concept. If you need GameObj in your inheritance tree, create an abstract class that extends it or an interface that complements it, and use that instead. That abstract class or interface must make significant changes to GameObj.

Take a look at the Inheritance & Subtyping rubric here.

JUnit Testable Component

This concept requires you to design an encapsulated game model that functions independently of the GUI, then implement JUnit tests for that model. The model should be updated and queried by calling methods - your code must be unit-testable by design.

An example of a testable model is PennPals. The ServerModel class stores internal state, but it does not deal with low-level components of the server’s networking and it does not deal with any graphical components.

Your unit tests should only interact with the game model, and should not interact with or have any dependence on the GUI or interactive components. For example, you should test jumping by checking velocity before/after calling jump(), not before/after a simulated SPACE keypress.

Take a look at the Testable Component rubric here.

Recursion

There are several useful recursive algorithms you might wish to implement, including depth-first search of a graph, traversing a tree structure, or finding a path through a maze. You should consider whether a recursive implementation is strictly necessary for this algorithm to work, and whether your algorithm can be easily implemented with an iterative solution.

Take a look at the Recursion rubric here.

Novel Linked or Recursive Data Structure

Some games might have states that aren’t easily modeled by an existing collection. For instance, you might have a maze or a network of rooms connected by corridors, and each node should know the others it is adjacent to. You might also find that a tree-like structure could be helpful for modeling a particular problem.

“Novel” is one of the key parts here; your implementation must be a data structure not readily available via collections in Java, Apache Commons, Google Guava, or other commonly used Java libraries.

Take a look at the Novel Linked/Recursive Data Structure rubric here.

Complex Game Logic

The only game currently approved for this concept is chess. If you are considering this concept for a game that is not chess, you must get approval from a Head TA or professor.

In the past, chess has been challenging for students to fully implement because of difficulties in core game logic. In order for your implementation of chess to get full credit for this concept, you must implement check, checkmate, en passant, and castling in addition to normal game features (moving pieces, capturing pieces, preventing invalid movement of pieces, etc.). For example, this concept includes making sure that a user’s piece should not be able to move into a state that results in check, and a user that is checked must be forced to resolve the check.

Put simply, your game of chess must implement the complete standard chess ruleset. If you do not implement these features of chess (or plan to implement these features but change your mind), you can still get full credit by notifying your TA and implementing four other concepts.

Take a look at the Complex Game Logic rubric here.

Advanced Topics

You may count exactly one advanced topic toward your four concepts. Any advanced topic must be approved by a TA.

If you have an idea for a more advanced topic, please ask your TA or make a post on Ed. Examples of possible advanced topics are as follows:

  • Collisions (beyond simple bounding boxes or circles)
  • 3D Graphics
  • Network I/O
  • Concurrency
  • AI

Feel free to make a public post on Ed if you have an idea for an advanced topic that no one else has suggested before (public posts help us avoid repeat suggestions). It is especially important that you get feedback on these new ideas, since a concept that sounds advanced isn’t necessarily hard to implement in practice.

If you plan on posting to Ed to ask about your own idea for an advanced topic, you must do so before the project proposal is due, and you cannot choose to use an advanced topic that has not been approved.

Take a look at the Advanced Topics rubric here.

Choosing which Design Concepts to Implement

When choosing which concepts to implement, we advise you to avoid getting too ambitious unless you’re certain that you have enough time. The turnaround from project proposal to complete game is pretty quick, and we don’t want you to add the stress of a complex game to all of the other coursework happening at this point in the semester. The point of this assignment is to demonstrate your understanding of the concepts taught in this course, not to show the most difficult or complex thing you can make.

This project has a maximum score of 100%. Additional concepts cannot bring your total to over 100%, nor can they compensate for other missing criteria. For example, if you fail to provide instructions, the highest score you can get is 95%, even if you implement every listed concept.

Part 2: Game Implementation

A Note about External Resources

You are not required to use any external resources to complete this homework. However, you are welcome to use them under the following conditions:

  • You may not read, follow along with, or copy anything from a tutorial that relates to any of your core concept implementations. We will be very strict in enforcing this policy because we want to make sure that everything we are grading is your work. This does not include high-level explanations of algorithms, but as mentioned, you are still not allowed to view or copy any code for them.

    If you are implementing something external to the core concepts we are grading, then you are allowed to view tutorials that explain concepts, but you must cite your sources in your README.txt.

  • For resources like images, you should be fine since this is a not-for-profit educational project. However, if you plan to distribute your game more widely, you should keep in mind the relevant laws regarding fair use of copyrighted material.

  • If you use a third-party code library, your submission will not compile on Gradescope. In this case, you are fully responsible for taking the following steps for us to accept your submission:

    • Ensuring that your code requires no modifications to compile and run when downloaded from Gradescope. You should download and open the project from Gradescope yourself to verify that this is the case!
    • Emailing cis1200@seas.upenn.edu to notify us that your code has been submitted with a third-party dependency.

If you have questions about whether your use of a third-party resource is allowed, consult the course staff for help.

Starter Code

Experienced programmers often start a new program by modifying existing code or by using a tool to automatically generate starter code. Our example code contains two very simple example games that you can use as a starting point. Read the section about setting up your project to see how to start from either of these examples.

Make sure you pick the appropriate starter code for your game’s design! Mushroom of Doom is a continuous, timer-based game, since its state updates at regular intervals regardless of user interaction. Tic-tac-toe is a turn-based game, since its state only updates after each user interaction.

Mushroom of Doom: a timer-based game

Our sample timer-based game is rather silly super cool! You can move the black square using the arrow keys. Then, there is this mushroom. If your black square touches it, you die. You win the game by catching the golden snitch. Try it out by switching the class in src/main/java/org/cis1200/Game.java to org.cis1200.mushroom.RunMushroomOfDoom(). Then run the main method in src/main/java/org/cis1200/Game.java.

Here’s an overview of the files:

  • Game.java: This file contains a class with a simple main method to run the game. It implements Runnable, which provides a run method. This method sets up a window with a Reset button, a Status line, and a GameCourt.
  • GameCourt.java: This is where the real action happens. The GameCourt is a JComponent on which the current game is displayed. It handles user keypresses and sets up a Timer to generate an event every 35 milliseconds so that the screen can be redrawn. It also has a Square, the Poison mushroom, and the Circle (i.e. the snitch). It updates all of them before redrawing the screen.
  • GameObj.java: GameObj is an abstract class which defines behavior common to the different objects in the game. A GameObj is a rectangular object which has a position, a size, a velocity, and bounds. Game objects can be moved, drawn, and bounced based on collisions with walls and other GameObjs. This game creates three subclasses of GameObj
    • Poison.java: A Poison is a GameObj that represents a poisonous mushroom. It doesn’t move, but it demonstrates how to display game objects using images.
    • Square.java: A Square is a GameObj which looks like a square. It is controlled by the keyboard in GameCourt.
    • Circle.java: A Circle is a moving GameObj which is displayed as a circle and bounces off of the walls and the Poison.

Tic-tac-toe: a turn-based game

Our other sample game, Tic-tac-toe, is also super cool. You can also see that the game’s state is entirely independent of the view and the controller in src/main/java/org/cis1200/tictactoe/TicTacToe.java. Try it out by switching the class in src/main/java/org/cis1200/Game.java to org.cis1200.tictactoe.RunTicTacToe(). Then run the main method in src/main/java/org/cis1200/Game.java.

This game is turn-based and adheres to a Model-View-Controller design framework. This design framework is very effective for turn-based games. We STRONGLY recommend you review the lecture notes chapter 31.8, to learn about the Model-View-Controller framework.

Here’s an overview of the files:

  • Game.java: This Game class implements Runnable. To play the game, run this file.

  • TicTacToe.java: This class is a model of a Tic-tac-toe game. Run this file to see the main method play a game of Tic-tac-toe, visualized with Strings printed to your console.

    The methods in this class let you play a game of Tic-tac-toe without a GUI or direct user interaction. This is an example of having independent, testable internal state.

  • GameBoard.java: In a Model-View-Controller framework, GameBoard stores the model as a field and acts as both the controller (with a MouseListener) and the view (with its paintComponent method and the status JLabel).

Note: Turn-based and timer-based functionalities are not mutually exclusive. You are welcome to implement games that involve both. For example, chess is turn-based, but players often have limited time in which to take their turns.

Setting up your project

IntelliJ

  1. Download the example code and import the folder into IntelliJ like a normal homework (check out Setting up a homework in IntelliJ).

  2. Create a new package for your game. Right-click on the org.cis1200 folder within src/main/java and select New > Package. Name this package org.cis1200.yourgame (replace yourgame with your actual game’s name). This folder should contain all of your game’s classes.

  3. Copy/paste the files from the starter code. In the folder of whichever game you’d like to start from, select all the files using cmd-click (or ctrl-click) on all the files, right-click, and select Copy. Then, right-click on your game’s folder and select Paste.

  4. Edit your game’s files. Right click on RunTicTacToe.java or RunMushroomOfDoom.java in your new package, hover over Refactor, click Rename, and rename the class to RunYourGame (replacing YourGame with the name of your game). Make sure to change this file’s contents while you build your game’s functionalities.

  5. Modify Game.java. The main method in Game.java determines which game is run when we run our project. In the main method, modify the first line to run your new game – both the package name and the method call should be changed. This is the only line you should need to change in Game.java.

    Runnable game = new org.cis1200.yourgame.RunYourGame();
    
  6. To run your game, right-click on Game.java and select Run Game.main(). Now you are ready to start coding your game!

Note that you should probably have classes and files other than Game.java, refer to the starter code we have provided for you on how to organize your files.

Codio

(We strongly recommend using IntelliJ for this project!)

  1. Create a new folder for your game: right-click on the cis1200 folder within src/main/java/org and select New Folder. Name this folder yourgame (replace yourgame with your actual game’s name). This folder will contain all of your game’s classes.

  2. Copy/paste the files from the starter code. In the folder of whichever game you’d like to start from, select all the files using cmd-click (or ctrl-click) on all the files, right-click, and select Copy. Then, right-click on your game’s folder and select Paste. In each file you’ve copied, replace the first line, package org.cis1200.mushroom, with package org.cis1200.yourgame.

  3. Edit your game’s files. Right click on RunTicTacToe.java or RunMushroomOfDoom.java in your game’s folder, click Rename, and rename the file to RunYourGame (replacing YourGame with the name of your game). Also, rename the class name to RunYourGame. Make sure to change this file’s contents while you build your game’s functionalities.

  4. Modify Game.java. The main method in Game.java determines which game is run when we run our project. In the main method, modify the first line to run your new game – both the package name and the method call should be changed. This is the only line you should need to change in Game.java.

    Runnable game = new org.cis1200.yourgame.RunYourGame();
    
  5. To run your game, select Compile from the dropdown. After compiling, select Run Game from the same dropdown. To view your game, click View Game from the second dropdown. Now you are ready to start coding your game!

Note that you should probably have classes and files other than Game.java, refer to the starter code we have provided for you on how to organize your files.

Implementing your Game

From here on out, you’re on your own! Your game project will be graded partly on a set of implementation criteria and partly on your explanation of the implementation during the demo session.

Backing Up Your Code

For this assignment, we strongly recommend that you make snapshots of your code periodically. You might want to consider learning and using a source control system such as Git.

At the very least, periodically make backups of your project by saving a copy of your code to a separate folder.

Submitting your Game

You must submit all of your Java files, README.txt, a screenshot of your file structure and any additional files you may have created. The most important requirement is that it must include a class called Game in the org.cis1200 package with a main method:

public static void main(String[] args)

Taking a screenshot of your file structure

In your homework submission, you must include a screenshot of your file structure. To do this, you can use the following steps:

  • Open the folder containing your game files
  • Take a screenshot of the folder structure (example image below)
  • Rename the screenshot to file_structure.png
  • Upload the screenshot to your gradescope submission

File Structure

If you are using Codio

These files should be organized similar to above (with a src and test directory) The easiest option is to use the Zip for Submission menu item in Codio. If you do this, you should delete the folders for the provided game code that you did not use (i.e. if you modified mushroom of doom, you should delete tictacttoe folders from both main and test, and vice-versa). You can directly upload the zip produced by Codio into Gradescope.

If you are using IntelliJ

Gradescope allows you to easily drag-and-drop files into it, or you can click “Browse” in Gradescope to open up a file browser on your computer to select files. The file structure does not need to be preserved – your TA will set up your game manually on their computer.

Submission Troubleshooting

The submission page attempts to compile your code and checks for the main method. It will tell you if this compilation fails. The most common cause is forgetting to include a file.

There is no penalty for extra submissions on this assignment, so get started early and submit often!

To run your game, we will execute the main method in your Game class. Non-compiling code will not receive any credit. For any extenuating circumstances, please reach out to cis1200@seas.upenn.edu. You will need to share a working copy of your game uploaded to Google Drive for us to verify that it has not been modified since the deadline.

Demonstrating your Game

Your game will be graded during a demo session with a TA. We will play the game so you can show us all of your features and we can look for bugs. We will expect you to walk us through your Java classes and explain how everything works during the demo session. Be prepared for questions about your implementation.

You must schedule a demo session with a TA (they will send you an email to arrange a demo time). Each demo slot will about 15-20 minutes long. Not showing up for your Game demo will result in a 20 point deduction! Even if you miss it, you MUST make up the demo or else you only get readme/proposal points.

Your TA will email you with more information about how to schedule your demo session closer to the due date.