If you run into Makefile/compilation errors, you can run the script cs3-check-files
to check that you’ve ported over all required files. The script will tell you which files are missing in the terminal, or you can check the .required-files
file in your repo. If all required files are present, the terminal will not print anything.
Introduction
This week, you will be implementing a library to help manage the assets (like fonts, images, etc.) that we use in our games. So far, we’ve managed assets by storing them in our state_t
struct. However, as our game grows, we will need a more organized way to create, store, and use assets. In this project, you will implement a library that will do exactly that! Finally, to test that it works, you will then use it to implement the same game as last week, but with our new asset library.
Overview
One of the pitfalls of storing all our individual assets in our state_t
struct is having to find the variable in state_t
that corresponds to the filepath of the asset we want to use. This is cumbersome for the programmer and error-prone. Instead, what if we had a struct like a cache, or store of assets, that could retrieve the asset for us using just the filepath? You will be implementing such a struct in asset_cache.c
.
asset_cache_t
To implement the functionality stated above, we will manage our assets using a map that is built on top of our list_t
struct! While our time complexity won’t be as good as a hash table, it will be more than sufficient for our purposes due to the (relatively) small number of assets we will be using.
To implement key-value pairs, we will use an entry_t
struct (provided in asset_cache.c
) with the following fields:
-
filepath
: This will be the filepath to the asset and serve as the “key” of our map. Note theconst char *
type! -
type
: This will be the “type” of asset that we are storing, represented as an enum that is defined inasset.h
. You can take a look at it if you want, but all you need to know is that the only defined types areASSET_IMAGE
andASSET_FONT
. -
obj
: This will be a pointer to the actual asset that we are storing (e.g.SDL_Texture
for images andTTF_Font
for fonts) and serve as the “value” of our map. Why do you think we are using avoid *
type here?
asset_cache_init
and asset_cache_destroy
have been provided for you. Before you take a look at them, here are a few things to keep in mind:
-
ASSET_CACHE
represents the singleasset_cache_t
that we will be using. Since we only need a single instance of the cache to store all our assets throughout the lifetime of our games, we can declare it as a global variable in our file. -
FONT_SIZE
is the font size that allTTF_Font
s will be rendered with. Since we can change the size of text by changing the size of the surface that it’s being rendered on, we will use this constant to simplify rendering text.
Now you’ll be implementing the rest of the functions in asset_cache.c
!
Task 1.
Implement the asset_cache_free_entry
and asset_cache_obj_get_or_create
functions in library/asset_cache.c
.
Take a look at the documentation in library/asset_cache.h
and the comments in library/asset_cache.c
to understand what each function should do.
asset_t
Having an asset_cache_t
is great, and now we can access assets by just using the filepath! However, we still have a few problems:
- We have to manage different
SDL_Texture
ANDTTF_Font
objects. With each, we also have to store asset-specific information (e.g. the text color). - Each asset also shares similar information like the size of the render surface.
It would be much easier to abstract these details away and use a single struct that contains all the information we need to render an asset. That way, all we need to do is to initialize an asset with its appropriate arguments and render it. This is where the asset_t
struct comes in!
The asset_t
struct will contain fields like the type
of the asset (corresponding to the same type
field that we used in the entry_t
struct!) and the bounding_box
that stores the dimensions and location of the asset when it’s rendered. However, since each asset also requires type-specific fields, we will implement two other asset structs that “inherit” from asset_t
using the C inheritance pattern. These structs have been defined for you in the asset.c
file.
Task 2.
Implement the asset_make_text
, asset_make_image
, and asset_render
functions in library/asset.c
.
Like before, take a look at the documentation in library/asset.h
and the comments in library/asset.c
to understand what each function should do.
Game
Now, it’s time to put it all together! We have given you starter code for last week’s meme generator project in game.c
. The only thing you need to implement is the generate_memes
function. We’ve included documentation about what it does, but also take a look at where generate_memes
is being called and what emscripten_main
is calling to get a general sense of how it’s being used.
Task 3.
Implement the generate_memes
function in game.c
to complete the meme generator.
Now you’ve completely transformed your meme generator to one that is much more encapsulated, abstracted, and easy to use. This will pay huge dividends for your game later down the line. Great work!
Open-ended Questions
Task 4. When you are done, your group should meet and complete the questions here.