Learning Zig by following along with the Handmade Hero series of videos by Casey Muratori. This implementation follows Casey's approach as closely as Zig allows with some minor departures when I want to explore some specific Zig feature (like using @Vector to get SIMD vector math for example).
Since the executable looks for the library in the same directory as the executable the regular zig build run approach doesn't work. The easiest solution is to build it first and then launch the built executable (so that it can find the library) with the correct working directory (so that it can find the assets).
PowerShell:
zig build ; Start-Process -NoNewWindow -FilePath ./zig-out/bin/handmade-zig.exe -WorkingDirectory ./data
ZSH + Wine on Linux:
zig build -fwine -Dtarget=x86_64-windows && (cd data && ../zig-out/bin/handmade-zig.exe)
Graphical and audio assets are not included as they are not created by me. The following assets from the pre-order data need to be present to run the game:
handmade_hero_legacy_art.zip/v0_hhasto be in the/datadirectory.handmade_hero_legacy_art.zip/png_art_packsto be in the/artdirectory.- Rename the file called
title_screen.pngtoplate_title_screen.png. - Rename the file called
hand_fire.pngtohand_undead_bones_dark.png. - Rename the file called
hand_glove.pngtohand_glove_fingers.png. - Rename the file called
hand_skeleton.pngtohand_undead_bones.png. - Rename the file called
block_forest_01.pngtoblock_floor_grass.png. - Rename the file called
block_orphanage_01.pngtoblock_wall_manmade_wood_drywall.png. - Rename the file called
block_orphanage_02.pngtoblock_floor_manmade_wood.png. - Rename the file called
block_orphanage_03.pngtoblock_floor_manmade_stone.png. - Rename the file called
character_template.pngtotemplate_character.png. - Rename the file called
item_template.pngtotemplate_item.png. - Rename the file called
character_mummy.pngtocharacter_undead_wrapped.png. - Rename the file called
character_skeleton.pngtocharacter_undead_bones.png. - Rename the file called
character_skeleton_broken.pngtocharacter_undead_bones_broken.png. - Rename the file called
character_skeleton_dark.pngtocharacter_undead_bones_dark.png. - Rename the file called
character_hannah.pngtocharacter_cat_birman_ghost.png. - Rename the file called
character_fred.pngtocharacter_cat_brown_tabby.png. - Rename the file called
character_molly.pngtocharacter_cat_gray_tabby.png. - Rename the file called
character_hero.pngtocharacter_orphan_00.png. - Move all
character_**_**.pngfiles to a subdirectory calledpending.
- Rename the file called
Until we reach v2_hhas the .hha files in /data need to be rewritten using hha-edit -- rewrite, see below.
The asset builder can be used to generate HHA files based on the early data located at handmade_hero_legacy_art/early_data, they are expected to be in the /data directory.
zig build build-assets -Dpackage=AssetBuilder
zig build run-png-reader -Dpackage=PNGReader -- test/gimp_test.png
The HHA edit tool can be used to create new empty HHA files.
zig build hha-edit -Dpackage=HHAEdit -- -create local.hha
zig build hha-edit -Dpackage=HHAEdit -- -info test.hha
zig build hha-edit -Dpackage=HHAEdit -- -rewrite source.hha dest.hha
zig build hha-edit -Dpackage=HHAEdit -- -dump source.hha dest.hha
This is a way to test the renderer standalone from the rest of the project.
It expects some .bmp images in the data/renderer_test directory:
test_cube_wall.bmp(block_orphanage_01.pngscaled down to 512x512px)test_cube_grass.bmp(block_forest_01.pngscaled down to 512x512px)test_sprite_head.bmp(the last srpite incharacter_krampus.png, cropped and scaled down to 512x512px).test_sprite_tree.bmp(the bottom left sprite inobstacles_forest.png, cropped and scaled down to 512px height).test_cover_grass.bmp(the top left sprite incover_forest.png, cropped to 512x512px).
zig build hha-edit -Dpackage=RendererTest run-renderer-test
The game is split up into an executable for the runtime and a DLL that contains the actual game. This allows hot reloading for most of the game code. When the DLL is rebuilt, the game will automatically reload it.
To make this even more automatic you can run a separate terminal which automatically rebuilds the DLL when you save a file:
zig build --watch -Dpackage=Library
The included debugger config under .vscode/launch.json is compatible with the nvim-dap plugin in Neovim and the C/C++ extension in VS Code. Using regular Visual Studio with C/C++ tooling appears to give the most reliable results. Another alternative that works almost as well as Visual Studio is RAD Debugger.
When running outside of an IDE, OutputDebugString messages can be viewed using DebugView.
The build is setup to emit the generated assembly code which can be used to analyze the code for bottlenecks using llvm-mca which is bundled with LLVM version 18+.
asm volatile("# LLVM-MCA-BEGIN ProcessPixel");
// Code to analyze.
// ...
asm volatile("# LLVM-MCA-END ProcessPixel");
Analyze the emitted assembly code:
llvm-mca .\zig-out\bin\handmade-dll.asm -bottleneck-analysis -o .\zig-out\bin\handmade-dll-mca.txt
- https://www.intel.com/content/www/us/en/docs/intrinsics-guide
- https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
- https://learn.microsoft.com/en-us/cpp/intrinsics/x64-amd64-intrinsics-list?view=msvc-170
- https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/24592.pdf
- https://docs.gl/
- https://registry.khronos.org/OpenGL/api/GL/glcorearb.h
- https://www.khronos.org/opengl/wiki/OpenGL_Type
- https://www.khronos.org/files/opengl-quick-reference-card.pdf
- https://www.khronos.org/opengl/wiki/Core_Language_(GLSL)