CS 3 (Spring 2021) Project 01: Bouncing Star

In this project, you will begin your physics engine by starting to build the underlying data structures. You will also implement a simple simulation of a star bouncing across the screen.

Code Correctness

Goals and Deliverables

In this project, you will begin writing the codebase you will be working with over the next several weeks. As groups combine, we will ask you to choose pieces of each person’s codebase; so, it is entirely possible that you will still be using some of this code in week 10 of the term. This week, you will build primitive physics engine objects, a data structure, and a simulation that uses your work.

vector_t

Last week, you wrote a simple set of functions that dynamically allocated memory for a (2D) vector_t using malloc, freed this memory, and added two vector_ts. For all the reasons discussed in class, it is not ideal to allocate all the vector_ts this way. So, this week, you’ll be writing a more extensive set of functions that act directly on vector_ts that are not pointers. Your vector_t will eventually represent position, velocity, acceleration, and other vector quantities in your physics engine.

vec_list_t

In CS 2, you may remember that we created an ArrayList in Java from scratch, making it auto-resizable and generic. We will eventually get to the same place in C, but, because C doesn’t provide as nice abstractions as Java, it’s going to take us a few weeks. This week, since we only need to represent a single polygon, all we need is a fixed-size ArrayList of vector_t *s. Notice that we are using pointers, not values here! This will be important later.

Polygons

A polygon can be represented as a fixed-size vec_list_t. We will take the convention that a polygon’s vertices are stored in a counter-clockwise order.

Bouncing Star

Finally, the fun part! Now, you get to build a graphical simulation of a star bouncing around the screen!

Ticks and the Main Run Loop

We’re going to be working through a lot of graphics-related code in this class, so it’s important to understand the basic concepts behind drawing graphical content to the screen.

When we talk about graphics in the context of writing software, we are dealing with computing the contents of individual frames in real-time, clearing the canvas of the previous frame, and drawing the new computed frame, all at regular intervals. If you want your graphics to look realistic, you need to have a reasonable measurement of the time between frames, since our goal is to generate a graphical representation that is independent of the speed at which frames are processed by the computer. This is why low frame rates in graphics-intensive games result in a scene that is choppy – each frame encompasses a large amount of real-world time, causing objects to move large distances in each frame. The most basic implementation of a graphical application, then, looks as follows:

while app_is_running:
    dt = time_since_last_frame()
    object_pos = compute_new_positions(object_pos, dt)
    
    clear_screen()
    draw_frame_offscreen()
    display_frame()

We’ve provided a few helper functions to help facilitate these operations, you can see how they interface with the lower-level SDL2 library in sdl_wrapper.c. Using the basic breakdown of a graphics runloop above, and the documentation in sdl_wrapper.h, you should be able to get a good idea of how to implement a graphical application in C, using our wrapper library.

A Bouncing Polygon

We are going to specifically be implementing a simulation consisting of a 5-sided star bouncing around the window while rotating. However, since we have not implemented the “physics” part of our physics engine, yet, we’ll be implementing collisions with the window as perfectly elastic collisions that reverse the velocity in the collision direction. In other words, if the star is moving towards the top wall and collides with it, its y-velocity will change direction.

You should update the position and velocity of your star at each frame using this rule, and the time elapsed since the last frame. You should also have your star rotate at a constant rate throughout your animation. Be sure to implement the run loop in a main function, and make sure to clean up all the memory you allocate, as well!

As always, you should practice good procedural decomposition. Hard-coding a star shape is not acceptable; write code to generate the star for you. Make sure this code is extensible– we might ask you to make a small alteration to your demo during the code review!

Running and Testing your Code: make and the Makefile

In project 0, you used clang (or cl.exe) to compile your one-file C programs. Going forward, our project will consist of many C files. It is important to organize projects carefully to help reduce the complexity that comes with larger programs. Your physics library will have the following directory structure:

We have provided you with a Makefile which is set up to build the project. It allows you to run the following commands:

To run the demo, you should run the following two commands (windows users should use ./bin/bounce.exe):

make all
./bin/bounce

To run all the tests, all you need to type is make test. To run compile and run an individual test suite, run the following commands (replacing vector with the test suite you want to run) (windows users should use ./bin/test_suite_vector.exe) :

make bin/test_suite_vector
./bin/test_suite_vector

OpenEnded

Submit OpenEndeds For Credit