CS 3 (Spring 2025) Project 01: Bouncing Star (Demo)

In this project, you will implement a simple simulation of a star bouncing across the screen.

Code Correctness

Goals and Deliverables

Before we start, register for the project using the registration tool.

This week, you will build a simulation that uses a basic library that is provided to you. Specifically, you will make a star that bounces off of the walls of the screen.

Unlike what you might have done in previous courses, we want you to use the library without knowing how it’s actually implemented. Using CS 2 as an analogy, think about this as writing the demo with only access to the interface, but without any implementations of the interface. You won’t see the function internals, but you know what they do given the documentation.

You’ll read more about this at the bottom of the page, but when you compile your demo, your bounce.c file will be compiled and linked to the compiled version of the library in the ref folder. As long as you call the methods specified in the .h files, your demo should work as intended.

In other words, for this week, you do NOT need to write implementations for any of the .h files. The ONLY file that you should be writing code in is bounce.c.

Now, here is a summary of said libraries that you will be using when writing your demo:

vector_t

In vector.h, we’ve provided function prototypes. See the provided documentation in vector.h for what the functionality should be. vector_t will 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 body, 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.

Bodies

A body can be represented as a fixed-size vec_list_t. We will take the convention that a body’s vertices are stored in a counter-clockwise order. However, we need a way to change the locations of these vertices. This is where body.h comes in. You will find the functions in there very helpful in moving your star.

Bouncing Star

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 writing these functions, you can see how they interface with the lower-level SDL2 library in sdl_wrapper.c.

Files of Importance

The above basic loop is implemented in emscripten.c, which relies on a number of functions you will write in your demos - namely, emscripten_init, emscripten_main, and emscripten_free. emscripten.c serves as the basic functionality of all our demos - you do not need to modify this file. Notably, because emscripten.c implements the main while loop described above, your bounce.c file should not have a main loop.

The header file for the functions you write in your demo is state.h, which tells emscripten.c that these three functions are properly defined elsewhere. You do not need to write a state.c file - you should write the three functions in the header in your bounce.c demo as mentioned above. Notably, state.h also includes an opaque type definition for a “state”. This is a struct that you will define in each of your demos (here, in bounce.c). This state struct is how you will pass information between your three functions - anything you initialize in emscripten_init that you need in your emscripten_main loop should be put in this state accordingly and returned. You are responsible for defining the state’s parameters, malloc’ing it in emscripten_init and freeing it in emscripten_free.

Using the basic breakdown of the files above, and the documentation in sdl_wrapper.h and state.h, you should be able to get a good idea of how to implement a graphical application in C, using our wrapper library.

Although it does not use the same abstractions, the circle.c demo works with emscripten.c and state.h in the same way you will.

A Bouncing Body

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.

In your bounce.c file, you should write your emscripten_init to initialize everything you need for the demo, including the SDL window itself (you will find a function in sdl_wrapper.c to be useful here). Then, in emscripten_main, 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. When the demo exits, emscripten_free is called, so you should write this function to clean up all the memory you allocated in the demo.

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 a code review!

Running and Testing your Code: make and the Makefile

In project 0, you used clang 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:

Note that the make commands that are supported depends on the type of project that week. Since this week’s project is a “demo,” make game and make test will not work.

This year, we will be testing demos via a web interface hosted on labradoodle, using a library called emscripten.
Every student has been assigned a port, which you can see after running make demo or make server, or by running cs3-port in a shell on labradoodle. To run your demo, you should run make demo or make server and then navigate to the link printed to the shell (the last line before “Serving HTTP on …”) and click the compiled demo .demo.html file. If you see an error that says Address already in use, please run cs3-kill-web in the terminal and rerun make demo.