# Retro Snow In this project, you will create a retro animation using terminal escape sequences, that mimics falling snow. This is, in fact, a trivial particle system. Sophisticated particle systems are a routine part of visual effects in television and film as well as crucial tools in scientific computing. ## A Particle A single particle looks like this: ```c++ struct Particle { int32_t line; int32_t column; }; ``` Thus, a particle is made up of two 32 bit integers side-by-side. The first provides the line of the particle, the second its column. ## Screen Size A default terminal window measures 80 characters across and 24 lines down. The origin is (1, 1) located at the top left corner. ## Cursor Movement Snow flakes (particles) will be positioned using an old school VT100 escape sequence. This sequence is: ```text ESC [ line ; column H ``` with no spaces. Using `printf()`, a template string can be employed: ```text "\033[%d;%dH" ``` In C++, you'd do something like this: ```c++ cout << "\033[" << line << ";" << column << "H"; ``` Note that there are no new lines being printed since this would in itself move the cursor to the left edge of the next line and could even cause scrolling - a disaster in this project. ## Erasing the Screen To erase the screen, use this escape sequence after first having moved to screen position (1, 1): ```text "\033[2J" ``` ## A C++ Object To Use As A Model The following C++ can be used to start your thinking about how to go about writing this project. ```c++ struct Particle { int32_t line; int32_t column; void Step(); void Render(); void Reset(); }; ``` ### `Step()` All particles use the `Step()` function to move into the future. The `line` is increased by one and the `column` can either remain unchanged, move to the left or move to the right. If the particle's `line` exceeds 24, the particle is `Reset()`. ### `Render()` To draw a particle, `Move()` to its location then print a "\*" all without emitting a new line. Before printing the "\*", check to ensure both the `line` and `column` are within the boundaries of the default terminal window (i.e. 1 ≤ line ≤ 24 and 1 ≤ column ≤ 80). If the particle's position is outside this range, don't print anything. ### `Reset()` A particle's initial `column` can be anywhere from 1 to 80 inclusive. Special care is given to setting the particle's initial `line`. Specifically, always place the particle above the visible screen... chosen randomly from -1 to -48. This allows for sufficient spacing so that the snow does not appear to fall in clumps. ## The Storm A single snow flakes does not a blizzard make. Therefore, allocate a large number of them - perhaps 150 to 200 flakes. Since assembly language doesn't have actual C++ objects, each flake occupies only the 2 `int32_t` values. Suppose *n* is the number of flakes you choose to model. Then allocate *2 \* 4 \* n* bytes using `malloc()`. Since you will then `Reset()` every one of them, initializing the newly allocated memory is not needed. Then, you'll need a `StepAll()` and a `RenderAll()`. ## The Main Loop * Position cursor at (1, 1). * Erase the screen. * `StepAll()` * `RenderAll()` * Position cursor at (1, 1) again and print a new line. * Delay a short time. In my implementation, I using `usleep()` to delay 217 microseconds. Note only one new line is printed per frame - this is used to force all output to be flushed to the terminal. ## Desired Outcome ![movie](./snow.gif) ## Solution The solution is [here](./main.s).