A simple and pure win32 Snake game, without any compressor trickery, just under 2,953 bytes!
The original source code was taken from MattKC's "Can you fit a whole game into a QR code?" video where he attempted to port the classic game of "Snake" into a single QR code using the Win32 API in C. Despite the efforts he failed and decided to use a compressor to complete the challange during the final stretch, which felt very lame and lazy to me. So much so that I took a glance at the source code to see if there were any optimizations to make.
My suspicions were proven correct as I was not only able to fit the program into the QR code threshold without changing its fundamental logic, but I also implememted some fixes and improvements compared to the original.
- No crinker/compressor is used to reduce the executable size. Only Win32 C code and some MSVC compiler flag shenanigans.
- A few visual and gameplay fixes have been added to the game to make it much closer to the HTML version that was shown in the video.
- You can pause the game now by pressing the enter key instead of the 'pause' or 'P' key.
- You can retry the game by pressing the 'R' key.
To see all of the differences it's best to compare this repository's snake.c and the original side by side. Here is a compiled list of the changes:
- The input system has been reworked to utilize only 2 variables instead of using an array of valid inputs. This reduces quite a considerable amount of space inside the executable, as the game now does a whole less for the same result.
- The food starts at a constant position instead of calling the
randfunction at startup. - All integers are
size_t(register-sized instructions are usually preffered in most cases). - A custom
randis implemented instead of relying on the C standard version. - Code to change the snake's color depending on the game state (playing/won/lost) has been reworked to be completely branchless.
WM_TIMER'swhileloop has been converted to a singleifstatement.- Removed the
bool movedvariable inWM_TIMERand usedgotoinstead. - Removed the
elsestatement atif (snake_len == MAX_TILE_COUNT). - Removed
GetModuleHandleAandAdjustWindowRect. - The app now uses stack memory instead of the heap to hold
snake_pos(this reduces the amount of OS calls needed to be called). - Removed
if (msg.message == WM_QUIT)in the main loop. - Removed
TranslateMessagein the main loop.
- The original
snake.cleaked memory by continuously not callingDeleteObjectwhen usingCreateSolidBrushdespite official documentation advising to cleanup after drawing. The only caveat with this is that this unfortunately comes with the cost of additional binary space.
- The apple is now green.
- You can now retry the game at anytime by pressing 'R'.
- The game's performance has been improved (less branching,
PosEqualdoes one check instead of 2, etc). - The pause button has been changed from
VK_PAUSEandPtoVK_ENTER. - Regular
WNDCLASSAandCreateWindowAare used instead of the expanded versions. - The game doesn't overallocate
dir_queuelike it did in the original.
NOTE: cl.exe is assumed to be x86, not x64. Compiling it in 64-bit will considerably increase the size of the binary.
Just copy the terminal commands from Makefile and paste them into the terminal.
This requires downloading msvc from msvc-wine. After that, just run make and you'll get correct binaries.
Once you compiled snake.exe, on Unix you can run make qrcode to generate code.png.