Code Correctness
In CS 3, we expect you to pay careful attention to the quality of your code (not just if it “works”). Each week, we will expect you to apply all the items we’ve been looking for in every previous week in addition to the new ones.
So, far, we’ve asked you to pay attention to:
- good variable and function names
- procedural decomposition
This week, we will focus on all of the previous items as well as the following:
- “overcommenting” (e.g., the comments do not explain things that are already clear from the code itself)
- usage of whitespace
- overmodularization (e.g., modularizing into functions that actually make the code less clear)
Deliverable
This week, you will be starting your game by implementing images using the SDL image library. However, before you get started, here is a little more information:
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:
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 game.c
file should not have a main loop.
The header file for the functions you write in your game 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 game.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. 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.
For a reference of a working demo that uses this overarching structure, please consult https://gitlab.caltech.edu/cs3-23sp/emscripten-demo.
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.
Images
Now, it’s time to implement images! We have given you an image in the assets
folder. You will be writing code so that when you compile your C program, the image will appear like the following:
For the current project and all future projects, make sure that all your assets (images, text, sound files, etc.) are stored in and referenced from ONLY the assets folder. Not only is this for stylistic purposes, but your files won’t be compiled if they aren’t in the right folder.
For some help, take a look at the official SDL documentation or some resources here! Also keep in mind that SDL_GetError()
and IMG_GetError()
may come in handy when debugging your code (more information in the previous links).
Since the game runs in the main while loop (that is implemented by emscripten.c
), you may end up indirectly calling IMG_LoadTexture
multiple times when rendering your image. While not noticeable at this stage, once you start adding more images to your game, this may cause it to run much slower. Thus, make sure you are writing your code so that you only need to load the image texture once!
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:
- include: header files go here
-
library: source files for your libraries (e.g.,
vec_list
,polygon
, etc.) - demo: source files for the demos go here
- tests: test source files go here
- out: built object files will be generated here
- ref: reference object files for the demo and game are provided here
- bin: built binaries will be generated here
We have provided you with a Makefile
which is set up to build the project. It allows you to run the following commands:
-
make demo
: compile the demo and runs the web server -
make game
: compile the game and runs the web server -
make test
: compile all libraries and tests and run all the tests -
make NO_ASAN=true demo
compiles the demo without asan - this is recommended for running demos -
make server
: Run the web server with the current binaries -
make clean
: remove all generated binaries
This year, we will be testing demos/games 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 game
or make server
, or by running cs3-port
in a shell on labradoodle.
To run your game, you should run make game
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 .game.html
file. If you see an error that says Address already in use
, please run cs3-kill-web
in the terminal and rerun make game
.
Task 1. When you are done, your group should meet and complete the questions here.