CSCI 136
Fundamentals of Computer Science II
Spring 2020

Montana Tech of The University of Montana
Computer Science & Software Engineering



ASSIGNMENT 4

In this assignment, you will be extending a video game called Staying Alive. In the process, you will gain experience using classes, objects, abstract classes and inheritance.


Staying Alive
This is the same game we wrote in CSCI 135, but this time I want you to take the existing code and 1) extend it, and 2) refactor it into simpler code through the use of inheritance and abstract classes.

The object of the game as it is now, is to avoid a bunch of objects that are zooming around the screen and bouncing off the walls. The game is over if the player is hit by any of the objects. The player scores a point for every time step of the game in which they stay alive. The game is played with the mouse. The player's character moves in the direction of where the mouse was clicked. The further the mouse cursor is away from the character's current location, the faster the player moves towards the mouse location.

You are to extend the game so that friendly objects randomly appear on the screen and give bonus points if the player hits them. Once a bonus object is hit, it is removed from the game.

Suggested Approach
First, you should read through the entire assignment so you understand what you need to do, and then look at the code have been provided. Once you have an understanding of what code needs to be added, implement the Bonus class and get that part to work. Then, look at the classes you have and the code you've been given and decide how best to use inheritance and an abstraction hierarchy to minimize code duplication. Once you have a design strategy, start implementing the class hierarchy.

Classes: You should start by downloading the file student.zip. This file contains some example control/configuration files and the associated images. These files will need to be in the same directory where you run your program. It also contains all the add-on python libraries such as StdDraw that you will need to run the code. The code provided will run as-is, to play the old version of the game.
Your first task is to implement the Bonus class, representing the friendly objects bouncing around. The API for this class, without inheritance, is shown below. There is a commented out method in the Game class called addBonus which will create these objects and add them to the game. (The import Bonus line at the top of the Game code file is also commented out.) Additionally, in the StayingAlive main game loop, there is commented out code that will decide at random whether to generate a bonus, and will update its position. Once you have implemented this class, you should test it by uncommenting that code and running it. The only modifications you should make to these two files, Game.py and StayingAlive.py, are to uncomment the commented out code.
class Bonus
-----------------------------------------------------------------------------------------
        __init__(float x, float y, float r, float vx, float vy, int points)
                          # create a Bonus at screen coordinates x, y with
                          #   radius r. It has x and y velocities of vx and vy,
                          #   and gives the user points number of points if hit

        draw()            # draws the Bonus as a filled red circle 
        updatePos()       # Adds the x and y velocities to the x and y positions
                          #   to store a new location for the Bonus object
 string toString()        # returns a string representation of a Bonus in the
                          #   same format as other space objects

Your next task is to decide how to simplify the code through inheritance and abstract classes. You must use at least two additional abstract classes, but how you implement these, and if you add more, is entirely up to you.

Once you have completed the final design and refactored the code (and it still works), make sure to document your design in the header comment of your top level abstract class. You should describe the inheritance structure of your classes and why you chose the structure you did.

You need to decide which class(es) should use inheritance, from which other classes, and which should abstract or not. Remember to comment every method (every method needs a comment describing what it does, what parameters it takes, and what it returns), and to comment every class.


Here is a description of the four program files provided to you: Control file. The client program StayingAlive.py calls Game to read in a game control file which is specified as a command line parameter. Note that you don't need to write this code - it has been done for you. Here is an example game control file hitchhiker.txt with comments at the end describing the order and meaning of the values:
stars.jpg
dont_panic_40.png 0.5 0.5 0.035 100
6
asteroid_small.png 0.1 0.1 0.018 -0.002 -0.003
asteroid_medium.png 0.2 0.2 0.030 0.002 -0.003
asteroid_large.png 0.3 0.3 0.065 -0.002 0.003
asteroid_small.png 0.4 0.4 0.018 -0.001 -0.004
asteroid_medium.png 0.6 0.6 0.030 0.002 -0.003
asteroid_large.png 0.7 0.7 0.065 -0.0035 0.0025

# Hitchhikers Guide to the Galaxy: Avoid a bunch of objects
#  <background image>
#  <player image> <player x-position> <player y-position> <player radius> <player speed factor>
#  <number enemies>
#  <enemy0 image> <enemy0 x-position> <enemy0 y-position> <enemy0 radius> <enemy0 x-velocity> <enemy0 y-velocity>
#  <enemy1 image> <enemy1 x-position> <enemy1 y-position> <enemy1 radius> <enemy1 x-velocity> <enemy1 y-velocity>
#  ...
Console output. The StayingAlive.py program will output the intial game state to the console window:
% python StayingAlive.py hitchhiker.txt 
PLAYER: (0.5, 0.5) vel (0, 0) r=0.035
ENEMY 0: (0.1, 0.1) vel (-0.002, -0.003) r=0.018
ENEMY 1: (0.2, 0.2) vel (0.002, -0.003) r=0.03
ENEMY 2: (0.3, 0.3) vel (-0.002, 0.003) r=0.065
ENEMY 3: (0.4, 0.4) vel (-0.001, -0.004) r=0.018
ENEMY 4: (0.6, 0.6) vel (0.002, -0.003) r=0.03
ENEMY 5: (0.7, 0.7) vel (-0.0035, 0.0025) r=0.065

Object dynamics. The following description of object movement is provided as a reference so you can implement your Bonus class. The Bonus objects should move in the same way as the Enemy objects, but of course, should increase points and disappear rather than signalling that the game is over.

Player dynamics. The Player object updates its x-position and y-position based on the current mouse location. The current mouse location is obtained by calling StdDraw.mouseX() and StdDraw.mouseY(). These methods return a double representing the mouse location in the current StdDraw coordinate system. The mouse coordinates are sent to the Player object via the updatePos(double mouseX, double mouseY) method. To calculate the player's new x-position, the code increments the current x-position by the difference between the mouse coordinate and the player's current position divided by the player's speed factor.

For example, if the player has a speed of 100 and is currently at an x-position of 0.5 and the mouse is at the x-coordinate 0.7: (0.7 - 0.5) / 100.0 = 0.002. After the update, the player's new x-position would be 0.5002. Note that a higher speed factor actually causes slower responsiveness to the mouse input.

Enemy dynamics. The Enemy objects update their position in the updatePos(double x, double y) method by adding their x-velocity and y-velocity to their x-position and y-position respectively. In updatePos(x, y), the code also checks if the position has gone out of the box (0.0, 0.0) - (1.0, 1.0). If so, the code inverts the x-velocity and/or y-velocity as appropriate.

Collision detection. For simplicity, we assume the player and other space objects are all circles. The game is over if the circle representing the player intersects with any enemy circle.


Grading Because you are creating your own design, there is once again no way to have an Autograder.py program. Next time? (Actually probably not, because the next assignment is creative also... but once we have more concrete assigments again, the autograder will come back...)

Grade ItemPoints PossiblePoints Earned
Programs Compile and Run
2
Comments on All Classes and Methods
4
Header Comment
2
Bonus Class Implemented Correctly
6
Uses Inheritance Appropriately
6
At least Two Abstract Classes
6
Appropriate Description of Design Choices
4
Total
30


How do I write comments on the inheritance structure? You can create a text based format of a UML diagram to show the relationships. Something like this, based on the example we did in class of multiple inheritance, would be appropriate:

Clock                            Calendar
------                           --------
hours                            days
minutes                          months
seconds                          years
-------                          --------
__init__()                       __init__()
set_Clock()                      leapyear()
toString()                       set_Calendar()
tick()                           toString()
   |                              advance()
   |                                  |
   |----------------|-----------------|
                    |
                ClockCalendar
                -------------
                
                -------------
                __init__()
                tick()
                toString()

Should I use multiple inheritance? Only if it makes sense in the way you've designed your class hierarchy. It is not required.


Extra credit. There are plenty of possibilities to improve the game. For example:
Submission. Submit your code Bonus.py and all other classes you have created or modified to the Moodle dropbox for Lab 4. Remember that except for removing the comments from the code in StayingAlive.py and Game.py, these files should not be changed, and do not need to be submitted. Be sure each submitted source file has the required header with your name and a description of the program, and all of your methods and classes use proper comments.

If you choose to do extra credit, submit those files to the Extra Credit drop box at the top of the Moodle webpage.

Page last updated: December 28, 2020