Fall 2018 CSE30264 Programming Assignment 4 - Online Pong Game
Total Points: 100 points
Goal: Create an Online Pong Game
Assigned: Nov. 5, 2018
Due: Nov. 30 (Friday), 2018, 12:30 pm Grouping: Completed by a group
Background
In this programming assignment, you will create a Pong game that can be played over the network. You can design the protocol that the game uses so that both competitors can see the same synchronized game board, and you may choose whether to use TCP or UDP. You are free to reuse parts of your programs from assignments 1-3 to finish this programming assignment. Note: please refer to appendix A for the port number assigned to you (the same as PG1).
For the assignment, you will turn in a gzipped tar file to your dropbox. The gzipped tar file should contain:
Reasonably commented code
A Makefile or other compilation instructions
README documentation
The Game
Pong is played by two competitors. A ball bounces between the two sides of the court, and each player controls a paddle to deflect the ball when it reaches their side. The goal is to score points by getting the ball past the opponent's paddle. A local (non-networked) implementation is provided at /afs/nd.edu/coursefa.18/cse/cse30264.01/files/program4/pong.c (along with its Makefile) for a starting point. The left paddle is controlled using the W / S keys, and the right paddle is controlled by the UP / DOWN arrow keys. The program uses ncurses for the interface, so it can be run through an ssh session.
Below is an example of the provided UI. The two paddles (controlled by the players) are on the sides, and the ball is currently in the upper right next to the score. The competitor on the left has 1 point, and the right has 0. This GUI along with the code to run it is provided at /afs/nd.edu/coursefa.18/cse/cse30264.01/files/program4/pong.c. Note: The provided code is formatted as a starting point to be modified, not as a library.
This assignment is intended to be far more open-ended than previous assignments. Here we provide a few suggestions based on what we have observed to work well, but we expect you to design the protocol you use. We also state requirements that you are responsible for implementing.
Structure
Your implementation should use a peer-to-peer structure. The alternative is to have a separate game server, making for three hosts in communication. However, since there are only two players in pong, using a direct connection between them can be much easier to implement than having a separate game server. Care must be taken, however, to resolve any discrepancies that arise because of timing issues. For example, if the ball is about to go past Player1's paddle, but Player1 moves the paddle just in time, then it is possible for Player1 to observe a save while Player2 observes that a point is scored. Your protocol must be able to resolve such discrepancies fairly, that is, there is no structural advantage for one player over the other.
Even though the structure is peer-to-peer, the initialization of the protocol requires one host to listen for incoming connections (i.e., it is hosting the game) while the other makes an outgoing connection. Therefore, you should use the flag "--host" to differentiate between the two roles in the initialization of the protocol.
Synchronization
You may choose how and when the two running instances of the game communicate with each other. Two popular approaches we can recommend are timer-based and event-based systems. In a timer-based system, the instances of the game send each other updated information (paddle position, ball position, points scored, etc.) at a fixed rate, e.g., 20 times each second. Alternatively, under an event-based scheme, updates are only sent when something important happens (e.g., paddle moves because of user input, a point is scored, the ball is deflected).
UDP vs TCP
You may choose whether to use UDP or TCP. We found that the TCP and UDP protocols work best when paired with certain update schemes. Since UDP is lightweight but does not guarantee error-free delivery, we found that it works best with a timer-based update scheme. If a packet is corrupted or fails to arrive, then the next one can be used instead. TCP, on the other hand, will bog down a game at a much slower update rate than UDP in a timer-based scheme. Therefore, TCP is better suited for an event-based scheme, where the built-in delivery guarantees that a packet won't be missed.
Quitting
The game exits when one competitor terminates the application, e.g., by pressing CTRL-C. When this happens, both players should exit gracefully. You may find it useful to set up a signal handler to intercept the CTRL-C:
#include <signal.h>
void handler(int signal) {
// do cleanup tasks (send termination message to peer, close socket cleanly, etc.)
endwin(); // clean up ncurses
exit(0);
}
Then, in your main method:
signal(SIGINT, handler);
Speed
The provided pong.c code allows players to set the difficulty, which corresponds to the time between ball movements (a smaller time interval means the ball moves faster, which makes the game harder). Your networked version should also allow difficulty settings. The three difficulties are: easy where the rate is 80 milliseconds, medium where it is 40 milliseconds, and hard where it is 20 milliseconds. The difficulty setting should be a runtime parameter to the peer acting as the server, i.e., receiving an incoming challenge.
When running the code, please use the following syntax for arguments:
[user@server ~]$ ./netpong --host PORT DIFFICULTY
[user@client ~]$ ./netpong HOSTNAME PORT
A demo:
Note: Please set the quality of the video to be 720p by clicking the gear in the lower right of the video.
Your code may be written in C or C++. Your submission should include a Makefile for building your code appropriately.
Don't forget that the Endian-ness matters. Use htons / ntohs in order to encode a 16 bit (short) value for transmission. Use htonl / ntohl for 32 bit (int) values.
When in doubt, add in extra printf or cout statements to assist with debugging. Make sure to add in a carriage return or do a flush on the I/O buffer to ensure that debug information is displayed before program crashes occur. Make sure to disable your debugging output before handing in the assignment.
The ncurses library, which is used for the graphics in this assignment, affects the position of the cursor. This may make debugging information difficult to read if it is multiple lines long. For extensive debugging, try writing output to a log file. In another terminal, you can use the command tail -f on the log file to monitor it in real time.
If you wish to use Valgrind to debug a segfault, configure it to use a log file rather than printing to stdout, e.g., valgrind --log-file=valgrind.out ./netpong ...
You can connect back to localhost (127.0.0.1), which will allow you to test your code on the same machine where you have the server running. Create a separate ssh terminal session back to the server and then run your client code by connecting to localhost.
If your test machine is overloaded (check using the top command), then you may need to switch to another machine in order for the game to run smoothly.
The peer that hosts the game by listening for a connection should listen on the specified port number [refer to Appendix for the port number for your group] that is given by command line argument. Your server should bind to the port and then listen for incoming client connections. You may want to allow for port reuse for quicker recovery after a crash.
Your game should be invoked as follows: ./netpong --host PORT DIFFICULTY
And on another computer: ./netpong HOSTNAME PORT
Submission
Submit a gzipped tar file of your entire assignment package to your dropbox/program4 directory. The archive must include the following:
Working game code
Makefile for the game
Source file(s) for the game
Appropriate comments and your name
README file
Listing of the included file names and example commands to run your code in the archive
Grading Rubric
Game code (90 pts total)
[20 pts] Game behaves and scores correctly.
[20 pts] Paddle and ball movements are synchronized between game instances.
[5 pts each] Easy, medium, and hard difficulty modes are implemented correctly.
[10 pts] Points are scored without discrepancies.
[10 pts] Random errors are handled correctly (packet loss, corruption, timing).
[10 pts] If a competitor quits (e.g., using CTRL-C), then the other exits gracefully.
[5 pts] Code provides reasonable error checking.
[5 pts] Reasonable code performance (runs without errors).
[5 pts] Code is commented with appropriate header information.
Overall (10 pts total)
[4 pts] Included Makefile and code compiles without errors.