Homework 1: Flappy Box
In this homework, you will implement "Flappy Box," a simplified version of Flappy Bird in Java.
Objectives
- Apply object-oriented programming principles to design and implement a game
- Review and practice Java programming concepts
- Improve code comprehension and coding skills
- Practice adhering to coding standards and style guidelines
- Gain familiarity with our homework structure and submission process
Important Dates
Event | Day | Date | Time |
---|---|---|---|
Release | Thu | Aug 29 | 09:00 AM ET |
Due | Thu | Sep 05 | 05:00 PM ET |
Homework Description
Flappy Box is a 2-dimensional side-scrolling game where the player controls a yellow square (box). The objective is to guide the box through a series of obstacles (pipes) without touching them, using the space bar to control its movements. The score tracks the player's progress as they navigate the obstacles, increasing every time an obstacle is successfully passed. The game ends when the box hits an obstacle, falls off the bottom of the canvas, or flies too high to reach the top of the canvas.
You will use an Object-Oriented approach for designing and implementing the game. The game will be written in multiple Java files, each containing a different "class". Additionally, the program will use Princeton's StdDraw.java
library.
The code should be well-organized, easy to read, and exhibit elements of object-oriented, structured, and modular programming. Moreover, it must comply with the provided checkstyle rules and specifications.
Homework 1 is an excellent way to start this Data Structures course. It is both fun and challenging, allowing you to demonstrate your understanding of the Java programming language and practice your problem-solving skills. The game is an engaging way for you to apply the skills you have acquired throughout the Gateway Computing: Java course.
Starter Code
Download the starter code from the following link: hw1.zip.
The starter code is a zip file named hw1-starter.zip
. You must unzip this file. After unzipping, you will get a folder called hw1-starter
. Open this folder as an IntelliJ project.
A common mistake students make when opening the homework projects is that they open a different folder, such as the folder containing the starter code or the source (src
) folder inside of it! Make sure you open the root folder as an IntelliJ project.
Tasks
Once the project is open, explore the files in the src/main/java/hw1
folder. You should do this through the Project View panel in IntelliJ. This panel appears on the left side of the IntelliJ window. If you don't see it, you should be able to toggle it open by going to the View menu, and then selecting Project from Tool Windows.
There are several folders and files in the starter code. The structure is consistent with how build tools like Maven and Gradle organize Java projects. However, in this course, you will not be using any of those build tools. You will be working primarily with files inside the src/main/java/
and src/test/java/
folders.
Source files
To open a file, you can double-click on it in the Project View panel. This will open the file in the editor window. Explore the source files in the following order:
-
Block.java
: A block is a game object with a rectangular bounding box. This file is completely implemented. -
Sprite.java
: A Sprite is a Block that can move. This class is also fully implemented. -
Box.java
: A Box is a square Sprite with a fixed length. This class is missing the implementation for theintersects
operation. You should implement this later. For now, just explore the codebase. -
FallingBox.java
: A FallingBox is a Box that falls with acceleration due to gravity. This class is partially implemented. You should update themove
method to ensure the FallingBox does not fall off the (bottom of the) screen. You will do this later! -
FallingBoxDemo.java
: A demo where a FallingBox falls from the top of the screen. Run this demo by clicking on the green play icon next to thepublic class FallingBoxDemo {
statement; select "Run 'FallingBoxDemo.main()'". You should see a window open with the title "Standard Draw". The window will have a sky blue background and include a yellow square "falling down". To stop the demo, you should close the "Standard Draw" window. Later, once you update theFallingBox.move()
operation, you should also update theFallingBoxDemo.runGameLoop()
method to end (i.e., setisGameOver
totrue
) when the FallingBox reaches/falls off the (bottom of the) screen. -
FlappyBox.java
: A FlappyBox is a FallingBox that can jump. Thejump
operation is left for you to implement. You will do this later! -
FlappyBoxDemo.java
: A demo where a FlappyBox can jump when the space key is pressed. Run this file; it should look similar to FallingBoxDemo. As the FlappyBox is falling, press the space key and look over the console in IntelliJ. You should see the word "Jump!" printed. -
Pipe.java
: A Pipe is a game object composed of multiple Boxes. Pipes are obstacles in the path of the FlappyBox. Each pipe has a hole, an opening space, as large as two boxes. The player must guide the FlappyBox to pass through the pipes' openings. The Pipe class is fully implemented. -
MovingPipeDemo.java
: Run this demo file. You should see the green pipes moving from right to left on the screen. You should explore the code to understand how the pipes are generated and moved. TheMovingPipeDemo
class is a good example of how to use thePipe
class in a game. -
GameConstant.java
: A class containing all the constants used in the game. This is a utility class and should not be instantiated (that is why it has a private constructor). -
Game.java
: The main class for the Flappy Box game. Most of the operations are left for you to implement (at a later time).
A note on StdDraw.java
: The StdDraw.java
library is a simple library for drawing graphics in Java. It is used in this homework to create a window and draw shapes on it. You do not need to understand how StdDraw.java
works. You can think of it as a "black box" that allows you to draw shapes on the screen. You can find more information about StdDraw.java
here.
A note on coordinates: All game objects exist in a standard X-Y coordinate plane. When a new Block is created, the top-left X and Y coordinates are specified, and then all other coordinates are calculated relative to it. For instance, the following image shows the corners of a 75x75 Block created at (100, 300):
From this, you can see that as a block falls, you'll decreate the Y coordinate -- and if it jumps, you'll increase it.
Test files
Next, you will explore the test files located in src/test/java/hw1
. We will teach you about testing later in this course. For the first homework, you do not need to have a deep understanding of how the tests work. You should only be able to run the tests.
-
BlockTest.java
: Open this file and click on the green play icon next to thepublic class BlockTest {
statement. Then select "Run 'BlockTest'". This will run all the tests in this file. You should see a report in IntelliJ including the list of 9 tests in this file. There must be a green check mark next to each test. -
SpriteTest.java
: Open this file and run the tests. All tests should pass. Notice a green play icon next to each test. If you want to run just one test, you can click on this icon and run it. For instance, try running only the test with the display name "Test initial speed is zero". -
BoxTest.java
: Open this file and run the tests. Notice some of the tests fail because theintersects
operation is not implemented yet. Go to theBox.intersects
operation and changereturn false;
toreturn true;
. Then, run the tests in BoxTest. Notice the tests that were failing before are now passing. However, the implementation ofBox.intersects
is still incorrect! This is a good example to show that it is not necessarily the case that when a test passes, your implementation is correct. This is why we don't use such tests to auto-grade your submission. The tests provide preliminary feedback. A teaching assistant will always carefully review your submission and grade it. -
Further explore
FallingBoxTest.java
,FlappyBoxTest.java
, andGameTest.java
files. Run their tests and notice some tests fail as there are missing implementations in their corresponding classes. However, all the tests inPipeTest.java
must pass asPipe.java
is already correctly implemented.
As you implement various operations in this project, use the provided tests to check your work. These tests also run when you submit your code to Gradescope. While not exhaustive, they offer a solid starting point to verify your implementation's correctness. For this homework, we've supplied the tests. In future assignments, you'll write your own—we'll teach you how in the coming weeks. We'll also have our own tests for each homework to evaluate your Gradescope submissions. These tests won't be shared with you!
Implementation
Now it is time to implement the game! I suggest the following plan:
-
Implement
FlappyBox.jump
. When thejump
operation is called, the flappy box must move up by the value ofjumpVelocity
. Moreover, you should reset the falling speed and acceleration to their corresponding initial values. You may want to look over the constructor ofFallingBox
to see how these values are initialized. Once thejump
operation is implemented, run the tests inFlappyBoxTest
and make sure they all pass. Moreover, run theFlappyBoxDemo
and ensure the flappy box jumps when you press the space bar. -
Implement
FallingBox.move
. You should update themove
method to ensure the FallingBox does not fall off the bottom of the screen. You should think about two things:-
How can you detect if the FallingBox has reached the bottom of the screen? Hint: the y-coordinate of the bottom of the box would be 0 when it reaches the bottom of the screen.
-
How can you stop the FallingBox from falling further down? Hint: when an object is not moving, its speed is zero.
Once the
move
operation is implemented, run the tests inFallingBoxTest
and make sure they all pass. Moreover, run theFallingBoxDemo
and ensure the falling box stops as it reaches the bottom of the screen. Additionally, update theFallingBoxDemo
to stop the game loop once the FallingBox has reached the bottom of the screen. -
-
Implement
Box.intersects
. You should return true if this box intersects with theother
box. You should think about various scenarios where two boxes can intersect. For instance, the two boxes might intersect partially or one might be entirely inside the other one. There are several tests provided in theBoxTest
class. These tests are not exhaustive and do not account for all cases, but they should give you a good starting point. All the tests in theBoxTest
class should pass if you implement theintersects
operation correctly. -
Implement the operations of the
Game.java
. You can look at the demo classes (FallingBoxDemo
,FlappyBoxDemo
, andMovingPipeDemo
) to find an initial implementation for most of the operations in theGame
class. The game should adhere to these specifications:-
The game begins with a canvas appearing on the screen. A "flappy box" is located on the left side, while several obstacles (pipes) are randomly generated and move from right to left.
-
During the game, the flappy box can be controlled by the player using the space bar key. Pressing the space bar will make the box jump.
-
The score, which is displayed at the top of the screen, tracks the player's progress as they navigate the obstacles. It increases every time an obstacle is successfully passed.
-
The game ends when the flappy box collides with an obstacle, such as a pipe. Hint: You might reasonably expect the
intersects
method to be transitive -- that is,pipe.intersects(flappyBox)
to do the same thing asflappyBox.intersects(pipe)
. However, given that aPipe
is composed of multipleBox
es, with a gap in the middle, this is not the case. Carefully think about which of these method calls will account for this. -
The game ends when the flappy box reaches the bottom of the canvas or flies too high to reach the top of the canvas.
-
After the game ends, a message displaying "game over" is shown over the canvas.
-
Discussion
Every homework will include a discussion section. The discussion section is an opportunity for you to reflect on the concepts you have learned and how they are applied in the homework. The discussion section is a critical part of the homework and will be graded.
You should write your answer in the README.md
file. The README.md
file is located at src/main/java/hw1/
. You can open this file in IntelliJ by double-clicking on it in the Project View panel. This will open the file in the editor window. Please keep your answers brief and to the point.
Part I
Describe the following terms with examples from the source code of this game: Class, Object, Encapsulation, Abstraction, Data type, Composite data type, Method, Constructor, Instance variable, Local variable, Parameter, Return type, Inheritance, Type Hierarchy, Apparent type, Actual type, Is-a relationship, Has-a relationship, Method overloading, Method overriding, Static polymorphism, Dynamic polymorphism.
You can use the StdDraw.java
library, along other classes in the game, as an example for some of the terms.
Part II
Provide examples of data structures used in the game. Explain why these data structures are used and how they help in the implementation of the game.
Part III
Provide an example of an algorithm used in the game. Explain how the algorithm works and how it helps in the implementation of the game.
Submission
In preparation, you must (1) run checkstyle to ensure your code is checkstyle compliant (if not, fix the styling issues). (2) Create a zip file containing the src
folder (and all therein). (3) Submit the zip file to Gradescope.
Checkstyle
To run checkstyle, go to the View menu, and then select CheckStyle from Tool Windows. Next, select "cs226" from the "Rules" dropdown. Finally, click on "Check Project." (One of the buttons on the left side of the CheckStyle panel under the green play icon). If there are any issues, you should see them in the CheckStyle panel. You can double-click on an issue to navigate to the corresponding line in the editor window.
Make sure your code is checkstyle compliant before submitting.
Zip File
You must create a zip file containing the src
folder (and all therein). You can usually do this by right-clicking on the src
folder (outside of IntelliJ) and selecting "compress" or "zip" or "archive," etc.
You should submit the zip file to Gradescope. A common mistake students make is submitting the wrong file or the wrong folder. For example, they zip the root folder of the project hw1-starter
instead of the src
folder inside it. Make sure you zip the correct folder.
Gradescope
Go to course Canvas page and click on the Gradescope link. You will see an assignment called "Homework 1: Flappy Box." Click on this assignment and upload your zip file. You can submit as many times as you like. We will only grade the last submission.
Rubric
Teaching assistants will evaluate your submission using the following criteria:
-
Spec 1: The game is written in multiple Java files, each containing a different "class". It utilizes Princeton's
StdDraw.java
library. [0.5 points] -
Spec 2: The game compiles without errors or warnings and runs smoothly without any delays or glitches. [1 point]
-
Spec 3: The game begins with a canvas appearing on the screen. A "flappy box" is located on the left side, while several obstacles (pipes) are randomly generated and move from right to left. [1 point]
-
Spec 4: The
FallingBox.java
file includes a correct implementation of themove
operations. The FallingBox does not fall off the bottom of the screen. Moreover, the game loop of theFallingBoxDemo.java
file stops when the FallingBox reaches the bottom of the screen. [1.5 points] -
Spec 5: The
FlappyBox.java
file contains a correct implementation of thejump
operation. The FlappyBox jumps when the space bar key is pressed and moves up by the value ofjumpVelocity
. The falling speed and acceleration are reset to their initial values. [1 points] -
Spec 6: The
Box.java
file includes a correct implementation of theintersects
operation. The operation returns true if this box intersects with theother
box. The tests in theBoxTest.java
file pass when theintersects
operation is implemented correctly. [2 points] -
Spec 7: During gameplay, the flappy box can be controlled by the player using the spacebar key. Pressing the spacebar will make the box jump. [1 point]
-
Spec 8: The score, which is displayed at the top of the screen, tracks the player's progress as they navigate the obstacles. It increases every time an obstacle is successfully passed. [1.5 point]
-
Spec 9: The game ends when the flappy box collides with an obstacle, such as a pipe. [1 point]
-
Spec 10: The game ends when the flappy box falls off the bottom of the canvas or flies too high to reach the top of the canvas. [1 point]
-
Spec 11: After the game ends, a message displaying "game over" is shown over the canvas. [1 point]
-
Spec 12: The code is well-organized, easy to read, and exhibits elements of object-oriented, structured, and modular programming. Moreover, it must comply with the provided checkstyle rules and specifications. [1 point]
-
Spec 13: The discussion questions in Part I accurately describe all requested terms with relevant examples from the game's source code. [5.5 points: 0.25 points per term]
-
Spec 14: The discussion questions in Part II provide appropriate examples of data structures used in the game, with clear explanations of their usage and benefits. [2 points: at least two examples; 1 point per example]
-
Spec 15: The discussion questions in Part III present a relevant algorithm example from the game, explaining its functionality and importance in the game's implementation. [1 points]
The total score for this homework is 22 points.