CS414 Spring 2017 Program #5

Due: Thursday, April 6th, 2017. This is a two-week assignment!.
Late penalties: Thu: -5%, Fri -10%, Sat, Sun, Mon -20%

Goals

This assignment expands the following skills:

Before You Begin:

When You Are Done:

To turn your work in, go to mycourses.unh.edu, find CS414, and find the assignment. Then click "Submit Assignment" to upload your main file, asteroids.py, plus any other files you have created.

Asteroids

The game Asteroids appeared in 1979. It has rocks (the asteroids) moving and tumbling across the screen. At the center of the screen is the user's ship. The user must fire bullets at the asteroids, to break them into smaller rocks. If a bullet hits a small rock, the rock is destroyed.

The game ends successfully when you have destroyed all the rocks. The game ends in failure when a rock hits the ship.

If a rock passes through the right edge of the play area, it re-appears on the left side. Similar things happen when a rock passes through the other sides: it reappears on the opposite side.

Here is a screenshot showing the game in action:

It shows the ship in the middle, and rocks of various sizes.

Controls

The ship is controlled with the keyboard, as follows:

Implementation

The central part of the game will be controled by the update_scene function:
      def update_scene():
          global time_before
          time_now = time.time()
          time_elapsed = time_now - time_before

          move_objects(time_elapsed)
          draw_objects()

          time_before = time_now
          t.ontimer(update_scene, 100)
    
The last line of the function: t.ontimer(update_scene,100) causes the update_scene() to be called 10 times per second.

As you can see, each time the function is called, it gets the current time, and finds out how much time has elapsed. It uses this to move the objects, and draw them in their positions.

Moving an object

The objects in the game (the rocks, the bullets, and the ship) move at constant speed, in straight lines. They also may rotate, as they move (only the rocks rotate, though).

Each object will need the following information (seven numbers):

Here is the math you need to move an object in this way. Suppose T is the time elapsed. Then
        x += vx * T
        y += vy * T
        angle += turn_rate * T
      

Motion Data

Each object needs seven numbers to describe its motion. We can simply store this in a list with 7 floats, for each object: [x, y, vx, vy, angle, turn_rate, size]. Let's call such a list a motion record. You will need these motion records, for the whole game:

Thus we can move an object as follows:
        def move_object(motion_record, T):
            vx    = motion_record[2]
            vy    = motion_record[3]
            rate  = motion_record[5]
            motion_record[0] += vx * T
            motion_record[1] += vy * T
            motion_record[4] += rate * T
      

Drawing an Object

In the screenshot above, the rocks have different shapes and sizes. In our game, all rocks will have the same shape, but may be of different sizes.

Drawing a bullet is simple. We just draw a dot which is, say 3 pixels wide:

        def draw_bullet(motion_record):
            x     = motion_record[0]
            y     = motion_record[1]
            turtle.penup()
            turtle.goto(x, y)
            turtle.dot(3)
      
To draw a rock, we have to consider its x y position, and its rotation angle:
        def draw_rock(motion_record):
            x     = motion_record[0]
            y     = motion_record[1]
            angle = motion_record[4]
            size  = motion_record[6]
            turtle.penup()
            turtle.goto(x, y)
            turtle.setheading(angle)
            turtle.pendown()
            ... then, a sequence of turtle.forward(...), and
                turtle.left(...) function calls, to draw a rock
      
And drawing the ship is similar to drawing a rock.

Firing Bullets

To fire a bullet, it should appear on the tip of the ship, and start moving. So, we must get its x y position, based on the ship's position and angle. Its velocity will also depend on the ship's angle.

You will need these values:

Then, you can use this math to compute the bullet's motion: Once you've created a bullet, just append its motion record to the list bullet_motions.





Checking for Collisions

If a rock hits the ship, the game is over. If a bullet hits a rock, the rocks is split into smaller rocks, or the rock is destroyed. So, need to know how to check if two objects have collided. Here, you should use a very simple test, which is approximate: just pretend that each object is a circle.

Two circles will overlap if their center-to-center distance is less than the sum of their radiuses:

        def collided(x1, y1, radius1, x2, y2, radius2):
            dx = x1 - x2
            dy = y1 - y2
            distance = math.sqrt(dx * dx  +  dy * dy)
            if distance < (radius1 + radius2):
                return True
            else:
                return False
      
All you need to do is figure a reasonable radius for each object. Then you should call this function, and pass it the centers and radius of the objects you think may have collided.