Workshop 4
Semester 1, 2021
Workshop
This week the focus is on learning to use the Bagel library. To get started, download the starter pack on
Canvas and unzip it. Open the directory as an IntelliJ project, and run the main method in BagelTest. If
you get errors, try right-clicking the file pom.xml and clicking Add as Maven project; this will force IntelliJ
to download and set up the appropriate dependencies for Bagel.
• In Bagel, the window is divided into pixels; by default, the window is 1024 pixels wide and 768 pixels
high.
• Coordinates in Bagel are specified from the top-left of the window (unlike in usual mathematics1, where
the origin is the bottom-left). Therefore, by default
– (0, 0) is the top-left
– (512, 384) is the centre
– (1024, 768) is the bottom-right
• The graphics in Bagel are handled by clearing the screen to blank many times per second, and re-
rendering all of the graphics. One clear-render step is called a frame. The update method inherited
from AbstractGame must be used to render the graphics, otherwise they will be erased at the beginning
of the frame. (We will learn more about inheritance this week.)
Questions
1. Study the BagelTest class, using the Bagel documentation available at https://people.eng.unimelb.
edu.au/mcmurtrye/bagel-doc to understand how it works. All resources, e.g., the image and font files,
are contained in the res/ folder.
(a) Look at the documentation for the Image class to understand how images are loaded and rendered.
(b) Similarly, look at the documentation for the Input class to understand how keyboard and mouse
input is handled.
2. Now, you are ready to commit and push the bagel-starter-pack – refer to Lecture 8 for GitLab com-
mands.
(a) First, clone your workshop repository. Head to:
https://gitlab.eng.unimelb.edu.au/swen20003-s2-2020/
and follow Lecture 8 slides and/or the demonstration in the live Zoom lecture to clone the repository.
(b) Copy the contents of bagel-starter-pack into the cloned repository (you should create a new
directly in the repository, e.g., “week5”, and copy call contents in bagel-starter-pack to this
folder). Run git add to add the files, and git commit -m “copied template” to make your first
commit. Then run git push to push to the remote repository; you should commit and push at the
end of each question below.
1You can blame the Microsoft programmers Craig Eisler, Alex St. John, and Eric Engstrom who created DirectX (one of the
first widely-used graphics libraries) in 1995 for this. They simply preferred “left-handed” coordinates.
1
https://people.eng.unimelb.edu.au/mcmurtrye/bagel-doc
https://people.eng.unimelb.edu.au/mcmurtrye/bagel-doc
3. Create the catch the ball game following the below instructions.
(a) When the game starts, the player should be rendered to the screen at the position: (200, 350),
and the ball should be rendered at position: (650, 180). You can use the Point class to define
the position.
• The player image is located at res/player.png, and the ball image is located at res/ball.png.
(b) The player should be able to move left, right, up, and down, using the respective arrow keys at a
constant step size (in pixels per frame). Try different values for the step size (a constant named as
STEP SIZE), starting at 1.
(c) If the player comes within 20 pixels of the ball, we say the player catches the ball and you should
print to the console “Great job!”. Remember, the Euclidean distance between points (x1, y1) and
(x2, y2) is given by:
d12 =
√
(x1 − x2)2 + (y1 − y2)2 (1)
(d) Instead of printing the greeting to the console, draw the text to the screen using the font provided
(res/conformable.otf). Draw it in size 24 font at coordinate (32, 32). (See the Font class in Bagel
documentation.)
(e) The game should exit when the Escape key is pressed.
(f) Now add, commit and push the code to the repository – remember to add a meaningful comment
when you commit the code to describe your changes to the code.
4. Now, we are revising the catch the Ball game so that the player moves toward the ball step by step. In
this question, you will learn how to set the player’s moving direction and how to let the player move
towards this direction by one step. Let the movement of the player controlled by the Enter key, not
the arrow keys: If the Enter key is pressed (use Input.wasPressed method), do the following:
(a) Calculate the direction (xd, yd) pointing from the player to the ball: for (x1, y1) and (x2, y2) being
the positions of the player and the ball respectively, set2:
xd =
x2 − x1√
(x1 − x2)2 + (y1 − y2)2
,
yd =
y2 − y1√
(x1 − x2)2 + (y1 − y2)2
(2)
(b) Moving in direction (xd, yd) by one step:
add STEP SIZE ∗ xd to x1,
add STEP SIZE ∗ yd to y1
(3)
(c) After each movement, print to the console the position of the player in the form of
x-coordinate, y-coordinate
Keep 2 decimal digits for both x-coordinate and y-coordinate. To do so, you can use the format
method in java.text.DecimalFormat class, e.g., define a static attribute
private static DecimalFormat df = new DecimalFormat(“0.00″);
and use it as
System.out.println(df.format(playerX) +”,” + df.format(playerY));
Check if the one-step movement is correct.
(d) Now add, commit and push the code to the repository – remember to add a meaningful comment
when you commit the code to describe your changes to the code.
5. Now, you will develop a more complex game of Catch the Ball game as follows.
(a) The player (in Question 3) needs to catch a moving ball (res/ball.png). When the game starts,
the ball should choose a random position on the window to be drawn at and a random direction.
Set the step size of the ball to 0.5.
2It should be noted that, the same as position, a direction has both x- and y-coordinates. The denominators in Equation (2)
equal to the Euclidean distance between (x1, y1) and (x2, y2) in Equation (1). By dividing this distance, the direction (xd, yd) in
Equation (2) is normalized so that the movement in Equation (3) has a length equal STEP SIZE.
2
(b) When the player is within 20 pixels of the ball, the ball should move to another random position.
(c) Keep track of the player’s score, which starts at 0 and increases by 1 every time the player catches
the ball. Draw this score (using Font) at the top-left of the window.
(d) Extend the code to make the ball choose a random diagonal direction, and move in that direction.
When the ball reaches the left and right edges of the window, it should reverse horizontal direction.
Similarly, when the ball reaches the top and bottom edges of the window, it should reverse vertical
direction. You can change the step size of player and ball when simulating.
(e) Now add, commit and push the code to the repository – remember to add a meaningful comment
when you commit the code to describe your changes to the code.
6. The below code (also on Canvas) contains bugs that stops it from working.
import java.util.Arrays;
public class VideoGame {
public final String name;
public final String platform;
private static final VideoGame[] games = new VideoGame[100];
private static int numGames = 0;
public VideoGame(String name, String platform) {
this.name = name;
this.platform = platform;
games[numGames++] = this;
}
public int compareTo(VideoGame other) {
int platformCompare = platform.compareTo(other.platform);
if (platformCompare != 0) {
return platformCompare;
} else {
return name.compareTo(other.name);
}
}
public static VideoGame[] getSortedVideoGames() {
// Create a copy of the array to sort
VideoGame[] sorted = Arrays.copyOf(games, games.length);
// Recursively sort the array
quickSort(sorted, 0, numGames – 1);
return sorted;
}
private static void quickSort(VideoGame[] array, int low, int high) {
if (low < high) { // Choose a pivot VideoGame pivot = array[high]; // Partition the array int i = low; for (int j = low; j < high; ++j) { if (array[j].compareTo(pivot) < 0) { // Swap the elements VideoGame temp = array[i]; array[j] = array[i]; array[j] = temp; ++i; } 3 } // Swap the elements VideoGame temp = array[i]; array[high] = array[i]; array[i] = temp; quickSort(array, low, i - 1); quickSort(array, i + 1, high - 1); } } public String toString() { return String.format("%s (%s)", name, platform); } public static void main(String[] args) { new VideoGame("Halo", "Xbox"); new VideoGame("Ocarina of Time", "Nintendo 64"); new VideoGame("Red Dead Redemption 2", "Xbox One"); new VideoGame("Majora's Mask", "Nintendo 64"); System.out.println(Arrays.toString(VideoGame.getSortedVideoGames())); } } Use the IntelliJ debugger to help you find the bugs. Click to the right of the line number to set a breakpoint, and click the bug icon (next to the play icon) in the top-right; the code will break (pause) at the line you selected. Experiment with the features of the debugger view. Particularly helpful will be the Variables view and the Step Over button. 4