- Use arrow keys to move starship: ⬆️, ⬇️, ⬅️, and ➡️
- Rotate the ship clockwise by pressing
$\textcolor{orange}{D}$ . - Rotate the ship counterclockwise by pressing
$\textcolor{orange}{A}$ . - To fire phaser blasts press the
$\textcolor{orange}{space bar}$ .
On Ubuntu run
apt install libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev
On Mac OS with Homebrew
brew install sdl2 sdl2_image sdl2_ttf
The project compiles in the Udacity workspace environment.
Criteria | Example |
---|---|
The project accepts user input and processes the input. | The Controller class handles user input. See for instance Controller::doKeyDown . |
The project reads data from a file and process the data, or the program writes data to a file. | The Renderer class reads texture files from the /resources directory. Specifically, in the member initialization list of constructor Renderer::Renderer(const int h, const int w) , line 137 of Renderer.cpp . |
Criteria | Example |
---|---|
Classes follow an appropriate inheritance hierarchy with virtual and override functions. | PhaserBlast , Asteroid , Player , are all derived from an abstract class called RenderableEntity . Function collidesWith is overridden in the derived classes. |
Class constructors utilize member initialization lists. | All class constructors in the project use initialization lists. See, for example, the constructor defined on line 9 of Game.cpp . |
Templates generalize functions or classes in the project. | Class ThreadSafeQueue wraps std::queue<T> ; consequently, all of its member functions are templated. |
Criteria | Example |
---|---|
The project uses scope / Resource Acquisition Is Initialization (RAII) where appropriate. | make_unique and make_shared are used to create PhaserBlast and Asteroid entities, respectively. Additionally, Asteroid collision detection is run on threads managed by each Asteroid instance. Furthermore, collision detection threads are properly destructed when the Asteroids owning them are deleted. |
The project follows the Rule of 5. | Classes Asteroid and Explosion define all 5 constructors. |
The project uses move semantics to move data instead of copying it, where possible. | Newly created PhaserBlast , Asteroid , and Explosion entities are pushed into their respective ThreadSafeQueue , by using move semantics. For instance, phaser blasts are create by a factory in the player instance when the corresponding key press event is captured in Controller::doKeyDown . The produced PhaserBlast instance is immediately moved into a ThreadSafeQueue<PhaserBlast> on line 30 of Controller.cpp . |
The project uses smart pointers instead of raw pointers. | make_unique and make_shared are used to create PhaserBlast and Asteroid entities, respectively. For instance, see line 40 of Game.cpp . |
Threads are created in a few places.
- On line
102
ofGame.cpp
, Asteroids are spawned on a thread separate from main, by functionGame::Spawn
.
// start asteroid spawning on its own thread.
_threads.emplace_back(&Game::spawn, this, std::ref(renderer));
- In function
Game::Spawn
, after a new asteroid is created, collision detection for the asteroid is started on a thread owned / managed by the asteroid.
/** Launch checkForCollision on its own thread. */
void Asteroid::detectCollision(...) {
this->_thread = std::thread(&Asteroid::checkForCollision, this, phaserBlasts, explosions, player, running, isInsideWindow);
}
- I defined
ThreadSafeQueue
to managePhaserBlast
,Explosion
, andAsteroid
collections.ThreadSafeQueue
guarantees safe access by blocking access to the underlying queue withlock_guard
and the mutex member_mutex
. For example thepush
method,
template<typename T>
void ThreadSafeQueue<T>::push(T&& t) {
std::lock_guard<std::mutex> lock(_mutex);
_queue.emplace_back(std::move(t));
}